diff --git a/main/ecrecover/ecrecover.zkasm b/main/ecrecover/ecrecover.zkasm index e2ee4037..0dc1d9f9 100644 --- a/main/ecrecover/ecrecover.zkasm +++ b/main/ecrecover/ecrecover.zkasm @@ -170,7 +170,10 @@ ecrecover_v_y2_same_parity: E + 1 => E :MSTORE(lastHashKIdUsed) 0 => HASHPOS 32 => D - + ; check keccak counters + $ => A :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) + $ => A :MLOAD(mulPointEc_p3_x) A :HASHK(E) @@ -180,8 +183,6 @@ ecrecover_v_y2_same_parity: A :HASHK(E) 64 :HASHKLEN(E) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) $ => A :HASHKDIGEST(E) ; for address take only last 20 bytes diff --git a/main/load-tx-rlp.zkasm b/main/load-tx-rlp.zkasm index 2f8d9d77..a7056bd7 100644 --- a/main/load-tx-rlp.zkasm +++ b/main/load-tx-rlp.zkasm @@ -45,7 +45,14 @@ shortList: A - 0xc0 => A endList: - A + C :MSTORE(txRLPLength) + A + C => B :MSTORE(txRLPLength) + ; Check enough zk counters to digest tx hash + B + 1 :MSTORE(arithA) + 136 :MSTORE(arithB) + :CALL(divARITH) + $ => B :MLOAD(arithRes1) + $ => D :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - B - D - 1:JMPN(handleOOCatRLP) ;; Read RLP 'nonce' ; 64 bits max @@ -315,12 +322,17 @@ vREADTx: ;; increase number of transaction to process $ => A :MLOAD(pendingTxs) A + 1 => A :MSTORE(pendingTxs) - HASHPOS :MSTORE(sigDataSize) ; save bytes length added to ethereum transaction hash +;; compute signature + $ => A :HASHKDIGEST(E) + A :MSTORE(txHash) :JMP(txLoopRLP) ;;;;;;;;; ;; E - Handler error RLP fields ;;;;;;;;; +handleOOCatRLP: + ${eventLog(onError, OOCK)} + $ => SR :MLOAD(batchSR) invalidTxRLP: ;; Append all missing 'batchL2Data' to 'batchDataHash' bytes diff --git a/main/main.zkasm b/main/main.zkasm index 54e47eb5..e8f6dc08 100644 --- a/main/main.zkasm +++ b/main/main.zkasm @@ -90,7 +90,6 @@ skipSetGlobalExitRoot: E+1 => E :MSTORE(lastHashKIdUsed) 0 :MSTORE(batchHashPos) E :MSTORE(batchHashDataId) - E :MSTORE(lastTxHashId) ; Points at first hash address to be used when processing transactions $ => A :MLOAD(lastCtxUsed) A :MSTORE(ctxTxToUse) ; Points at first context to be used when processing transactions @@ -154,7 +153,6 @@ processTxsEnd: $ :MLOAD(batchL2DataLength), ASSERT ;; Compute 'batchHashData' - ; Compute 'batchHashData' A => HASHPOS $ => E :MLOAD(batchHashDataId) diff --git a/main/opcodes/block.zkasm b/main/opcodes/block.zkasm index 73bf945a..9603aabb 100644 --- a/main/opcodes/block.zkasm +++ b/main/opcodes/block.zkasm @@ -23,8 +23,6 @@ opBLOCKHASH: A :HASHK(E) %STATE_ROOT_STORAGE_POS :HASHK(E) HASHPOS :HASHKLEN(E) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1:JMPN(outOfCountersKeccak) $ => C :HASHKDIGEST(E) %ADDRESS_SYSTEM => A %SMT_KEY_SC_STORAGE => B diff --git a/main/opcodes/calldata-returndata-code.zkasm b/main/opcodes/calldata-returndata-code.zkasm index 0372b1ad..ddc30ec9 100644 --- a/main/opcodes/calldata-returndata-code.zkasm +++ b/main/opcodes/calldata-returndata-code.zkasm @@ -241,10 +241,6 @@ opCODECOPY: GAS - 3 => GAS :JMPN(outOfGas) GAS - ${3*((E+31)/32)} => GAS :JMPN(outOfGas) :CALL(saveMem) - ; check memory limits - 0x200000 => A - C + E => B - $ :LT,JMPC(errorMLOADMSTORE) ; Check if offset is above data len D => A $ => B :MLOAD(bytecodeLength) @@ -357,11 +353,6 @@ opEXTCODECOPY: GAS - ${3*((E+31)/32)} => GAS :JMPN(outOfGas) :CALL(saveMem) - ; check memory limits - 0x200000 => A - C + E => B - $ :LT,JMPC(errorMLOADMSTORE) - ; Check if offset is above data len D => A $ => B :MLOAD(tmpContractLength) @@ -389,6 +380,17 @@ opEXTCODECOPYCheckHash: 0 => A D => B $ :EQ, JMPC(opEXTCODECOPYCheckHashEnd) + ; check poseidon counters + ; 56 is the value used by the prover to increment poseidon counters depending on the hash length + RR :MSTORE(tmpZkPC) + B + 1 :MSTORE(arithA) + 56 :MSTORE(arithB) + :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => RR :MLOAD(tmpZkPC) + $ => B :MLOAD(arithRes1) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 1 => A + $ :LT, JMPC(outOfCountersPoseidon) + E => A ; get hash contract %SMT_KEY_SC_CODE => B @@ -408,7 +410,7 @@ opEXTCODECOPYCheckHash: ; TODO: it could be improved by computing how many 32 bytes slots are needed opEXTCODECOPYCheckHashLoop: - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) B - 1 :JMPN(opEXTCODECOPYCheckHashLoopEnd) ; finish reading bytecode 1 => D diff --git a/main/opcodes/crypto.zkasm b/main/opcodes/crypto.zkasm index b0a9cb4c..0048b94d 100644 --- a/main/opcodes/crypto.zkasm +++ b/main/opcodes/crypto.zkasm @@ -16,8 +16,6 @@ opSHA3: %MAX_CNT_ARITH - CNT_ARITH - 192 :JMPN(outOfCountersArith) %MAX_CNT_BINARY - CNT_BINARY - 193 :JMPN(outOfCountersBinary) %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 2 :JMPN(outOfCountersMemalign) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 10 :JMPN(outOfCountersPoseidon) %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) @@ -29,6 +27,7 @@ opSHA3: SP - 1 => SP $ => E :MLOAD(SP--); [offset => E] $ => C :MLOAD(SP) ; [size => C] + ; store lastMemOffset for memory expansion gas cost E :MSTORE(lastMemOffset) ; store lastMemLength for memory expansion gas cost @@ -50,6 +49,17 @@ opSHA3: :CALL(mulARITH) $ => A :MLOAD(arithRes1) GAS - A => GAS :JMPN(outOfGas) ; dynamic_gas = 6 * minimum_word_size + memory_expansion_cost + + ; check keccak counters + C + 1 :MSTORE(arithA) + 136 :MSTORE(arithB) + :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => B :MLOAD(arithRes1) + $ => A :MLOAD(cntKeccakPreProcess) + ; checks keccak counters + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 => A + $ :LT, JMPC(outOfCountersKeccak) + ; new hash id $ => B :MLOAD(lastHashKIdUsed) B + 1 => B :MSTORE(lastHashKIdUsed) @@ -94,17 +104,7 @@ opSHA3End: ; get current hash pointer $ => E :MLOAD(lastHashKIdUsed) ; append A to hash pointer E - HASHPOS :HASHKLEN(E) - - ; Check keccak counters - HASHPOS :MSTORE(arithA) - 136 :MSTORE(arithB) - :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] - $ => B :MLOAD(arithRes1) - $ => A :MLOAD(cntKeccakPreProcess) - ; checks keccak counters - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 => A - $ :LT, JMPC(outOfCountersKeccak) + HASHPOS :HASHKLEN(E) ; compute hash $ => A :HASHKDIGEST(E) ; store hash diff --git a/main/opcodes/storage-memory.zkasm b/main/opcodes/storage-memory.zkasm index 2a607809..b13337e5 100644 --- a/main/opcodes/storage-memory.zkasm +++ b/main/opcodes/storage-memory.zkasm @@ -110,9 +110,7 @@ opMSTORE8: B :MSTORE(lastMemOffset) ; store lastMemLength for memory expansion gas cost. In case of MSTORE8, always 1 byte 1 :MSTORE(lastMemLength) - ; check offset is below memory limit - 0x200000 => A - $ :LT,JMPC(errorMLOADMSTORE) + :CALL(saveMem); in: [lastMemOffset, lastMemLength] B => A :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] $ => B :MLOAD(SP); [value => B] @@ -122,7 +120,6 @@ opMSTORE8: B :MEM_ALIGN_WR8 ; only use LSB of B, rest of bytes could be non zero. ; write at memory position E D :MSTORE(MEM:E) - :CALL(saveMem); in: [lastMemOffset, lastMemLength] :JMP(readCode) /** diff --git a/main/process-tx.zkasm b/main/process-tx.zkasm index 48a74a32..373f8022 100644 --- a/main/process-tx.zkasm +++ b/main/process-tx.zkasm @@ -32,25 +32,8 @@ processTx: ; Minimum of 100000 steps left to process a tx %MAX_CNT_STEPS - STEP - 100000 :JMPN(outOfCountersStep) - - ; Get sigDataSize - $ => HASHPOS :MLOAD(sigDataSize) - - ; Check keccak counters - HASHPOS :MSTORE(arithA) - 136 :MSTORE(arithB) - :CALL(divARITH) - $ => B :MLOAD(arithRes1) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 => A - $ :LT, JMPC(outOfCountersKeccak) - - ; Get hash address previously stored in RLP parsing - $ => E :MLOAD(lastTxHashId) - E+1 => E :MSTORE(lastTxHashId) - + $ => A :MLOAD(txHash) ; Check the signature - $ => A :HASHKDIGEST(E) $ => B :MLOAD(txR) $ => C :MLOAD(txS) $ => D :MLOAD(txV) @@ -241,6 +224,9 @@ getContractAddress: ; Check if create is with CREATE2 opcode $ => A :MLOAD(isCreate2) 0 - A :JMPN(create2) + ; Check keccak counters + $ => A :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1:JMPN(outOfCountersKeccak) $ => A :MLOAD(txNonce) 0x80 => B $ :LT,JMPC(nonce1byte) @@ -278,10 +264,21 @@ nonceIs0: ;; compute new contract address as CREATE2 spec: keccak256(0xff ++ address ++ salt ++ keccak256(init_code))[12:] (https://eips.ethereum.org/EIPS/eip-1014) create2: $ => C :MLOAD(txCalldataLen) + ; Check keccak counters + C + 1 :MSTORE(arithA) + 136 :MSTORE(arithB) + :CALL(divARITH) + $ => B :MLOAD(arithRes1) + $ => A :MLOAD(cntKeccakPreProcess) + ; -2 because we will use one more keccack for generating contract address + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 2 => A + $ :LT, JMPC(outOfCountersKeccak) + $ => CTX :MLOAD(originCTX) $ => B :MLOAD(argsOffsetCall) loopCreate2: + ; check zk-counters %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) @@ -308,15 +305,8 @@ endloopCreate2: create2end: $ => CTX :MLOAD(currentCTX) HASHPOS :HASHKLEN(E) - ; Check keccak counters - HASHPOS :MSTORE(arithA) - 136 :MSTORE(arithB) - :CALL(divARITH) - $ => B :MLOAD(arithRes1) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 => A - $ :LT, JMPC(outOfCountersKeccak) $ => C :HASHKDIGEST(E) + ; new hash with position 0 is started 0 => HASHPOS $ => E :MLOAD(lastHashKIdUsed) @@ -334,16 +324,6 @@ create2end: endContractAddress: HASHPOS :HASHKLEN(E) - - ; Check keccak counters - HASHPOS :MSTORE(arithA) - 136 :MSTORE(arithB) - :CALL(divARITH) - $ => B :MLOAD(arithRes1) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 => A - $ :LT, JMPC(outOfCountersKeccak) - $ => A :HASHKDIGEST(E) :CALL(maskAddress) ; Mask address to 20 bytes A :MSTORE(createContractAddress) @@ -450,6 +430,15 @@ callContract: 0 => A $ :EQ, JMPC(defaultOpCode) ;no bytecode + ; check poseidon counters + ; 56 is the value used by the prover to increment poseidon counters depending on the hash length + B :MSTORE(arithA) + 56 :MSTORE(arithB) + :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => B :MLOAD(arithRes1) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 1 => A + $ :LT, JMPC(outOfCountersPoseidon) + $ => A :MLOAD(txDestAddr) ; get hash contract %SMT_KEY_SC_CODE => B diff --git a/main/utils.zkasm b/main/utils.zkasm index a36d536f..472a5a84 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -156,7 +156,7 @@ MSTORE32: D :MSTORE(tmpVarD) E :MSTORE(tmpVarE) E => A - 0x200000 => B + 0x400000 => B $ :LT,JMPC(initMSTORE) :JMP(errorMLOADMSTORE) @@ -264,7 +264,7 @@ MLOAD32: C :MSTORE(tmpVarC) D :MSTORE(tmpVarD) E => A - 0x200000 => B + 0x400000 => B $ :LT,JMPC(initMLOAD) :JMP(errorMLOADMSTORE) @@ -988,6 +988,15 @@ hashPoseidonLinearFromMemory: $ => C :MLOAD(memSizeLinearPoseidon) 0 => D C - 1 :JMPN(hashPoseidonReturn) + ; check poseidon counters + ; 56 is the value used by the prover to increment poseidon counters depending on the hash length + C :MSTORE(arithA) + 56 :MSTORE(arithB) + :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => B :MLOAD(arithRes1) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 1 => A + $ :LT, JMPC(outOfCountersPoseidon) + ; get a new hashPId $ => B :MLOAD(nextHashPId) B :MSTORE(tmpContractHashId) @@ -1043,6 +1052,10 @@ maskAddress: :RETURN updateSystemData: + ; check keccak counters + $ => A :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1:JMPN(outOfCountersKeccak) + ; Get last tx count %LAST_TX_STORAGE_POS => C %ADDRESS_SYSTEM => A @@ -1061,8 +1074,6 @@ updateSystemData: A :HASHK(E) %STATE_ROOT_STORAGE_POS :HASHK(E) HASHPOS :HASHKLEN(E) - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1:JMPN(outOfCountersKeccak) $ => C :HASHKDIGEST(E) %ADDRESS_SYSTEM => A SR => D diff --git a/main/vars.zkasm b/main/vars.zkasm index 98ce6fdd..919e8a24 100644 --- a/main/vars.zkasm +++ b/main/vars.zkasm @@ -17,7 +17,6 @@ VAR GLOBAL batchL2DataParsed ; Number of bytes read when decoding RLP transactio 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 lastTxHashId ; First hash address to be used when processing transactions VAR GLOBAL lastHashKIdUsed ; Last hash address used VAR GLOBAL nextHashPId ; Next posidon hash address available @@ -61,6 +60,7 @@ VAR CTX txS ; transaction parameter: ecdsa signature S VAR CTX txR ; transaction parameter: ecdsa signature R VAR CTX txV ; transaction parameter: ecdsa signature V VAR CTX txSrcAddr ; address that sends a transaction 'message.sender' +VAR CTX txHash ; signed tx hash VAR CTX txCalldataLen ; calldata length VAR CTX isCreateContract ; flag to determine if a transaction will create a new contract VAR CTX createContractAddress ; address computed of a new contract @@ -87,7 +87,6 @@ VAR CTX isDelegateCall ; flag to determine if a new context comes from a DELEGAT VAR CTX isCreate2 ; flag to determine if a new context comes from a CREATE2 opcode VAR CTX salt ; CREATE2 parameter 'salt' used to compute new contract address VAR CTX gasCTX ; remaining gas in the origin CTX when a new context is created -VAR CTX sigDataSize ; hash position for the ethereum transaction hash VAR CTX dataStarts; hash position where de transaction 'data' starts in the batchHashData VAR CTX isPreEIP155 ; flag to check if the current tx is legacy, previous to Spurious Dragon (EIP-155) VAR CTX initTouchedSR ; touched root once a new context begins \ No newline at end of file