From 87668c903d5025208a8831c41824364c0892d04d Mon Sep 17 00:00:00 2001 From: krlosMata Date: Tue, 2 Aug 2022 17:50:11 +0200 Subject: [PATCH 1/2] update calculateSnarkInput to match pil-stark --- src/contract-utils.js | 28 ++++--- src/utils.js | 34 ++++++++ test/contract-utils.test.js | 15 ++-- .../test-vectors/inputs-executor/input_0.json | 79 ------------------ .../inputs-executor/input_executor.json | 80 +++++++++++++++++++ 5 files changed, 141 insertions(+), 95 deletions(-) delete mode 100644 test/helpers/test-vectors/inputs-executor/input_0.json create mode 100644 test/helpers/test-vectors/inputs-executor/input_executor.json diff --git a/src/contract-utils.js b/src/contract-utils.js index d4a08920..b13ef627 100644 --- a/src/contract-utils.js +++ b/src/contract-utils.js @@ -1,6 +1,8 @@ const ethers = require('ethers'); const { Scalar } = require('ffjavascript'); -const { FrSNARK } = require('./constants'); +const { sha256Snark, padZeros } = require('./utils'); +const { string2fea } = require('./smt-utils'); +const getPoseidon = require('./poseidon'); /** * Compute globalHash for STARK circuit @@ -55,7 +57,7 @@ function calculateStarkInput( * @param {String} aggregatorAddress - Aggregator Ethereum address in hex string * @returns {String} - sha256(globalHash, aggregatorAddress) % FrSNARK in hex encoding */ -function calculateSnarkInput( +async function calculateSnarkInput( currentStateRoot, currentLocalExitRoot, newStateRoot, @@ -65,6 +67,9 @@ function calculateSnarkInput( timestamp, aggregatorAddress, ) { + const poseidon = await getPoseidon(); + const { F } = poseidon; + const hashKeccak = calculateStarkInput( currentStateRoot, currentLocalExitRoot, @@ -75,15 +80,20 @@ function calculateSnarkInput( timestamp, ); - const hashSha256 = ethers.utils.soliditySha256( - ['bytes32', 'address'], - [ - hashKeccak, - aggregatorAddress, - ], + // 20 bytes agggregator adsress + const strAggregatorAddress = padZeros((Scalar.fromString(aggregatorAddress, 16)).toString(16), 40); + + // 8 bytes each field element + const feaHashKeccak = string2fea(F, hashKeccak); + const strFea = feaHashKeccak.reduce( + (previousValue, currentValue) => previousValue + padZeros(currentValue.toString(16), 16), + '', ); - return `0x${Scalar.mod(Scalar.fromString(hashSha256, 16), FrSNARK).toString(16).padStart(64, '0')}`; + // build final bytes sha256 + const finalStr = strAggregatorAddress.concat(strFea); + + return sha256Snark(finalStr); } /** diff --git a/src/utils.js b/src/utils.js index 0ae30a34..b70c439d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,4 +1,8 @@ /* eslint-disable no-restricted-syntax */ +const crypto = require('crypto'); +const { Scalar } = require('ffjavascript'); +const { FrSNARK } = require('./constants'); + /** * Log2 function * @param {Number} V - value @@ -48,8 +52,38 @@ function hexString2byteArray(_hex) { return byteArray; } +/** + * Pad a string hex number with 0 + * @param {String} str - String input + * @param {Number} length - Length of the resulting string + * @returns {String} Resulting string + */ +function padZeros(str, length) { + if (length > str.length) { + str = '0'.repeat(length - str.length) + str; + } + + return str; +} + +/** + * (Hash Sha256 of an hexadecimal string) % (Snark field) + * @param {String} str - String input in hexadecimal encoding + * @returns {Scalar} Resulting sha256 hash + */ +function sha256Snark(str) { + const hash = crypto.createHash('sha256') + .update(str, 'hex') + .digest('hex'); + const h = Scalar.mod(Scalar.fromString(hash, 16), FrSNARK); + + return h; +} + module.exports = { log2, byteArray2HexString, hexString2byteArray, + sha256Snark, + padZeros, }; diff --git a/test/contract-utils.test.js b/test/contract-utils.test.js index b049381a..4aa40062 100644 --- a/test/contract-utils.test.js +++ b/test/contract-utils.test.js @@ -11,12 +11,13 @@ describe('contractUtils', function () { this.timeout(10000); let testVector; - const expectedBatchHashData = '0xa4e1166ff3f7ecf8c8ff3049fc2e28b03091d3bf0db4bce702d954840196f79d'; - const expectedSnarkInputHash = '0x0b0a9c614cdc5473f2a9251d171230e92e5ae31fab0b165b13586100dad3a2c0'; - const expectedStarkHashExecutor = '0x73855bab378977b439591bdee0bbde9c1b1cf3f48e20418da906ab7abfcc42cf'; + const expectedBatchHashData = '0x9370689d3c20a5a4739f902a31e2ea20c7d7be121a0fc19468a2e1b5d87f4111'; + // input taken from pil-stark + const expectedSnarkInputHash = '14918438705377636817563619860509474434188349281706594260803853913155748736842'; + const expectedStarkHashExecutor = '0xd072c5e95f2a1aa8dee6f1e0667f72f9e66ed47f7ff5f5e3ad6f504379c73c26'; before(async () => { - testVector = JSON.parse(fs.readFileSync(path.join(pathTestVectors, 'inputs-executor/input_0.json'))); + testVector = JSON.parse(fs.readFileSync(path.join(pathTestVectors, 'inputs-executor/input_executor.json'))); }); it('calculateBatchHashData', async () => { @@ -34,7 +35,7 @@ describe('contractUtils', function () { }); it('calculateSnarkInput', async () => { - const aggregatorAddress = '0x123456789ABCDDEF123456789ABCDDEF12345678'; + const aggregatorAddress = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'; const { oldLocalExitRoot, @@ -45,7 +46,7 @@ describe('contractUtils', function () { timestamp, } = testVector; - const computedGlobalHash = await contractUtils.calculateSnarkInput( + const computedSnark = await contractUtils.calculateSnarkInput( oldStateRoot, oldLocalExitRoot, newStateRoot, @@ -56,7 +57,7 @@ describe('contractUtils', function () { aggregatorAddress, ); - expect(computedGlobalHash).to.be.equal(expectedSnarkInputHash); + expect(computedSnark.toString()).to.be.equal(expectedSnarkInputHash.toString()); }); it('calculateStarkInput', async () => { diff --git a/test/helpers/test-vectors/inputs-executor/input_0.json b/test/helpers/test-vectors/inputs-executor/input_0.json deleted file mode 100644 index 63af5079..00000000 --- a/test/helpers/test-vectors/inputs-executor/input_0.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "oldStateRoot": "0xbdde84a5932a2f0a1a4c6c51f3b64ea265d4f1461749298cfdd09b31122ce0d6", - "chainId": 1000, - "db": { - "0xbdde84a5932a2f0a1a4c6c51f3b64ea265d4f1461749298cfdd09b31122ce0d6": [ - "1a0d795be0685727", - "7e5015ec34ec7ddb", - "63f773d86711f009", - "7362d3d38ae13b42", - "be7504d1f462446a", - "800a590ce8e1a655", - "2e02faf1e8960768", - "dd70b7575de5d707", - "0000000000000000", - "0000000000000000", - "0000000000000000", - "0000000000000000" - ], - "0x7362d3d38ae13b4263f773d86711f0097e5015ec34ec7ddb1a0d795be0685727": [ - "36342ae9f65d7d22", - "aa40eaf9c734be40", - "23c274f23b7310fb", - "0502d5aba4bc15b2", - "35f28afeae0ff489", - "b6d75a1b213c2f7c", - "521f1ce7fca92f45", - "2afffacb569cf689", - "0000000000000001", - "0000000000000000", - "0000000000000000", - "0000000000000000" - ], - "0x2afffacb569cf689521f1ce7fca92f45b6d75a1b213c2f7c35f28afeae0ff489": [ - "0000000063100000", - "000000006bc75e2d", - "0000000000000005", - "0000000000000000", - "0000000000000000", - "0000000000000000", - "0000000000000000", - "0000000000000000" - ], - "0xdd70b7575de5d7072e02faf1e8960768800a590ce8e1a655be7504d1f462446a": [ - "36da373cc0a834b8", - "d8a2ee873acd68d4", - "9528e3bbd35021e4", - "07b11c7b6464fe0a", - "494f9491c8507dc3", - "e92914c00b37a1cd", - "f6b613135380bd5f", - "b487e2e7e1d98168", - "0000000000000001", - "0000000000000000", - "0000000000000000", - "0000000000000000" - ], - "0xb487e2e7e1d98168f6b613135380bd5fe92914c00b37a1cd494f9491c8507dc3": [ - "00000000c6200000", - "00000000d78ebc5a", - "000000000000000a", - "0000000000000000", - "0000000000000000", - "0000000000000000", - "0000000000000000", - "0000000000000000" - ] - }, - "sequencerAddr": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e980801186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb9700910c26408b64b51c5da36ba2f38ef55ba1cee719d5a6c012259687999074321b", - "newStateRoot": "0x51a06272e5d84cac0be27f8ccb0e67026ac69f481f9f0c18ec4f712f9dd7b2a5", - "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "globalExitRoot": "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9", - "batchHashData": "0x3d53e7e5be04b00f66af647512af6d17e4e767a5e41fa1293010b885c9fe06db", - "inputHash": "0x58dc76197a13d9a9f0894e3d5984098339944ad4fa2cff01945b053d39cd1c9e", - "numBatch": 1, - "timestamp": 1944498031, - "contractsBytecode": {} -} \ No newline at end of file diff --git a/test/helpers/test-vectors/inputs-executor/input_executor.json b/test/helpers/test-vectors/inputs-executor/input_executor.json new file mode 100644 index 00000000..0350d1a3 --- /dev/null +++ b/test/helpers/test-vectors/inputs-executor/input_executor.json @@ -0,0 +1,80 @@ +{ + "oldStateRoot": "0x2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90", + "db": { + "0x2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90": [ + "0000000000000000", + "0000000000000000", + "0000000000000000", + "0000000000000000", + "0d1f0da5a7b620c8", + "43fd1e18e59fd724", + "d428d25da0cb1888", + "e31f5542ac227c06", + "0000000000000000", + "0000000000000000", + "0000000000000000", + "0000000000000000" + ], + "0xe31f5542ac227c06d428d25da0cb188843fd1e18e59fd7240d1f0da5a7b620c8": [ + "ed22ec7734d89ff2", + "b2e639153607b7c5", + "42b2bd6ec2788851", + "b781932941084783", + "3e63658ee0db910d", + "0b3e34316e81aa10", + "e0dc203d93f4e3e5", + "e10053d0ebc64602", + "0000000000000000", + "0000000000000000", + "0000000000000000", + "0000000000000000" + ], + "0xb78193294108478342b2bd6ec2788851b2e639153607b7c5ed22ec7734d89ff2": [ + "16dde42596b907f0", + "49015d7e991a1528", + "94dd9dadd060910b", + "60b4d5e9af514018", + "b69b044f5e694795", + "f57d81efba5d4445", + "339438195426ad0a", + "3efad1dd58c2259d", + "0000000000000001", + "0000000000000000", + "0000000000000000", + "0000000000000000" + ], + "0x3efad1dd58c2259d339438195426ad0af57d81efba5d4445b69b044f5e694795": [ + "00000000dea00000", + "0000000035c9adc5", + "0000000000000036", + "0000000000000000", + "0000000000000000", + "0000000000000000", + "0000000000000000", + "0000000000000000" + ], + "0xe10053d0ebc64602e0dc203d93f4e3e50b3e34316e81aa103e63658ee0db910d": [ + "66ee2be0687eea76", + "6926f8ca8796c78a", + "4c2f3e938869b82d", + "649e63bfe1247ba4", + "b69b044f5e694795", + "f57d81efba5d4445", + "339438195426ad0a", + "3efad1dd58c2259d", + "0000000000000001", + "0000000000000000", + "0000000000000000", + "0000000000000000" + ] + }, + "sequencerAddr": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e880801cee7e01dc62f69a12c3510c6d64de04ee6346d84b6a017f3e786c7d87f963e75d8cc91fa983cd6d9cf55fff80d73bd26cd333b0f098acc1e58edb1fd484ad731b", + "newStateRoot": "0xbff23fc2c168c033aaac77503ce18f958e9689d5cdaebb88c5524ce5c0319de3", + "oldLocalExitRoot": "0x17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "globalExitRoot": "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9", + "numBatch": 1, + "timestamp": 1944498031, + "contractsBytecode": {} +} \ No newline at end of file From 440469e18ef0d5395263188e60e5c44edfb3d982 Mon Sep 17 00:00:00 2001 From: krlosMata Date: Fri, 5 Aug 2022 15:44:12 +0200 Subject: [PATCH 2/2] update version package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 85e0f7d8..fe3d6177 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@0xpolygonhermez/zkevm-commonjs", "description": "Javascript library implementing common utilities for zkevm", - "version": "0.0.37", + "version": "0.0.38", "main": "index.js", "scripts": { "setup": "npm i",