From 980e7abd05f0e0d8325da1d76347fe6f32640134 Mon Sep 17 00:00:00 2001 From: laisolizq Date: Tue, 28 Feb 2023 13:19:45 +0100 Subject: [PATCH 1/4] fix MSTOREX2 --- counters/countersConstants.zkasm | 2 +- counters/tests/MSTOREX.zkasm | 2 +- main/utils.zkasm | 27 +++++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/counters/countersConstants.zkasm b/counters/countersConstants.zkasm index 1815bf91..1d2a39b6 100644 --- a/counters/countersConstants.zkasm +++ b/counters/countersConstants.zkasm @@ -216,7 +216,7 @@ CONST %OPCALLDATALOAD_CNT_PADDING_PG = 0 + %SHLARITH_CNT_PADDING_PG + %SHRARITH_ CONST %OPCALLDATALOAD_CNT_POSEIDON_G = 0 + %SHLARITH_CNT_POSEIDON_G + %SHRARITH_CNT_POSEIDON_G + %DIVARITH_CNT_POSEIDON_G ; opCALLDATACOPY - COMPLEX - hardcoded values at test CONST %OPCALLDATACOPY_STEP = 100 -CONST %OPCALLDATACOPY_CNT_BINARY = 21 +CONST %OPCALLDATACOPY_CNT_BINARY = 20 CONST %OPCALLDATACOPY_CNT_ARITH = 8 CONST %OPCALLDATACOPY_CNT_KECCAK_F = 0 CONST %OPCALLDATACOPY_CNT_MEM_ALIGN = 2 diff --git a/counters/tests/MSTOREX.zkasm b/counters/tests/MSTOREX.zkasm index 32a1b843..a16120e5 100644 --- a/counters/tests/MSTOREX.zkasm +++ b/counters/tests/MSTOREX.zkasm @@ -15,7 +15,7 @@ operation: :CALL(MSTOREX) %MSTOREX_STEP - STEP:JMPN(failedCounters) - 13 - CNT_BINARY :JMPNZ(failedCounters) + 12 - CNT_BINARY :JMPNZ(failedCounters) ;%MSTOREX_CNT_BINARY - CNT_BINARY :JMPNZ(failedCounters) 7 - CNT_ARITH :JMPNZ(failedCounters) ;%MSTOREX_CNT_ARITH - CNT_ARITH :JMPNZ(failedCounters) diff --git a/main/utils.zkasm b/main/utils.zkasm index d2ccfd8a..9470553b 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -190,7 +190,7 @@ initMSTORE: zkPC+1 => RR :JMP(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] ; is storing <32 bytes, jump to store last bytes or finish if 0 bytes left $ => B :MLOAD(isMSTOREX), JMPZ(finalMSTORE) - ; if C has value, bytes splitted in two memory slots + ; if C has value, offset != 0 C :JMPNZ(MSTOREX2) $ => C :MLOAD(tmpVarCmstore) ; load bytes to store @@ -211,10 +211,12 @@ initMSTORE: 0 => C 0 :MSTORE(isMSTOREX), JMP(finalMSTORE) -; used if memory to store is allocated in two different slots +; used if bytesToStore.length < 32 && offset != 0 MSTOREX2: $ => D :MLOAD(tmpVarCmstore) C + D => D + 32 - D :JMPN(MSTOREX3) + ; if bytesToStore.length < 32 && memory to load is allocated in two different slots ; load memory from slot E $ => A :MLOAD(MEM:E) ; shift loaded memory from slot E @@ -236,6 +238,27 @@ MSTOREX2: zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] ; append loaded bytes from concurrent slots + A + B => A :MSTORE(bytesToStore) + :JMP(finalMSTORE) + +; used if bytesToStore.length < 32 && memory to load is allocated in one slot +MSTOREX3: + D - 32 => D + ; load memory from slot E+1 + $ => A :MLOAD(MEM:E+1) + ; shift bytes to store + zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] + $ => D :MLOAD(tmpVarCmstore) + zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] + ; join both results + A => B + $ => A :MLOAD(bytesToStore) + $ => D :MLOAD(tmpVarCmstore) + 32 - D => D + ; shift bytes to store + zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] + zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] + ; append loaded bytes from concurrent slots A + B => A :MSTORE(bytesToStore) finalMSTORE: From 5d9ad79721d232ae744caf9573d5a3825f115cec Mon Sep 17 00:00:00 2001 From: laisolizq Date: Thu, 2 Mar 2023 12:14:01 +0100 Subject: [PATCH 2/4] add mstorex test --- package.json | 1 + test/mstorex.zkasm | 171 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 test/mstorex.zkasm diff --git a/package.json b/package.json index e1a0af5a..699c9dc0 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "test:rotate": "mkdir -p build && npx zkasm test/rotate.zkasm -o build/rotate.test.json", "test:touched": "mkdir -p build && npx zkasm test/touched-assert.zkasm -o build/touched.test.json", "test:counters": "node counters/counters-executor.js", + "test:mstorex": "mkdir -p build && npx zkasm test/mstorex.zkasm -o build/mstorex.test.json", "eslint": "npx eslint tools/**.js", "eslint:fix": "npx eslint tools/**.js --fix", "test:gen": "node tools/gen-parallel-tests.js", diff --git a/test/mstorex.zkasm b/test/mstorex.zkasm new file mode 100644 index 00000000..472a3fa2 --- /dev/null +++ b/test/mstorex.zkasm @@ -0,0 +1,171 @@ +start: + + STEP => A + 0 :ASSERT + + ; TEST-1 (simple test) + + 0 => E :CALL(fillMemPattern) + + 3*32+5 => E + 0xFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000n :MSTORE(bytesToStore) + 6 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFn :MLOAD(MEM:E+2) + 0xC0C1C2C3C4FFFFFFFFFFFFCBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-2 (between memory words) + + 0 => E :CALL(fillMemPattern) + + 2*32+29 => E + 0xABCDEFFEDCBA0000000000000000000000000000000000000000000000000000n :MSTORE(bytesToStore) + 6 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCABCDEFn :MLOAD(MEM:E+2) + 0xFEDCBAC3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-3 (relative offset 0) + + 0 => E :CALL(fillMemPattern) + + 2*32 => E + 0xABCDEFFEDCBA0000000000000000000000000000000000000000000000000000n :MSTORE(bytesToStore) + 6 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xABCDEFFEDCBAA6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFn :MLOAD(MEM:E+2) + 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-4 (32 bytes, offset > 0) + + 0 => E :CALL(fillMemPattern) + + 2*32 + 18 => E + 0x102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E20210n :MSTORE(bytesToStore) + 32 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1102030405060708090A0B0C0D0E0n :MLOAD(MEM:E+2) + 0xF101112131415161718191A1B1C1D1E20210D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-5 (0 bytes) + + 0 => E :CALL(fillMemPattern) + + 2*32 + 18 => E + 0x102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E20210n :MSTORE(bytesToStore) + 0 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFn :MLOAD(MEM:E+2) + 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-6 (32 bytes, offset 0) + + 0 => E :CALL(fillMemPattern) + + 2*32 => E + 0x102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E20210n :MSTORE(bytesToStore) + 32 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0x102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E20210n :MLOAD(MEM:E+2) + 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-7 (high address) + + 2**17-6 => E :CALL(fillMemPattern) + + 2**22-6*32+2*32+29 => E + 0xABCDEFFEDCBA0000000000000000000000000000000000000000000000000000n :MSTORE(bytesToStore) + 6 => C + :CALL(MSTOREX) + + 2**17-6 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCABCDEFn :MLOAD(MEM:E+2) + 0xFEDCBAC3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-8 (1 byte, offset = 31) + + 0 => E :CALL(fillMemPattern) + + 2*32+31 => E + 0x882030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E20210n :MSTORE(bytesToStore) + 1 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE88n :MLOAD(MEM:E+2) + 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + ; TEST-9 (31 bytes, offset = 31) + + 0 => E :CALL(fillMemPattern) + + 2*32+31 => E + 0x882030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E20210n :MSTORE(bytesToStore) + 31 => C + :CALL(MSTOREX) + + 0 => E + 0x0000000000000000000000000000000000000000000000000000000000000000n :MLOAD(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MLOAD(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE88n :MLOAD(MEM:E+2) + 0x2030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E202DEDFn :MLOAD(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MLOAD(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MLOAD(MEM:E+5) + + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 + :JMP(finalizeExecution) + +fillMemPattern: + + 0x0000000000000000000000000000000000000000000000000000000000000000n :MSTORE(MEM:E) + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E2021n :MSTORE(MEM:E+1) + 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFn :MSTORE(MEM:E+2) + 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFn :MSTORE(MEM:E+3) + 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEn :MSTORE(MEM:E+4) + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn :MSTORE(MEM:E+5), RETURN + +INCLUDE "../main/main.zkasm" \ No newline at end of file From 3d42356b69cad9cf72ed41fbce74c00d25141bb2 Mon Sep 17 00:00:00 2001 From: laisolizq Date: Thu, 2 Mar 2023 12:15:25 +0100 Subject: [PATCH 3/4] update package tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 699c9dc0..fb93e371 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "devDependencies": { "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs#864399e9e78ac6a24601c0e620909e1be02110aa", - "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#v0.7.0.0-rc.2", + "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#feature/add-test-mstorex", "chai": "^4.3.6", "chalk": "^3.0.0", "eslint": "^8.25.0", From f76bf6be72daf0c16b622837254c0f5ce2d2b8dc Mon Sep 17 00:00:00 2001 From: krlosMata Date: Thu, 23 Feb 2023 00:11:42 +0100 Subject: [PATCH 4/4] fix jmpn, reduntant jump and typos --- counters/countersConstants.zkasm | 4 +- main/load-tx-rlp.zkasm | 11 ++++- main/main.zkasm | 5 +-- main/opcodes/block.zkasm | 30 ++++++------- main/opcodes/calldata-returndata-code.zkasm | 2 +- main/opcodes/comparison.zkasm | 2 +- main/opcodes/create-terminate-context.zkasm | 23 +++++----- main/opcodes/storage-memory.zkasm | 2 +- main/process-tx.zkasm | 12 ++++- main/utils.zkasm | 50 ++++++++++++--------- main/vars.zkasm | 14 +++--- package.json | 2 +- 12 files changed, 89 insertions(+), 68 deletions(-) diff --git a/counters/countersConstants.zkasm b/counters/countersConstants.zkasm index 1d2a39b6..cf3d0c95 100644 --- a/counters/countersConstants.zkasm +++ b/counters/countersConstants.zkasm @@ -248,7 +248,7 @@ CONST %OPEXTCODECOPY_CNT_PADDING_PG = 0 CONST %OPEXTCODECOPY_CNT_POSEIDON_G = 8 ; opCREATE - COMPLEX - hardcoded values at test CONST %OPCREATE_STEP = 100 -CONST %OPCREATE_CNT_BINARY = 21 +CONST %OPCREATE_CNT_BINARY = 22 CONST %OPCREATE_CNT_ARITH = 4 CONST %OPCREATE_CNT_KECCAK_F = 0 CONST %OPCREATE_CNT_MEM_ALIGN = 2 @@ -256,7 +256,7 @@ CONST %OPCREATE_CNT_PADDING_PG = 0 CONST %OPCREATE_CNT_POSEIDON_G = 23 ; opCREATE2 - COMPLEX - hardcoded values at test CONST %OPCREATE2_STEP = 200 -CONST %OPCREATE2_CNT_BINARY = 27 +CONST %OPCREATE2_CNT_BINARY = 28 CONST %OPCREATE2_CNT_ARITH = 5 CONST %OPCREATE2_CNT_KECCAK_F = 0 CONST %OPCREATE2_CNT_MEM_ALIGN = 2 diff --git a/main/load-tx-rlp.zkasm b/main/load-tx-rlp.zkasm index 0968987f..10737d02 100644 --- a/main/load-tx-rlp.zkasm +++ b/main/load-tx-rlp.zkasm @@ -34,6 +34,10 @@ loadTx_rlp: :CALL(addBatchHashData) A - 0xc0 :JMPN(invalidTxRLP) A - 0xf8 :JMPN(shortList) + ; do not allow lists over 2**24 bytes + ; Transaction could not have more than 300.000 due to smart contract limitation (keccaks counters) + ; meaning that the RLP encoding is wrong + A - 0xfb :JMPN(longList, invalidTxRLP) longList: A - 0xf7 => D :CALL(addHashTx) @@ -167,7 +171,10 @@ dataREAD: A - 0x80 :JMPN(veryShortData) A - 0x81 :JMPN(endData) A - 0xb8 :JMPN(shortData) - A - 0xc0 :JMPN(longData, invalidTxRLP) + ; do not allow string over 2**24 bytes + ; Transaction could not have more than 300.000 due to smart contract limitation (keccaks counters) + ; meaning that the RLP encoding is wrong + A - 0xbb :JMPN(longData, invalidTxRLP) veryShortData: 1 :MSTORE(txCalldataLen) @@ -238,7 +245,7 @@ endChainId: setPreEIP155Flag: 1 :MSTORE(isPreEIP155) ;; size verification - ; checks RLP lenght read at the RLP header with bytes read during RLP parsing + ; checks RLP length read at the RLP header with bytes read during RLP parsing sizeVerification: C => A $ => B :MLOAD(txRLPLength) diff --git a/main/main.zkasm b/main/main.zkasm index e43f1e17..4a9af18a 100644 --- a/main/main.zkasm +++ b/main/main.zkasm @@ -11,13 +11,11 @@ INCLUDE "vars.zkasm" start: ; main zkROM entry point ;;;;;;;;;;;;;;;;;; -;; A - Load input variabales +;; A - Load input variables ;;;;;;;;;;;;;;;;;; STEP => A 0 :ASSERT ; Ensure it is the beginning of the execution - ; it is assumed that forkID is less than 32 bits - ; hence, 'JMPZ' instruction is safe CTX :MSTORE(forkID) CTX - %FORK_ID :JMPNZ(failAssert) @@ -65,6 +63,7 @@ setGlobalExitRoot: ; read timestamp given the globalExitRoot ; skip overwrite timestamp if it is different than 0 + ; Since timestamp is enforced by the smart contract it is safe to compare only 32 bits in 'op0' with JMPNZ $ => D :SLOAD, JMPNZ(skipSetGlobalExitRoot) $ => D :MLOAD(timestamp) diff --git a/main/opcodes/block.zkasm b/main/opcodes/block.zkasm index 14be3eeb..bd3b5afc 100644 --- a/main/opcodes/block.zkasm +++ b/main/opcodes/block.zkasm @@ -10,10 +10,10 @@ */ opBLOCKHASH: ; checks zk-counters - %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 255 :JMPN(outOfCountersPoseidon) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 255 :JMPN(outOfCountersPoseidon) + $ => A :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) ; check stack underflow SP - 1 => SP :JMPN(stackUnderflow) @@ -21,12 +21,9 @@ opBLOCKHASH: ; check out-of-gas GAS - %GAS_EXT_STEP => GAS :JMPN(outOfGas) - ; Get last tx count - $ => B :MLOAD(txCount) - B + 1 => B - $ => A :MLOAD(SP) ; [blockNumber => A] - ; Check batch block is lt current block number, else return 0 - B - A - 1 :JMPN(opBLOCKHASHzero) + $ => B :MLOAD(SP) ; [blockNumber => B] + ; If block number does not exist in the smart conract system, it will return 0 + ; Create key for the batch hash mapping key ; set bytes length to D 32 => D @@ -34,7 +31,7 @@ opBLOCKHASH: 0 => HASHPOS $ => E :MLOAD(lastHashKIdUsed) E+1 => E :MSTORE(lastHashKIdUsed) - A :HASHK(E) + B :HASHK(E) %STATE_ROOT_STORAGE_POS :HASHK(E) HASHPOS :HASHKLEN(E) ; blockhash key = hash(blockNumber, STATE_ROOT_STORAGE_POS) @@ -47,10 +44,6 @@ opBLOCKHASH: ; store result value in the stack E :MSTORE(SP++), JMP(readCode); [hash(E) => SP] -; Handle when is asking for the hash of a not computed batch, return 0 -opBLOCKHASHzero: - 0 :MSTORE(SP++), JMP(readCode); [0 => SP] - /** * @link [https://www.evm.codes/#41?fork=berlin] * @zk-counters @@ -105,8 +98,11 @@ opNUMBER: ; check out-of-gas GAS - %GAS_QUICK_STEP => GAS :JMPN(outOfGas) ; Get current tx count - $ => D :MLOAD(txCount) - D + 1 :MSTORE(SP++); [blockNumber => SP] + $ => A :MLOAD(txCount) + 1 => B + + ; call binary:add state machine and push to the stack + $ :ADD, MSTORE(SP++); [blockNumber => SP] ; check stack overflow %CALLDATA_OFFSET - SP :JMPN(stackOverflow, readCode) diff --git a/main/opcodes/calldata-returndata-code.zkasm b/main/opcodes/calldata-returndata-code.zkasm index 66ac2a79..aee51602 100644 --- a/main/opcodes/calldata-returndata-code.zkasm +++ b/main/opcodes/calldata-returndata-code.zkasm @@ -37,7 +37,7 @@ opCALLDATALOAD2: $ => A :MLOAD(SP++) ; reading beyond the calldata length will result in reading 0 ; calldata memory reservation in zkEVM (2**16 * 32 bytes) is larger than maximum bytes allowed as calldata fixed in the smart contract (300.000 bytes) - ; therefore it is assured that remaining memory space will be always 0 and never writen or over exceeded + ; therefore it is assured that remaining memory space will be always 0 and never writen or over exceed $ => B :MLOAD(SP) $ => A :MEM_ALIGN_RD ; recover SP diff --git a/main/opcodes/comparison.zkasm b/main/opcodes/comparison.zkasm index 87e0abd0..6a7ef2d9 100644 --- a/main/opcodes/comparison.zkasm +++ b/main/opcodes/comparison.zkasm @@ -396,7 +396,7 @@ opSAR: ; check out-of-gas GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas) - ; read two items form the stack + ; read two items from the stack SP - 1 => SP $ => C :MLOAD(SP--) ; [shift (bits) => C] $ => A :MLOAD(SP) ; [value => A] diff --git a/main/opcodes/create-terminate-context.zkasm b/main/opcodes/create-terminate-context.zkasm index 15c25f16..3755c4c1 100644 --- a/main/opcodes/create-terminate-context.zkasm +++ b/main/opcodes/create-terminate-context.zkasm @@ -54,7 +54,7 @@ opSTOPend: opCREATE: ; checks zk-counters %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 255*3 :JMPN(outOfCountersPoseidon) ; check out-of-gas @@ -96,7 +96,7 @@ opCREATE: D => B $ :LT,JMPC(opCreateFail) - ; check nonce overlow + ; check nonce overflow $ => A :MLOAD(storageAddr) ; set key for smt nonce query %SMT_KEY_NONCE => B @@ -125,7 +125,8 @@ opCREATE: :CALL(getLenBytes); in: [B: value] out: [A: value bytes length] A :MSTORE(lengthNonce) ; increase nonce - B + 1 => D + 1 => A + $ => D :ADD C => A ; set key for smt nonce query %SMT_KEY_NONCE => B @@ -263,7 +264,7 @@ opCALLend: $ => C :LT, CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))] $ => CTX :MLOAD(originCTX) GAS - A :MSTORE(gasCTX) - ; add estipend (2300) in case of tx with value + ; add stipend (2300) in case of tx with value A + %CALL_STIPEND*C => A ; move is static bool value to following CTX $ => D :MLOAD(isStaticCall) @@ -371,7 +372,7 @@ opCALLCODEend: $ => C :LT, CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))] $ => CTX :MLOAD(originCTX) GAS - A :MSTORE(gasCTX) - ; Add estipend (2300) in case of tx with value + ; Add stipend (2300) in case of tx with value A + %CALL_STIPEND*C => A ; move is static bool value to following CTX $ => D :MLOAD(isStaticCall) @@ -508,7 +509,7 @@ opRETURNcreate: $ => D :MLOAD(txNonce) ; set bytecode length and read bytecode first byte - $ => A :MLOAD(createContractAddress), CALL(checkBytecodeStartsEF) + $ => A :MLOAD(createContractAddress), CALL(checkBytecodeStartsEF) ; in: [memOffset], out: [startsWithEFn ; check bytecode first byte != 0xEF $ :MLOAD(startsWithEF), JMPNZ(invalidCodeStartsEF) @@ -646,7 +647,7 @@ opDELEGATECALLend: opCREATE2: ; checks zk-counters %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 255*2 :JMPN(outOfCountersPoseidon) ; check out-of-gas GAS - %CREATE_2_GAS => GAS :JMPN(outOfGas) @@ -687,7 +688,7 @@ opCREATE2: A - B => GAS GAS :MSTORE(gasCall) - ; check correctness of Create: depth, can transfer, nonce overlfow, + ; check correctness of Create: depth, can transfer, nonce overflow, ; can transfer $ => A :MLOAD(storageAddr) ; set key for smt balance query @@ -699,7 +700,7 @@ opCREATE2: $ => B :MLOAD(valueCall) $ :LT,JMPC(opCreateFail) - ; check nonce overlow + ; check nonce overflow $ => A :MLOAD(storageAddr) ; set key for smt nonce query %SMT_KEY_NONCE => B @@ -729,7 +730,9 @@ opCREATE2: B :MSTORE(txNonce), CALL(getLenBytes); in: [B: value] out: [A: value bytes length] A :MSTORE(lengthNonce) ; increase nonce - B + 1 => D + 1 => A + $ => D :ADD + C => A ; set key for smt nonce query %SMT_KEY_NONCE => B diff --git a/main/opcodes/storage-memory.zkasm b/main/opcodes/storage-memory.zkasm index 49a7cf80..806f69c1 100644 --- a/main/opcodes/storage-memory.zkasm +++ b/main/opcodes/storage-memory.zkasm @@ -207,7 +207,7 @@ opSSTOREinit: ; set key for smt storage query %SMT_KEY_SC_STORAGE => B $ => E :SLOAD - ; change context to check sotrage original value + ; change context to check storage original value SR :MSTORE(auxSR) $ => SR :MLOAD(originSR) $ => B :SLOAD ; origin value diff --git a/main/process-tx.zkasm b/main/process-tx.zkasm index f1141e35..617ee46c 100644 --- a/main/process-tx.zkasm +++ b/main/process-tx.zkasm @@ -81,7 +81,9 @@ endCheckChainId: $ => A :SLOAD $ => B :MLOAD(txNonce) $ => C :EQ, JMPNC(invalidIntrinsicTxNonce) ; Compare nonce state tree with nonce transaction - A + 1 => D + ; increase nonce by 1 + 1 => B + $ => D :ADD ; compute [nonce + 1 => D] E => A %SMT_KEY_NONCE => B 0 => C @@ -152,6 +154,7 @@ endCalldataIntrinsicGas: $ => B :MLOAD(txValue) D :MSTORE(arithA) B :MSTORE(arithB), CALL(addARITH) + $ :MLOAD(addArithOverflow), JMPNZ(invalidIntrinsicTxBalance) $ => B :MLOAD(arithRes1) ; Comparison C => A @@ -214,6 +217,11 @@ getContractAddress: $ :LT,JMPC(nonce1byte) $ => C :MLOAD(lengthNonce) ; 1 byte length address + 20 bytes address + 1 byte length nonce + C bytes nonce + ; RLPlist[RLP(address):RLP(nonce)] --> 1 byte length address + 20 bytes address + 1 byte length nonce + C bytes nonce + ; --> 0xc0 + address RLP bytes(1 + 20) + nonce RLP bytes (variable) + ; RLP(address) --> 20 bytes header + address value --> 0x94 + address value + ; RLP(nonce) --> nonce < 128 --> 1 byte --> value itself + ; --> nonce > 128 --> (1 byte + length nonce) + value itself 0xc0 + 22 + C :HASHK1(E) 0x94 :HASHK1(E) 20 => D @@ -435,7 +443,7 @@ endDeploy: ; save offset memory and length to compute hash bytecode. Read bytecode first byte E :MSTORE(memOffsetLinearPoseidon) - C :MSTORE(memSizeLinearPoseidon), CALL(checkBytecodeStartsEF) + C :MSTORE(memSizeLinearPoseidon), CALL(checkBytecodeStartsEF) ; in: [memOffset], out: [startsWithEFn] ; check bytecode first byte != 0xEF $ :MLOAD(startsWithEF), JMPNZ(invalidCodeStartsEF) diff --git a/main/utils.zkasm b/main/utils.zkasm index 9470553b..7642bd39 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -27,7 +27,7 @@ copySP: RR :MSTORE(tmpZkPCcopy) ; store current ctx CTX :MSTORE(currentCTX) - ; set SP at the begginning of calldata memory allocation + ; set SP at the beginning of calldata memory allocation %CALLDATA_OFFSET => SP ; retrieve previous context $ => CTX :MLOAD(originCTX) @@ -200,7 +200,7 @@ initMSTORE: zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] A => B - ; load from memoty + ; load from memory $ => A :MLOAD(MEM:E) 32 - D => D ; shift loaded bytes @@ -317,7 +317,7 @@ MLOADX: %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) - 32 - C :JMPN(errorMLOADMSTORE) ; TDDO Should be unreachable! check it + 32 - C :JMPN(errorMLOADMSTORE) 32 - C - 1 :JMPN(MLOAD32) 1 :MSTORE(isMLOADX) @@ -353,7 +353,7 @@ initMLOAD: memAlignOptionMLOAD: $ => A :MLOAD(MEM:E) $ => B :MLOAD(MEM:E+1) - ; get memeory value + ; get memory value $ => A :MEM_ALIGN_RD E*32 + C => E $ => B :MLOAD(isMLOADX) @@ -584,6 +584,7 @@ VAR GLOBAL arithRes1 VAR GLOBAL arithRes2 VAR GLOBAL arithOverflow +VAR GLOBAL addArithOverflow ; @info binary addition ; @in: arithA: addend value ; @in: arithB: addend value @@ -593,8 +594,13 @@ addARITH: RR :MSTORE(tmpZkPCArith), CALL(storeTmp) $ => A :MLOAD(arithA) $ => B :MLOAD(arithB) - $ => E :ADD, MSTORE(arithRes1) + $ => E :ADD, MSTORE(arithRes1), JMPC(setAddArithOverflow) + 0 :MSTORE(addArithOverflow), JMP(finishAddArith) + +setAddArithOverflow: + 1 :MSTORE(addArithOverflow) +finishAddArith: $ => RR :MLOAD(tmpZkPCArith), JMP(loadTmp) ; @info binary substraction @@ -635,7 +641,7 @@ mulARITH: ; @info arithmetic division ; @in: arithA: dividend value ; @in: arithB: divisor value -; @out: arithRes1: quotien of division arithA / arithB +; @out: arithRes1: quotient of division arithA / arithB ; @out: arithRes2: remainder of division arithA % arithB divARITH: ; check zk-counters @@ -657,7 +663,7 @@ divARITH: $ :LT, JMPC(divisorSmallerDiv) C => A - ${E%A} => C ; reminder + ${E%A} => C ; remainder ${E/A} => B 0 => D E :ARITH @@ -665,9 +671,9 @@ divARITH: B :MSTORE(arithRes1) C :MSTORE(arithRes2) - ; check divisor > reminder + ; check divisor > remainder A => B ; divisor - C => A ; reminder + C => A ; remainder $ => A :LT 1 :ASSERT,CALL(loadTmp) $ => RR :MLOAD(tmpZkPCArith) @@ -1043,7 +1049,7 @@ readPush: D => A 0x04 => B $ :LT,JMPNC(failAssert) - 0 => B :JMP(readPushBlock) + 0 => B readPushBlock: %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) @@ -1066,10 +1072,10 @@ readPushBlock: $ => A :HASHP1(E) HASHPOS - 2 => HASHPOS - A*16777216 + C => C :JMP(doRotate) + A*16777216 + C => C doRotate: - B - 1 => A :JMP(doRotateLoop) + B - 1 => A doRotateLoop: %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) @@ -1156,7 +1162,7 @@ utilsAddBatchHashBytebyByteLoop: 1 => D :CALL(addBatchHashData); in:[D: length of the hash] ; check loop B => D - ; D + 1 => D we set 33 in stead of 32 to earn 1 step + ; D + 1 => D, we set 33 instead of 32 to earn 1 step 33 - D => D $ => B :MLOAD(tmpVarDaddB) D - B - 1 :JMPN(utilsAddBatchHashBytebyByteLoop) @@ -1187,7 +1193,7 @@ checkBytecodeStartsEF: $ => E :MLOAD(memOffsetLinearPoseidon) ; get 1 byte from memory - 1 => C :CALL(MLOADX) ; in: [E: offset, C: lenght] out: [A: value , E: new offset] + 1 => C :CALL(MLOADX) ; in: [E: offset, C: length] out: [A: value , E: new offset] 31 => D :CALL(SHRarith) ; in: [A: value, D: #bytes to right shift] out: [A: shifted result] ; check if byte read is equal to 0xEF @@ -1285,7 +1291,7 @@ maskAddress: $ => A :AND $ => B :MLOAD(tmpVarBmask), RETURN -;@info: updates the address sytem storage with current batch and state root +;@info: updates the address system storage with current batch and state root updateSystemData: ; check keccak counters $ => A :MLOAD(cntKeccakPreProcess) @@ -1294,12 +1300,14 @@ updateSystemData: %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 255*2 :JMPN(outOfCountersPoseidon) ; Get last tx count + $ => A :MLOAD(txCount) + ;Update last tx Count at system storage + 1 => B + $ => D :ADD, MSTORE(txCount) + %LAST_TX_STORAGE_POS => C %ADDRESS_SYSTEM => A %SMT_KEY_SC_STORAGE => B - $ => D :MLOAD(txCount) - ;Update last tx Count at system storage - D + 1 => D :MSTORE(txCount) $ => SR :SSTORE ;Update state root mapping @@ -1342,8 +1350,8 @@ utilMULMOD: ; A * B + 0 = D*2^256 + E ; K * N + mulModResult = D*2^256 + E - ; Since the k can be bigger than 2²⁵⁶ and therefore does not fit in a register we divedit in the - ; most significan and less significant part: + ; Since the k can be bigger than 2²⁵⁶ and therefore does not fit in a register, we split it in the + ; most significant and less significant part: ; (k.l + k.h * 2²⁵⁶) * N + mulModResult = (D1 + D2) * 2²⁵⁶ + E ; And divide this operation in 2 which fits in 2²⁵⁶ digits @@ -1511,7 +1519,7 @@ expADend: $ => RR :MLOAD(tmpZkPCexp) $ => E :MLOAD(tmpVarEexp), RETURN -;@info function to force a failed assertt +;@info function to force a failed assert failAssert: 1 => A 2 :ASSERT \ No newline at end of file diff --git a/main/vars.zkasm b/main/vars.zkasm index 03b705b6..96e7b6a4 100644 --- a/main/vars.zkasm +++ b/main/vars.zkasm @@ -2,7 +2,7 @@ VAR GLOBAL oldStateRoot ; Previous state-tree root VAR GLOBAL oldAccInputHash ; Previous accumulated input hash VAR GLOBAL globalExitRoot ; Global exit-tree root -VAR GLOBAL oldNumBatch ; Previous batch processsed +VAR GLOBAL oldNumBatch ; Previous batch processed VAR GLOBAL sequencerAddr ; Coinbase address which will receive the fees VAR GLOBAL batchHashData ; batchHashData = H_keccak( transactions ) VAR GLOBAL timestamp ; Current batch timestamp @@ -12,14 +12,14 @@ VAR GLOBAL forkID ; Fork identifier ; Output variables VAR GLOBAL newAccInputHash ; Final accumulated input hash. newAccInputHash = H_keccak( oldAccInputHash | batchHashData | globalExitRoot | timestamp | sequencerAddr ) VAR GLOBAL newLocalExitRoot ; Updated local exit tree root -VAR GLOBAL newNumBatch ; Current batch processsed +VAR GLOBAL newNumBatch ; Current batch processed VAR GLOBAL batchL2DataParsed ; Number of bytes read when decoding RLP transactions. Computed during RLP loop VAR GLOBAL pendingTxs ; Number of transactions decoded in RLP block VAR GLOBAL lastCtxUsed ; Last context that has been used VAR GLOBAL ctxTxToUse ; First context to be used when processing transactions VAR GLOBAL lastHashKIdUsed ; Last hash address used -VAR GLOBAL nextHashPId ; Next posidon hash address available +VAR GLOBAL nextHashPId ; Next poseidon hash address available VAR GLOBAL batchL2DataLength ; Transactions bytes read from the input VAR GLOBAL batchHashDataId ; hash address used when adding bytes to batchHashData @@ -31,7 +31,7 @@ VAR GLOBAL gasCalldata ; gas spent by the calldata VAR GLOBAL gasCall ; total gas forwarded when creating a new context VAR GLOBAL addrCall ; address parameter when creating a new context VAR GLOBAL valueCall ; value parameter when creating a new context -VAR GLOBAL argsLengthCall ; size af the calldata creating a new context +VAR GLOBAL argsLengthCall ; size of the calldata creating a new context VAR GLOBAL txSrcOriginAddr ; origin address of a tx VAR GLOBAL txGasPrice ; transaction parameter: 'gasPrice' global var VAR GLOBAL depth ; Current depth execution @@ -44,10 +44,10 @@ VAR GLOBAL txCount ; Current transaction count VAR GLOBAL touchedSR ; touched tree root VAR GLOBAL numTopics ; number of topics depending on LOG opcode call -VAR GLOBAL SPw ; aux variable to store Stack poimnter 'SP' -VAR GLOBAL auxSR ; auxiliaty variable. Temporary state root +VAR GLOBAL SPw ; aux variable to store Stack pointer 'SP' +VAR GLOBAL auxSR ; auxiliary variable. Temporary state root VAR GLOBAL txRLPLength ; transaction RLP list length -VAR GLOBAL txDataRead ; aux varible to check transaction 'data' left that needs to be read +VAR GLOBAL txDataRead ; aux variable to check transaction 'data' left that needs to be read VAR CTX txGasLimit ; transaction parameter: 'gas limit' VAR CTX txDestAddr ; transaction parameter: 'to' diff --git a/package.json b/package.json index fb93e371..8500ede4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xpolygonhermez/zkrom", - "version": "0.7.0.0", + "version": "0.8.0.0", "description": "zkROM source code", "main": "index.js", "scripts": {