UNPKG

5.99 kBJavaScriptView Raw
1let BIP32 = require('../')
2let tape = require('tape')
3let fixtures = require('./fixtures/index.json')
4let LITECOIN = {
5 wif: 0xb0,
6 bip32: {
7 public: 0x019da462,
8 private: 0x019d9cfe
9 }
10}
11
12// TODO: amend the JSON
13let validAll = []
14fixtures.valid.forEach((f) => {
15 f.master.network = f.network
16 f.master.children = f.children
17 f.master.comment = f.comment
18 f.children.forEach((fc) => {
19 fc.network = f.network
20 validAll.push(fc)
21 })
22 delete f.children
23 validAll.push(f.master)
24})
25
26function verify (t, hd, prv, f, network) {
27 t.equal(hd.chainCode.toString('hex'), f.chainCode)
28 t.equal(hd.depth, f.depth >>> 0)
29 t.equal(hd.index, f.index >>> 0)
30 t.equal(hd.fingerprint.toString('hex'), f.fingerprint)
31 t.equal(hd.identifier.toString('hex'), f.identifier)
32 t.equal(hd.publicKey.toString('hex'), f.pubKey)
33 if (prv) t.equal(hd.toBase58(), f.base58Priv)
34 if (prv) t.equal(hd.privateKey.toString('hex'), f.privKey)
35 if (prv) t.equal(hd.toWIF(), f.wif)
36 if (!prv) t.throws(() => hd.toWIF(), /Missing private key/)
37 if (!prv) t.equal(hd.privateKey, null)
38 t.equal(hd.neutered().toBase58(), f.base58)
39 t.equal(hd.isNeutered(), !prv)
40
41 if (!f.children) return
42 if (!prv && f.children.some(x => x.hardened)) return
43
44 // test deriving path from master
45 f.children.forEach((cf) => {
46 let chd = hd.derivePath(cf.path)
47 verify(t, chd, prv, cf, network)
48
49 let chdNoM = hd.derivePath(cf.path.slice(2)) // no m/
50 verify(t, chdNoM, prv, cf, network)
51 })
52
53 // test deriving path from successive children
54 let shd = hd
55 f.children.forEach((cf) => {
56 if (cf.m === undefined) return
57 if (cf.hardened) {
58 shd = shd.deriveHardened(cf.m)
59 } else {
60 // verify any publicly derived children
61 if (cf.base58) verify(t, shd.neutered().derive(cf.m), false, cf, network)
62
63 shd = shd.derive(cf.m)
64 verify(t, shd, prv, cf, network)
65 }
66
67 t.throws(() => {
68 shd.derivePath('m/0')
69 }, /Expected master, got child/)
70
71 verify(t, shd, prv, cf, network)
72 })
73}
74
75validAll.forEach((ff) => {
76 tape(ff.comment || ff.base58Priv, (t) => {
77 let network
78 if (ff.network === 'litecoin') network = LITECOIN
79
80 let hd = BIP32.fromBase58(ff.base58Priv, network)
81 verify(t, hd, true, ff, network)
82
83 hd = BIP32.fromBase58(ff.base58, network)
84 verify(t, hd, false, ff, network)
85
86 if (ff.seed) {
87 let seed = Buffer.from(ff.seed, 'hex')
88 hd = BIP32.fromSeed(seed, network)
89 verify(t, hd, true, ff, network)
90 }
91
92 t.end()
93 })
94})
95
96tape('fromBase58 throws', (t) => {
97 fixtures.invalid.fromBase58.forEach((f) => {
98 t.throws(() => {
99 let network
100 if (f.network === 'litecoin') network = LITECOIN
101
102 BIP32.fromBase58(f.string, network)
103 }, new RegExp(f.exception))
104 })
105
106 t.end()
107})
108
109tape('works for Private -> public (neutered)', (t) => {
110 let f = fixtures.valid[1]
111 let c = f.master.children[0]
112
113 let master = BIP32.fromBase58(f.master.base58Priv)
114 let child = master.derive(c.m).neutered()
115
116 t.plan(1)
117 t.equal(child.toBase58(), c.base58)
118})
119
120tape('works for Private -> public (neutered, hardened)', (t) => {
121 let f = fixtures.valid[0]
122 let c = f.master.children[0]
123
124 let master = BIP32.fromBase58(f.master.base58Priv)
125 let child = master.deriveHardened(c.m).neutered()
126
127 t.plan(1)
128 t.equal(c.base58, child.toBase58())
129})
130
131tape('works for Public -> public', (t) => {
132 let f = fixtures.valid[1]
133 let c = f.master.children[0]
134
135 let master = BIP32.fromBase58(f.master.base58)
136 let child = master.derive(c.m)
137
138 t.plan(1)
139 t.equal(c.base58, child.toBase58())
140})
141
142tape('throws on Public -> public (hardened)', (t) => {
143 let f = fixtures.valid[0]
144 let c = f.master.children[0]
145
146 let master = BIP32.fromBase58(f.master.base58)
147
148 t.plan(1)
149 t.throws(() => {
150 master.deriveHardened(c.m)
151 }, /Missing private key for hardened child key/)
152})
153
154tape('throws on wrong types', (t) => {
155 let f = fixtures.valid[0]
156 let master = BIP32.fromBase58(f.master.base58)
157
158 fixtures.invalid.derive.forEach((fx) => {
159 t.throws(() => {
160 master.derive(fx)
161 }, /Expected UInt32/)
162 })
163
164 fixtures.invalid.deriveHardened.forEach((fx) => {
165 t.throws(() => {
166 master.deriveHardened(fx)
167 }, /Expected UInt31/)
168 })
169
170 fixtures.invalid.derivePath.forEach((fx) => {
171 t.throws(() => {
172 master.derivePath(fx)
173 }, /Expected BIP32Path, got/)
174 })
175
176 let ZERO = Buffer.alloc(32, 0)
177 let ONES = Buffer.alloc(32, 1)
178
179 t.throws(() => {
180 BIP32.fromPrivateKey(Buffer.alloc(2), ONES)
181 }, /Expected property "privateKey" of type Buffer\(Length: 32\), got Buffer\(Length: 2\)/)
182
183 t.throws(() => {
184 BIP32.fromPrivateKey(ZERO, ONES)
185 }, /Private key not in range \[1, n\)/)
186
187 t.end()
188})
189
190tape('works when private key has leading zeros', (t) => {
191 let key = 'xprv9s21ZrQH143K3ckY9DgU79uMTJkQRLdbCCVDh81SnxTgPzLLGax6uHeBULTtaEtcAvKjXfT7ZWtHzKjTpujMkUd9dDb8msDeAfnJxrgAYhr'
192 let hdkey = BIP32.fromBase58(key)
193
194 t.plan(2)
195 t.equal(hdkey.privateKey.toString('hex'), '00000055378cf5fafb56c711c674143f9b0ee82ab0ba2924f19b64f5ae7cdbfd')
196 let child = hdkey.derivePath('m/44\'/0\'/0\'/0/0\'')
197 t.equal(child.privateKey.toString('hex'), '3348069561d2a0fb925e74bf198762acc47dce7db27372257d2d959a9e6f8aeb')
198})
199
200tape('fromSeed', (t) => {
201 // TODO
202// 'throws if IL is not within interval [1, n - 1] | IL === n || IL === 0'
203 fixtures.invalid.fromSeed.forEach((f) => {
204 t.throws(() => {
205 BIP32.fromSeed(Buffer.from(f.seed, 'hex'))
206 }, new RegExp(f.exception))
207 })
208
209 t.end()
210})
211
212tape('ecdsa', (t) => {
213 let seed = Buffer.alloc(32, 1)
214 let hash = Buffer.alloc(32, 2)
215 let signature = Buffer.from('9636ee2fac31b795a308856b821ebe297dda7b28220fb46ea1fbbd7285977cc04c82b734956246a0f15a9698f03f546d8d96fe006c8e7bd2256ca7c8229e6f5c', 'hex')
216 let node = BIP32.fromSeed(seed)
217
218 t.plan(3)
219 t.equal(node.sign(hash).toString('hex'), signature.toString('hex'))
220 t.equal(node.verify(hash, signature), true)
221 t.equal(node.verify(seed, signature), false)
222})