Completed
Pull Request — master (#89)
by thomas
20:32
created

BIP32Key::fromString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 3
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Blocktrail\SDK\Bitcoin;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
6
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
7
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKeyFactory;
8
use BitWasp\Bitcoin\Network\NetworkInterface;
9
10
/**
11
 * Class BIP32Key
12
 *
13
 * Container for a BIP32 key and path
14
 */
15
class BIP32Key {
16
    /**
17
     * @var HierarchicalKey
18
     */
19
    private $key;
20
21
    /**
22
     * @var BIP32Path
23
     */
24
    private $path;
25
26
    /**
27
     * @var NetworkInterface
28
     */
29
    private $network;
30
31
    /**
32
     * @var string|null
33
     */
34
    private $publicKeyHex = null;
35
36
    /**
37
     * @var BIP32Key[]
38
     */
39
    private $derivations = [];
40
41
    /**
42
     * @param HierarchicalKey  $key
43
     * @param NetworkInterface $network
44
     * @param string|null      $path
45
     * @throws \Exception
46
     */
47 23
    public function __construct(NetworkInterface $network, HierarchicalKey $key, $path = null) {
48 23
        $this->key = $key;
49 23
        $this->path = BIP32Path::path($path);
50 23
        $this->network = $network;
51
52 23
        return;
53
54
        if (is_array($key) && count($key) == 2) {
0 ignored issues
show
Unused Code introduced by
if (is_array($key) && co...ception('Bad input'); } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
55
            $this->key = $key[0];
56
            $this->path = BIP32Path::path($key[1]);
57
        } elseif (is_string($key) && is_string($path) && strlen($key) && strlen($path)) {
58
            $this->key = $key;
0 ignored issues
show
Documentation Bug introduced by
It seems like $key of type string is incompatible with the declared type object<BitWasp\Bitcoin\K...nistic\HierarchicalKey> of property $key.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
59
            $this->path = BIP32Path::path($path);
60
        } else {
61
            throw new \Exception("Bad input");
62
        }
63
    }
64
65
    /**
66
     * static method to initialize class
67
     *
68
     * @param NetworkInterface $network
69
     * @param HierarchicalKey  $key
70
     * @param string|null      $path
71
     * @return BIP32Key
72
     */
73 23
    public static function create(NetworkInterface $network, HierarchicalKey $key, $path = null) {
74 23
        return new BIP32Key($network, $key, $path);
75
    }
76
77
    /**
78
     * @param NetworkInterface $network
79
     * @param string $key
80
     * @param string|null $path
81
     * @return BIP32Key
82
     */
83 5
    public static function fromString(NetworkInterface $network, $key, $path = null) {
84 5
        return static::create($network, HierarchicalKeyFactory::fromExtended($key, $network), $path);
85
    }
86
87
    /**
88
     * @return NetworkInterface
89
     */
90
    public function network() {
91
        return $this->network;
92
    }
93
94
    /**
95
     * @return HierarchicalKey
96
     */
97 23
    public function key() {
98 23
        return $this->key;
99
    }
100
101
    /**
102
     * @return PublicKeyInterface
103
     */
104 19
    public function publicKey() {
105 19
        return $this->key->getPublicKey();
106
    }
107
108
    /**
109
     * get the HEX of the plain public key for the current BIP32 key
110
     *
111
     * @return string
112
     */
113 1
    public function publicKeyHex() {
114
        // if this is a BIP32 Private key then we first build the public key
115
        //  that way it will be cached nicely
116 1
        if (!$this->path->isPublicPath()) {
117 1
            return $this->buildKey($this->path->publicPath())->publicKey()->getHex();
118
        } else {
119
            if (is_null($this->publicKeyHex)) {
120
                $this->publicKeyHex = $this->key->getPublicKey()->getHex();
121
            }
122
123
            return $this->publicKeyHex;
124
        }
125
    }
126
127
    /**
128
     * @return BIP32Path
129
     */
130 17
    public function path() {
131 17
        return $this->path;
132
    }
133
134
    /**
135
     * @return BIP32Path
136
     */
137 1
    public function bip32Path() {
138 1
        return BIP32Path::path($this->path);
139
    }
140
141 14
    public function tuple() {
142 14
        return [$this->key->toExtendedKey($this->network), (string)$this->path];
143
    }
144
145
    /**
146
     * build child key
147
     *
148
     * @param string|BIP32Path  $path
149
     * @return BIP32Key
150
     * @throws \Exception
151
     */
152 20
    public function buildKey($path) {
153 20
        $path = BIP32Path::path($path);
154 20
        $originalPath = (string)$path;
155
156 20
        if (!isset($this->derivations[$originalPath])) {
157 20
            $key = $this->key;
158
159 20
            $toPublic = $path[0] === "M" && $this->path[0] === "m";
160 20
            if ($toPublic) {
161 12
                $path = $path->privatePath();
162
            }
163
164 20
            assert(strpos(strtolower((string)$path), strtolower((string)$this->path)) === 0);
165
166 20
            $path = substr((string)$path, strlen((string)$this->path));
167
168 20
            if (substr($path, 0, 1) == "/") {
169 19
                $path = substr($path, 1);
170
            }
171
172 20
            if (strlen($path)) {
173 19
                $key = $key->derivePath($path);
174
            }
175
176 20
            if ($toPublic) {
177 12
                $key = $key->toPublic();
178
            }
179
180 20
            $this->derivations[$originalPath] = BIP32Key::create($this->network, $key, $originalPath);
181
        }
182
183 20
        return $this->derivations[$originalPath];
184
    }
185
}
186