@opcat-labs/opcat 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/.mocharc.yaml +3 -0
  2. package/index.d.ts +1541 -0
  3. package/index.js +74 -0
  4. package/lib/address.js +478 -0
  5. package/lib/block/block.js +277 -0
  6. package/lib/block/blockheader.js +295 -0
  7. package/lib/block/index.js +4 -0
  8. package/lib/block/merkleblock.js +323 -0
  9. package/lib/bn.js +3423 -0
  10. package/lib/crypto/bn.js +278 -0
  11. package/lib/crypto/ecdsa.js +339 -0
  12. package/lib/crypto/hash.browser.js +171 -0
  13. package/lib/crypto/hash.js +2 -0
  14. package/lib/crypto/hash.node.js +171 -0
  15. package/lib/crypto/point.js +221 -0
  16. package/lib/crypto/random.browser.js +28 -0
  17. package/lib/crypto/random.js +2 -0
  18. package/lib/crypto/random.node.js +11 -0
  19. package/lib/crypto/signature.js +325 -0
  20. package/lib/encoding/base58.js +111 -0
  21. package/lib/encoding/base58check.js +121 -0
  22. package/lib/encoding/bufferreader.js +212 -0
  23. package/lib/encoding/bufferwriter.js +140 -0
  24. package/lib/encoding/decode-asm.js +24 -0
  25. package/lib/encoding/decode-hex.js +32 -0
  26. package/lib/encoding/decode-script-chunks.js +43 -0
  27. package/lib/encoding/encode-hex.js +284 -0
  28. package/lib/encoding/is-hex.js +7 -0
  29. package/lib/encoding/varint.js +75 -0
  30. package/lib/errors/index.js +54 -0
  31. package/lib/errors/spec.js +314 -0
  32. package/lib/hash-cache.js +50 -0
  33. package/lib/hdprivatekey.js +678 -0
  34. package/lib/hdpublickey.js +525 -0
  35. package/lib/message/message.js +191 -0
  36. package/lib/mnemonic/mnemonic.js +303 -0
  37. package/lib/mnemonic/pbkdf2.browser.js +68 -0
  38. package/lib/mnemonic/pbkdf2.js +2 -0
  39. package/lib/mnemonic/pbkdf2.node.js +68 -0
  40. package/lib/mnemonic/words/chinese.js +2054 -0
  41. package/lib/mnemonic/words/english.js +2054 -0
  42. package/lib/mnemonic/words/french.js +2054 -0
  43. package/lib/mnemonic/words/index.js +8 -0
  44. package/lib/mnemonic/words/italian.js +2054 -0
  45. package/lib/mnemonic/words/japanese.js +2054 -0
  46. package/lib/mnemonic/words/spanish.js +2054 -0
  47. package/lib/networks.js +379 -0
  48. package/lib/opcode.js +255 -0
  49. package/lib/privatekey.js +374 -0
  50. package/lib/publickey.js +386 -0
  51. package/lib/script/index.js +5 -0
  52. package/lib/script/interpreter.js +1834 -0
  53. package/lib/script/script.js +1074 -0
  54. package/lib/script/stack.js +109 -0
  55. package/lib/script/write-i32-le.js +17 -0
  56. package/lib/script/write-push-data.js +35 -0
  57. package/lib/script/write-u16-le.js +12 -0
  58. package/lib/script/write-u32-le.js +16 -0
  59. package/lib/script/write-u64-le.js +24 -0
  60. package/lib/script/write-u8-le.js +8 -0
  61. package/lib/script/write-varint.js +46 -0
  62. package/lib/transaction/index.js +7 -0
  63. package/lib/transaction/input/index.js +5 -0
  64. package/lib/transaction/input/input.js +354 -0
  65. package/lib/transaction/input/multisig.js +242 -0
  66. package/lib/transaction/input/publickey.js +100 -0
  67. package/lib/transaction/input/publickeyhash.js +118 -0
  68. package/lib/transaction/output.js +231 -0
  69. package/lib/transaction/sighash.js +167 -0
  70. package/lib/transaction/signature.js +97 -0
  71. package/lib/transaction/transaction.js +1639 -0
  72. package/lib/transaction/unspentoutput.js +113 -0
  73. package/lib/util/_.js +47 -0
  74. package/lib/util/js.js +90 -0
  75. package/lib/util/preconditions.js +33 -0
  76. package/package.json +26 -0
  77. package/test/address.js +509 -0
  78. package/test/block/block.js +251 -0
  79. package/test/block/blockheader.js +275 -0
  80. package/test/block/merklebloack.js +211 -0
  81. package/test/crypto/bn.js +177 -0
  82. package/test/crypto/ecdsa.js +391 -0
  83. package/test/crypto/hash.browser.js +135 -0
  84. package/test/crypto/hash.js +136 -0
  85. package/test/crypto/point.js +224 -0
  86. package/test/crypto/random.js +32 -0
  87. package/test/crypto/signature.js +409 -0
  88. package/test/data/bip69.json +215 -0
  89. package/test/data/bitcoind/base58_keys_invalid.json +52 -0
  90. package/test/data/bitcoind/base58_keys_valid.json +335 -0
  91. package/test/data/bitcoind/blocks.json +22 -0
  92. package/test/data/bitcoind/script_tests.json +3822 -0
  93. package/test/data/bitcoind/sig_canonical.json +7 -0
  94. package/test/data/bitcoind/sig_noncanonical.json +36 -0
  95. package/test/data/bitcoind/tx_invalid.json +445 -0
  96. package/test/data/bitcoind/tx_valid.json +44 -0
  97. package/test/data/blk86756-testnet.dat +0 -0
  98. package/test/data/blk86756-testnet.js +14 -0
  99. package/test/data/blk86756-testnet.json +684 -0
  100. package/test/data/block.hex +1 -0
  101. package/test/data/ecdsa.json +230 -0
  102. package/test/data/merkleblocks.js +488 -0
  103. package/test/data/messages.json +22 -0
  104. package/test/data/sighash.json +12 -0
  105. package/test/data/tx_creation.json +95 -0
  106. package/test/encoding/base58.js +131 -0
  107. package/test/encoding/base58check.js +136 -0
  108. package/test/encoding/bufferreader.js +337 -0
  109. package/test/encoding/bufferwriter.js +172 -0
  110. package/test/encoding/varint.js +104 -0
  111. package/test/hashCache.js +67 -0
  112. package/test/hdkeys.js +445 -0
  113. package/test/hdprivatekey.js +332 -0
  114. package/test/hdpublickey.js +304 -0
  115. package/test/index.js +16 -0
  116. package/test/message/message.js +204 -0
  117. package/test/mnemonic/data/fixtures.json +300 -0
  118. package/test/mnemonic/mnemonic.js +259 -0
  119. package/test/mnemonic/mocha.opts +1 -0
  120. package/test/mnemonic/pbkdf2.test.js +59 -0
  121. package/test/networks.js +159 -0
  122. package/test/opcode.js +161 -0
  123. package/test/privatekey.js +439 -0
  124. package/test/publickey.js +554 -0
  125. package/test/script/interpreter.js +734 -0
  126. package/test/script/script.js +1437 -0
  127. package/test/transaction/deserialize.js +34 -0
  128. package/test/transaction/input/input.js +90 -0
  129. package/test/transaction/input/multisig.js +90 -0
  130. package/test/transaction/input/publickey.js +68 -0
  131. package/test/transaction/input/publickeyhash.js +51 -0
  132. package/test/transaction/output.js +185 -0
  133. package/test/transaction/sighash.js +65 -0
  134. package/test/transaction/signature.js +114 -0
  135. package/test/transaction/transaction.js +1109 -0
  136. package/test/transaction/unspentoutput.js +110 -0
  137. package/test/util/js.js +76 -0
  138. package/test/util/preconditions.js +79 -0
@@ -0,0 +1,678 @@
1
+ 'use strict';
2
+
3
+ var assert = require('assert');
4
+ var _ = require('./util/_');
5
+ var $ = require('./util/preconditions');
6
+
7
+ var BN = require('./crypto/bn');
8
+ var Base58 = require('./encoding/base58');
9
+ var Base58Check = require('./encoding/base58check');
10
+ var Hash = require('./crypto/hash');
11
+ var Network = require('./networks');
12
+ var Point = require('./crypto/point');
13
+ var PrivateKey = require('./privatekey');
14
+ var Random = require('./crypto/random');
15
+
16
+ var errors = require('./errors');
17
+ var hdErrors = errors.HDPrivateKey;
18
+ var JSUtil = require('./util/js');
19
+
20
+ var MINIMUM_ENTROPY_BITS = 128;
21
+ var BITS_TO_BYTES = 1 / 8;
22
+ var MAXIMUM_ENTROPY_BITS = 512;
23
+
24
+ /**
25
+ * Represents an instance of an hierarchically derived private key.
26
+ *
27
+ * More info on https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
28
+ *
29
+ * @constructor
30
+ * @param {string|Buffer|Object} arg
31
+ */
32
+ function HDPrivateKey(arg) {
33
+ if (arg instanceof HDPrivateKey) {
34
+ return arg;
35
+ }
36
+ if (!(this instanceof HDPrivateKey)) {
37
+ return new HDPrivateKey(arg);
38
+ }
39
+ if (!arg) {
40
+ return this._generateRandomly();
41
+ }
42
+
43
+ if (Network.get(arg)) {
44
+ return this._generateRandomly(arg);
45
+ } else if (_.isString(arg) || Buffer.isBuffer(arg)) {
46
+ if (HDPrivateKey.isValidSerialized(arg)) {
47
+ this._buildFromSerialized(arg);
48
+ } else if (JSUtil.isValidJSON(arg)) {
49
+ this._buildFromJSON(arg);
50
+ } else if (Buffer.isBuffer(arg) && HDPrivateKey.isValidSerialized(arg.toString())) {
51
+ this._buildFromSerialized(arg.toString());
52
+ } else {
53
+ throw HDPrivateKey.getSerializedError(arg);
54
+ }
55
+ } else if (_.isObject(arg)) {
56
+ this._buildFromObject(arg);
57
+ } else {
58
+ throw new hdErrors.UnrecognizedArgument(arg);
59
+ }
60
+ }
61
+
62
+ HDPrivateKey.fromRandom = function () {
63
+ return new HDPrivateKey();
64
+ };
65
+
66
+ /**
67
+ * Verifies that a given path is valid.
68
+ *
69
+ * @param {string|number} arg
70
+ * @param {boolean?} hardened
71
+ * @return {boolean}
72
+ */
73
+ HDPrivateKey.isValidPath = function (arg, hardened) {
74
+ if (_.isString(arg)) {
75
+ var indexes = HDPrivateKey._getDerivationIndexes(arg);
76
+ return indexes !== null && _.every(indexes, HDPrivateKey.isValidPath);
77
+ }
78
+
79
+ if (_.isNumber(arg)) {
80
+ if (arg < HDPrivateKey.Hardened && hardened === true) {
81
+ arg += HDPrivateKey.Hardened;
82
+ }
83
+ return arg >= 0 && arg < HDPrivateKey.MaxIndex;
84
+ }
85
+
86
+ return false;
87
+ };
88
+
89
+ /**
90
+ * Internal function that splits a string path into a derivation index array.
91
+ * It will return null if the string path is malformed.
92
+ * It does not validate if indexes are in bounds.
93
+ *
94
+ * @param {string} path
95
+ * @return {Array}
96
+ */
97
+ HDPrivateKey._getDerivationIndexes = function (path) {
98
+ var steps = path.split('/');
99
+
100
+ // Special cases:
101
+ if (_.includes(HDPrivateKey.RootElementAlias, path)) {
102
+ return [];
103
+ }
104
+
105
+ if (!_.includes(HDPrivateKey.RootElementAlias, steps[0])) {
106
+ return null;
107
+ }
108
+
109
+ var indexes = steps.slice(1).map(function (step) {
110
+ var isHardened = step.slice(-1) === "'";
111
+ if (isHardened) {
112
+ step = step.slice(0, -1);
113
+ }
114
+ if (!step || step[0] === '-') {
115
+ return NaN;
116
+ }
117
+ var index = +step; // cast to number
118
+ if (isHardened) {
119
+ index += HDPrivateKey.Hardened;
120
+ }
121
+
122
+ return index;
123
+ });
124
+
125
+ return _.some(indexes, isNaN) ? null : indexes;
126
+ };
127
+
128
+ /**
129
+ * WARNING: This method is deprecated. Use deriveChild or deriveNonCompliantChild instead. This is not BIP32 compliant
130
+ *
131
+ *
132
+ * Get a derived child based on a string or number.
133
+ *
134
+ * If the first argument is a string, it's parsed as the full path of
135
+ * derivation. Valid values for this argument include "m" (which returns the
136
+ * same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened
137
+ * derivation.
138
+ *
139
+ * If the first argument is a number, the child with that index will be
140
+ * derived. If the second argument is truthy, the hardened version will be
141
+ * derived. See the example usage for clarification.
142
+ *
143
+ * @example
144
+ * ```javascript
145
+ * var parent = new HDPrivateKey('xprv...');
146
+ * var child_0_1_2h = parent.derive(0).derive(1).derive(2, true);
147
+ * var copy_of_child_0_1_2h = parent.derive("m/0/1/2'");
148
+ * assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h);
149
+ * ```
150
+ *
151
+ * @param {string|number} arg
152
+ * @param {boolean?} hardened
153
+ */
154
+ HDPrivateKey.prototype.derive = function () {
155
+ throw new Error(
156
+ 'derive has been deprecated. use deriveChild or, for the old way, deriveNonCompliantChild.',
157
+ );
158
+ };
159
+
160
+ /**
161
+ * WARNING: This method will not be officially supported until v1.0.0.
162
+ *
163
+ *
164
+ * Get a derived child based on a string or number.
165
+ *
166
+ * If the first argument is a string, it's parsed as the full path of
167
+ * derivation. Valid values for this argument include "m" (which returns the
168
+ * same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened
169
+ * derivation.
170
+ *
171
+ * If the first argument is a number, the child with that index will be
172
+ * derived. If the second argument is truthy, the hardened version will be
173
+ * derived. See the example usage for clarification.
174
+ *
175
+ * WARNING: The `nonCompliant` option should NOT be used, except for older implementation
176
+ * that used a derivation strategy that used a non-zero padded private key.
177
+ *
178
+ * @example
179
+ * ```javascript
180
+ * var parent = new HDPrivateKey('xprv...');
181
+ * var child_0_1_2h = parent.deriveChild(0).deriveChild(1).deriveChild(2, true);
182
+ * var copy_of_child_0_1_2h = parent.deriveChild("m/0/1/2'");
183
+ * assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h);
184
+ * ```
185
+ *
186
+ * @param {string|number} arg
187
+ * @param {boolean?} hardened
188
+ */
189
+ HDPrivateKey.prototype.deriveChild = function (arg, hardened) {
190
+ if (_.isNumber(arg)) {
191
+ return this._deriveWithNumber(arg, hardened);
192
+ } else if (_.isString(arg)) {
193
+ return this._deriveFromString(arg);
194
+ } else {
195
+ throw new hdErrors.InvalidDerivationArgument(arg);
196
+ }
197
+ };
198
+
199
+ /**
200
+ * WARNING: This method will not be officially supported until v1.0.0
201
+ *
202
+ *
203
+ * WARNING: If this is a new implementation you should NOT use this method, you should be using
204
+ * `derive` instead.
205
+ *
206
+ * This method is explicitly for use and compatibility with an implementation that
207
+ * was not compliant with BIP32 regarding the derivation algorithm. The private key
208
+ * must be 32 bytes hashing, and this implementation will use the non-zero padded
209
+ * serialization of a private key, such that it's still possible to derive the privateKey
210
+ * to recover those funds.
211
+ *
212
+ * @param {string|number} arg
213
+ * @param {boolean?} hardened
214
+ */
215
+ HDPrivateKey.prototype.deriveNonCompliantChild = function (arg, hardened) {
216
+ if (_.isNumber(arg)) {
217
+ return this._deriveWithNumber(arg, hardened, true);
218
+ } else if (_.isString(arg)) {
219
+ return this._deriveFromString(arg, true);
220
+ } else {
221
+ throw new hdErrors.InvalidDerivationArgument(arg);
222
+ }
223
+ };
224
+
225
+ HDPrivateKey.prototype._deriveWithNumber = function (index, hardened, nonCompliant) {
226
+ if (!HDPrivateKey.isValidPath(index, hardened)) {
227
+ throw new hdErrors.InvalidPath(index);
228
+ }
229
+
230
+ hardened = index >= HDPrivateKey.Hardened ? true : hardened;
231
+ if (index < HDPrivateKey.Hardened && hardened === true) {
232
+ index += HDPrivateKey.Hardened;
233
+ }
234
+
235
+ var indexBuffer = JSUtil.integerAsBuffer(index);
236
+ var data;
237
+ if (hardened && nonCompliant) {
238
+ // The private key serialization in this case will not be exactly 32 bytes and can be
239
+ // any value less, and the value is not zero-padded.
240
+ var nonZeroPadded = this.privateKey.bn.toBuffer();
241
+ data = Buffer.concat([Buffer.from([0]), nonZeroPadded, indexBuffer]);
242
+ } else if (hardened) {
243
+ // This will use a 32 byte zero padded serialization of the private key
244
+ var privateKeyBuffer = this.privateKey.bn.toBuffer({ size: 32 });
245
+ assert(
246
+ privateKeyBuffer.length === 32,
247
+ 'length of private key buffer is expected to be 32 bytes',
248
+ );
249
+ data = Buffer.concat([Buffer.from([0]), privateKeyBuffer, indexBuffer]);
250
+ } else {
251
+ data = Buffer.concat([this.publicKey.toBuffer(), indexBuffer]);
252
+ }
253
+ var hash = Hash.sha512hmac(data, this._buffers.chainCode);
254
+ var leftPart = BN.fromBuffer(hash.slice(0, 32), {
255
+ size: 32,
256
+ });
257
+ var chainCode = hash.slice(32, 64);
258
+
259
+ var privateKey = leftPart.add(this.privateKey.toBigNumber()).umod(Point.getN()).toBuffer({
260
+ size: 32,
261
+ });
262
+
263
+ if (!PrivateKey.isValid(privateKey)) {
264
+ // Index at this point is already hardened, we can pass null as the hardened arg
265
+ return this._deriveWithNumber(index + 1, null, nonCompliant);
266
+ }
267
+
268
+ var derived = new HDPrivateKey({
269
+ network: this.network,
270
+ depth: this.depth + 1,
271
+ parentFingerPrint: this.fingerPrint,
272
+ childIndex: index,
273
+ chainCode: chainCode,
274
+ privateKey: privateKey,
275
+ });
276
+
277
+ return derived;
278
+ };
279
+
280
+ HDPrivateKey.prototype._deriveFromString = function (path, nonCompliant) {
281
+ if (!HDPrivateKey.isValidPath(path)) {
282
+ throw new hdErrors.InvalidPath(path);
283
+ }
284
+
285
+ var indexes = HDPrivateKey._getDerivationIndexes(path);
286
+ var derived = indexes.reduce(function (prev, index) {
287
+ return prev._deriveWithNumber(index, null, nonCompliant);
288
+ }, this);
289
+
290
+ return derived;
291
+ };
292
+
293
+ /**
294
+ * Verifies that a given serialized private key in base58 with checksum format
295
+ * is valid.
296
+ *
297
+ * @param {string|Buffer} data - the serialized private key
298
+ * @param {string|Network=} network - optional, if present, checks that the
299
+ * network provided matches the network serialized.
300
+ * @return {boolean}
301
+ */
302
+ HDPrivateKey.isValidSerialized = function (data, network) {
303
+ return !HDPrivateKey.getSerializedError(data, network);
304
+ };
305
+
306
+ /**
307
+ * Checks what's the error that causes the validation of a serialized private key
308
+ * in base58 with checksum to fail.
309
+ *
310
+ * @param {string|Buffer} data - the serialized private key
311
+ * @param {string|Network=} network - optional, if present, checks that the
312
+ * network provided matches the network serialized.
313
+ * @return {errors.InvalidArgument|null}
314
+ */
315
+ HDPrivateKey.getSerializedError = function (data, network) {
316
+ if (!(_.isString(data) || Buffer.isBuffer(data))) {
317
+ return new hdErrors.UnrecognizedArgument('Expected string or buffer');
318
+ }
319
+ if (!Base58.validCharacters(data)) {
320
+ return new errors.InvalidB58Char('(unknown)', data);
321
+ }
322
+ try {
323
+ data = Base58Check.decode(data);
324
+ } catch (e) {
325
+ return new errors.InvalidB58Checksum(data);
326
+ }
327
+ if (data.length !== HDPrivateKey.DataLength) {
328
+ return new hdErrors.InvalidLength(data);
329
+ }
330
+ if (!_.isUndefined(network)) {
331
+ var error = HDPrivateKey._validateNetwork(data, network);
332
+ if (error) {
333
+ return error;
334
+ }
335
+ }
336
+ return null;
337
+ };
338
+
339
+ HDPrivateKey._validateNetwork = function (data, networkArg) {
340
+ var network = Network.get(networkArg);
341
+ if (!network) {
342
+ return new errors.InvalidNetworkArgument(networkArg);
343
+ }
344
+ var version = data.slice(0, 4);
345
+ if (version.readUInt32BE(0) !== network.xprivkey) {
346
+ return new errors.InvalidNetwork(version);
347
+ }
348
+ return null;
349
+ };
350
+
351
+ HDPrivateKey.fromString = function (arg) {
352
+ $.checkArgument(_.isString(arg), 'No valid string was provided');
353
+ return new HDPrivateKey(arg);
354
+ };
355
+
356
+ HDPrivateKey.fromObject = function (arg) {
357
+ $.checkArgument(_.isObject(arg), 'No valid argument was provided');
358
+ return new HDPrivateKey(arg);
359
+ };
360
+
361
+ HDPrivateKey.prototype._buildFromJSON = function (arg) {
362
+ return this._buildFromObject(JSON.parse(arg));
363
+ };
364
+
365
+ HDPrivateKey.prototype._buildFromObject = function (arg) {
366
+ // TODO: Type validation
367
+ var buffers = {
368
+ version: arg.network ? JSUtil.integerAsBuffer(Network.get(arg.network).xprivkey) : arg.version,
369
+ depth: _.isNumber(arg.depth) ? Buffer.from([arg.depth & 0xff]) : arg.depth,
370
+ parentFingerPrint: _.isNumber(arg.parentFingerPrint)
371
+ ? JSUtil.integerAsBuffer(arg.parentFingerPrint)
372
+ : arg.parentFingerPrint,
373
+ childIndex: _.isNumber(arg.childIndex)
374
+ ? JSUtil.integerAsBuffer(arg.childIndex)
375
+ : arg.childIndex,
376
+ chainCode: _.isString(arg.chainCode) ? Buffer.from(arg.chainCode, 'hex') : arg.chainCode,
377
+ privateKey:
378
+ _.isString(arg.privateKey) && JSUtil.isHexa(arg.privateKey)
379
+ ? Buffer.from(arg.privateKey, 'hex')
380
+ : arg.privateKey,
381
+ checksum: arg.checksum
382
+ ? arg.checksum.length
383
+ ? arg.checksum
384
+ : JSUtil.integerAsBuffer(arg.checksum)
385
+ : undefined,
386
+ };
387
+ return this._buildFromBuffers(buffers);
388
+ };
389
+
390
+ HDPrivateKey.prototype._buildFromSerialized = function (arg) {
391
+ var decoded = Base58Check.decode(arg);
392
+ var buffers = {
393
+ version: decoded.slice(HDPrivateKey.VersionStart, HDPrivateKey.VersionEnd),
394
+ depth: decoded.slice(HDPrivateKey.DepthStart, HDPrivateKey.DepthEnd),
395
+ parentFingerPrint: decoded.slice(
396
+ HDPrivateKey.ParentFingerPrintStart,
397
+ HDPrivateKey.ParentFingerPrintEnd,
398
+ ),
399
+ childIndex: decoded.slice(HDPrivateKey.ChildIndexStart, HDPrivateKey.ChildIndexEnd),
400
+ chainCode: decoded.slice(HDPrivateKey.ChainCodeStart, HDPrivateKey.ChainCodeEnd),
401
+ privateKey: decoded.slice(HDPrivateKey.PrivateKeyStart, HDPrivateKey.PrivateKeyEnd),
402
+ checksum: decoded.slice(HDPrivateKey.ChecksumStart, HDPrivateKey.ChecksumEnd),
403
+ xprivkey: arg,
404
+ };
405
+ return this._buildFromBuffers(buffers);
406
+ };
407
+
408
+ HDPrivateKey.prototype._generateRandomly = function (network) {
409
+ return HDPrivateKey.fromSeed(Random.getRandomBuffer(64), network);
410
+ };
411
+
412
+ /**
413
+ * Generate a private key from a seed, as described in BIP32
414
+ *
415
+ * @param {string|Buffer} hexa
416
+ * @param {*} network
417
+ * @return HDPrivateKey
418
+ */
419
+ HDPrivateKey.fromSeed = function (hexa, network) {
420
+ if (JSUtil.isHexaString(hexa)) {
421
+ hexa = Buffer.from(hexa, 'hex');
422
+ }
423
+ if (!Buffer.isBuffer(hexa)) {
424
+ throw new hdErrors.InvalidEntropyArgument(hexa);
425
+ }
426
+ if (hexa.length < MINIMUM_ENTROPY_BITS * BITS_TO_BYTES) {
427
+ throw new hdErrors.InvalidEntropyArgument.NotEnoughEntropy(hexa);
428
+ }
429
+ if (hexa.length > MAXIMUM_ENTROPY_BITS * BITS_TO_BYTES) {
430
+ throw new hdErrors.InvalidEntropyArgument.TooMuchEntropy(hexa);
431
+ }
432
+ var hash = Hash.sha512hmac(hexa, Buffer.from('Bitcoin seed'));
433
+
434
+ return new HDPrivateKey({
435
+ network: Network.get(network) || Network.defaultNetwork,
436
+ depth: 0,
437
+ parentFingerPrint: 0,
438
+ childIndex: 0,
439
+ privateKey: hash.slice(0, 32),
440
+ chainCode: hash.slice(32, 64),
441
+ });
442
+ };
443
+
444
+ HDPrivateKey.prototype._calcHDPublicKey = function () {
445
+ if (!this._hdPublicKey) {
446
+ var HDPublicKey = require('./hdpublickey');
447
+ this._hdPublicKey = new HDPublicKey(this);
448
+ }
449
+ };
450
+
451
+ /**
452
+ * Receives a object with buffers in all the properties and populates the
453
+ * internal structure
454
+ *
455
+ * @param {Object} arg
456
+ * @param {buffer.Buffer} arg.version
457
+ * @param {buffer.Buffer} arg.depth
458
+ * @param {buffer.Buffer} arg.parentFingerPrint
459
+ * @param {buffer.Buffer} arg.childIndex
460
+ * @param {buffer.Buffer} arg.chainCode
461
+ * @param {buffer.Buffer} arg.privateKey
462
+ * @param {buffer.Buffer} arg.checksum
463
+ * @param {string=} arg.xprivkey - if set, don't recalculate the base58
464
+ * representation
465
+ * @return {HDPrivateKey} this
466
+ */
467
+ HDPrivateKey.prototype._buildFromBuffers = function (arg) {
468
+ HDPrivateKey._validateBufferArguments(arg);
469
+
470
+ JSUtil.defineImmutable(this, {
471
+ _buffers: arg,
472
+ });
473
+
474
+ var sequence = [
475
+ arg.version,
476
+ arg.depth,
477
+ arg.parentFingerPrint,
478
+ arg.childIndex,
479
+ arg.chainCode,
480
+ Buffer.alloc(1),
481
+ arg.privateKey,
482
+ ];
483
+ var concat = Buffer.concat(sequence);
484
+ if (!arg.checksum || !arg.checksum.length) {
485
+ arg.checksum = Base58Check.checksum(concat);
486
+ } else {
487
+ if (arg.checksum.toString() !== Base58Check.checksum(concat).toString()) {
488
+ throw new errors.InvalidB58Checksum(concat);
489
+ }
490
+ }
491
+
492
+ var network = Network.get(arg.version.readUInt32BE(0));
493
+ var xprivkey;
494
+ xprivkey = Base58Check.encode(Buffer.concat(sequence));
495
+ arg.xprivkey = Buffer.from(xprivkey);
496
+
497
+ var privateKey = new PrivateKey(BN.fromBuffer(arg.privateKey), network);
498
+ var publicKey = privateKey.toPublicKey();
499
+ var size = HDPrivateKey.ParentFingerPrintSize;
500
+ var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size);
501
+
502
+ JSUtil.defineImmutable(this, {
503
+ xprivkey: xprivkey,
504
+ network: network,
505
+ depth: arg.depth[0],
506
+ privateKey: privateKey,
507
+ publicKey: publicKey,
508
+ fingerPrint: fingerPrint,
509
+ });
510
+
511
+ this._hdPublicKey = null;
512
+
513
+ Object.defineProperty(this, 'hdPublicKey', {
514
+ configurable: false,
515
+ enumerable: true,
516
+ get: function () {
517
+ this._calcHDPublicKey();
518
+ return this._hdPublicKey;
519
+ },
520
+ });
521
+ Object.defineProperty(this, 'xpubkey', {
522
+ configurable: false,
523
+ enumerable: true,
524
+ get: function () {
525
+ this._calcHDPublicKey();
526
+ return this._hdPublicKey.xpubkey;
527
+ },
528
+ });
529
+ return this;
530
+ };
531
+
532
+ HDPrivateKey._validateBufferArguments = function (arg) {
533
+ var checkBuffer = function (name, size) {
534
+ var buff = arg[name];
535
+ assert(Buffer.isBuffer(buff), name + ' argument is not a buffer');
536
+ assert(
537
+ buff.length === size,
538
+ name + ' has not the expected size: found ' + buff.length + ', expected ' + size,
539
+ );
540
+ };
541
+ checkBuffer('version', HDPrivateKey.VersionSize);
542
+ checkBuffer('depth', HDPrivateKey.DepthSize);
543
+ checkBuffer('parentFingerPrint', HDPrivateKey.ParentFingerPrintSize);
544
+ checkBuffer('childIndex', HDPrivateKey.ChildIndexSize);
545
+ checkBuffer('chainCode', HDPrivateKey.ChainCodeSize);
546
+ checkBuffer('privateKey', HDPrivateKey.PrivateKeySize);
547
+ if (arg.checksum && arg.checksum.length) {
548
+ checkBuffer('checksum', HDPrivateKey.CheckSumSize);
549
+ }
550
+ };
551
+
552
+ /**
553
+ * Returns the string representation of this private key (a string starting
554
+ * with "xprv..."
555
+ *
556
+ * @return string
557
+ */
558
+ HDPrivateKey.prototype.toString = function () {
559
+ return this.xprivkey;
560
+ };
561
+
562
+ /**
563
+ * Returns the console representation of this extended private key.
564
+ * @return string
565
+ */
566
+ HDPrivateKey.prototype.inspect = function () {
567
+ return '<HDPrivateKey: ' + this.xprivkey + '>';
568
+ };
569
+
570
+ /**
571
+ * Returns a plain object with a representation of this private key.
572
+ *
573
+ * Fields include:<ul>
574
+ * <li> network: either 'livenet' or 'testnet'
575
+ * <li> depth: a number ranging from 0 to 255
576
+ * <li> fingerPrint: a number ranging from 0 to 2^32-1, taken from the hash of the
577
+ * <li> associated public key
578
+ * <li> parentFingerPrint: a number ranging from 0 to 2^32-1, taken from the hash
579
+ * <li> of this parent's associated public key or zero.
580
+ * <li> childIndex: the index from which this child was derived (or zero)
581
+ * <li> chainCode: an hexa string representing a number used in the derivation
582
+ * <li> privateKey: the private key associated, in hexa representation
583
+ * <li> xprivkey: the representation of this extended private key in checksum
584
+ * <li> base58 format
585
+ * <li> checksum: the base58 checksum of xprivkey
586
+ * </ul>
587
+ * @return {Object}
588
+ */
589
+ HDPrivateKey.prototype.toObject = HDPrivateKey.prototype.toJSON = function toObject() {
590
+ return {
591
+ network: Network.get(this._buffers.version.readUInt32BE(0), 'xprivkey').name,
592
+ depth: this._buffers.depth[0],
593
+ fingerPrint: this.fingerPrint.readUInt32BE(0),
594
+ parentFingerPrint: this._buffers.parentFingerPrint.readUInt32BE(0),
595
+ childIndex: this._buffers.childIndex.readUInt32BE(0),
596
+ chainCode: this._buffers.chainCode.toString('hex'),
597
+ privateKey: this.privateKey.toBuffer().toString('hex'),
598
+ checksum: this._buffers.checksum.readUInt32BE(0),
599
+ xprivkey: this.xprivkey,
600
+ };
601
+ };
602
+
603
+ /**
604
+ * Build a HDPrivateKey from a buffer
605
+ *
606
+ * @param {Buffer} arg
607
+ * @return {HDPrivateKey}
608
+ */
609
+ HDPrivateKey.fromBuffer = function (buf) {
610
+ return new HDPrivateKey(buf.toString());
611
+ };
612
+
613
+ /**
614
+ * Build a HDPrivateKey from a hex string
615
+ *
616
+ * @param {string} hex
617
+ * @return {HDPrivateKey}
618
+ */
619
+ HDPrivateKey.fromHex = function (hex) {
620
+ return HDPrivateKey.fromBuffer(Buffer.from(hex, 'hex'));
621
+ };
622
+
623
+ /**
624
+ * Returns a buffer representation of the HDPrivateKey
625
+ *
626
+ * @return {string}
627
+ */
628
+ HDPrivateKey.prototype.toBuffer = function () {
629
+ return Buffer.from(this.toString());
630
+ };
631
+
632
+ /**
633
+ * Returns a hex string representation of the HDPrivateKey
634
+ *
635
+ * @return {string}
636
+ */
637
+ HDPrivateKey.prototype.toHex = function () {
638
+ return this.toBuffer().toString('hex');
639
+ };
640
+
641
+ HDPrivateKey.DefaultDepth = 0;
642
+ HDPrivateKey.DefaultFingerprint = 0;
643
+ HDPrivateKey.DefaultChildIndex = 0;
644
+ HDPrivateKey.Hardened = 0x80000000;
645
+ HDPrivateKey.MaxIndex = 2 * HDPrivateKey.Hardened;
646
+
647
+ HDPrivateKey.RootElementAlias = ['m', 'M', "m'", "M'"];
648
+
649
+ HDPrivateKey.VersionSize = 4;
650
+ HDPrivateKey.DepthSize = 1;
651
+ HDPrivateKey.ParentFingerPrintSize = 4;
652
+ HDPrivateKey.ChildIndexSize = 4;
653
+ HDPrivateKey.ChainCodeSize = 32;
654
+ HDPrivateKey.PrivateKeySize = 32;
655
+ HDPrivateKey.CheckSumSize = 4;
656
+
657
+ HDPrivateKey.DataLength = 78;
658
+ HDPrivateKey.SerializedByteSize = 82;
659
+
660
+ HDPrivateKey.VersionStart = 0;
661
+ HDPrivateKey.VersionEnd = HDPrivateKey.VersionStart + HDPrivateKey.VersionSize;
662
+ HDPrivateKey.DepthStart = HDPrivateKey.VersionEnd;
663
+ HDPrivateKey.DepthEnd = HDPrivateKey.DepthStart + HDPrivateKey.DepthSize;
664
+ HDPrivateKey.ParentFingerPrintStart = HDPrivateKey.DepthEnd;
665
+ HDPrivateKey.ParentFingerPrintEnd =
666
+ HDPrivateKey.ParentFingerPrintStart + HDPrivateKey.ParentFingerPrintSize;
667
+ HDPrivateKey.ChildIndexStart = HDPrivateKey.ParentFingerPrintEnd;
668
+ HDPrivateKey.ChildIndexEnd = HDPrivateKey.ChildIndexStart + HDPrivateKey.ChildIndexSize;
669
+ HDPrivateKey.ChainCodeStart = HDPrivateKey.ChildIndexEnd;
670
+ HDPrivateKey.ChainCodeEnd = HDPrivateKey.ChainCodeStart + HDPrivateKey.ChainCodeSize;
671
+ HDPrivateKey.PrivateKeyStart = HDPrivateKey.ChainCodeEnd + 1;
672
+ HDPrivateKey.PrivateKeyEnd = HDPrivateKey.PrivateKeyStart + HDPrivateKey.PrivateKeySize;
673
+ HDPrivateKey.ChecksumStart = HDPrivateKey.PrivateKeyEnd;
674
+ HDPrivateKey.ChecksumEnd = HDPrivateKey.ChecksumStart + HDPrivateKey.CheckSumSize;
675
+
676
+ assert(HDPrivateKey.ChecksumEnd === HDPrivateKey.SerializedByteSize);
677
+
678
+ module.exports = HDPrivateKey;