From af76cfb218cf72cdf96477f626eceb4f28dec530 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Tue, 7 May 2024 13:49:40 +0200 Subject: [PATCH 1/5] Test for len bytes optimization --- test/get-len-bytes.zkasm | 110 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 test/get-len-bytes.zkasm diff --git a/test/get-len-bytes.zkasm b/test/get-len-bytes.zkasm new file mode 100644 index 00000000..3f878ab1 --- /dev/null +++ b/test/get-len-bytes.zkasm @@ -0,0 +1,110 @@ +VAR GLOBAL test + +;; Comments 'readPush' function +; @info Read bytes opcode PUSHX +; @internalParam {numBlocks} 4 bytes blocks to read +; @internalParam {leftBytes} remaining bytes +; @in D => bytes to read +; @out E => value read + +start: + ; init vars + 0 => HASHPOS + 1 => D + $${var rounds} + + 0x0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20n => B :CALL(getLenBytes) + 32 :ASSERT + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 32 :ASSERT + 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 31 :ASSERT + 0x004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 31 :ASSERT + 0x00004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 30 :ASSERT + 0x00000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 29 :ASSERT + 0x0000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 28 :ASSERT + 0x000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 27 :ASSERT + 0x00000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 26 :ASSERT + 0x0000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 25 :ASSERT + 0x000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 24 :ASSERT + 0x00000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 23 :ASSERT + 0x0000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 22 :ASSERT + 0x000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 21 :ASSERT + 0x00000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 20 :ASSERT + 0x0000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 19 :ASSERT + 0x000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 18 :ASSERT + 0x00000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 17 :ASSERT + 0x0000000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 16 :ASSERT + 0x000000000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 15 :ASSERT + 0x00000000000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 14 :ASSERT + 0x0000000000000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 13 :ASSERT + 0x000000000000000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 12 :ASSERT + 0x00000000000000000000000000000000000000000004FFFFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 11 :ASSERT + 0x0000000000000000000000000000000000000000000004FFFFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 10 :ASSERT + 0x000000000000000000000000000000000000000000000004FFFFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 9 :ASSERT + 0x00000000000000000000000000000000000000000000000004FFFFFFFFFFFFFFn => B :CALL(getLenBytes) + 8 :ASSERT + 0x0000000000000000000000000000000000000000000000000004FFFFFFFFFFFFn => B :CALL(getLenBytes) + 7 :ASSERT + 0x000000000000000000000000000000000000000000000000000004FFFFFFFFFFn => B :CALL(getLenBytes) + 6 :ASSERT + 0x00000000000000000000000000000000000000000000000000000004FFFFFFFFn => B :CALL(getLenBytes) + 5 :ASSERT + 0x0000000000000000000000000000000000000000000000000000000004FFFFFFn => B :CALL(getLenBytes) + 4 :ASSERT + 0x000000000000000000000000000000000000000000000000000000000004FFFFn => B :CALL(getLenBytes) + 3 :ASSERT + 0x00000000000000000000000000000000000000000000000000000000000004FFn => B :CALL(getLenBytes) + 2 :ASSERT + 0x00000000000000000000000000000000000000000000000000000000000001FFn => B :CALL(getLenBytes) + 2 :ASSERT + 0x000000000000000000000000000000000000000000000000000000000000FFFFn => B :CALL(getLenBytes) + 2 :ASSERT + 0x0000000000000000000000000000000000000000000000000000000000000004n => B :CALL(getLenBytes) + 1 :ASSERT + 0x00000000000000000000000000000000000000000000000000000000000000FFn => B :CALL(getLenBytes) + 1 :ASSERT + 0x000000000000000000000000000000000000000000000000000000000000000Fn => B :CALL(getLenBytes) + 1 :ASSERT + 0x0000000000000000000000000000000000000000000000000000000000000000n => B :CALL(getLenBytes) + 0 :ASSERT + + :JMP(finalizeExecution) + +initLoop: + $${rounds = 32} + 0 => B ; to allow $$ + +loopAdd32Byte: + $${rounds = rounds - 1} + 0 => E + ${(A >> (rounds * 8)) & 0xFF} => E :HASHP1(E) + ${rounds} :JMPZ(endLoop, loopAdd32Byte) + +endLoop: + :RETURN + +INCLUDE "../main/main.zkasm" From aa9092792e20564a91e53d01113ec93fb9c695eb Mon Sep 17 00:00:00 2001 From: Ignasi Date: Wed, 8 May 2024 10:31:25 +0200 Subject: [PATCH 2/5] getLenBytes optimization --- main/utils.zkasm | 150 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 125 insertions(+), 25 deletions(-) diff --git a/main/utils.zkasm b/main/utils.zkasm index 48d25adf..d810accc 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -23,31 +23,131 @@ absIsNeg: ; @out A => bytes length getLenBytes: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) - ; store current registries - :SAVE(B,C,D,E,RR,RCX) - ; set C as counter to 0 - 0 => C - B => A - -getLenBytesLoop: - ; checks zk-counters - %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) - - 0 => B - ; if A is zero, finish counter - $ :EQ,JMPC(getLenEnd) - ; right shift one byte - 1 => D :CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] - ; increase counter - C + 1 => C :JMP(getLenBytesLoop) - -getLenEnd: - ; counter to A - C => A - ; recover registries - :RESTORE, RETURN + %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep), SAVE(B,C,D,E,RR,RCX) + ; Check length slot by slot starting with slot 7 + ;[7], [6], [5], [4], [3], [2], [1], [0] + ;[6], [5], [4], [3], [2], [1], [0], [7] -> ROTL_C + B => C + ROTL_C :JMPZ(checkSlot6) ; length less than 29 bytes + ROTL_C - 0x00000100 :JMPN(lenBytes29) + ROTL_C - 0x00010000 :JMPN(lenBytes30) + ROTL_C - 0x01000000 :JMPN(lenBytes31, lenBytes32) + +checkSlot6: + ROTL_C => C + ROTL_C :JMPZ(checkSlot5) + ROTL_C - 0x00000100 :JMPN(lenBytes25) + ROTL_C - 0x00010000 :JMPN(lenBytes26) + ROTL_C - 0x01000000 :JMPN(lenBytes27, lenBytes28) + +checkSlot5: + ROTL_C => C + ROTL_C :JMPZ(checkSlot4) + ROTL_C - 0x00000100 :JMPN(lenBytes21) + ROTL_C - 0x00010000 :JMPN(lenBytes22) + ROTL_C - 0x01000000 :JMPN(lenBytes23, lenBytes24) + +checkSlot4: + ROTL_C => C + ROTL_C :JMPZ(checkSlot3) + ROTL_C - 0x00000100 :JMPN(lenBytes17) + ROTL_C - 0x00010000 :JMPN(lenBytes18) + ROTL_C - 0x01000000 :JMPN(lenBytes19, lenBytes20) + +checkSlot3: + ROTL_C => C + ROTL_C :JMPZ(checkSlot2) + ROTL_C - 0x00000100 :JMPN(lenBytes13) + ROTL_C - 0x00010000 :JMPN(lenBytes14) + ROTL_C - 0x01000000 :JMPN(lenBytes15, lenBytes16) + +checkSlot2: + ROTL_C => C + ROTL_C :JMPZ(checkSlot1) + ROTL_C - 0x00000100 :JMPN(lenBytes9) + ROTL_C - 0x00010000 :JMPN(lenBytes10) + ROTL_C - 0x01000000 :JMPN(lenBytes11, lenBytes12) + +checkSlot1: + ROTL_C => C + ROTL_C :JMPZ(checkSlot0) + ROTL_C - 0x00000100 :JMPN(lenBytes5) + ROTL_C - 0x00010000 :JMPN(lenBytes6) + ROTL_C - 0x01000000 :JMPN(lenBytes7, lenBytes8) + +checkSlot0: + ROTL_C => C + ROTL_C :JMPZ(lenBytes0) + ROTL_C - 0x00000100 :JMPN(lenBytes1) + ROTL_C - 0x00010000 :JMPN(lenBytes2) + ROTL_C - 0x01000000 :JMPN(lenBytes3, lenBytes4) + +lenBytes32: + 32 => A :RESTORE, RETURN +lenBytes31: + 31 => A :RESTORE, RETURN +lenBytes30: + 30 => A :RESTORE, RETURN +lenBytes29: + 29 => A :RESTORE, RETURN +lenBytes28: + 28 => A :RESTORE, RETURN +lenBytes27: + 27 => A :RESTORE, RETURN +lenBytes26: + 26 => A :RESTORE, RETURN +lenBytes25: + 25 => A :RESTORE, RETURN +lenBytes24: + 24 => A :RESTORE, RETURN +lenBytes23: + 23 => A :RESTORE, RETURN +lenBytes22: + 22 => A :RESTORE, RETURN +lenBytes21: + 21 => A :RESTORE, RETURN +lenBytes20: + 20 => A :RESTORE, RETURN +lenBytes19: + 19 => A :RESTORE, RETURN +lenBytes18: + 18 => A :RESTORE, RETURN +lenBytes17: + 17 => A :RESTORE, RETURN +lenBytes16: + 16 => A :RESTORE, RETURN +lenBytes15: + 15 => A :RESTORE, RETURN +lenBytes14: + 14 => A :RESTORE, RETURN +lenBytes13: + 13 => A :RESTORE, RETURN +lenBytes12: + 12 => A :RESTORE, RETURN +lenBytes11: + 11 => A :RESTORE, RETURN +lenBytes10: + 10 => A :RESTORE, RETURN +lenBytes9: + 9 => A :RESTORE, RETURN +lenBytes8: + 8 => A :RESTORE, RETURN +lenBytes7: + 7 => A :RESTORE, RETURN +lenBytes6: + 6 => A :RESTORE, RETURN +lenBytes5: + 5 => A :RESTORE, RETURN +lenBytes4: + 4 => A :RESTORE, RETURN +lenBytes3: + 3 => A :RESTORE, RETURN +lenBytes2: + 2 => A :RESTORE, RETURN +lenBytes1: + 1 => A :RESTORE, RETURN +lenBytes0: + 0 => A :RESTORE, RETURN ; @info bits length of B ; @in B => number From 09365d8e932ed537119dcfee34c3a824fd6f7e8a Mon Sep 17 00:00:00 2001 From: Ignasi Date: Wed, 8 May 2024 15:52:42 +0200 Subject: [PATCH 3/5] Separate utils + len opt --- main/load-tx-rlp.zkasm | 3 +- main/utils.zkasm | 878 +------------------------- main/utils/compute-merkle-proof.zkasm | 579 +++++++++++++++++ main/utils/get-len-bytes.zkasm | 130 ++++ main/utils/read-push.zkasm | 162 +++++ 5 files changed, 877 insertions(+), 875 deletions(-) create mode 100644 main/utils/compute-merkle-proof.zkasm create mode 100644 main/utils/get-len-bytes.zkasm create mode 100644 main/utils/read-push.zkasm diff --git a/main/load-tx-rlp.zkasm b/main/load-tx-rlp.zkasm index 08305f6a..4693dd8e 100644 --- a/main/load-tx-rlp.zkasm +++ b/main/load-tx-rlp.zkasm @@ -93,8 +93,7 @@ nonce0: 0 => A :MSTORE(lengthNonce), JMP(endNonce) shortNonce: - A - 0x80 => D - D :MSTORE(lengthNonce),CALL(addHashTx) + A - 0x80 => D :MSTORE(lengthNonce),CALL(addHashTx) :CALL(checkShortRLP) :CALL(checkNonLeadingZeros) diff --git a/main/utils.zkasm b/main/utils.zkasm index d810accc..710196c3 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -18,136 +18,6 @@ absIsNeg: $ => A :SUB 1 => B :RETURN -; @info byte length of B -; @in B => number -; @out A => bytes length -getLenBytes: - ; checks zk-counters - %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep), SAVE(B,C,D,E,RR,RCX) - ; Check length slot by slot starting with slot 7 - ;[7], [6], [5], [4], [3], [2], [1], [0] - ;[6], [5], [4], [3], [2], [1], [0], [7] -> ROTL_C - B => C - ROTL_C :JMPZ(checkSlot6) ; length less than 29 bytes - ROTL_C - 0x00000100 :JMPN(lenBytes29) - ROTL_C - 0x00010000 :JMPN(lenBytes30) - ROTL_C - 0x01000000 :JMPN(lenBytes31, lenBytes32) - -checkSlot6: - ROTL_C => C - ROTL_C :JMPZ(checkSlot5) - ROTL_C - 0x00000100 :JMPN(lenBytes25) - ROTL_C - 0x00010000 :JMPN(lenBytes26) - ROTL_C - 0x01000000 :JMPN(lenBytes27, lenBytes28) - -checkSlot5: - ROTL_C => C - ROTL_C :JMPZ(checkSlot4) - ROTL_C - 0x00000100 :JMPN(lenBytes21) - ROTL_C - 0x00010000 :JMPN(lenBytes22) - ROTL_C - 0x01000000 :JMPN(lenBytes23, lenBytes24) - -checkSlot4: - ROTL_C => C - ROTL_C :JMPZ(checkSlot3) - ROTL_C - 0x00000100 :JMPN(lenBytes17) - ROTL_C - 0x00010000 :JMPN(lenBytes18) - ROTL_C - 0x01000000 :JMPN(lenBytes19, lenBytes20) - -checkSlot3: - ROTL_C => C - ROTL_C :JMPZ(checkSlot2) - ROTL_C - 0x00000100 :JMPN(lenBytes13) - ROTL_C - 0x00010000 :JMPN(lenBytes14) - ROTL_C - 0x01000000 :JMPN(lenBytes15, lenBytes16) - -checkSlot2: - ROTL_C => C - ROTL_C :JMPZ(checkSlot1) - ROTL_C - 0x00000100 :JMPN(lenBytes9) - ROTL_C - 0x00010000 :JMPN(lenBytes10) - ROTL_C - 0x01000000 :JMPN(lenBytes11, lenBytes12) - -checkSlot1: - ROTL_C => C - ROTL_C :JMPZ(checkSlot0) - ROTL_C - 0x00000100 :JMPN(lenBytes5) - ROTL_C - 0x00010000 :JMPN(lenBytes6) - ROTL_C - 0x01000000 :JMPN(lenBytes7, lenBytes8) - -checkSlot0: - ROTL_C => C - ROTL_C :JMPZ(lenBytes0) - ROTL_C - 0x00000100 :JMPN(lenBytes1) - ROTL_C - 0x00010000 :JMPN(lenBytes2) - ROTL_C - 0x01000000 :JMPN(lenBytes3, lenBytes4) - -lenBytes32: - 32 => A :RESTORE, RETURN -lenBytes31: - 31 => A :RESTORE, RETURN -lenBytes30: - 30 => A :RESTORE, RETURN -lenBytes29: - 29 => A :RESTORE, RETURN -lenBytes28: - 28 => A :RESTORE, RETURN -lenBytes27: - 27 => A :RESTORE, RETURN -lenBytes26: - 26 => A :RESTORE, RETURN -lenBytes25: - 25 => A :RESTORE, RETURN -lenBytes24: - 24 => A :RESTORE, RETURN -lenBytes23: - 23 => A :RESTORE, RETURN -lenBytes22: - 22 => A :RESTORE, RETURN -lenBytes21: - 21 => A :RESTORE, RETURN -lenBytes20: - 20 => A :RESTORE, RETURN -lenBytes19: - 19 => A :RESTORE, RETURN -lenBytes18: - 18 => A :RESTORE, RETURN -lenBytes17: - 17 => A :RESTORE, RETURN -lenBytes16: - 16 => A :RESTORE, RETURN -lenBytes15: - 15 => A :RESTORE, RETURN -lenBytes14: - 14 => A :RESTORE, RETURN -lenBytes13: - 13 => A :RESTORE, RETURN -lenBytes12: - 12 => A :RESTORE, RETURN -lenBytes11: - 11 => A :RESTORE, RETURN -lenBytes10: - 10 => A :RESTORE, RETURN -lenBytes9: - 9 => A :RESTORE, RETURN -lenBytes8: - 8 => A :RESTORE, RETURN -lenBytes7: - 7 => A :RESTORE, RETURN -lenBytes6: - 6 => A :RESTORE, RETURN -lenBytes5: - 5 => A :RESTORE, RETURN -lenBytes4: - 4 => A :RESTORE, RETURN -lenBytes3: - 3 => A :RESTORE, RETURN -lenBytes2: - 2 => A :RESTORE, RETURN -lenBytes1: - 1 => A :RESTORE, RETURN -lenBytes0: - 0 => A :RESTORE, RETURN ; @info bits length of B ; @in B => number @@ -866,169 +736,6 @@ invalidCall: $ => PC :MLOAD(lastPC) 0 :MSTORE(SP++), JMP(readCode) -VAR GLOBAL pushBytes -VAR GLOBAL pushBytes_RR -; @info Read bytes opcode PUSHX -; @internalParam {numBlocks} 4 bytes blocks to read -; @internalParam {leftBytes} remaining bytes -; @in D,E => bytes to read (1..32) -; @out E => value read - -readPush: - :JMP(@readPush+E) ;0 -readPush1: - PC => HASHPOS :JMP(_readPush1) ;1 -readPush2: - PC => HASHPOS :JMP(_readPush2) ;2 -readPush3: - PC => HASHPOS :JMP(_readPush3) ;3 -readPush4: - PC => HASHPOS :JMP(_readPush4) ;4 -readPush5: - PC => HASHPOS :JMP(_readPushX) ;5 -readPush6: - PC => HASHPOS :JMP(_readPushX) ;6 -readPush7: - PC => HASHPOS :JMP(_readPushX) ;7 -readPush8: - PC => HASHPOS :JMP(_readPushX) ;8 -readPush9: - PC => HASHPOS :JMP(_readPushX) ;9 -readPush10: - PC => HASHPOS :JMP(_readPushX) ;10 -readPush11: - PC => HASHPOS :JMP(_readPushX) ;11 -readPush12: - PC => HASHPOS :JMP(_readPushX) ;12 -readPush13: - PC => HASHPOS :JMP(_readPushX) ;13 -readPush14: - PC => HASHPOS :JMP(_readPushX) ;14 -readPush15: - PC => HASHPOS :JMP(_readPushX) ;15 -readPush16: - PC => HASHPOS :JMP(_readPushX) ;16 -readPush17: - PC => HASHPOS :JMP(_readPushX) ;17 -readPush18: - PC => HASHPOS :JMP(_readPushX) ;18 -readPush19: - PC => HASHPOS :JMP(_readPushX) ;19 -readPush20: - PC => HASHPOS :JMP(_readPushX) ;20 -readPush21: - PC => HASHPOS :JMP(_readPushX) ;21 -readPush22: - PC => HASHPOS :JMP(_readPushX) ;22 -readPush23: - PC => HASHPOS :JMP(_readPushX) ;23 -readPush24: - PC => HASHPOS :JMP(_readPushX) ;24 -readPush25: - PC => HASHPOS :JMP(_readPushX) ;25 -readPush26: - PC => HASHPOS :JMP(_readPushX) ;26 -readPush27: - PC => HASHPOS :JMP(_readPushX) ;27 -readPush28: - PC => HASHPOS :JMP(_readPushX) ;28 -readPush29: - PC => HASHPOS :JMP(_readPushX) ;29 -readPush30: - PC => HASHPOS :JMP(_readPushX) ;30 -readPush31: - PC => HASHPOS :JMP(_readPushX) ;31 -readPush32: - PC => HASHPOS :JMP(_readPush32) ;32 - -_readPush1: - $ => E :MLOAD(contractHashId) - $ => E :HASHP1(E),RETURN - -_readPush2: - $ => E :MLOAD(contractHashId) - $ => C :HASHP1(E) - C * 256 + $ => E :F_HASHP1(E), RETURN - -_readPush3: - $ => E :MLOAD(contractHashId) - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => E :F_HASHP1(E), RETURN - -_readPush4: - $ => E :MLOAD(contractHashId) - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => E :F_HASHP1(E), RETURN - -_readPush32: - $ => E :MLOAD(contractHashId) - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => C :F_HASHP1(E) - - ; 28 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => C :F_HASHP1(E) - - ; 24 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => C :F_HASHP1(E) - - ; 20 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => C :F_HASHP1(E) - - ; 16 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => C :F_HASHP1(E) - - ; 12 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => C :F_HASHP1(E) - - ; 8 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => C :F_HASHP1(E) - - ; 4 bytes - - $ => A :HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - A * 256 + $ => A :F_HASHP1(E) - ROTL_C + A * 256 + $ => E :F_HASHP1(E),RETURN - -_readPushBaseTable: - -_readPushX: - $ => B :MLOAD(contractHashId) - -readPushBytes: - 0 => A, C - B => E :JMP(@_readPushBaseTable - E) - VAR GLOBAL startsWithEF ; @info check bytecode first byte != 0xEF as defined in EIP-3541 (https://eips.ethereum.org/EIPS/eip-3541) ; @internalParam {memOffset} memory offset to read bytes from @@ -1316,585 +1023,6 @@ expADend: failAssert: A - 1 :ASSERT -VAR GLOBAL tmpZkPCComputeMerkleProof -;@info Computes merkle root with from currentL1InfoTreeRoot, currentL1InfoTreeIndex and siblings -;@out C: merkle tree root -computeMerkleProof: - ; check zk-counters - ; 1 keccak for the leaf and 32 for the L1InfoTree - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - 33 :JMPN(outOfCountersKeccak) - ; 7 steps at most per bit + 21 statics - %MAX_CNT_STEPS - STEP - 7 * 32 - 21 :JMPN(outOfCountersStep) - - RR :MSTORE(tmpZkPCComputeMerkleProof) - ; initialization registers for smt verify - 0 => D, A - - $ => B :MLOAD(currentL1InfoTreeIndex) - $ => C :MLOAD(currentL1InfoTreeRoot) - ; prepare new hash - $ => E :MLOAD(nextHashKId) - E + 1 :MSTORE(nextHashKId) - 32 => D - - ; - Start loop 32 levels: - ; - provide each 'indexL1InfoTree' bit to either hash left/right the merkle tree nodes - ; - compute linear combination of 'indexL1InfoTree' bits to match the 'indexL1InfoTree' itself at the end of the loop - - ; BIT 0 - 0 => HASHPOS - ${B & 0x00000001} :JMPZ(hashLeft0) - -hashRight0: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 0)} :HASHK(E+0) - C :HASHK(E+0) - A + 0x00000001 => A :JMP(hashBranchEnd0) - -hashLeft0: - C :HASHK(E+0) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 0)} :HASHK(E+0) - -hashBranchEnd0: - HASHPOS :HASHKLEN(E+0) - $ => C :HASHKDIGEST(E+0) - - ; BIT 1 - 0 => HASHPOS - ${B & 0x00000002} :JMPZ(hashLeft1) - -hashRight1: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 1)} :HASHK(E+1) - C :HASHK(E+1) - A + 0x00000002 => A :JMP(hashBranchEnd1) - -hashLeft1: - C :HASHK(E+1) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 1)} :HASHK(E+1) - -hashBranchEnd1: - HASHPOS :HASHKLEN(E+1) - $ => C :HASHKDIGEST(E+1) - - ; BIT 2 - 0 => HASHPOS - ${B & 0x00000004} :JMPZ(hashLeft2) - -hashRight2: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 2)} :HASHK(E+2) - C :HASHK(E+2) - A + 0x00000004 => A :JMP(hashBranchEnd2) - -hashLeft2: - C :HASHK(E+2) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 2)} :HASHK(E+2) - -hashBranchEnd2: - HASHPOS :HASHKLEN(E+2) - $ => C :HASHKDIGEST(E+2) - - ; BIT 3 - 0 => HASHPOS - ${B & 0x00000008} :JMPZ(hashLeft3) - -hashRight3: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 3)} :HASHK(E+3) - C :HASHK(E+3) - A + 0x00000008 => A :JMP(hashBranchEnd3) - -hashLeft3: - C :HASHK(E+3) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 3)} :HASHK(E+3) - -hashBranchEnd3: - HASHPOS :HASHKLEN(E+3) - $ => C :HASHKDIGEST(E+3) - - ; BIT 4 - 0 => HASHPOS - ${B & 0x00000010} :JMPZ(hashLeft4) - -hashRight4: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 4)} :HASHK(E+4) - C :HASHK(E+4) - A + 0x00000010 => A :JMP(hashBranchEnd4) - -hashLeft4: - C :HASHK(E+4) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 4)} :HASHK(E+4) - -hashBranchEnd4: - HASHPOS :HASHKLEN(E+4) - $ => C :HASHKDIGEST(E+4) - - ; BIT 5 - 0 => HASHPOS - ${B & 0x00000020} :JMPZ(hashLeft5) - -hashRight5: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 5)} :HASHK(E+5) - C :HASHK(E+5) - A + 0x00000020 => A :JMP(hashBranchEnd5) - -hashLeft5: - C :HASHK(E+5) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 5)} :HASHK(E+5) - -hashBranchEnd5: - HASHPOS :HASHKLEN(E+5) - $ => C :HASHKDIGEST(E+5) - - ; BIT 6 - 0 => HASHPOS - ${B & 0x00000040} :JMPZ(hashLeft6) - -hashRight6: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 6)} :HASHK(E+6) - C :HASHK(E+6) - A + 0x00000040 => A :JMP(hashBranchEnd6) - -hashLeft6: - C :HASHK(E+6) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 6)} :HASHK(E+6) - -hashBranchEnd6: - HASHPOS :HASHKLEN(E+6) - $ => C :HASHKDIGEST(E+6) - - ; BIT 7 - 0 => HASHPOS - ${B & 0x00000080} :JMPZ(hashLeft7) - -hashRight7: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 7)} :HASHK(E+7) - C :HASHK(E+7) - A + 0x00000080 => A :JMP(hashBranchEnd7) - -hashLeft7: - C :HASHK(E+7) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 7)} :HASHK(E+7) - -hashBranchEnd7: - HASHPOS :HASHKLEN(E+7) - $ => C :HASHKDIGEST(E+7) - - ; BIT 8 - 0 => HASHPOS - ${B & 0x00000100} :JMPZ(hashLeft8) - -hashRight8: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 8)} :HASHK(E+8) - C :HASHK(E+8) - A + 0x00000100 => A :JMP(hashBranchEnd8) - -hashLeft8: - C :HASHK(E+8) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 8)} :HASHK(E+8) - -hashBranchEnd8: - HASHPOS :HASHKLEN(E+8) - $ => C :HASHKDIGEST(E+8) - - ; BIT 9 - 0 => HASHPOS - ${B & 0x00000200} :JMPZ(hashLeft9) - -hashRight9: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 9)} :HASHK(E+9) - C :HASHK(E+9) - A + 0x00000200 => A :JMP(hashBranchEnd9) - -hashLeft9: - C :HASHK(E+9) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 9)} :HASHK(E+9) - -hashBranchEnd9: - HASHPOS :HASHKLEN(E+9) - $ => C :HASHKDIGEST(E+9) - - ; BIT 10 - 0 => HASHPOS - ${B & 0x00000400} :JMPZ(hashLeft10) - -hashRight10: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 10)} :HASHK(E+10) - C :HASHK(E+10) - A + 0x00000400 => A :JMP(hashBranchEnd10) - -hashLeft10: - C :HASHK(E+10) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 10)} :HASHK(E+10) - -hashBranchEnd10: - HASHPOS :HASHKLEN(E+10) - $ => C :HASHKDIGEST(E+10) - - ; BIT 11 - 0 => HASHPOS - ${B & 0x00000800} :JMPZ(hashLeft11) - -hashRight11: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 11)} :HASHK(E+11) - C :HASHK(E+11) - A + 0x00000800 => A :JMP(hashBranchEnd11) - -hashLeft11: - C :HASHK(E+11) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 11)} :HASHK(E+11) - -hashBranchEnd11: - HASHPOS :HASHKLEN(E+11) - $ => C :HASHKDIGEST(E+11) - - - ; BIT 12 - 0 => HASHPOS - ${B & 0x00001000} :JMPZ(hashLeft12) - -hashRight12: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 12)} :HASHK(E+12) - C :HASHK(E+12) - A + 0x00001000 => A :JMP(hashBranchEnd12) - -hashLeft12: - C :HASHK(E+12) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 12)} :HASHK(E+12) - -hashBranchEnd12: - HASHPOS :HASHKLEN(E+12) - $ => C :HASHKDIGEST(E+12) - - ; BIT 13 - 0 => HASHPOS - ${B & 0x00002000} :JMPZ(hashLeft13) - -hashRight13: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 13)} :HASHK(E+13) - C :HASHK(E+13) - A + 0x00002000 => A :JMP(hashBranchEnd13) - -hashLeft13: - C :HASHK(E+13) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 13)} :HASHK(E+13) - -hashBranchEnd13: - HASHPOS :HASHKLEN(E+13) - $ => C :HASHKDIGEST(E+13) - - ; BIT 14 - 0 => HASHPOS - ${B & 0x00004000} :JMPZ(hashLeft14) - -hashRight14: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 14)} :HASHK(E+14) - C :HASHK(E+14) - A + 0x00004000 => A :JMP(hashBranchEnd14) - -hashLeft14: - C :HASHK(E+14) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 14)} :HASHK(E+14) - -hashBranchEnd14: - HASHPOS :HASHKLEN(E+14) - $ => C :HASHKDIGEST(E+14) - - ; BIT 15 - 0 => HASHPOS - ${B & 0x00008000} :JMPZ(hashLeft15) - -hashRight15: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 15)} :HASHK(E+15) - C :HASHK(E+15) - A + 0x00008000 => A :JMP(hashBranchEnd15) - -hashLeft15: - C :HASHK(E+15) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 15)} :HASHK(E+15) - -hashBranchEnd15: - HASHPOS :HASHKLEN(E+15) - $ => C :HASHKDIGEST(E+15) - - ; BIT 16 - 0 => HASHPOS - ${B & 0x00010000} :JMPZ(hashLeft16) - -hashRight16: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 16)} :HASHK(E+16) - C :HASHK(E+16) - A + 0x00010000 => A :JMP(hashBranchEnd16) - -hashLeft16: - C :HASHK(E+16) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 16)} :HASHK(E+16) - -hashBranchEnd16: - HASHPOS :HASHKLEN(E+16) - $ => C :HASHKDIGEST(E+16) - - ; BIT 17 - 0 => HASHPOS - ${B & 0x00020000} :JMPZ(hashLeft17) - -hashRight17: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 17)} :HASHK(E+17) - C :HASHK(E+17) - A + 0x00020000 => A :JMP(hashBranchEnd17) - -hashLeft17: - C :HASHK(E+17) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 17)} :HASHK(E+17) - -hashBranchEnd17: - HASHPOS :HASHKLEN(E+17) - $ => C :HASHKDIGEST(E+17) - - ; BIT 18 - 0 => HASHPOS - ${B & 0x00040000} :JMPZ(hashLeft18) - -hashRight18: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 18)} :HASHK(E+18) - C :HASHK(E+18) - A + 0x00040000 => A :JMP(hashBranchEnd18) - -hashLeft18: - C :HASHK(E+18) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 18)} :HASHK(E+18) - -hashBranchEnd18: - HASHPOS :HASHKLEN(E+18) - $ => C :HASHKDIGEST(E+18) - - ; BIT 19 - 0 => HASHPOS - ${B & 0x00080000} :JMPZ(hashLeft19) - -hashRight19: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 19)} :HASHK(E+19) - C :HASHK(E+19) - A + 0x00080000 => A :JMP(hashBranchEnd19) - -hashLeft19: - C :HASHK(E+19) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 19)} :HASHK(E+19) - -hashBranchEnd19: - HASHPOS :HASHKLEN(E+19) - $ => C :HASHKDIGEST(E+19) - - ; BIT 20 - 0 => HASHPOS - ${B & 0x00100000} :JMPZ(hashLeft20) - -hashRight20: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 20)} :HASHK(E+20) - C :HASHK(E+20) - A + 0x00100000 => A :JMP(hashBranchEnd20) - -hashLeft20: - C :HASHK(E+20) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 20)} :HASHK(E+20) - -hashBranchEnd20: - HASHPOS :HASHKLEN(E+20) - $ => C :HASHKDIGEST(E+20) - - ; BIT 21 - 0 => HASHPOS - ${B & 0x00200000} :JMPZ(hashLeft21) - -hashRight21: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 21)} :HASHK(E+21) - C :HASHK(E+21) - A + 0x00200000 => A :JMP(hashBranchEnd21) - -hashLeft21: - C :HASHK(E+21) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 21)} :HASHK(E+21) - -hashBranchEnd21: - HASHPOS :HASHKLEN(E+21) - $ => C :HASHKDIGEST(E+21) - - ; BIT 22 - 0 => HASHPOS - ${B & 0x00400000} :JMPZ(hashLeft22) - -hashRight22: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 22)} :HASHK(E+22) - C :HASHK(E+22) - A + 0x00400000 => A :JMP(hashBranchEnd22) - -hashLeft22: - C :HASHK(E+22) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 22)} :HASHK(E+22) - -hashBranchEnd22: - HASHPOS :HASHKLEN(E+22) - $ => C :HASHKDIGEST(E+22) - - ; BIT 23 - 0 => HASHPOS - ${B & 0x00800000} :JMPZ(hashLeft23) - -hashRight23: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 23)} :HASHK(E+23) - C :HASHK(E+23) - A + 0x00800000 => A :JMP(hashBranchEnd23) - -hashLeft23: - C :HASHK(E+23) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 23)} :HASHK(E+23) - -hashBranchEnd23: - HASHPOS :HASHKLEN(E+23) - $ => C :HASHKDIGEST(E+23) - - ; BIT 24 - 0 => HASHPOS - ${B & 0x01000000} :JMPZ(hashLeft24) - -hashRight24: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 24)} :HASHK(E+24) - C :HASHK(E+24) - A + 0x01000000 => A :JMP(hashBranchEnd24) - -hashLeft24: - C :HASHK(E+24) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 24)} :HASHK(E+24) - -hashBranchEnd24: - HASHPOS :HASHKLEN(E+24) - $ => C :HASHKDIGEST(E+24) - - ; BIT 25 - 0 => HASHPOS - ${B & 0x02000000} :JMPZ(hashLeft25) - -hashRight25: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 25)} :HASHK(E+25) - C :HASHK(E+25) - A + 0x02000000 => A :JMP(hashBranchEnd25) - -hashLeft25: - C :HASHK(E+25) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 25)} :HASHK(E+25) - -hashBranchEnd25: - HASHPOS :HASHKLEN(E+25) - $ => C :HASHKDIGEST(E+25) - - ; BIT 26 - 0 => HASHPOS - ${B & 0x04000000} :JMPZ(hashLeft26) - -hashRight26: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 26)} :HASHK(E+26) - C :HASHK(E+26) - A + 0x04000000 => A :JMP(hashBranchEnd26) - -hashLeft26: - C :HASHK(E+26) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 26)} :HASHK(E+26) - -hashBranchEnd26: - HASHPOS :HASHKLEN(E+26) - $ => C :HASHKDIGEST(E+26) - - ; BIT 27 - 0 => HASHPOS - ${B & 0x08000000} :JMPZ(hashLeft27) - -hashRight27: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 27)} :HASHK(E+27) - C :HASHK(E+27) - A + 0x08000000 => A :JMP(hashBranchEnd27) - -hashLeft27: - C :HASHK(E+27) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 27)} :HASHK(E+27) - -hashBranchEnd27: - HASHPOS :HASHKLEN(E+27) - $ => C :HASHKDIGEST(E+27) - - ; BIT 28 - 0 => HASHPOS - ${B & 0x10000000} :JMPZ(hashLeft28) - -hashRight28: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 28)} :HASHK(E+28) - C :HASHK(E+28) - A + 0x10000000 => A :JMP(hashBranchEnd28) - -hashLeft28: - C :HASHK(E+28) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 28)} :HASHK(E+28) - -hashBranchEnd28: - HASHPOS :HASHKLEN(E+28) - $ => C :HASHKDIGEST(E+28) - - ; BIT 29 - 0 => HASHPOS - ${B & 0x20000000} :JMPZ(hashLeft29) - -hashRight29: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 29)} :HASHK(E+29) - C :HASHK(E+29) - A + 0x20000000 => A :JMP(hashBranchEnd29) - -hashLeft29: - C :HASHK(E+29) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 29)} :HASHK(E+29) - -hashBranchEnd29: - HASHPOS :HASHKLEN(E+29) - $ => C :HASHKDIGEST(E+29) - - ; BIT 30 - 0 => HASHPOS - ${B & 0x40000000} :JMPZ(hashLeft30) - -hashRight30: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 30)} :HASHK(E+30) - C :HASHK(E+30) - A + 0x40000000 => A :JMP(hashBranchEnd30) - -hashLeft30: - C :HASHK(E+30) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 30)} :HASHK(E+30) - -hashBranchEnd30: - HASHPOS :HASHKLEN(E+30) - $ => C :HASHKDIGEST(E+30) - - ; BIT 31 - 0 => HASHPOS - ${B & 0x80000000} :JMPZ(hashLeft31) - -hashRight31: - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 31)} :HASHK(E+31) - C :HASHK(E+31) - A + 0x80000000 => A :JMP(hashBranchEnd31) - -hashLeft31: - C :HASHK(E+31) - ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 31)} :HASHK(E+31) - -hashBranchEnd31: - HASHPOS :HASHKLEN(E+31) - ; Merkle root at C - $ => C :HASHKDIGEST(E+31) - - ; verify linear combination of 'indexL1InfoTree' - B :ASSERT - E + 32 => E :MSTORE(nextHashKId) - -computeMerkleProofReturn: - $ => RR :MLOAD(tmpZkPCComputeMerkleProof) - :RETURN - VAR GLOBAL readXFromCalldataOffset VAR GLOBAL readXFromCalldataLength VAR GLOBAL readXFromCalldataResult @@ -1935,4 +1063,8 @@ saveCalldataPointer: ; move to current CTX and store data $ => CTX :MLOAD(currentCTX) A :MSTORE(calldataCTX) - B :MSTORE(calldataOffset), RETURN \ No newline at end of file + B :MSTORE(calldataOffset), RETURN + +INCLUDE "./utils/get-len-bytes.zkasm" +INCLUDE "./utils/read-push.zkasm" +INCLUDE "./utils/compute-merkle-proof.zkasm" \ No newline at end of file diff --git a/main/utils/compute-merkle-proof.zkasm b/main/utils/compute-merkle-proof.zkasm new file mode 100644 index 00000000..3e1a2855 --- /dev/null +++ b/main/utils/compute-merkle-proof.zkasm @@ -0,0 +1,579 @@ + +VAR GLOBAL tmpZkPCComputeMerkleProof +;@info Computes merkle root with from currentL1InfoTreeRoot, currentL1InfoTreeIndex and siblings +;@out C: merkle tree root +computeMerkleProof: + ; check zk-counters + ; 1 keccak for the leaf and 32 for the L1InfoTree + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - 33 :JMPN(outOfCountersKeccak) + ; 7 steps at most per bit + 21 statics + %MAX_CNT_STEPS - STEP - 7 * 32 - 21 :JMPN(outOfCountersStep) + + RR :MSTORE(tmpZkPCComputeMerkleProof) + ; initialization registers for smt verify + 0 => D, A + + $ => B :MLOAD(currentL1InfoTreeIndex) + $ => C :MLOAD(currentL1InfoTreeRoot) + ; prepare new hash + $ => E :MLOAD(nextHashKId) + E + 1 :MSTORE(nextHashKId) + 32 => D + + ; - Start loop 32 levels: + ; - provide each 'indexL1InfoTree' bit to either hash left/right the merkle tree nodes + ; - compute linear combination of 'indexL1InfoTree' bits to match the 'indexL1InfoTree' itself at the end of the loop + + ; BIT 0 + 0 => HASHPOS + ${B & 0x00000001} :JMPZ(hashLeft0) + +hashRight0: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 0)} :HASHK(E+0) + C :HASHK(E+0) + A + 0x00000001 => A :JMP(hashBranchEnd0) + +hashLeft0: + C :HASHK(E+0) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 0)} :HASHK(E+0) + +hashBranchEnd0: + HASHPOS :HASHKLEN(E+0) + $ => C :HASHKDIGEST(E+0) + + ; BIT 1 + 0 => HASHPOS + ${B & 0x00000002} :JMPZ(hashLeft1) + +hashRight1: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 1)} :HASHK(E+1) + C :HASHK(E+1) + A + 0x00000002 => A :JMP(hashBranchEnd1) + +hashLeft1: + C :HASHK(E+1) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 1)} :HASHK(E+1) + +hashBranchEnd1: + HASHPOS :HASHKLEN(E+1) + $ => C :HASHKDIGEST(E+1) + + ; BIT 2 + 0 => HASHPOS + ${B & 0x00000004} :JMPZ(hashLeft2) + +hashRight2: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 2)} :HASHK(E+2) + C :HASHK(E+2) + A + 0x00000004 => A :JMP(hashBranchEnd2) + +hashLeft2: + C :HASHK(E+2) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 2)} :HASHK(E+2) + +hashBranchEnd2: + HASHPOS :HASHKLEN(E+2) + $ => C :HASHKDIGEST(E+2) + + ; BIT 3 + 0 => HASHPOS + ${B & 0x00000008} :JMPZ(hashLeft3) + +hashRight3: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 3)} :HASHK(E+3) + C :HASHK(E+3) + A + 0x00000008 => A :JMP(hashBranchEnd3) + +hashLeft3: + C :HASHK(E+3) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 3)} :HASHK(E+3) + +hashBranchEnd3: + HASHPOS :HASHKLEN(E+3) + $ => C :HASHKDIGEST(E+3) + + ; BIT 4 + 0 => HASHPOS + ${B & 0x00000010} :JMPZ(hashLeft4) + +hashRight4: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 4)} :HASHK(E+4) + C :HASHK(E+4) + A + 0x00000010 => A :JMP(hashBranchEnd4) + +hashLeft4: + C :HASHK(E+4) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 4)} :HASHK(E+4) + +hashBranchEnd4: + HASHPOS :HASHKLEN(E+4) + $ => C :HASHKDIGEST(E+4) + + ; BIT 5 + 0 => HASHPOS + ${B & 0x00000020} :JMPZ(hashLeft5) + +hashRight5: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 5)} :HASHK(E+5) + C :HASHK(E+5) + A + 0x00000020 => A :JMP(hashBranchEnd5) + +hashLeft5: + C :HASHK(E+5) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 5)} :HASHK(E+5) + +hashBranchEnd5: + HASHPOS :HASHKLEN(E+5) + $ => C :HASHKDIGEST(E+5) + + ; BIT 6 + 0 => HASHPOS + ${B & 0x00000040} :JMPZ(hashLeft6) + +hashRight6: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 6)} :HASHK(E+6) + C :HASHK(E+6) + A + 0x00000040 => A :JMP(hashBranchEnd6) + +hashLeft6: + C :HASHK(E+6) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 6)} :HASHK(E+6) + +hashBranchEnd6: + HASHPOS :HASHKLEN(E+6) + $ => C :HASHKDIGEST(E+6) + + ; BIT 7 + 0 => HASHPOS + ${B & 0x00000080} :JMPZ(hashLeft7) + +hashRight7: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 7)} :HASHK(E+7) + C :HASHK(E+7) + A + 0x00000080 => A :JMP(hashBranchEnd7) + +hashLeft7: + C :HASHK(E+7) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 7)} :HASHK(E+7) + +hashBranchEnd7: + HASHPOS :HASHKLEN(E+7) + $ => C :HASHKDIGEST(E+7) + + ; BIT 8 + 0 => HASHPOS + ${B & 0x00000100} :JMPZ(hashLeft8) + +hashRight8: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 8)} :HASHK(E+8) + C :HASHK(E+8) + A + 0x00000100 => A :JMP(hashBranchEnd8) + +hashLeft8: + C :HASHK(E+8) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 8)} :HASHK(E+8) + +hashBranchEnd8: + HASHPOS :HASHKLEN(E+8) + $ => C :HASHKDIGEST(E+8) + + ; BIT 9 + 0 => HASHPOS + ${B & 0x00000200} :JMPZ(hashLeft9) + +hashRight9: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 9)} :HASHK(E+9) + C :HASHK(E+9) + A + 0x00000200 => A :JMP(hashBranchEnd9) + +hashLeft9: + C :HASHK(E+9) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 9)} :HASHK(E+9) + +hashBranchEnd9: + HASHPOS :HASHKLEN(E+9) + $ => C :HASHKDIGEST(E+9) + + ; BIT 10 + 0 => HASHPOS + ${B & 0x00000400} :JMPZ(hashLeft10) + +hashRight10: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 10)} :HASHK(E+10) + C :HASHK(E+10) + A + 0x00000400 => A :JMP(hashBranchEnd10) + +hashLeft10: + C :HASHK(E+10) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 10)} :HASHK(E+10) + +hashBranchEnd10: + HASHPOS :HASHKLEN(E+10) + $ => C :HASHKDIGEST(E+10) + + ; BIT 11 + 0 => HASHPOS + ${B & 0x00000800} :JMPZ(hashLeft11) + +hashRight11: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 11)} :HASHK(E+11) + C :HASHK(E+11) + A + 0x00000800 => A :JMP(hashBranchEnd11) + +hashLeft11: + C :HASHK(E+11) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 11)} :HASHK(E+11) + +hashBranchEnd11: + HASHPOS :HASHKLEN(E+11) + $ => C :HASHKDIGEST(E+11) + + + ; BIT 12 + 0 => HASHPOS + ${B & 0x00001000} :JMPZ(hashLeft12) + +hashRight12: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 12)} :HASHK(E+12) + C :HASHK(E+12) + A + 0x00001000 => A :JMP(hashBranchEnd12) + +hashLeft12: + C :HASHK(E+12) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 12)} :HASHK(E+12) + +hashBranchEnd12: + HASHPOS :HASHKLEN(E+12) + $ => C :HASHKDIGEST(E+12) + + ; BIT 13 + 0 => HASHPOS + ${B & 0x00002000} :JMPZ(hashLeft13) + +hashRight13: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 13)} :HASHK(E+13) + C :HASHK(E+13) + A + 0x00002000 => A :JMP(hashBranchEnd13) + +hashLeft13: + C :HASHK(E+13) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 13)} :HASHK(E+13) + +hashBranchEnd13: + HASHPOS :HASHKLEN(E+13) + $ => C :HASHKDIGEST(E+13) + + ; BIT 14 + 0 => HASHPOS + ${B & 0x00004000} :JMPZ(hashLeft14) + +hashRight14: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 14)} :HASHK(E+14) + C :HASHK(E+14) + A + 0x00004000 => A :JMP(hashBranchEnd14) + +hashLeft14: + C :HASHK(E+14) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 14)} :HASHK(E+14) + +hashBranchEnd14: + HASHPOS :HASHKLEN(E+14) + $ => C :HASHKDIGEST(E+14) + + ; BIT 15 + 0 => HASHPOS + ${B & 0x00008000} :JMPZ(hashLeft15) + +hashRight15: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 15)} :HASHK(E+15) + C :HASHK(E+15) + A + 0x00008000 => A :JMP(hashBranchEnd15) + +hashLeft15: + C :HASHK(E+15) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 15)} :HASHK(E+15) + +hashBranchEnd15: + HASHPOS :HASHKLEN(E+15) + $ => C :HASHKDIGEST(E+15) + + ; BIT 16 + 0 => HASHPOS + ${B & 0x00010000} :JMPZ(hashLeft16) + +hashRight16: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 16)} :HASHK(E+16) + C :HASHK(E+16) + A + 0x00010000 => A :JMP(hashBranchEnd16) + +hashLeft16: + C :HASHK(E+16) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 16)} :HASHK(E+16) + +hashBranchEnd16: + HASHPOS :HASHKLEN(E+16) + $ => C :HASHKDIGEST(E+16) + + ; BIT 17 + 0 => HASHPOS + ${B & 0x00020000} :JMPZ(hashLeft17) + +hashRight17: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 17)} :HASHK(E+17) + C :HASHK(E+17) + A + 0x00020000 => A :JMP(hashBranchEnd17) + +hashLeft17: + C :HASHK(E+17) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 17)} :HASHK(E+17) + +hashBranchEnd17: + HASHPOS :HASHKLEN(E+17) + $ => C :HASHKDIGEST(E+17) + + ; BIT 18 + 0 => HASHPOS + ${B & 0x00040000} :JMPZ(hashLeft18) + +hashRight18: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 18)} :HASHK(E+18) + C :HASHK(E+18) + A + 0x00040000 => A :JMP(hashBranchEnd18) + +hashLeft18: + C :HASHK(E+18) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 18)} :HASHK(E+18) + +hashBranchEnd18: + HASHPOS :HASHKLEN(E+18) + $ => C :HASHKDIGEST(E+18) + + ; BIT 19 + 0 => HASHPOS + ${B & 0x00080000} :JMPZ(hashLeft19) + +hashRight19: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 19)} :HASHK(E+19) + C :HASHK(E+19) + A + 0x00080000 => A :JMP(hashBranchEnd19) + +hashLeft19: + C :HASHK(E+19) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 19)} :HASHK(E+19) + +hashBranchEnd19: + HASHPOS :HASHKLEN(E+19) + $ => C :HASHKDIGEST(E+19) + + ; BIT 20 + 0 => HASHPOS + ${B & 0x00100000} :JMPZ(hashLeft20) + +hashRight20: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 20)} :HASHK(E+20) + C :HASHK(E+20) + A + 0x00100000 => A :JMP(hashBranchEnd20) + +hashLeft20: + C :HASHK(E+20) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 20)} :HASHK(E+20) + +hashBranchEnd20: + HASHPOS :HASHKLEN(E+20) + $ => C :HASHKDIGEST(E+20) + + ; BIT 21 + 0 => HASHPOS + ${B & 0x00200000} :JMPZ(hashLeft21) + +hashRight21: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 21)} :HASHK(E+21) + C :HASHK(E+21) + A + 0x00200000 => A :JMP(hashBranchEnd21) + +hashLeft21: + C :HASHK(E+21) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 21)} :HASHK(E+21) + +hashBranchEnd21: + HASHPOS :HASHKLEN(E+21) + $ => C :HASHKDIGEST(E+21) + + ; BIT 22 + 0 => HASHPOS + ${B & 0x00400000} :JMPZ(hashLeft22) + +hashRight22: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 22)} :HASHK(E+22) + C :HASHK(E+22) + A + 0x00400000 => A :JMP(hashBranchEnd22) + +hashLeft22: + C :HASHK(E+22) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 22)} :HASHK(E+22) + +hashBranchEnd22: + HASHPOS :HASHKLEN(E+22) + $ => C :HASHKDIGEST(E+22) + + ; BIT 23 + 0 => HASHPOS + ${B & 0x00800000} :JMPZ(hashLeft23) + +hashRight23: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 23)} :HASHK(E+23) + C :HASHK(E+23) + A + 0x00800000 => A :JMP(hashBranchEnd23) + +hashLeft23: + C :HASHK(E+23) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 23)} :HASHK(E+23) + +hashBranchEnd23: + HASHPOS :HASHKLEN(E+23) + $ => C :HASHKDIGEST(E+23) + + ; BIT 24 + 0 => HASHPOS + ${B & 0x01000000} :JMPZ(hashLeft24) + +hashRight24: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 24)} :HASHK(E+24) + C :HASHK(E+24) + A + 0x01000000 => A :JMP(hashBranchEnd24) + +hashLeft24: + C :HASHK(E+24) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 24)} :HASHK(E+24) + +hashBranchEnd24: + HASHPOS :HASHKLEN(E+24) + $ => C :HASHKDIGEST(E+24) + + ; BIT 25 + 0 => HASHPOS + ${B & 0x02000000} :JMPZ(hashLeft25) + +hashRight25: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 25)} :HASHK(E+25) + C :HASHK(E+25) + A + 0x02000000 => A :JMP(hashBranchEnd25) + +hashLeft25: + C :HASHK(E+25) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 25)} :HASHK(E+25) + +hashBranchEnd25: + HASHPOS :HASHKLEN(E+25) + $ => C :HASHKDIGEST(E+25) + + ; BIT 26 + 0 => HASHPOS + ${B & 0x04000000} :JMPZ(hashLeft26) + +hashRight26: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 26)} :HASHK(E+26) + C :HASHK(E+26) + A + 0x04000000 => A :JMP(hashBranchEnd26) + +hashLeft26: + C :HASHK(E+26) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 26)} :HASHK(E+26) + +hashBranchEnd26: + HASHPOS :HASHKLEN(E+26) + $ => C :HASHKDIGEST(E+26) + + ; BIT 27 + 0 => HASHPOS + ${B & 0x08000000} :JMPZ(hashLeft27) + +hashRight27: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 27)} :HASHK(E+27) + C :HASHK(E+27) + A + 0x08000000 => A :JMP(hashBranchEnd27) + +hashLeft27: + C :HASHK(E+27) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 27)} :HASHK(E+27) + +hashBranchEnd27: + HASHPOS :HASHKLEN(E+27) + $ => C :HASHKDIGEST(E+27) + + ; BIT 28 + 0 => HASHPOS + ${B & 0x10000000} :JMPZ(hashLeft28) + +hashRight28: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 28)} :HASHK(E+28) + C :HASHK(E+28) + A + 0x10000000 => A :JMP(hashBranchEnd28) + +hashLeft28: + C :HASHK(E+28) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 28)} :HASHK(E+28) + +hashBranchEnd28: + HASHPOS :HASHKLEN(E+28) + $ => C :HASHKDIGEST(E+28) + + ; BIT 29 + 0 => HASHPOS + ${B & 0x20000000} :JMPZ(hashLeft29) + +hashRight29: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 29)} :HASHK(E+29) + C :HASHK(E+29) + A + 0x20000000 => A :JMP(hashBranchEnd29) + +hashLeft29: + C :HASHK(E+29) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 29)} :HASHK(E+29) + +hashBranchEnd29: + HASHPOS :HASHKLEN(E+29) + $ => C :HASHKDIGEST(E+29) + + ; BIT 30 + 0 => HASHPOS + ${B & 0x40000000} :JMPZ(hashLeft30) + +hashRight30: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 30)} :HASHK(E+30) + C :HASHK(E+30) + A + 0x40000000 => A :JMP(hashBranchEnd30) + +hashLeft30: + C :HASHK(E+30) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 30)} :HASHK(E+30) + +hashBranchEnd30: + HASHPOS :HASHKLEN(E+30) + $ => C :HASHKDIGEST(E+30) + + ; BIT 31 + 0 => HASHPOS + ${B & 0x80000000} :JMPZ(hashLeft31) + +hashRight31: + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 31)} :HASHK(E+31) + C :HASHK(E+31) + A + 0x80000000 => A :JMP(hashBranchEnd31) + +hashLeft31: + C :HASHK(E+31) + ${getSmtProofPreviousIndex(mem.indexL1InfoTree, 31)} :HASHK(E+31) + +hashBranchEnd31: + HASHPOS :HASHKLEN(E+31) + ; Merkle root at C + $ => C :HASHKDIGEST(E+31) + + ; verify linear combination of 'indexL1InfoTree' + B :ASSERT + E + 32 => E :MSTORE(nextHashKId) + +computeMerkleProofReturn: + $ => RR :MLOAD(tmpZkPCComputeMerkleProof) + :RETURN \ No newline at end of file diff --git a/main/utils/get-len-bytes.zkasm b/main/utils/get-len-bytes.zkasm new file mode 100644 index 00000000..a91a6012 --- /dev/null +++ b/main/utils/get-len-bytes.zkasm @@ -0,0 +1,130 @@ +; @info byte length of B +; @in B => number +; @out A => bytes length +getLenBytes: + ; checks zk-counters + %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep), SAVE(B,C,D,E,RR,RCX) + ; Check length slot by slot starting with slot 7 + ;[7], [6], [5], [4], [3], [2], [1], [0] + ;[6], [5], [4], [3], [2], [1], [0], [7] -> ROTL_C + B => C + ROTL_C :JMPZ(checkSlot6) ; length less than 29 bytes + ROTL_C - 0x00000100 :JMPN(lenBytes29) + ROTL_C - 0x00010000 :JMPN(lenBytes30) + ROTL_C - 0x01000000 :JMPN(lenBytes31, lenBytes32) + +checkSlot6: + ROTL_C => C + ROTL_C :JMPZ(checkSlot5) + ROTL_C - 0x00000100 :JMPN(lenBytes25) + ROTL_C - 0x00010000 :JMPN(lenBytes26) + ROTL_C - 0x01000000 :JMPN(lenBytes27, lenBytes28) + +checkSlot5: + ROTL_C => C + ROTL_C :JMPZ(checkSlot4) + ROTL_C - 0x00000100 :JMPN(lenBytes21) + ROTL_C - 0x00010000 :JMPN(lenBytes22) + ROTL_C - 0x01000000 :JMPN(lenBytes23, lenBytes24) + +checkSlot4: + ROTL_C => C + ROTL_C :JMPZ(checkSlot3) + ROTL_C - 0x00000100 :JMPN(lenBytes17) + ROTL_C - 0x00010000 :JMPN(lenBytes18) + ROTL_C - 0x01000000 :JMPN(lenBytes19, lenBytes20) + +checkSlot3: + ROTL_C => C + ROTL_C :JMPZ(checkSlot2) + ROTL_C - 0x00000100 :JMPN(lenBytes13) + ROTL_C - 0x00010000 :JMPN(lenBytes14) + ROTL_C - 0x01000000 :JMPN(lenBytes15, lenBytes16) + +checkSlot2: + ROTL_C => C + ROTL_C :JMPZ(checkSlot1) + ROTL_C - 0x00000100 :JMPN(lenBytes9) + ROTL_C - 0x00010000 :JMPN(lenBytes10) + ROTL_C - 0x01000000 :JMPN(lenBytes11, lenBytes12) + +checkSlot1: + ROTL_C => C + ROTL_C :JMPZ(checkSlot0) + ROTL_C - 0x00000100 :JMPN(lenBytes5) + ROTL_C - 0x00010000 :JMPN(lenBytes6) + ROTL_C - 0x01000000 :JMPN(lenBytes7, lenBytes8) + +checkSlot0: + ROTL_C => C + ROTL_C :JMPZ(lenBytes0) + ROTL_C - 0x00000100 :JMPN(lenBytes1) + ROTL_C - 0x00010000 :JMPN(lenBytes2) + ROTL_C - 0x01000000 :JMPN(lenBytes3, lenBytes4) + +lenBytes32: + 32 => A :RESTORE, RETURN +lenBytes31: + 31 => A :RESTORE, RETURN +lenBytes30: + 30 => A :RESTORE, RETURN +lenBytes29: + 29 => A :RESTORE, RETURN +lenBytes28: + 28 => A :RESTORE, RETURN +lenBytes27: + 27 => A :RESTORE, RETURN +lenBytes26: + 26 => A :RESTORE, RETURN +lenBytes25: + 25 => A :RESTORE, RETURN +lenBytes24: + 24 => A :RESTORE, RETURN +lenBytes23: + 23 => A :RESTORE, RETURN +lenBytes22: + 22 => A :RESTORE, RETURN +lenBytes21: + 21 => A :RESTORE, RETURN +lenBytes20: + 20 => A :RESTORE, RETURN +lenBytes19: + 19 => A :RESTORE, RETURN +lenBytes18: + 18 => A :RESTORE, RETURN +lenBytes17: + 17 => A :RESTORE, RETURN +lenBytes16: + 16 => A :RESTORE, RETURN +lenBytes15: + 15 => A :RESTORE, RETURN +lenBytes14: + 14 => A :RESTORE, RETURN +lenBytes13: + 13 => A :RESTORE, RETURN +lenBytes12: + 12 => A :RESTORE, RETURN +lenBytes11: + 11 => A :RESTORE, RETURN +lenBytes10: + 10 => A :RESTORE, RETURN +lenBytes9: + 9 => A :RESTORE, RETURN +lenBytes8: + 8 => A :RESTORE, RETURN +lenBytes7: + 7 => A :RESTORE, RETURN +lenBytes6: + 6 => A :RESTORE, RETURN +lenBytes5: + 5 => A :RESTORE, RETURN +lenBytes4: + 4 => A :RESTORE, RETURN +lenBytes3: + 3 => A :RESTORE, RETURN +lenBytes2: + 2 => A :RESTORE, RETURN +lenBytes1: + 1 => A :RESTORE, RETURN +lenBytes0: + 0 => A :RESTORE, RETURN \ No newline at end of file diff --git a/main/utils/read-push.zkasm b/main/utils/read-push.zkasm new file mode 100644 index 00000000..d1e66fb1 --- /dev/null +++ b/main/utils/read-push.zkasm @@ -0,0 +1,162 @@ + +VAR GLOBAL pushBytes +; @info Read bytes opcode PUSHX +; @internalParam {numBlocks} 4 bytes blocks to read +; @internalParam {leftBytes} remaining bytes +; @in D,E => bytes to read (1..32) +; @out E => value read + +readPush: + :JMP(@readPush+E) ;0 +readPush1: + PC => HASHPOS :JMP(_readPush1) ;1 +readPush2: + PC => HASHPOS :JMP(_readPush2) ;2 +readPush3: + PC => HASHPOS :JMP(_readPush3) ;3 +readPush4: + PC => HASHPOS :JMP(_readPush4) ;4 +readPush5: + PC => HASHPOS :JMP(_readPushX) ;5 +readPush6: + PC => HASHPOS :JMP(_readPushX) ;6 +readPush7: + PC => HASHPOS :JMP(_readPushX) ;7 +readPush8: + PC => HASHPOS :JMP(_readPushX) ;8 +readPush9: + PC => HASHPOS :JMP(_readPushX) ;9 +readPush10: + PC => HASHPOS :JMP(_readPushX) ;10 +readPush11: + PC => HASHPOS :JMP(_readPushX) ;11 +readPush12: + PC => HASHPOS :JMP(_readPushX) ;12 +readPush13: + PC => HASHPOS :JMP(_readPushX) ;13 +readPush14: + PC => HASHPOS :JMP(_readPushX) ;14 +readPush15: + PC => HASHPOS :JMP(_readPushX) ;15 +readPush16: + PC => HASHPOS :JMP(_readPushX) ;16 +readPush17: + PC => HASHPOS :JMP(_readPushX) ;17 +readPush18: + PC => HASHPOS :JMP(_readPushX) ;18 +readPush19: + PC => HASHPOS :JMP(_readPushX) ;19 +readPush20: + PC => HASHPOS :JMP(_readPushX) ;20 +readPush21: + PC => HASHPOS :JMP(_readPushX) ;21 +readPush22: + PC => HASHPOS :JMP(_readPushX) ;22 +readPush23: + PC => HASHPOS :JMP(_readPushX) ;23 +readPush24: + PC => HASHPOS :JMP(_readPushX) ;24 +readPush25: + PC => HASHPOS :JMP(_readPushX) ;25 +readPush26: + PC => HASHPOS :JMP(_readPushX) ;26 +readPush27: + PC => HASHPOS :JMP(_readPushX) ;27 +readPush28: + PC => HASHPOS :JMP(_readPushX) ;28 +readPush29: + PC => HASHPOS :JMP(_readPushX) ;29 +readPush30: + PC => HASHPOS :JMP(_readPushX) ;30 +readPush31: + PC => HASHPOS :JMP(_readPushX) ;31 +readPush32: + PC => HASHPOS :JMP(_readPush32) ;32 + +_readPush1: + $ => E :MLOAD(contractHashId) + $ => E :HASHP1(E),RETURN + +_readPush2: + $ => E :MLOAD(contractHashId) + $ => C :HASHP1(E) + C * 256 + $ => E :F_HASHP1(E), RETURN + +_readPush3: + $ => E :MLOAD(contractHashId) + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => E :F_HASHP1(E), RETURN + +_readPush4: + $ => E :MLOAD(contractHashId) + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => E :F_HASHP1(E), RETURN + +_readPush32: + $ => E :MLOAD(contractHashId) + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => C :F_HASHP1(E) + + ; 28 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => C :F_HASHP1(E) + + ; 24 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => C :F_HASHP1(E) + + ; 20 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => C :F_HASHP1(E) + + ; 16 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => C :F_HASHP1(E) + + ; 12 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => C :F_HASHP1(E) + + ; 8 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => C :F_HASHP1(E) + + ; 4 bytes + + $ => A :HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + A * 256 + $ => A :F_HASHP1(E) + ROTL_C + A * 256 + $ => E :F_HASHP1(E),RETURN + +_readPushBaseTable: + +_readPushX: + $ => B :MLOAD(contractHashId) + +readPushBytes: + 0 => A, C + B => E :JMP(@_readPushBaseTable - E) From 4bbe44ed7df30fb7b4efed2f0f7d42b42e055615 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Thu, 9 May 2024 17:44:11 +0200 Subject: [PATCH 4/5] mulmod optimization --- main/opcodes/arithmetic.zkasm | 29 +++++--- main/utils.zkasm | 122 +--------------------------------- 2 files changed, 21 insertions(+), 130 deletions(-) diff --git a/main/opcodes/arithmetic.zkasm b/main/opcodes/arithmetic.zkasm index fe22f1d5..a36fb617 100644 --- a/main/opcodes/arithmetic.zkasm +++ b/main/opcodes/arithmetic.zkasm @@ -262,18 +262,28 @@ zeroOneAddMod: */ opMULMOD: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 15 :JMPN(outOfCountersStep) + %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) ; check stack underflow - SP - 3 :JMPN(stackUnderflow) + SP - 3 :JMPN(stackUnderflow) ; check out-of-gas - GAS - %GAS_MID_STEP => GAS :JMPN(outOfGas) + GAS - %GAS_MID_STEP => GAS :JMPN(outOfGas) SP - 1 => SP - $ => A :MLOAD(SP--); [a => A] - $ => B :MLOAD(SP--); [b => B] - $ => C :MLOAD(SP); [N => C] - zkPC+1 => RR :JMP(utilMULMOD); in: [A, B, C] out: [C: (A * B) % C] - C :MSTORE(SP++), JMP(readCode); [C => SP] + $ => C :MLOAD(SP--); [a => A] + $ => E :MLOAD(SP--); [b => B] + $ => A, D :MLOAD(SP); [N => C] + ; Check mod is zero, arith would fail otherwise + 0 => B + $ :EQ, JMPC(opMULMODZero) + C => A + E => B + 0 => C + ; compute ARITH_MOD => A*B+C= op (mod D) + ${(A*B) % D} => E :ARITH_MOD + E :MSTORE(SP++), JMP(readCode); [C => SP] +opMULMODZero: + 0 :MSTORE(SP++), JMP(readCode); [C => SP] /** * @link [https://www.evm.codes/#0A?fork=berlin] @@ -299,8 +309,7 @@ opEXP: GAS - %GAS_SLOW_STEP - %EXP_BYTE_GAS * A => GAS :JMPN(outOfGas) ; compute exponentiation - C => A - zkPC+1 => RR :JMP(expAD) ; in: [A, D] out: [A: A ** D] + C => A :CALL(expAD) ; in: [A, D] out: [A: A ** D] A :MSTORE(SP++), JMP(readCode) ; [a ** exp => SP] /** diff --git a/main/utils.zkasm b/main/utils.zkasm index 710196c3..48f5ca36 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -843,129 +843,12 @@ maskAddress: $ => A :AND $ => B :MLOAD(tmpVarBmask), RETURN -VAR GLOBAL mulModOutC -VAR GLOBAL tmpVarMulMod1 - -; @info (A*B)%C => C -; @in A -; @in B -; @in C -; @out C -utilMULMOD: - ; checks zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) - %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) - - A :SAVE(B,C,D,E,RCX,RR) - - ; The following approach will be followed in order to verify the mulmod operation - ; 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 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 - - ;k.l * N + mulModResult = D1 * 2²⁵⁶ + E - ;k.h * 2²⁵⁶ * N = D2 * 2²⁵⁶ --> k.h * N = D2 - - ; Mul operation with Arith - $${var _mulMod = A * B} - A :MSTORE(arithA) - ; here we perform the: A * B + 0 = D*2^256 + E - ; result is stored in: arithRes1(E) and mulArithOverflowValue(D) - B :MSTORE(arithB), CALL(mulARITH) - C => A - ; Check if modulus is 0 or 1 - 2 => B - $ :LT, JMPC(zeroOneMod) - ; Now we will try to perform the following equation: - ; (k.l + k.h * 2²⁵⁶) * N + mulModResult = (D1 + D2) * 2²⁵⁶ + E - - ${(_mulMod / C) >> 256} => B ; k.h - ; We can jump with Js, because later it's all verified by the ARITH - ; the two paths must be mutually exclusive. - ; mulModNoKH: if kh is non zero, not found a solution only with kl - ${cond(B == 0)} :JMPN(mulModNoKH) - - ; in case of malicious prover, check that B was different of zero to - ; avoid dual path. - 0 => A - 0 :EQ ; assert B != 0 - - ; Since there's k.h we will split the equation in those 2 - ;k.l * N + mulModResult = D1 * 2²⁵⁶ + E - ;k.h * 2²⁵⁶ * N = D2 * 2²⁵⁶ --> k.h * N = D2 - - ; k.h * N = D2 - ; B * A + 0 = 0 * 2²⁵⁶ + E - ; D2 must be less than 2²⁵⁶ - C => A ; Modulus - 0 => C, D - ${B * A} => E :MSTORE(tmpVarMulMod1), ARITH ; D2 - - ; k.l * N + mulModResult = D1 * 2²⁵⁶ + E - ; B * A + C = D*2^256 + E - ; remember that: - ; result of mul is stored in: arithRes1(E) and mulArithOverflowValue(D) - - ${(_mulMod / A) % (1 << 256)} => B ; k.l - ${_mulMod % A} => C ; mulModResult - ${(B * A + C) >> 256} => D ; D1 - $ :MLOAD(arithRes1), ARITH - - ; Finally we need to assert the following: - ; N>resultModulus - ; D1 + D2 = D - ; N>resultModulus ; LT; ASSERT - A => B ; modulus - C => A ; mulModResult - $ => A :LT - 1 :ASSERT - - ; Assert D1 + D2 = D ; ADD ;ASSERT - D => A ; D1 - $ => B :MLOAD(tmpVarMulMod1) ;D2 - - ; verify no carry, because D = D1 + D2 must be less than 2**256 - ; to pass arithmetic equation A * B + C = D * 2**256 + op - $ => A :ADD,JMPC(failAssert) - $ :MLOAD(mulArithOverflowValue), ASSERT, JMP(utilMULMODend) - -mulModNoKH: - ; if theres no K.h the equation is simplified as: - ; K * N + mulModResult = D*2^256 + E - ; B * A + C = D*2^256 + E - - C => A ; Modulus on A - ${(_mulMod / A)} => B ; k - ${_mulMod % A} => C ; mulModResult - $ => D :MLOAD(mulArithOverflowValue) - $ :MLOAD(arithRes1), ARITH - - A => B ; modulus - C => A ; mulModResult - $ => A :LT - 1 :ASSERT, JMP(utilMULMODend) - -zeroOneMod: - 0 => C - -utilMULMODend: - C :MSTORE(mulModOutC) - $ => A :RESTORE - $ => C :MLOAD(mulModOutC), RETURN - ;@info exp(A,D) --> A^D ;@in A, D => A^D ;@out A => result expAD: %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) - :SAVE(B,C,D,E,RCX,RR) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep), SAVE(B,C,D,E,RCX,RR) ;E base A => E ;B exp @@ -1016,8 +899,7 @@ expAD0: 0 => D expADend: - C => A - :RESTORE, RETURN + C => A :RESTORE, RETURN ;@info function to force a failed assert failAssert: From a2b63428d613d128b669c7ef5133af67278327a7 Mon Sep 17 00:00:00 2001 From: zkronos73 Date: Tue, 21 May 2024 22:28:38 +0200 Subject: [PATCH 5/5] add optimization to get-len-bytes --- main/utils/get-len-bytes.zkasm | 74 ++++++++++++++++------------------ 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/main/utils/get-len-bytes.zkasm b/main/utils/get-len-bytes.zkasm index a91a6012..8d894281 100644 --- a/main/utils/get-len-bytes.zkasm +++ b/main/utils/get-len-bytes.zkasm @@ -8,59 +8,53 @@ getLenBytes: ;[7], [6], [5], [4], [3], [2], [1], [0] ;[6], [5], [4], [3], [2], [1], [0], [7] -> ROTL_C B => C - ROTL_C :JMPZ(checkSlot6) ; length less than 29 bytes - ROTL_C - 0x00000100 :JMPN(lenBytes29) - ROTL_C - 0x00010000 :JMPN(lenBytes30) - ROTL_C - 0x01000000 :JMPN(lenBytes31, lenBytes32) -checkSlot6: - ROTL_C => C - ROTL_C :JMPZ(checkSlot5) - ROTL_C - 0x00000100 :JMPN(lenBytes25) - ROTL_C - 0x00010000 :JMPN(lenBytes26) - ROTL_C - 0x01000000 :JMPN(lenBytes27, lenBytes28) + ROTL_C => C,B :JMPZ(checkSlot6) ; length less than 29 bytes + B - 0x00000100 :JMPN(lenBytes29) + B - 0x00010000 :JMPN(lenBytes30) + B - 0x01000000 :JMPN(lenBytes31, lenBytes32) + +checkSlot6: + ROTL_C => C,B :JMPZ(checkSlot5) + B - 0x00000100 :JMPN(lenBytes25) + B - 0x00010000 :JMPN(lenBytes26) + B - 0x01000000 :JMPN(lenBytes27, lenBytes28) checkSlot5: - ROTL_C => C - ROTL_C :JMPZ(checkSlot4) - ROTL_C - 0x00000100 :JMPN(lenBytes21) - ROTL_C - 0x00010000 :JMPN(lenBytes22) - ROTL_C - 0x01000000 :JMPN(lenBytes23, lenBytes24) + ROTL_C => C,B :JMPZ(checkSlot4) + B - 0x00000100 :JMPN(lenBytes21) + B - 0x00010000 :JMPN(lenBytes22) + B - 0x01000000 :JMPN(lenBytes23, lenBytes24) checkSlot4: - ROTL_C => C - ROTL_C :JMPZ(checkSlot3) - ROTL_C - 0x00000100 :JMPN(lenBytes17) - ROTL_C - 0x00010000 :JMPN(lenBytes18) - ROTL_C - 0x01000000 :JMPN(lenBytes19, lenBytes20) + ROTL_C => C,B :JMPZ(checkSlot3) + B - 0x00000100 :JMPN(lenBytes17) + B - 0x00010000 :JMPN(lenBytes18) + B - 0x01000000 :JMPN(lenBytes19, lenBytes20) checkSlot3: - ROTL_C => C - ROTL_C :JMPZ(checkSlot2) - ROTL_C - 0x00000100 :JMPN(lenBytes13) - ROTL_C - 0x00010000 :JMPN(lenBytes14) - ROTL_C - 0x01000000 :JMPN(lenBytes15, lenBytes16) + ROTL_C => C,B :JMPZ(checkSlot2) + B - 0x00000100 :JMPN(lenBytes13) + B - 0x00010000 :JMPN(lenBytes14) + B - 0x01000000 :JMPN(lenBytes15, lenBytes16) checkSlot2: - ROTL_C => C - ROTL_C :JMPZ(checkSlot1) - ROTL_C - 0x00000100 :JMPN(lenBytes9) - ROTL_C - 0x00010000 :JMPN(lenBytes10) - ROTL_C - 0x01000000 :JMPN(lenBytes11, lenBytes12) + ROTL_C => C,B :JMPZ(checkSlot1) + B - 0x00000100 :JMPN(lenBytes9) + B - 0x00010000 :JMPN(lenBytes10) + B - 0x01000000 :JMPN(lenBytes11, lenBytes12) checkSlot1: - ROTL_C => C - ROTL_C :JMPZ(checkSlot0) - ROTL_C - 0x00000100 :JMPN(lenBytes5) - ROTL_C - 0x00010000 :JMPN(lenBytes6) - ROTL_C - 0x01000000 :JMPN(lenBytes7, lenBytes8) + ROTL_C => C,B :JMPZ(checkSlot0) + B - 0x00000100 :JMPN(lenBytes5) + B - 0x00010000 :JMPN(lenBytes6) + B - 0x01000000 :JMPN(lenBytes7, lenBytes8) checkSlot0: - ROTL_C => C - ROTL_C :JMPZ(lenBytes0) - ROTL_C - 0x00000100 :JMPN(lenBytes1) - ROTL_C - 0x00010000 :JMPN(lenBytes2) - ROTL_C - 0x01000000 :JMPN(lenBytes3, lenBytes4) + ROTL_C => C,B :JMPZ(lenBytes0) + B - 0x00000100 :JMPN(lenBytes1) + B - 0x00010000 :JMPN(lenBytes2) + B - 0x01000000 :JMPN(lenBytes3, lenBytes4) lenBytes32: 32 => A :RESTORE, RETURN