Completed
Push — master ( 29ec42...778040 )
by thomas
9s
created

PartialMerkleTreeSerializer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
namespace BitWasp\Bitcoin\Serializer\Block;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Block\PartialMerkleTree;
7
use BitWasp\Buffertools\Buffer;
8
use BitWasp\Buffertools\BufferInterface;
9
use BitWasp\Buffertools\Parser;
10
use BitWasp\Buffertools\TemplateFactory;
11
12
class PartialMerkleTreeSerializer
13
{
14
    /**
15
     * @var \BitWasp\Buffertools\Template
16
     */
17
    private $template;
18
19
    /**
20
     * PartialMerkleTreeSerializer constructor.
21
     */
22 12
    public function __construct()
23
    {
24 12
        $this->template = $this->getTemplate();
25 12
    }
26
27
    /**
28
     * @return \BitWasp\Buffertools\Template
29
     */
30 12
    public function getTemplate()
31
    {
32 12
        return (new TemplateFactory())
33 12
            ->uint32le()
34
            ->vector(function (Parser $parser) {
35 6
                return $parser->readBytes(32);
36 12
            })
37 12
            ->vector(function (Parser $parser) {
38 6
                return $parser->readBytes(1);
39 12
            })
40 12
            ->getTemplate();
41
    }
42
43
    /**
44
     * @param int $last
45
     * @param BufferInterface[] $vBytes
46
     * @return array
47
     */
48 6
    private function buffersToBitArray($last, array $vBytes)
49
    {
50 6
        $size = count($vBytes) * 8;
51 6
        $vBits = [];
52
53 6
        for ($p = 0; $p < $size; $p++) {
54 6
            $byteIndex = (int)floor($p / 8);
55 6
            $byte = ord($vBytes[$byteIndex]->getBinary());
56 6
            $vBits[$p] = (int) (($byte & (1 << ($p % 8))) !== 0);
57 4
        }
58
59 6
        return array_slice($vBits, 0, $last);
60
    }
61
62
    /**
63
     * @param Parser $parser
64
     * @return PartialMerkleTree
65
     */
66 6
    public function fromParser(Parser $parser)
67
    {
68 6
        list ($txCount, $vHash, $vBits) = $this->template->parse($parser);
69
70 6
        return new PartialMerkleTree(
71 6
            (int)$txCount,
72 4
            $vHash,
73 6
            $this->buffersToBitArray($txCount, $vBits)
74 4
        );
75
    }
76
77
    /**
78
     * @param $data
79
     * @return PartialMerkleTree
80
     */
81 3
    public function parse($data)
82
    {
83 3
        return $this->fromParser(new Parser($data));
84
    }
85
86
    /**
87
     * @param array $bits
88
     * @return array
89
     */
90 12
    private function bitsToBuffers(array $bits)
91
    {
92 12
        $math = Bitcoin::getMath();
93 12
        $vBuffers = str_split(str_pad('', (count($bits)+7)/8, '0', STR_PAD_LEFT));
94 12
        $nBits = count($bits);
95
96 12
        for ($p = 0; $p < $nBits; $p++) {
97 12
            $index = (int)floor($p / 8);
98 12
            $vBuffers[$index] |= $bits[$p] << ($p % 8);
99 8
        }
100
101 12
        foreach ($vBuffers as &$value) {
102 12
            $value = Buffer::int($value, null, $math);
103 8
        }
104 12
        unset($value);
105
106 12
        return $vBuffers;
107
    }
108
109
    /**
110
     * @param PartialMerkleTree $tree
111
     * @return \BitWasp\Buffertools\Buffer
112
     */
113 12
    public function serialize(PartialMerkleTree $tree)
114
    {
115 12
        return $this->template->write([
116 12
            $tree->getTxCount(),
117 12
            $tree->getHashes(),
118 12
            $this->bitsToBuffers($tree->getFlagBits())
119 8
        ]);
120
    }
121
}
122