MerkleNode::hash()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace loophp\phptree\Node;
11
12
use drupol\phpmerkle\Hasher\DoubleSha256;
13
use drupol\phpmerkle\Hasher\HasherInterface;
14
use loophp\phptree\Modifier\FulfillCapacity;
15
use loophp\phptree\Modifier\ModifierInterface;
16
use loophp\phptree\Modifier\RemoveNullNode;
17
18
/**
19
 * Class MerkleNode.
20
 */
21
class MerkleNode extends ValueNode implements MerkleNodeInterface
22
{
23
    /**
24
     * @var HasherInterface
25
     */
26
    private $hasher;
27
28
    /**
29
     * @var ModifierInterface[]
30
     */
31
    private $modifiers = [];
32
33
    /**
34
     * MerkleNode constructor.
35
     *
36
     * @param mixed $value
37
     * @param HasherInterface $hasher
38
     */
39 8
    public function __construct(
40
        $value,
41
        int $capacity = 2,
42
        ?HasherInterface $hasher = null
43
    ) {
44 8
        parent::__construct($value, $capacity, null, null);
45
46 8
        $this->hasher = $hasher ?? new DoubleSha256();
47 8
        $this->modifiers = [
48 8
            new RemoveNullNode(),
49 8
            new FulfillCapacity(),
50
        ];
51 8
    }
52
53 6
    public function hash(): string
54
    {
55 6
        return $this->hasher->unpack($this->doHash($this->normalize()));
56
    }
57
58 1
    public function label(): string
59
    {
60 1
        return $this->isLeaf() ?
61 1
            $this->getValue() :
62 1
            $this->hash();
63
    }
64
65 6
    public function normalize(): MerkleNodeInterface
66
    {
67 6
        return array_reduce(
68 6
            $this->modifiers,
69
            static function (MerkleNodeInterface $tree, ModifierInterface $modifier): MerkleNodeInterface {
70 6
                return $modifier->modify($tree);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $modifier->modify($tree) returns the type loophp\phptree\Node\NodeInterface which includes types incompatible with the type-hinted return loophp\phptree\Node\MerkleNodeInterface.
Loading history...
71 6
            },
72 6
            $this->clone()
73
        );
74
    }
75
76 6
    private function doHash(MerkleNodeInterface $node): string
77
    {
78
        // If node is a leaf, then compute its hash from its value.
79 6
        if ($node->isLeaf()) {
80 6
            return $this->hasher->hash($node->getValue());
0 ignored issues
show
Bug introduced by
It seems like $node->getValue() can also be of type null; however, parameter $data of drupol\phpmerkle\Hasher\HasherInterface::hash() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
            return $this->hasher->hash(/** @scrutinizer ignore-type */ $node->getValue());
Loading history...
81
        }
82
83 6
        $hash = '';
84
        /** @var MerkleNodeInterface $child */
85 6
        foreach ($node->children() as $child) {
86 6
            $hash .= $this->doHash($child);
87
        }
88
89 6
        return $this->hasher->hash($hash);
90
    }
91
}
92