Completed
Pull Request — master (#591)
by thomas
22:54 queued 09:12
created

ExtendedKeySerializer::checkNetwork()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.1481

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 3
nop 1
dl 0
loc 9
ccs 4
cts 6
cp 0.6667
crap 2.1481
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Serializer\Key\HierarchicalKey;
6
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
8
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
9
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
10
use BitWasp\Bitcoin\Key\PublicKeyFactory;
11
use BitWasp\Bitcoin\Network\NetworkInterface;
12
use BitWasp\Bitcoin\Serializer\Types;
13
use BitWasp\Buffertools\Buffer;
14
use BitWasp\Buffertools\BufferInterface;
15
use BitWasp\Buffertools\Exceptions\ParserOutOfRange;
16
use BitWasp\Buffertools\Parser;
17
18
class ExtendedKeySerializer
19
{
20
    /**
21
     * @var EcAdapterInterface
22
     */
23
    private $ecAdapter;
24
25
    /**
26
     * @var \BitWasp\Buffertools\Types\ByteString
27
     */
28
    private $bytestring4;
29
30
    /**
31
     * @var \BitWasp\Buffertools\Types\Uint8
32
     */
33
    private $uint8;
34
35
    /**
36
     * @var \BitWasp\Buffertools\Types\Uint32
37
     */
38
    private $uint32;
39
40
    /**
41
     * @var \BitWasp\Buffertools\Types\ByteString
42
     */
43
    private $bytestring32;
44
45
    /**
46
     * @var \BitWasp\Buffertools\Types\ByteString
47
     */
48
    private $bytestring33;
49
50
    /**
51
     * @param EcAdapterInterface $ecAdapter
52
     * @throws \Exception
53
     */
54 43
    public function __construct(EcAdapterInterface $ecAdapter)
55
    {
56 43
        $this->ecAdapter = $ecAdapter;
57 43
        $this->bytestring4 = Types::bytestring(4);
58 43
        $this->uint8 = Types::uint8();
59 43
        $this->uint32 = Types::uint32();
60 43
        $this->bytestring32 = Types::bytestring(32);
61 43
        $this->bytestring33 = Types::bytestring(33);
62 43
    }
63
64
    /**
65
     * @param NetworkInterface $network
66
     * @param HierarchicalKey $key
67
     * @return BufferInterface
68
     * @throws \Exception
69
     */
70 11
    public function serialize(NetworkInterface $network, HierarchicalKey $key): BufferInterface
71
    {
72 11
        list ($prefix, $data) = $key->isPrivate()
73 11
            ? [$network->getHDPrivByte(), new Buffer("\x00". $key->getPrivateKey()->getBinary(), 33)]
74 11
            : [$network->getHDPubByte(), $key->getPublicKey()->getBuffer()];
75
76 11
        return new Buffer(
77 11
            pack("H*", $prefix) .
78 11
            $this->uint8->write($key->getDepth()) .
79 11
            $this->uint32->write($key->getFingerprint()) .
80 11
            $this->uint32->write($key->getSequence()) .
81 11
            $this->bytestring32->write($key->getChainCode()) .
0 ignored issues
show
Compatibility introduced by
$key->getChainCode() of type object<BitWasp\Buffertools\BufferInterface> is not a sub-type of object<BitWasp\Buffertools\Buffer>. It seems like you assume a concrete implementation of the interface BitWasp\Buffertools\BufferInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
82 11
            $this->bytestring33->write($data)
0 ignored issues
show
Compatibility introduced by
$data of type object<BitWasp\Buffertools\BufferInterface> is not a sub-type of object<BitWasp\Buffertools\Buffer>. It seems like you assume a concrete implementation of the interface BitWasp\Buffertools\BufferInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
83
        );
84
    }
85
86
    /**
87
     * @param NetworkInterface $network
88
     * @param Parser $parser
89
     * @return HierarchicalKey
90
     * @throws ParserOutOfRange
91
     */
92 36
    public function fromParser(NetworkInterface $network, Parser $parser): HierarchicalKey
93
    {
94
        try {
95
            list ($bytes, $depth, $parentFingerprint, $sequence, $chainCode, $keyData) = [
96 36
                $this->bytestring4->read($parser),
97 34
                (int) $this->uint8->read($parser),
98 34
                (int) $this->uint32->read($parser),
99 34
                (int) $this->uint32->read($parser),
100 34
                $this->bytestring32->read($parser),
101 33
                $this->bytestring33->read($parser),
102
            ];
103
104 33
            $bytes = $bytes->getHex();
105 3
        } catch (ParserOutOfRange $e) {
106 3
            throw new ParserOutOfRange('Failed to extract HierarchicalKey from parser');
107
        }
108
109 33
        if ($bytes !== $network->getHDPubByte() && $bytes !== $network->getHDPrivByte()) {
110 1
            throw new \InvalidArgumentException('HD key magic bytes do not match network magic bytes');
111
        }
112
113 32
        $key = ($network->getHDPrivByte() === $bytes)
114 16
            ? PrivateKeyFactory::fromBuffer($keyData->slice(1), true, $this->ecAdapter)
115 32
            : PublicKeyFactory::fromBuffer($keyData, $this->ecAdapter);
116
117 32
        return new HierarchicalKey($this->ecAdapter, $depth, $parentFingerprint, $sequence, $chainCode, $key);
118
    }
119
120
    /**
121
     * @param NetworkInterface $network
122
     * @param BufferInterface $buffer
123
     * @return HierarchicalKey
124
     * @throws ParserOutOfRange
125
     */
126 36
    public function parse(NetworkInterface $network, BufferInterface $buffer): HierarchicalKey
127
    {
128 36
        return $this->fromParser($network, new Parser($buffer));
129
    }
130
}
131