]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blob - libs/ethereumjs-util/index.js
Add ethereumjs-util to libs directory
[perso/Immae/Projets/Cryptomonnaies/BIP39.git] / libs / ethereumjs-util / index.js
1 const createKeccakHash = require('keccak')
2 const secp256k1 = require('secp256k1')
3 const assert = require('assert')
4 const rlp = require('rlp')
5 const BN = require('bn.js')
6 const createHash = require('create-hash')
7 const Buffer = require('safe-buffer').Buffer
8 Object.assign(exports, require('ethjs-util'))
9
10 /**
11 * the max integer that this VM can handle (a ```BN```)
12 * @var {BN} MAX_INTEGER
13 */
14 exports.MAX_INTEGER = new BN('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)
15
16 /**
17 * 2^256 (a ```BN```)
18 * @var {BN} TWO_POW256
19 */
20 exports.TWO_POW256 = new BN('10000000000000000000000000000000000000000000000000000000000000000', 16)
21
22 /**
23 * Keccak-256 hash of null (a ```String```)
24 * @var {String} KECCAK256_NULL_S
25 */
26 exports.KECCAK256_NULL_S = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
27
28 /**
29 * Keccak-256 hash of null (a ```Buffer```)
30 * @var {Buffer} KECCAK256_NULL
31 */
32 exports.KECCAK256_NULL = Buffer.from(exports.KECCAK256_NULL_S, 'hex')
33
34 /**
35 * Keccak-256 of an RLP of an empty array (a ```String```)
36 * @var {String} KECCAK256_RLP_ARRAY_S
37 */
38 exports.KECCAK256_RLP_ARRAY_S = '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'
39
40 /**
41 * Keccak-256 of an RLP of an empty array (a ```Buffer```)
42 * @var {Buffer} KECCAK256_RLP_ARRAY
43 */
44 exports.KECCAK256_RLP_ARRAY = Buffer.from(exports.KECCAK256_RLP_ARRAY_S, 'hex')
45
46 /**
47 * Keccak-256 hash of the RLP of null (a ```String```)
48 * @var {String} KECCAK256_RLP_S
49 */
50 exports.KECCAK256_RLP_S = '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'
51
52 /**
53 * Keccak-256 hash of the RLP of null (a ```Buffer```)
54 * @var {Buffer} KECCAK256_RLP
55 */
56 exports.KECCAK256_RLP = Buffer.from(exports.KECCAK256_RLP_S, 'hex')
57
58 /**
59 * [`BN`](https://github.com/indutny/bn.js)
60 * @var {Function}
61 */
62 exports.BN = BN
63
64 /**
65 * [`rlp`](https://github.com/ethereumjs/rlp)
66 * @var {Function}
67 */
68 exports.rlp = rlp
69
70 /**
71 * [`secp256k1`](https://github.com/cryptocoinjs/secp256k1-node/)
72 * @var {Object}
73 */
74 exports.secp256k1 = secp256k1
75
76 /**
77 * Returns a buffer filled with 0s
78 * @method zeros
79 * @param {Number} bytes the number of bytes the buffer should be
80 * @return {Buffer}
81 */
82 exports.zeros = function (bytes) {
83 return Buffer.allocUnsafe(bytes).fill(0)
84 }
85
86 /**
87 * Returns a zero address
88 * @method zeroAddress
89 * @return {String}
90 */
91 exports.zeroAddress = function () {
92 const addressLength = 20
93 const zeroAddress = exports.zeros(addressLength)
94 return exports.bufferToHex(zeroAddress)
95 }
96
97 /**
98 * Left Pads an `Array` or `Buffer` with leading zeros till it has `length` bytes.
99 * Or it truncates the beginning if it exceeds.
100 * @method lsetLength
101 * @param {Buffer|Array} msg the value to pad
102 * @param {Number} length the number of bytes the output should be
103 * @param {Boolean} [right=false] whether to start padding form the left or right
104 * @return {Buffer|Array}
105 */
106 exports.setLengthLeft = exports.setLength = function (msg, length, right) {
107 const buf = exports.zeros(length)
108 msg = exports.toBuffer(msg)
109 if (right) {
110 if (msg.length < length) {
111 msg.copy(buf)
112 return buf
113 }
114 return msg.slice(0, length)
115 } else {
116 if (msg.length < length) {
117 msg.copy(buf, length - msg.length)
118 return buf
119 }
120 return msg.slice(-length)
121 }
122 }
123
124 /**
125 * Right Pads an `Array` or `Buffer` with leading zeros till it has `length` bytes.
126 * Or it truncates the beginning if it exceeds.
127 * @param {Buffer|Array} msg the value to pad
128 * @param {Number} length the number of bytes the output should be
129 * @return {Buffer|Array}
130 */
131 exports.setLengthRight = function (msg, length) {
132 return exports.setLength(msg, length, true)
133 }
134
135 /**
136 * Trims leading zeros from a `Buffer` or an `Array`
137 * @param {Buffer|Array|String} a
138 * @return {Buffer|Array|String}
139 */
140 exports.unpad = exports.stripZeros = function (a) {
141 a = exports.stripHexPrefix(a)
142 let first = a[0]
143 while (a.length > 0 && first.toString() === '0') {
144 a = a.slice(1)
145 first = a[0]
146 }
147 return a
148 }
149 /**
150 * Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method.
151 * @param {*} v the value
152 */
153 exports.toBuffer = function (v) {
154 if (!Buffer.isBuffer(v)) {
155 if (Array.isArray(v)) {
156 v = Buffer.from(v)
157 } else if (typeof v === 'string') {
158 if (exports.isHexString(v)) {
159 v = Buffer.from(exports.padToEven(exports.stripHexPrefix(v)), 'hex')
160 } else {
161 v = Buffer.from(v)
162 }
163 } else if (typeof v === 'number') {
164 v = exports.intToBuffer(v)
165 } else if (v === null || v === undefined) {
166 v = Buffer.allocUnsafe(0)
167 } else if (BN.isBN(v)) {
168 v = v.toArrayLike(Buffer)
169 } else if (v.toArray) {
170 // converts a BN to a Buffer
171 v = Buffer.from(v.toArray())
172 } else {
173 throw new Error('invalid type')
174 }
175 }
176 return v
177 }
178
179 /**
180 * Converts a `Buffer` to a `Number`
181 * @param {Buffer} buf
182 * @return {Number}
183 * @throws If the input number exceeds 53 bits.
184 */
185 exports.bufferToInt = function (buf) {
186 return new BN(exports.toBuffer(buf)).toNumber()
187 }
188
189 /**
190 * Converts a `Buffer` into a hex `String`
191 * @param {Buffer} buf
192 * @return {String}
193 */
194 exports.bufferToHex = function (buf) {
195 buf = exports.toBuffer(buf)
196 return '0x' + buf.toString('hex')
197 }
198
199 /**
200 * Interprets a `Buffer` as a signed integer and returns a `BN`. Assumes 256-bit numbers.
201 * @param {Buffer} num
202 * @return {BN}
203 */
204 exports.fromSigned = function (num) {
205 return new BN(num).fromTwos(256)
206 }
207
208 /**
209 * Converts a `BN` to an unsigned integer and returns it as a `Buffer`. Assumes 256-bit numbers.
210 * @param {BN} num
211 * @return {Buffer}
212 */
213 exports.toUnsigned = function (num) {
214 return Buffer.from(num.toTwos(256).toArray())
215 }
216
217 /**
218 * Creates Keccak hash of the input
219 * @param {Buffer|Array|String|Number} a the input data
220 * @param {Number} [bits=256] the Keccak width
221 * @return {Buffer}
222 */
223 exports.keccak = function (a, bits) {
224 a = exports.toBuffer(a)
225 if (!bits) bits = 256
226
227 return createKeccakHash('keccak' + bits).update(a).digest()
228 }
229
230 /**
231 * Creates Keccak-256 hash of the input, alias for keccak(a, 256)
232 * @param {Buffer|Array|String|Number} a the input data
233 * @return {Buffer}
234 */
235 exports.keccak256 = function (a) {
236 return exports.keccak(a)
237 }
238
239 /**
240 * Creates SHA256 hash of the input
241 * @param {Buffer|Array|String|Number} a the input data
242 * @return {Buffer}
243 */
244 exports.sha256 = function (a) {
245 a = exports.toBuffer(a)
246 return createHash('sha256').update(a).digest()
247 }
248
249 /**
250 * Creates RIPEMD160 hash of the input
251 * @param {Buffer|Array|String|Number} a the input data
252 * @param {Boolean} padded whether it should be padded to 256 bits or not
253 * @return {Buffer}
254 */
255 exports.ripemd160 = function (a, padded) {
256 a = exports.toBuffer(a)
257 const hash = createHash('rmd160').update(a).digest()
258 if (padded === true) {
259 return exports.setLength(hash, 32)
260 } else {
261 return hash
262 }
263 }
264
265 /**
266 * Creates SHA-3 hash of the RLP encoded version of the input
267 * @param {Buffer|Array|String|Number} a the input data
268 * @return {Buffer}
269 */
270 exports.rlphash = function (a) {
271 return exports.keccak(rlp.encode(a))
272 }
273
274 /**
275 * Checks if the private key satisfies the rules of the curve secp256k1.
276 * @param {Buffer} privateKey
277 * @return {Boolean}
278 */
279 exports.isValidPrivate = function (privateKey) {
280 return secp256k1.privateKeyVerify(privateKey)
281 }
282
283 /**
284 * Checks if the public key satisfies the rules of the curve secp256k1
285 * and the requirements of Ethereum.
286 * @param {Buffer} publicKey The two points of an uncompressed key, unless sanitize is enabled
287 * @param {Boolean} [sanitize=false] Accept public keys in other formats
288 * @return {Boolean}
289 */
290 exports.isValidPublic = function (publicKey, sanitize) {
291 if (publicKey.length === 64) {
292 // Convert to SEC1 for secp256k1
293 return secp256k1.publicKeyVerify(Buffer.concat([ Buffer.from([4]), publicKey ]))
294 }
295
296 if (!sanitize) {
297 return false
298 }
299
300 return secp256k1.publicKeyVerify(publicKey)
301 }
302
303 /**
304 * Returns the ethereum address of a given public key.
305 * Accepts "Ethereum public keys" and SEC1 encoded keys.
306 * @param {Buffer} pubKey The two points of an uncompressed key, unless sanitize is enabled
307 * @param {Boolean} [sanitize=false] Accept public keys in other formats
308 * @return {Buffer}
309 */
310 exports.pubToAddress = exports.publicToAddress = function (pubKey, sanitize) {
311 pubKey = exports.toBuffer(pubKey)
312 if (sanitize && (pubKey.length !== 64)) {
313 pubKey = secp256k1.publicKeyConvert(pubKey, false).slice(1)
314 }
315 assert(pubKey.length === 64)
316 // Only take the lower 160bits of the hash
317 return exports.keccak(pubKey).slice(-20)
318 }
319
320 /**
321 * Returns the ethereum public key of a given private key
322 * @param {Buffer} privateKey A private key must be 256 bits wide
323 * @return {Buffer}
324 */
325 const privateToPublic = exports.privateToPublic = function (privateKey) {
326 privateKey = exports.toBuffer(privateKey)
327 // skip the type flag and use the X, Y points
328 return secp256k1.publicKeyCreate(privateKey, false).slice(1)
329 }
330
331 /**
332 * Converts a public key to the Ethereum format.
333 * @param {Buffer} publicKey
334 * @return {Buffer}
335 */
336 exports.importPublic = function (publicKey) {
337 publicKey = exports.toBuffer(publicKey)
338 if (publicKey.length !== 64) {
339 publicKey = secp256k1.publicKeyConvert(publicKey, false).slice(1)
340 }
341 return publicKey
342 }
343
344 /**
345 * ECDSA sign
346 * @param {Buffer} msgHash
347 * @param {Buffer} privateKey
348 * @param {Number} [chainId]
349 * @return {Object}
350 */
351 exports.ecsign = function (msgHash, privateKey, chainId) {
352 const sig = secp256k1.sign(msgHash, privateKey)
353
354 const ret = {}
355 ret.r = sig.signature.slice(0, 32)
356 ret.s = sig.signature.slice(32, 64)
357 ret.v = chainId ? sig.recovery + (chainId * 2 + 35) : sig.recovery + 27
358 return ret
359 }
360
361 /**
362 * Returns the keccak-256 hash of `message`, prefixed with the header used by the `eth_sign` RPC call.
363 * The output of this function can be fed into `ecsign` to produce the same signature as the `eth_sign`
364 * call for a given `message`, or fed to `ecrecover` along with a signature to recover the public key
365 * used to produce the signature.
366 * @param message
367 * @returns {Buffer} hash
368 */
369 exports.hashPersonalMessage = function (message) {
370 const prefix = exports.toBuffer('\u0019Ethereum Signed Message:\n' + message.length.toString())
371 return exports.keccak(Buffer.concat([prefix, message]))
372 }
373
374 /**
375 * ECDSA public key recovery from signature
376 * @param {Buffer} msgHash
377 * @param {Number} v
378 * @param {Buffer} r
379 * @param {Buffer} s
380 * @param {Number} [chainId]
381 * @return {Buffer} publicKey
382 */
383 exports.ecrecover = function (msgHash, v, r, s, chainId) {
384 const signature = Buffer.concat([exports.setLength(r, 32), exports.setLength(s, 32)], 64)
385 const recovery = calculateSigRecovery(v, chainId)
386 if (!isValidSigRecovery(recovery)) {
387 throw new Error('Invalid signature v value')
388 }
389 const senderPubKey = secp256k1.recover(msgHash, signature, recovery)
390 return secp256k1.publicKeyConvert(senderPubKey, false).slice(1)
391 }
392
393 /**
394 * Convert signature parameters into the format of `eth_sign` RPC method
395 * @param {Number} v
396 * @param {Buffer} r
397 * @param {Buffer} s
398 * @param {Number} [chainId]
399 * @return {String} sig
400 */
401 exports.toRpcSig = function (v, r, s, chainId) {
402 let recovery = calculateSigRecovery(v, chainId)
403 if (!isValidSigRecovery(recovery)) {
404 throw new Error('Invalid signature v value')
405 }
406
407 // geth (and the RPC eth_sign method) uses the 65 byte format used by Bitcoin
408 return exports.bufferToHex(Buffer.concat([
409 exports.setLengthLeft(r, 32),
410 exports.setLengthLeft(s, 32),
411 exports.toBuffer(v)
412 ]))
413 }
414
415 /**
416 * Convert signature format of the `eth_sign` RPC method to signature parameters
417 * NOTE: all because of a bug in geth: https://github.com/ethereum/go-ethereum/issues/2053
418 * @param {String} sig
419 * @return {Object}
420 */
421 exports.fromRpcSig = function (sig) {
422 sig = exports.toBuffer(sig)
423
424 // NOTE: with potential introduction of chainId this might need to be updated
425 if (sig.length !== 65) {
426 throw new Error('Invalid signature length')
427 }
428
429 let v = sig[64]
430 // support both versions of `eth_sign` responses
431 if (v < 27) {
432 v += 27
433 }
434
435 return {
436 v: v,
437 r: sig.slice(0, 32),
438 s: sig.slice(32, 64)
439 }
440 }
441
442 /**
443 * Returns the ethereum address of a given private key
444 * @param {Buffer} privateKey A private key must be 256 bits wide
445 * @return {Buffer}
446 */
447 exports.privateToAddress = function (privateKey) {
448 return exports.publicToAddress(privateToPublic(privateKey))
449 }
450
451 /**
452 * Checks if the address is a valid. Accepts checksummed addresses too
453 * @param {String} address
454 * @return {Boolean}
455 */
456 exports.isValidAddress = function (address) {
457 return /^0x[0-9a-fA-F]{40}$/.test(address)
458 }
459
460 /**
461 * Checks if a given address is a zero address
462 * @method isZeroAddress
463 * @param {String} address
464 * @return {Boolean}
465 */
466 exports.isZeroAddress = function (address) {
467 const zeroAddress = exports.zeroAddress()
468 return zeroAddress === exports.addHexPrefix(address)
469 }
470
471 /**
472 * Returns a checksummed address
473 * @param {String} address
474 * @return {String}
475 */
476 exports.toChecksumAddress = function (address) {
477 address = exports.stripHexPrefix(address).toLowerCase()
478 const hash = exports.keccak(address).toString('hex')
479 let ret = '0x'
480
481 for (let i = 0; i < address.length; i++) {
482 if (parseInt(hash[i], 16) >= 8) {
483 ret += address[i].toUpperCase()
484 } else {
485 ret += address[i]
486 }
487 }
488
489 return ret
490 }
491
492 /**
493 * Checks if the address is a valid checksummed address
494 * @param {Buffer} address
495 * @return {Boolean}
496 */
497 exports.isValidChecksumAddress = function (address) {
498 return exports.isValidAddress(address) && (exports.toChecksumAddress(address) === address)
499 }
500
501 /**
502 * Generates an address of a newly created contract
503 * @param {Buffer} from the address which is creating this new address
504 * @param {Buffer} nonce the nonce of the from account
505 * @return {Buffer}
506 */
507 exports.generateAddress = function (from, nonce) {
508 from = exports.toBuffer(from)
509 nonce = new BN(nonce)
510
511 if (nonce.isZero()) {
512 // in RLP we want to encode null in the case of zero nonce
513 // read the RLP documentation for an answer if you dare
514 nonce = null
515 } else {
516 nonce = Buffer.from(nonce.toArray())
517 }
518
519 // Only take the lower 160bits of the hash
520 return exports.rlphash([from, nonce]).slice(-20)
521 }
522
523 /**
524 * Generates an address for a contract created using CREATE2
525 * @param {Buffer} from the address which is creating this new address
526 * @param {Buffer} salt a salt
527 * @param {Buffer} initCode the init code of the contract being created
528 * @return {Buffer}
529 */
530 exports.generateAddress2 = function (from, salt, initCode) {
531 from = exports.toBuffer(from)
532 salt = exports.toBuffer(salt)
533 initCode = exports.toBuffer(initCode)
534
535 assert(from.length === 20)
536 assert(salt.length === 32)
537
538 let address = exports.keccak256(Buffer.concat([
539 Buffer.from('ff', 'hex'),
540 from,
541 salt,
542 exports.keccak256(initCode)
543 ]))
544
545 return address.slice(-20)
546 }
547
548 /**
549 * Returns true if the supplied address belongs to a precompiled account (Byzantium)
550 * @param {Buffer|String} address
551 * @return {Boolean}
552 */
553 exports.isPrecompiled = function (address) {
554 const a = exports.unpad(address)
555 return a.length === 1 && a[0] >= 1 && a[0] <= 8
556 }
557
558 /**
559 * Adds "0x" to a given `String` if it does not already start with "0x"
560 * @param {String} str
561 * @return {String}
562 */
563 exports.addHexPrefix = function (str) {
564 if (typeof str !== 'string') {
565 return str
566 }
567
568 return exports.isHexPrefixed(str) ? str : '0x' + str
569 }
570
571 /**
572 * Validate ECDSA signature
573 * @method isValidSignature
574 * @param {Buffer} v
575 * @param {Buffer} r
576 * @param {Buffer} s
577 * @param {Boolean} [homestead=true]
578 * @param {Number} [chainId]
579 * @return {Boolean}
580 */
581
582 exports.isValidSignature = function (v, r, s, homestead, chainId) {
583 const SECP256K1_N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16)
584 const SECP256K1_N = new BN('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 16)
585
586 if (r.length !== 32 || s.length !== 32) {
587 return false
588 }
589
590 if (!isValidSigRecovery(calculateSigRecovery(v, chainId))) {
591 return false
592 }
593
594 r = new BN(r)
595 s = new BN(s)
596
597 if (r.isZero() || r.gt(SECP256K1_N) || s.isZero() || s.gt(SECP256K1_N)) {
598 return false
599 }
600
601 if ((homestead === false) && (new BN(s).cmp(SECP256K1_N_DIV_2) === 1)) {
602 return false
603 }
604
605 return true
606 }
607
608 /**
609 * Converts a `Buffer` or `Array` to JSON
610 * @param {Buffer|Array} ba
611 * @return {Array|String|null}
612 */
613 exports.baToJSON = function (ba) {
614 if (Buffer.isBuffer(ba)) {
615 return '0x' + ba.toString('hex')
616 } else if (ba instanceof Array) {
617 const array = []
618 for (let i = 0; i < ba.length; i++) {
619 array.push(exports.baToJSON(ba[i]))
620 }
621 return array
622 }
623 }
624
625 /**
626 * Defines properties on a `Object`. It make the assumption that underlying data is binary.
627 * @param {Object} self the `Object` to define properties on
628 * @param {Array} fields an array fields to define. Fields can contain:
629 * * `name` - the name of the properties
630 * * `length` - the number of bytes the field can have
631 * * `allowLess` - if the field can be less than the length
632 * * `allowEmpty`
633 * @param {*} data data to be validated against the definitions
634 */
635 exports.defineProperties = function (self, fields, data) {
636 self.raw = []
637 self._fields = []
638
639 // attach the `toJSON`
640 self.toJSON = function (label) {
641 if (label) {
642 const obj = {}
643 self._fields.forEach((field) => {
644 obj[field] = '0x' + self[field].toString('hex')
645 })
646 return obj
647 }
648 return exports.baToJSON(this.raw)
649 }
650
651 self.serialize = function serialize () {
652 return rlp.encode(self.raw)
653 }
654
655 fields.forEach((field, i) => {
656 self._fields.push(field.name)
657 function getter () {
658 return self.raw[i]
659 }
660 function setter (v) {
661 v = exports.toBuffer(v)
662
663 if (v.toString('hex') === '00' && !field.allowZero) {
664 v = Buffer.allocUnsafe(0)
665 }
666
667 if (field.allowLess && field.length) {
668 v = exports.stripZeros(v)
669 assert(field.length >= v.length, 'The field ' + field.name + ' must not have more ' + field.length + ' bytes')
670 } else if (!(field.allowZero && v.length === 0) && field.length) {
671 assert(field.length === v.length, 'The field ' + field.name + ' must have byte length of ' + field.length)
672 }
673
674 self.raw[i] = v
675 }
676
677 Object.defineProperty(self, field.name, {
678 enumerable: true,
679 configurable: true,
680 get: getter,
681 set: setter
682 })
683
684 if (field.default) {
685 self[field.name] = field.default
686 }
687
688 // attach alias
689 if (field.alias) {
690 Object.defineProperty(self, field.alias, {
691 enumerable: false,
692 configurable: true,
693 set: setter,
694 get: getter
695 })
696 }
697 })
698
699 // if the constuctor is passed data
700 if (data) {
701 if (typeof data === 'string') {
702 data = Buffer.from(exports.stripHexPrefix(data), 'hex')
703 }
704
705 if (Buffer.isBuffer(data)) {
706 data = rlp.decode(data)
707 }
708
709 if (Array.isArray(data)) {
710 if (data.length > self._fields.length) {
711 throw (new Error('wrong number of fields in data'))
712 }
713
714 // make sure all the items are buffers
715 data.forEach((d, i) => {
716 self[self._fields[i]] = exports.toBuffer(d)
717 })
718 } else if (typeof data === 'object') {
719 const keys = Object.keys(data)
720 fields.forEach((field) => {
721 if (keys.indexOf(field.name) !== -1) self[field.name] = data[field.name]
722 if (keys.indexOf(field.alias) !== -1) self[field.alias] = data[field.alias]
723 })
724 } else {
725 throw new Error('invalid data')
726 }
727 }
728 }
729
730 function calculateSigRecovery (v, chainId) {
731 return chainId ? v - (2 * chainId + 35) : v - 27
732 }
733
734 function isValidSigRecovery (recovery) {
735 return recovery === 0 || recovery === 1
736 }