Completed
Push — master ( 6d3301...6b3d75 )
by thomas
84:48 queued 14:45
created

ExtendedKeySerializer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
4
namespace BitWasp\Bitcoin\Serializer\Key\HierarchicalKey;
5
6
use BitWasp\Buffertools\Buffer;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
8
use BitWasp\Buffertools\BufferInterface;
9
use BitWasp\Buffertools\Exceptions\ParserOutOfRange;
10
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
11
use BitWasp\Bitcoin\Key\PublicKeyFactory;
12
use BitWasp\Bitcoin\Network\NetworkInterface;
13
use BitWasp\Buffertools\Parser;
14
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
15
use BitWasp\Buffertools\TemplateFactory;
16
17
class ExtendedKeySerializer
18
{
19
    /**
20
     * @var EcAdapterInterface
21
     */
22
    private $ecAdapter;
23
24
    /**
25
     * @param EcAdapterInterface $ecAdapter
26
     * @throws \Exception
27
     */
28
    public function __construct(EcAdapterInterface $ecAdapter)
29
    {
30
        $this->ecAdapter = $ecAdapter;
31
    }
32
33
    /**
34 120
     * @return \BitWasp\Buffertools\Template
35
     */
36
    public function getTemplate()
37 120
    {
38 114
        return (new TemplateFactory())
39 63
            ->bytestring(4)
40 6
            ->uint8()
41
            ->uint32()
42
            ->uint32()
43 114
            ->bytestring(32)
44 114
            ->bytestring(33)
45 114
            ->getTemplate();
46
    }
47
48
    /**
49
     * @param NetworkInterface $network
50 114
     * @throws \Exception
51
     */
52 114
    private function checkNetwork(NetworkInterface $network)
53 114
    {
54 114
        try {
55 114
            $network->getHDPrivByte();
56 114
            $network->getHDPubByte();
57 114
        } catch (\Exception $e) {
58 114
            throw new \Exception('Network not configured for HD wallets');
59 114
        }
60
    }
61
62
    /**
63
     * @param NetworkInterface $network
64
     * @param HierarchicalKey $key
65
     * @return Buffer
66 30
     */
67
    public function serialize(NetworkInterface $network, HierarchicalKey $key)
68 30
    {
69 30
        $this->checkNetwork($network);
70 30
71
        list ($prefix, $data) = ($key->isPrivate())
72 30
            ? [$network->getHDPrivByte(), '00' . $key->getPrivateKey()->getHex()]
73 30
            : [$network->getHDPubByte(), $key->getPublicKey()->getHex()];
74 30
75 30
        return $this->getTemplate()->write([
76 30
            Buffer::hex($prefix, 4),
77 30
            $key->getDepth(),
78 30
            $key->getFingerprint(),
79 15
            $key->getSequence(),
80
            $key->getChainCode(),
81
            Buffer::hex($data, 33)
82
        ]);
83
    }
84
85
    /**
86
     * @param NetworkInterface $network
87 96
     * @param Parser $parser
88
     * @return HierarchicalKey
89
     * @throws ParserOutOfRange
90 96
     */
91
    public function fromParser(NetworkInterface $network, Parser $parser)
92
    {
93 84
        $this->checkNetwork($network);
94 54
95 12
        try {
96
            list ($bytes, $depth, $parentFingerprint, $sequence, $chainCode, $keyData) = $this->getTemplate()->parse($parser);
97
            /** @var BufferInterface $keyData */
98 84
            /** @var BufferInterface $bytes */
99 6
            $bytes = $bytes->getHex();
100
        } catch (ParserOutOfRange $e) {
101
            throw new ParserOutOfRange('Failed to extract HierarchicalKey from parser');
102 78
        }
103 54
104 78
        if ($bytes !== $network->getHDPubByte() && $bytes !== $network->getHDPrivByte()) {
105
            throw new \InvalidArgumentException('HD key magic bytes do not match network magic bytes');
106 78
        }
107
108
        $key = ($network->getHDPrivByte() === $bytes)
109
            ? PrivateKeyFactory::fromHex($keyData->slice(1)->getHex(), true, $this->ecAdapter)
110
            : PublicKeyFactory::fromHex($keyData->getHex(), $this->ecAdapter);
111
112
        return new HierarchicalKey($this->ecAdapter, $depth, $parentFingerprint, $sequence, $chainCode, $key);
113
    }
114
115 96
    /**
116
     * @param NetworkInterface $network
117 96
     * @param BufferInterface $buffer
118 96
     * @return HierarchicalKey
119
     */
120
    public function parse(NetworkInterface $network, BufferInterface $buffer)
121
    {
122
        $parser = new Parser($buffer);
123
        return $this->fromParser($network, $parser);
124
    }
125
}
126