diff --git a/package.json b/package.json index 1d08d3d..7045a0d 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@typescript-eslint/parser": "^3.0.2", "babelify": "^10.0.0", "browserify": "^16.5.1", + "circomlibjs": "^0.1.7", "crypto": "0.0.3", "ethereum-cryptography": "^1.0.3", "ethereumjs-util": "^7.0.9", @@ -88,6 +89,8 @@ "plugins": [ "@typescript-eslint/eslint-plugin" ], - "globals": ["BigInt"] + "globals": [ + "BigInt" + ] } } diff --git a/src/Base.ts b/src/Base.ts index 7c2ba00..52af0b5 100644 --- a/src/Base.ts +++ b/src/Base.ts @@ -169,6 +169,8 @@ export class Base { return Buffer.from(value) } else if (typeof value === 'bigint') { return Buffer.from(value.toString(16), 'hex') + } else if (value instanceof Uint8Array) { + return Buffer.from(value.buffer) } else if (typeof value === 'number') { let s = value.toString() if (s.length % 2) { @@ -193,15 +195,20 @@ export class Base { } if (typeof value === 'string') { - if (Base.isHexString(value)) { + if (value.startsWith('0x') && Base.isHexString(value)) { return BigInt('0x' + value.replace('0x', '').toString()) } + return BigInt(value) } if (Buffer.isBuffer(value)) { return BigInt('0x' + value.toString('hex')) } + if (value instanceof Uint8Array) { + return BigInt(value) + } + if (typeof value === 'number') { return BigInt(value) } @@ -368,6 +375,10 @@ export class Base { protected _zip (a: any[], b: any[]): any[][] { return a.map((e, i) => [e, b[i]]) } + + static hexZeroPad (hexStr: string, length: number) { + return '0x' + hexStr.replace('0x', '').padStart(length, '0') + } } export default Base diff --git a/test/Base.test.js b/test/Base.test.js index 219826a..d2432f5 100644 --- a/test/Base.test.js +++ b/test/Base.test.js @@ -2,7 +2,7 @@ const test = require('tape') const { Base } = require('../dist/Base') test('bufferify', t => { - t.plan(5) + t.plan(6) const base = new Base() t.deepEqual(base.bufferify(''), Buffer.alloc(0)) @@ -10,25 +10,29 @@ test('bufferify', t => { t.deepEqual(base.bufferify('123'), Buffer.from('123', 'hex')) t.deepEqual(base.bufferify(Buffer.from('123')), Buffer.from('123')) t.deepEqual(base.bufferify(BigInt('0x123')), Buffer.from('123', 'hex')) + t.deepEqual(base.bufferify(new Uint8Array([123])), Buffer.from([123])) }) test('bufferifyFn', t => { - t.plan(3) + t.plan(5) const base = new Base() const fn = base.bufferifyFn(value => value) t.deepEqual(fn('123'), Buffer.from('123', 'hex')) t.deepEqual(fn('0x123'), Buffer.from('123', 'hex')) t.deepEqual(fn('XYZ'), Buffer.from('XYZ')) + t.deepEqual(fn(BigInt('0x123')), Buffer.from('123', 'hex')) + t.deepEqual(fn(new Uint8Array([123])), Buffer.from([123])) }) test('bigNumberify', t => { - t.plan(3) + t.plan(4) const base = new Base() t.deepEqual(base.bigNumberify(123), BigInt(123)) t.deepEqual(base.bigNumberify('0x123'), BigInt('0x123')) t.deepEqual(base.bigNumberify(BigInt(123)), BigInt(123)) + t.deepEqual(base.bigNumberify(new Uint8Array([123])), BigInt(123)) }) test('binarySearch', t => { diff --git a/test/MerkleTree.test.js b/test/MerkleTree.test.js index c1f26b0..32d5646 100644 --- a/test/MerkleTree.test.js +++ b/test/MerkleTree.test.js @@ -9,7 +9,7 @@ const SHA256 = require('crypto-js/sha256') const SHA3 = require('crypto-js/sha3') const sha1 = require('sha1') const { keccak256: ethCryptoKeccak256 } = require('ethereum-cryptography/keccak') -const { poseidon } = require('circomlibjs') +const { buildPoseidon } = require('circomlibjs') const { MerkleTree } = require('../') @@ -1324,22 +1324,24 @@ test.skip('1M leaves keccak256', t => { t.false(tree.verify(proof, keccak256(`${max + 1}`), tree.getRoot())) }) -test('poseidon hash', t => { +test('poseidon hash', async t => { t.plan(4) - const _poseidon = (elements) => { - const bigInts = elements.map(MerkleTree.bigNumberify) - return Buffer.from(poseidon(bigInts).toString(16), 'hex') + const _poseidon = await buildPoseidon() + const poseidonHash = (inputs) => { + const hash = _poseidon(inputs.map(MerkleTree.bigNumberify)) + const bn = MerkleTree.bigNumberify(_poseidon.F.toString(hash)) + return MerkleTree.bufferify(bn) } - const result1 = _poseidon([1, 2].map(MerkleTree.bufferify)) + const result1 = poseidonHash([1, 2]) t.equal(result1.toString('hex'), '115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a') - const result2 = _poseidon([1, 2, 3, 4].map(MerkleTree.bufferify)) + const result2 = poseidonHash([1, 2, 3, 4]) t.equal(result2.toString('hex'), '299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465') - const leaves = [1, 2, 3, 4].map(x => _poseidon([x])) - const tree = new MerkleTree(leaves, _poseidon, { + const leaves = [1, 2, 3, 4].map(x => poseidonHash([x])) + const tree = new MerkleTree(leaves, poseidonHash, { concatFn: (hashes) => hashes }) t.equal(tree.getHexRoot(), '0xd24e045226875e22b37ce607ea2af7a9fbb137ee128caa0ce3663615350245')