Completed
Pull Request — master (#118)
by Ruben de
07:42
created

BIP32Key::bip32Path()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
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 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Blocktrail\SDK\Bitcoin;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key\PublicKey;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
7
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
8
9
/**
10
 * Class BIP32Key
11
 *
12
 * Container for a BIP32 key and path
13
 */
14
class BIP32Key {
15
    /**
16
     * @var HierarchicalKey
17
     */
18
    private $key;
19
20
    /**
21
     * @var BIP32Path
22
     */
23
    private $path;
24
25
    /**
26
     * @var string|null
27
     */
28
    private $publicKeyHex = null;
29
30
    /**
31
     * @var BIP32Key[]
32
     */
33
    private $derivations = [];
34
35
    /**
36
     * @param HierarchicalKey $key
37
     * @param string|null     $path
38
     * @throws \Exception
39
     */
40 3
    public function __construct(HierarchicalKey $key, $path = null) {
41 3
        $this->key = $key;
42 3
        $this->path = BIP32Path::path($path);
43
44 3
        return;
45
46
        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...
47
            $this->key = $key[0];
48
            $this->path = BIP32Path::path($key[1]);
49
        } elseif (is_string($key) && is_string($path) && strlen($key) && strlen($path)) {
50
            $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...
51
            $this->path = BIP32Path::path($path);
52
        } else {
53
            throw new \Exception("Bad input");
54
        }
55
    }
56
57
    /**
58
     * static method to initialize class
59
     *
60
     * @param HierarchicalKey $key
61
     * @param string|null     $path
62
     * @return BIP32Key
63
     */
64 3
    public static function create(HierarchicalKey $key, $path = null) {
65 3
        return new BIP32Key($key, $path);
66
    }
67
68
    /**
69
     * @return HierarchicalKey
70
     */
71 2
    public function key() {
72 2
        return $this->key;
73
    }
74
75
    /**
76
     * @return PublicKeyInterface
77
     */
78 3
    public function publicKey() {
79 3
        return $this->key->getPublicKey();
80
    }
81
82
    /**
83
     * get the HEX of the plain public key for the current BIP32 key
84
     *
85
     * @return string
86
     */
87
    public function publicKeyHex() {
88
        // if this is a BIP32 Private key then we first build the public key
89
        //  that way it will be cached nicely
90
        if (!$this->path->isPublicPath()) {
91
            return $this->buildKey($this->path->publicPath())->publicKey()->getHex();
92
        } else {
93
            if (is_null($this->publicKeyHex)) {
94
                $this->publicKeyHex = $this->key->getPublicKey()->getHex();
95
            }
96
97
            return $this->publicKeyHex;
98
        }
99
    }
100
101
    /**
102
     * @return BIP32Path
103
     */
104 3
    public function path() {
105 3
        return $this->path;
106
    }
107
108
    /**
109
     * @return BIP32Path
110
     */
111
    public function bip32Path() {
112
        return BIP32Path::path($this->path);
113
    }
114
115 2
    public function tuple() {
116 2
        return [$this->key->toExtendedKey(), (string)$this->path];
117
    }
118
119
    /**
120
     * build child key
121
     *
122
     * @param string|BIP32Path  $path
123
     * @return BIP32Key
124
     * @throws \Exception
125
     */
126 3
    public function buildKey($path) {
127 3
        $path = BIP32Path::path($path);
128 3
        $originalPath = (string)$path;
129
130 3
        if (!isset($this->derivations[$originalPath])) {
131 3
            $key = $this->key;
132
133 3
            $toPublic = $path[0] === "M" && $this->path[0] === "m";
134 3
            if ($toPublic) {
135 1
                $path = $path->privatePath();
136
            }
137
138 3
            assert(strpos(strtolower((string)$path), strtolower((string)$this->path)) === 0);
139
140 3
            $path = substr((string)$path, strlen((string)$this->path));
141
142 3
            if (substr($path, 0, 1) == "/") {
143 3
                $path = substr($path, 1);
144
            }
145
146 3
            if (strlen($path)) {
147 3
                $key = $key->derivePath($path);
148
            }
149
150 3
            if ($toPublic) {
151 1
                $key = $key->toPublic();
152
            }
153
154 3
            $this->derivations[$originalPath] = BIP32Key::create($key, $originalPath);
155
        }
156
157 3
        return $this->derivations[$originalPath];
158
    }
159
}
160