Completed
Pull Request — master (#446)
by thomas
105:00 queued 101:56
created

ExtendedKeySerializer::getTemplate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 0
dl 0
loc 11
ccs 7
cts 7
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
4
namespace BitWasp\Bitcoin\Serializer\Key\HierarchicalKey;
5
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
7
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
8
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
9
use BitWasp\Bitcoin\Key\PublicKeyFactory;
10
use BitWasp\Bitcoin\Network\NetworkInterface;
11
use BitWasp\Bitcoin\Serializer\Types;
12
use BitWasp\Buffertools\Buffer;
13
use BitWasp\Buffertools\BufferInterface;
14
use BitWasp\Buffertools\Exceptions\ParserOutOfRange;
15
use BitWasp\Buffertools\Parser;
16
use BitWasp\Buffertools\Template;
17
18
class ExtendedKeySerializer
19
{
20
    /**
21
     * @var EcAdapterInterface
22
     */
23
    private $ecAdapter;
24
25
    /**
26
     * @param EcAdapterInterface $ecAdapter
27
     * @throws \Exception
28
     */
29 52
    public function __construct(EcAdapterInterface $ecAdapter)
30
    {
31 52
        $this->ecAdapter = $ecAdapter;
32 52
        $uint32 = Types::uint32();
33 52
        $this->template = new Template([
0 ignored issues
show
Bug introduced by
The property template does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
34 52
            Types::bytestring(4),
35 52
            Types::uint8(),
36 52
            $uint32,
37 52
            $uint32,
38 52
            Types::bytestring(32),
39 52
            Types::bytestring(33)
40
        ]);
41 52
    }
42
43
    /**
44
     * @param NetworkInterface $network
45
     * @throws \Exception
46
     */
47 52
    private function checkNetwork(NetworkInterface $network)
48
    {
49
        try {
50 52
            $network->getHDPrivByte();
51 50
            $network->getHDPubByte();
52 2
        } catch (\Exception $e) {
53 2
            throw new \Exception('Network not configured for HD wallets');
54
        }
55 50
    }
56
57
    /**
58
     * @param NetworkInterface $network
59
     * @param HierarchicalKey $key
60
     * @return Buffer
61
     */
62 10
    public function serialize(NetworkInterface $network, HierarchicalKey $key)
63
    {
64 10
        $this->checkNetwork($network);
65
66 10
        list ($prefix, $data) = $key->isPrivate()
67 10
            ? [$network->getHDPrivByte(), new Buffer("\x00". $key->getPrivateKey()->getBinary(), 33)]
68 10
            : [$network->getHDPubByte(), $key->getPublicKey()->getBuffer()];
69
70 10
        return $this->template->write([
71 10
            Buffer::hex($prefix, 4),
72 10
            $key->getDepth(),
73 10
            $key->getFingerprint(),
74 10
            $key->getSequence(),
75 10
            $key->getChainCode(),
76 10
            $data
77
        ]);
78
    }
79
80
    /**
81
     * @param NetworkInterface $network
82
     * @param Parser $parser
83
     * @return HierarchicalKey
84
     * @throws ParserOutOfRange
85
     */
86 46
    public function fromParser(NetworkInterface $network, Parser $parser)
87
    {
88 46
        $this->checkNetwork($network);
89
90
        try {
91 44
            list ($bytes, $depth, $parentFingerprint, $sequence, $chainCode, $keyData) = $this->template->parse($parser);
92
93
            /** @var BufferInterface $keyData */
94
            /** @var BufferInterface $bytes */
95 40
            $bytes = $bytes->getHex();
96 4
        } catch (ParserOutOfRange $e) {
97 4
            throw new ParserOutOfRange('Failed to extract HierarchicalKey from parser');
98
        }
99
100 40
        if ($bytes !== $network->getHDPubByte() && $bytes !== $network->getHDPrivByte()) {
101 2
            throw new \InvalidArgumentException('HD key magic bytes do not match network magic bytes');
102
        }
103
104 38
        $key = ($network->getHDPrivByte() === $bytes)
105 22
            ? PrivateKeyFactory::fromHex($keyData->slice(1), true, $this->ecAdapter)
106 38
            : PublicKeyFactory::fromHex($keyData, $this->ecAdapter);
107
108 38
        return new HierarchicalKey($this->ecAdapter, $depth, $parentFingerprint, $sequence, $chainCode, $key);
109
    }
110
111
    /**
112
     * @param NetworkInterface $network
113
     * @param BufferInterface $buffer
114
     * @return HierarchicalKey
115
     */
116 46
    public function parse(NetworkInterface $network, BufferInterface $buffer)
117
    {
118 46
        return $this->fromParser($network, new Parser($buffer));
119
    }
120
}
121