Completed
Pull Request — master (#317)
by thomas
16:45 queued 06:42
created

ExtendedKeySerializer::getTemplate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

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