UNPKG

16.1 kBJavaScriptView Raw
1'use strict'
2
3var chai = require('chai')
4var should = chai.should()
5var expect = chai.expect
6
7var bsv = require('..')
8var BN = bsv.crypto.BN
9var Point = bsv.crypto.Point
10var PrivateKey = bsv.PrivateKey
11var Networks = bsv.Networks
12var Base58Check = bsv.encoding.Base58Check
13
14var validbase58 = require('./data/bitcoind/base58_keys_valid.json')
15var invalidbase58 = require('./data/bitcoind/base58_keys_invalid.json')
16
17describe('PrivateKey', function () {
18 var hex = '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a'
19 var hex2 = '8080808080808080808080808080808080808080808080808080808080808080'
20 var buf = Buffer.from(hex, 'hex')
21 var wifTestnet = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG'
22 var wifTestnetUncompressed = '92jJzK4tbURm1C7udQXxeCBvXHoHJstDXRxAMouPG1k1XUaXdsu'
23 var wifLivenet = 'L2Gkw3kKJ6N24QcDuH4XDqt9cTqsKTVNDGz1CRZhk9cq4auDUbJy'
24 var wifLivenetUncompressed = '5JxgQaFM1FMd38cd14e3mbdxsdSa9iM2BV6DHBYsvGzxkTNQ7Un'
25 var wifNamecoin = '74pxNKNpByQ2kMow4d9kF6Z77BYeKztQNLq3dSyU4ES1K5KLNiz'
26
27 it('should create a new random private key', function () {
28 var a = new PrivateKey()
29 should.exist(a)
30 should.exist(a.bn)
31 var b = PrivateKey()
32 should.exist(b)
33 should.exist(b.bn)
34 })
35
36 it('should create a privatekey from hexa string', function () {
37 var a = new PrivateKey(hex2)
38 should.exist(a)
39 should.exist(a.bn)
40 })
41
42 it('should create a new random testnet private key with only one argument', function () {
43 var a = new PrivateKey(Networks.testnet)
44 should.exist(a)
45 should.exist(a.bn)
46 })
47
48 it('should create a private key from a custom network WIF string', function () {
49 var nmc = {
50 name: 'namecoin',
51 alias: 'namecoin',
52 pubkeyhash: 0x34,
53 privatekey: 0xB4,
54 // these below aren't the real NMC version numbers
55 scripthash: 0x08,
56 xpubkey: 0x0278b20e,
57 xprivkey: 0x0278ade4,
58 networkMagic: 0xf9beb4fe,
59 port: 20001,
60 dnsSeeds: [
61 'localhost',
62 'mynet.localhost'
63 ]
64 }
65 Networks.add(nmc)
66 var nmcNet = Networks.get('namecoin')
67 var a = new PrivateKey(wifNamecoin, nmcNet)
68 should.exist(a)
69 should.exist(a.bn)
70 Networks.remove(nmcNet)
71 })
72
73 it('should create a new random testnet private key with empty data', function () {
74 var a = new PrivateKey(null, Networks.testnet)
75 should.exist(a)
76 should.exist(a.bn)
77 })
78
79 it('should create a private key from WIF string', function () {
80 var a = new PrivateKey('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m')
81 should.exist(a)
82 should.exist(a.bn)
83 })
84
85 it('should create a private key from WIF buffer', function () {
86 var a = new PrivateKey(Base58Check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m'))
87 should.exist(a)
88 should.exist(a.bn)
89 })
90
91 describe('bitcoind compliance', function () {
92 validbase58.map(function (d) {
93 if (d[2].isPrivkey) {
94 it('should instantiate WIF private key ' + d[0] + ' with correct properties', function () {
95 var network = Networks.livenet
96 if (d[2].isTestnet) {
97 network = Networks.testnet
98 }
99 var key = new PrivateKey(d[0])
100 key.compressed.should.equal(d[2].isCompressed)
101 key.network.should.equal(network)
102 })
103 }
104 })
105 invalidbase58.map(function (d) {
106 it('should describe input ' + d[0].slice(0, 10) + '... as invalid', function () {
107 expect(function () {
108 return new PrivateKey(d[0])
109 }).to.throw(Error)
110 })
111 })
112 })
113
114 describe('instantiation', function () {
115 it('should not be able to instantiate private key greater than N', function () {
116 expect(function () {
117 return new PrivateKey(Point.getN())
118 }).to.throw('Number must be less than N')
119 })
120
121 it('should not be able to instantiate private key because of network mismatch', function () {
122 expect(function () {
123 return new PrivateKey('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m', 'testnet')
124 }).to.throw('Private key network mismatch')
125 })
126
127 it('should not be able to instantiate private key WIF is too long', function () {
128 expect(function () {
129 var buf = Base58Check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m')
130 var buf2 = Buffer.concat([buf, Buffer.alloc(0x01)])
131 return new PrivateKey(buf2)
132 }).to.throw('Length of buffer must be 33 (uncompressed) or 34 (compressed')
133 })
134
135 it('should not be able to instantiate private key WIF because of unknown network byte', function () {
136 expect(function () {
137 var buf = Base58Check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m')
138 var buf2 = Buffer.concat([Buffer.from('ff', 'hex'), buf.slice(1, 33)])
139 return new PrivateKey(buf2)
140 }).to.throw('Invalid network')
141 })
142
143 it('should not be able to instantiate private key WIF because of network mismatch', function () {
144 expect(function () {
145 new PrivateKey(wifNamecoin, 'testnet') //eslint-disable-line
146 }).to.throw('Invalid network')
147 })
148
149 it('can be instantiated from a hex string', function () {
150 var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff'
151 var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc'
152 var privkey = new PrivateKey(privhex)
153 privkey.publicKey.toString().should.equal(pubhex)
154 })
155
156 it('should not be able to instantiate because of unrecognized data', function () {
157 expect(function () {
158 return new PrivateKey(new Error())
159 }).to.throw('First argument is an unrecognized data type.')
160 })
161
162 it('should not be able to instantiate with unknown network', function () {
163 expect(function () {
164 return new PrivateKey(new BN(2), 'unknown')
165 }).to.throw('Must specify the network ("livenet" or "testnet")')
166 })
167
168 it('should not create a zero private key', function () {
169 expect(function () {
170 var bn = new BN(0)
171 return new PrivateKey(bn)
172 }).to.throw(TypeError)
173 })
174
175 it('should create a livenet private key', function () {
176 var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet')
177 privkey.toWIF().should.equal(wifLivenet)
178 })
179
180 it('should create a default network private key', function () {
181 // keep the original
182 var network = Networks.defaultNetwork
183 Networks.defaultNetwork = Networks.livenet
184 var a = new PrivateKey(BN.fromBuffer(buf))
185 a.network.should.equal(Networks.livenet)
186 // change the default
187 Networks.defaultNetwork = Networks.testnet
188 var b = new PrivateKey(BN.fromBuffer(buf))
189 b.network.should.equal(Networks.testnet)
190 // restore the default
191 Networks.defaultNetwork = network
192 })
193
194 it('returns the same instance if a PrivateKey is provided (immutable)', function () {
195 var privkey = new PrivateKey()
196 new PrivateKey(privkey).should.equal(privkey)
197 })
198 })
199
200 describe('#json/object', function () {
201 it('should input/output json', function () {
202 var json = JSON.stringify({
203 bn: '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a',
204 compressed: false,
205 network: 'livenet'
206 })
207 var key = PrivateKey.fromObject(JSON.parse(json))
208 JSON.stringify(key).should.equal(json)
209 })
210
211 it('should input/output json', function () {
212 var json = JSON.stringify({
213 bn: '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a',
214 compressed: false,
215 network: 'livenet'
216 })
217 var key = PrivateKey.fromJSON(JSON.parse(json))
218 JSON.stringify(key).should.equal(json)
219 })
220
221 it('input json should correctly initialize network field', function () {
222 ['livenet', 'testnet', 'mainnet'].forEach(function (net) {
223 var pk = PrivateKey.fromObject({
224 bn: '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a',
225 compressed: false,
226 network: net
227 })
228 pk.network.should.be.deep.equal(Networks.get(net))
229 })
230 })
231
232 it('fails on invalid argument', function () {
233 expect(function () {
234 return PrivateKey.fromJSON('¹')
235 }).to.throw()
236 })
237
238 it('also accepts an object as argument', function () {
239 expect(function () {
240 return PrivateKey.fromObject(new PrivateKey().toObject())
241 }).to.not.throw()
242 })
243
244 it('also accepts an object as argument', function () {
245 expect(function () {
246 return PrivateKey.fromObject(new PrivateKey().toJSON())
247 }).to.not.throw()
248 })
249 })
250
251 it('coverage: public key cache', function () {
252 expect(function () {
253 var privateKey = new PrivateKey()
254 var publicKey = privateKey.publicKey
255 return publicKey
256 }).to.not.throw()
257 })
258
259 describe('#toString', function () {
260 it('should output this address correctly', function () {
261 var privkey = PrivateKey.fromWIF(wifLivenetUncompressed)
262 privkey.toWIF().should.equal(wifLivenetUncompressed)
263 })
264 })
265
266 describe('#toAddress', function () {
267 it('should output this known livenet address correctly', function () {
268 var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m')
269 var address = privkey.toAddress()
270 address.toString().should.equal('1A6ut1tWnUq1SEQLMr4ttDh24wcbJ5o9TT')
271 })
272
273 it('should output this known testnet address correctly', function () {
274 var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq')
275 var address = privkey.toAddress()
276 address.toString().should.equal('mtX8nPZZdJ8d3QNLRJ1oJTiEi26Sj6LQXS')
277 })
278
279 it('creates network specific address', function () {
280 var pk = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq')
281 pk.toAddress(Networks.livenet).network.name.should.equal(Networks.livenet.name)
282 pk.toAddress(Networks.testnet).network.name.should.equal(Networks.testnet.name)
283 })
284 })
285
286 describe('#inspect', function () {
287 it('should output known livenet address for console', function () {
288 var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m')
289 privkey.inspect().should.equal(
290 '<PrivateKey: b9de6e778fe92aa7edb69395556f843f1dce0448350112e14906efc2a80fa61a, network: livenet>'
291 )
292 })
293
294 it('should output known testnet address for console', function () {
295 var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq')
296 privkey.inspect().should.equal(
297 '<PrivateKey: 67fd2209ce4a95f6f1d421ab3fbea47ada13df11b73b30c4d9a9f78cc80651ac, network: testnet>'
298 )
299 })
300
301 it('outputs "uncompressed" for uncompressed imported WIFs', function () {
302 var privkey = PrivateKey.fromWIF(wifLivenetUncompressed)
303 privkey.inspect().should.equal('<PrivateKey: 96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a, network: livenet, uncompressed>')
304 })
305 })
306
307 describe('#getValidationError', function () {
308 it('should get an error because private key greater than N', function () {
309 var n = Point.getN()
310 var a = PrivateKey.getValidationError(n)
311 a.message.should.equal('Number must be less than N')
312 })
313
314 it('should validate as false because private key greater than N', function () {
315 var n = Point.getN()
316 var a = PrivateKey.isValid(n)
317 a.should.equal(false)
318 })
319
320 it('should recognize that undefined is an invalid private key', function () {
321 PrivateKey.isValid().should.equal(false)
322 })
323
324 it('should validate as true', function () {
325 var a = PrivateKey.isValid('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m')
326 a.should.equal(true)
327 })
328 })
329
330 describe('buffer serialization', function () {
331 it('returns an expected value when creating a PrivateKey from a buffer', function () {
332 var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet')
333 privkey.toHex().should.equal(buf.toString('hex'))
334 })
335
336 it('roundtrips correctly when using toBuffer/fromBuffer', function () {
337 var privkey = new PrivateKey(BN.fromBuffer(buf))
338 var toBuffer = new PrivateKey(privkey.toBuffer())
339 var fromBuffer = PrivateKey.fromBuffer(toBuffer.toBuffer())
340 fromBuffer.toHex().should.equal(privkey.toHex())
341 })
342 })
343
344 describe('#toBigNumber', function () {
345 it('should output known BN', function () {
346 var a = BN.fromBuffer(buf)
347 var privkey = new PrivateKey(a, 'livenet')
348 var b = privkey.toBigNumber()
349 b.toString('hex').should.equal(a.toString('hex'))
350 })
351 })
352
353 describe('#fromRandom', function () {
354 it('should set bn gt 0 and lt n, and should be compressed', function () {
355 var privkey = PrivateKey.fromRandom()
356 privkey.bn.gt(new BN(0)).should.equal(true)
357 privkey.bn.lt(Point.getN()).should.equal(true)
358 privkey.compressed.should.equal(true)
359 })
360 })
361
362 describe('#fromWIF', function () {
363 it('should parse this compressed testnet address correctly', function () {
364 var privkey = PrivateKey.fromWIF(wifLivenet)
365 privkey.toWIF().should.equal(wifLivenet)
366 })
367 })
368
369 describe('#toWIF', function () {
370 it('should parse this compressed testnet address correctly', function () {
371 var privkey = PrivateKey.fromWIF(wifTestnet)
372 privkey.toWIF().should.equal(wifTestnet)
373 })
374 })
375
376 describe('#fromString', function () {
377 it('should parse this uncompressed testnet address correctly', function () {
378 var privkey = PrivateKey.fromString(wifTestnetUncompressed)
379 privkey.toWIF().should.equal(wifTestnetUncompressed)
380 })
381 })
382
383 describe('#toString', function () {
384 it('should parse this uncompressed livenet address correctly', function () {
385 var privkey = PrivateKey.fromString(wifLivenetUncompressed)
386 privkey.toHex().should.equal('96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a')
387 })
388 })
389
390 describe('#toPublicKey', function () {
391 it('should convert this known PrivateKey to known PublicKey', function () {
392 var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff'
393 var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc'
394 var privkey = new PrivateKey(new BN(Buffer.from(privhex, 'hex')))
395 var pubkey = privkey.toPublicKey()
396 pubkey.toString().should.equal(pubhex)
397 })
398
399 it('should have a "publicKey" property', function () {
400 var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff'
401 var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc'
402 var privkey = new PrivateKey(new BN(Buffer.from(privhex, 'hex')))
403 privkey.publicKey.toString().should.equal(pubhex)
404 })
405
406 it('should convert this known PrivateKey to known PublicKey and preserve compressed=true', function () {
407 var privwif = 'L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m'
408 var privkey = new PrivateKey(privwif, 'livenet')
409 var pubkey = privkey.toPublicKey()
410 pubkey.compressed.should.equal(true)
411 })
412
413 it('should convert this known PrivateKey to known PublicKey and preserve compressed=false', function () {
414 var privwif = '92jJzK4tbURm1C7udQXxeCBvXHoHJstDXRxAMouPG1k1XUaXdsu'
415 var privkey = new PrivateKey(privwif, 'testnet')
416 var pubkey = privkey.toPublicKey()
417 pubkey.compressed.should.equal(false)
418 })
419 })
420
421 it('creates an address as expected from WIF, livenet', function () {
422 var privkey = new PrivateKey('5J2NYGstJg7aJQEqNwYp4enG5BSfFdKXVTtBLvHicnRGD5kjxi6')
423 privkey.publicKey.toAddress().toString().should.equal('135bwugFCmhmNU3SeCsJeTqvo5ViymgwZ9')
424 })
425
426 it('creates an address as expected from WIF, testnet', function () {
427 var privkey = new PrivateKey('92VYMmwFLXRwXn5688edGxYYgMFsc3fUXYhGp17WocQhU6zG1kd')
428 privkey.publicKey.toAddress().toString().should.equal('moiAvLUw16qgrwhFGo1eDnXHC2wPMYiv7Y')
429 })
430})