diff --git a/main/constants.zkasm b/main/constants.zkasm index e211d8da..86a1ae9b 100644 --- a/main/constants.zkasm +++ b/main/constants.zkasm @@ -143,6 +143,4 @@ CONST %TX_TYPE_NUM_BYTES = 1 CONST %MEM_ALIGN_SIZE = 2**7 CONST %MEM_ALIGN_OFFSET = 1 CONST %MEM_ALIGN_LEFT_ALIGNMENT = 2**13 -CONST %MEM_ALIGN_LITTLE_ENDIAN = 2**14 - -; CHECK not used constants and vars \ No newline at end of file +CONST %MEM_ALIGN_LITTLE_ENDIAN = 2**14 \ No newline at end of file diff --git a/main/ecrecover/dblScalarMulSecp256k1.zkasm b/main/ecrecover/dblScalarMulSecp256k1.zkasm index 60590b7e..b1cd5fae 100644 --- a/main/ecrecover/dblScalarMulSecp256k1.zkasm +++ b/main/ecrecover/dblScalarMulSecp256k1.zkasm @@ -160,7 +160,7 @@ dblScalarMulSecp256k1_loop_fi: ; high_bit(k1) == 0 high_bit(k2) == ?? dblScalarMulSecp256k1_k10_fi: ; Receive the next MSB bit of k2 - $0{(mem.dblScalarMulSecp256k1_k2) >> RR & 0x1} :JMPZ(failAssert, @dblScalarMulSecp256k1_scalar_table_k10_k21 + RR) + $0{(mem.dblScalarMulSecp256k1_k2) >> RR & 0x1} :JMPZ(failAssertEcrecover, @dblScalarMulSecp256k1_scalar_table_k10_k21 + RR) ; ------------------------------ diff --git a/main/load-tx-rlp-utils.zkasm b/main/load-tx-rlp-utils.zkasm index 0d64aae7..bb1da887 100644 --- a/main/load-tx-rlp-utils.zkasm +++ b/main/load-tx-rlp-utils.zkasm @@ -38,7 +38,6 @@ addHashTxByteByByte: $ - HASHPOS - D :F_MLOAD(txRLPLength), JMPN(invalidTxRLP) $ => B :MLOAD(batchL2DataParsed) ; Save current registers - ; CHECK: Is correct to save here in same line as JMPN? $ - B - C - D :F_MLOAD(batchL2DataLength), JMPN(invalidTxRLP), SAVE(B,C,D,E,RR,RCX) $ => HASHPOS :MLOAD(batchHashPos) D => E diff --git a/main/load-tx-rlp.zkasm b/main/load-tx-rlp.zkasm index 53d6b108..f6fb6144 100644 --- a/main/load-tx-rlp.zkasm +++ b/main/load-tx-rlp.zkasm @@ -61,7 +61,7 @@ loadTx_rlp_continue: A - 0xc1 :JMPN(invalidTxRLP) A - 0xf8 :JMPN(shortList) ; do not allow lists over 2**24 bytes length - ; Transaction could not have more than 120.000 due to smart contract limitation (keccaks counters) + ; Transaction could not have more than 4096*31 bytes due to smart contract limitation (keccaks counters) ; meaning that the RLP encoding is wrong A - 0xfb :JMPN(longList, invalidTxRLP) @@ -197,7 +197,7 @@ dataREAD: A - 0x81 :JMPN(zeroBytesData) A - 0xb8 :JMPN(shortData) ; do not allow string over 2**24 bytes length - ; Transaction could not have more than 120.000 due to smart contract limitation (keccaks counters) + ; Transaction could not have more than 4096*31 bytes due to smart contract limitation (keccaks counters) ; meaning that the RLP encoding is wrong A - 0xbb :JMPN(longData, invalidTxRLP) @@ -267,7 +267,7 @@ zeroBytesData: endData: ; Check all bytes read to detect pre EIP-155 tx, if bytes read are the same as txLength, we reached the end, so it's a pre EIP-155 tx - ; txRLPLength and C is at most 120.000 bytes, no need to use a binary for comparison + ; txRLPLength and C is at most 4096*31 bytes, no need to use a binary for comparison $ => B :MLOAD(txRLPLength) C - B :JMPZ(setPreEIP155Flag) @@ -302,7 +302,7 @@ setPreEIP155Flag: ;; size verification ; checks RLP length read at the RLP header with bytes read during RLP parsing sizeVerification: - ; txRLPLength and C is at most 120.000 bytes, no need to use a binary for comparison + ; txRLPLength and C is at most 4096*31 bytes, no need to use a binary for comparison $ => B :MLOAD(txRLPLength) C - B :JMPZ(sizeVerificationSuccess, invalidTxRLP) sizeVerificationSuccess: diff --git a/main/main.zkasm b/main/main.zkasm index c6dc41fa..e20c8622 100644 --- a/main/main.zkasm +++ b/main/main.zkasm @@ -18,7 +18,7 @@ start: ; main zkROM entry point 0 :ASSERT ; Ensure it is the beginning of the execution CTX :MSTORE(forkID) ; Fork id from CTX, assumed to be less than 32 bits - CTX - %FORK_ID :JMPNZ(failAssert) + CTX - %FORK_ID :JMPNZ(failAssertInvalidForkId) SR => A :MSTORE(oldStateRoot) ; oldStateRoot from SR SR :MSTORE(batchSR) diff --git a/main/modexp/array_lib/array_add_AGTB.zkasm b/main/modexp/array_lib/array_add_AGTB.zkasm index 5281c8a5..1f52de6c 100644 --- a/main/modexp/array_lib/array_add_AGTB.zkasm +++ b/main/modexp/array_lib/array_add_AGTB.zkasm @@ -132,7 +132,7 @@ array_add_AGTB_check_carry: array_add_AGTB_is_carry: ; Carry path - E - %ARRAY_MAX_LEN_DOUBLED :JMPZ(failAssert) + E - %ARRAY_MAX_LEN_DOUBLED :JMPZ(failAssertModexp) ; In this case, the carry = 1 and we should append it to the result 1 :MSTORE(array_add_AGTB_out + E) diff --git a/main/modexp/array_lib/array_div_long.zkasm b/main/modexp/array_lib/array_div_long.zkasm index de803a25..6af8d9ed 100644 --- a/main/modexp/array_lib/array_div_long.zkasm +++ b/main/modexp/array_lib/array_div_long.zkasm @@ -86,7 +86,7 @@ array_div_long: RR :JMPN(array_div_long_check_inALTinB) - C - RR :JMPN(failAssert) ; if C < RR ERROR + C - RR :JMPN(failAssertModexp) ; if C < RR ERROR RR - 1 => RR ; Moving from i+1 to i ; Ensure the received chunk is higher @@ -125,7 +125,7 @@ array_div_long_same_input: 1 :MSTORE(array_div_long_len_rem), JMP(array_div_long_end) array_div_long_check_inALTinB: - RR + C :JMPN(failAssert) ; if RR < -C ERROR + RR + C :JMPN(failAssertModexp) ; if RR < -C ERROR -RR - 1 => RR ; Moving from -i-1 to i ; Ensure that the received chunk is lower @@ -168,10 +168,10 @@ array_div_long_inAGTinB: ; len(Q) + len(inB) - 1 <= len(Q·inB) <= len(inA) ; 1] The received length must satisfy 1 <= len(Q) <= len(inA) - len(inB) + 1 - C - 1 => RR :JMPN(failAssert) ; if len(Q) < 1 ERROR + C - 1 => RR :JMPN(failAssertModexp) ; if len(Q) < 1 ERROR $ => A :MLOAD(array_div_long_len_inA) $ => B :MLOAD(array_div_long_len_inB) - A - B + 1 - C :JMPN(failAssert) ; if len(inA) - len(inB) + 1 < len(Q) ERROR + A - B + 1 - C :JMPN(failAssertModexp) ; if len(inA) - len(inB) + 1 < len(Q) ERROR ; 2] To avoid non-determinism, we must ensure that the quotient is trimmed ; i.e., that its last chunk is not 0 @@ -214,9 +214,9 @@ array_div_long_mul_quo_inB: $0{receiveLenRemainder()} => D :JMPZ(array_div_long_rem_is_zero) ; 1] The received length must satisfy 1 <= len(R) <= len(inB) <= len(inA) - D - 1 => E :JMPN(failAssert) ; if len(R) < 1 ERROR + D - 1 => E :JMPN(failAssertModexp) ; if len(R) < 1 ERROR $ => C :MLOAD(array_div_long_len_inB) - C - D :JMPN(failAssert) ; if len(inB) < len(R) ERROR + C - D :JMPN(failAssertModexp) ; if len(inB) < len(R) ERROR ; 2] To avoid non-determinism, we must ensure that the remainder is trimmed ; i.e., that its last chunk is not 0 @@ -236,8 +236,8 @@ array_div_long_mul_quo_inB: D - C :JMPN(array_div_long_rem_lower) ; If len(R) == len(B), then we must compare them chunk by chunk - ${getFirstDiffChunkRem(addr.array_div_long_inB,mem.array_div_long_len_inB)} => RR :JMPN(failAssert) - D - 1 - RR :JMPN(failAssert) ; if D - 1 < RR ERROR + ${getFirstDiffChunkRem(addr.array_div_long_inB,mem.array_div_long_len_inB)} => RR :JMPN(failAssertModexp) + D - 1 - RR :JMPN(failAssertModexp) ; if D - 1 < RR ERROR ; if it is the last chunk, then we are done E - RR :JMPZ(array_div_long_compare_rem_first) diff --git a/main/modexp/array_lib/array_div_short.zkasm b/main/modexp/array_lib/array_div_short.zkasm index 13c2bf77..33f506c5 100644 --- a/main/modexp/array_lib/array_div_short.zkasm +++ b/main/modexp/array_lib/array_div_short.zkasm @@ -78,7 +78,7 @@ array_div_short_equal_len: RR :JMPN(array_div_short_check_inALTinB) - 1 - RR :JMPN(failAssert) ; if 1 < RR ERROR + 1 - RR :JMPN(failAssertModexp) ; if 1 < RR ERROR ; Ensure that the chunk is higher $ => A :MLOAD(array_div_short_inB) @@ -103,7 +103,7 @@ array_div_short_same_input: 0 :MSTORE(array_div_short_rem), JMP(array_div_short_end) array_div_short_check_inALTinB: - RR + 1 :JMPN(failAssert) ; if RR < -1 ERROR + RR + 1 :JMPN(failAssertModexp) ; if RR < -1 ERROR $ => A :MLOAD(array_div_short_inA) $ => B :MLOAD(array_div_short_inB) @@ -126,9 +126,9 @@ array_div_short_inAGTinB: $0{receiveLenQuotient_short()} => C ; It cannot be zero because q=0 happens only when inA < inB ; 1] The received length must satisfy 1 <= len(Q) <= len(inA) - C - 1 => RR :JMPN(failAssert) ; if len(Q) < 1 ERROR + C - 1 => RR :JMPN(failAssertModexp) ; if len(Q) < 1 ERROR $ => A :MLOAD(array_div_short_len_inA) - A - C :JMPN(failAssert) ; if len(inA) < len(Q) ERROR + A - C :JMPN(failAssertModexp) ; if len(inA) < len(Q) ERROR ; 2] To avoid non-determinism, we must ensure that the quotient is trimmed ; i.e., that its last chunk is not 0 diff --git a/main/modexp/array_lib/array_div_two.zkasm b/main/modexp/array_lib/array_div_two.zkasm index ca2836d9..d5e23f2c 100644 --- a/main/modexp/array_lib/array_div_two.zkasm +++ b/main/modexp/array_lib/array_div_two.zkasm @@ -54,7 +54,7 @@ array_div_two: RR :JMPN(array_div_two_check_inALTtwo) - 1 - RR :JMPN(failAssert) ; if 1 < RR ERROR + 1 - RR :JMPN(failAssertModexp) ; if 1 < RR ERROR ; Ensure that the chunk is higher 2 => A @@ -71,7 +71,7 @@ array_div_two_same_input: 1 :MSTORE(array_div_two_len_quo), JMP(array_div_two_end) array_div_two_check_inALTtwo: - RR + 1 :JMPN(failAssert) ; if RR < -1 ERROR + RR + 1 :JMPN(failAssertModexp) ; if RR < -1 ERROR $ => A :MLOAD(array_div_two_in) 2 => B @@ -92,9 +92,9 @@ array_div_two_inAGTinB: $0{receiveLenQuotient_short()} => C ; It cannot be zero because q=0 happens only when in < 2 ; 1] The received length must satisfy 1 <= len(Q) <= len(in) - C - 1 => RR :JMPN(failAssert) ; if len(Q) < 1 ERROR + C - 1 => RR :JMPN(failAssertModexp) ; if len(Q) < 1 ERROR $ => A :MLOAD(array_div_two_len_in) - A - C :JMPN(failAssert) ; if len(in) < len(Q) ERROR + A - C :JMPN(failAssertModexp) ; if len(in) < len(Q) ERROR ; 2] To avoid non-determinism, we must ensure that the quotient is trimmed ; i.e., that its last chunk is not 0 diff --git a/main/modexp/array_lib/array_mul_long.zkasm b/main/modexp/array_lib/array_mul_long.zkasm index 5aeac600..b858f92c 100644 --- a/main/modexp/array_lib/array_mul_long.zkasm +++ b/main/modexp/array_lib/array_mul_long.zkasm @@ -199,7 +199,7 @@ array_mul_long_check_carry: $ :EQ, JMPNZ(array_mul_long_trim) ; Carry path - E - %ARRAY_MAX_LEN_DOUBLED :JMPZ(failAssert) + E - %ARRAY_MAX_LEN_DOUBLED :JMPZ(failAssertModexp) E + 1 :MSTORE(array_mul_long_len_out), JMP(array_mul_long_end) diff --git a/main/modexp/array_lib/array_mul_two.zkasm b/main/modexp/array_lib/array_mul_two.zkasm index fab9067b..29812825 100644 --- a/main/modexp/array_lib/array_mul_two.zkasm +++ b/main/modexp/array_lib/array_mul_two.zkasm @@ -91,7 +91,7 @@ array_mul_two_check_carry: array_mul_two_is_carry: ; Carry path - E - %ARRAY_MAX_LEN :JMPZ(failAssert) + E - %ARRAY_MAX_LEN :JMPZ(failAssertModexp) ; In this case, the carry = 1 and we should append it to the result 1 :MSTORE(array_mul_two_out + E) diff --git a/main/opcodes/calldata-returndata-code.zkasm b/main/opcodes/calldata-returndata-code.zkasm index cdff1ed6..eaf6c324 100644 --- a/main/opcodes/calldata-returndata-code.zkasm +++ b/main/opcodes/calldata-returndata-code.zkasm @@ -391,7 +391,7 @@ opEXTCODECOPY: ; store lastMemLength for memory expansion gas cost, we store also at RCX to recover later ; compute memory expansion gas cost - E => RCX :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength] + E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength] ; check out-of-gas ;${3*((E+31)/32)} @@ -402,7 +402,8 @@ opEXTCODECOPY: ; 3*((E+31)/32) ; check out-of-gas GAS - 3 * E => GAS :JMPN(outOfGas) - RCX => E + ; Recover secured lastMemLength at E + $ => E :MLOAD(lastMemLength) B => C ; if offset is above data len, length => offset D => A @@ -508,7 +509,7 @@ opRETURNDATACOPY: ; store lastMemOffset for memory expansion gas cost D :MSTORE(lastMemOffset) ; store lastMemLength for memory expansion gas cost, we store also at RCX to recover later - C => RCX :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength] + C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength] ; if retDataCTX is 0, end opcode execution $ => B :MLOAD(retDataCTX), JMPZ(opRETURNDATACOPYEmpty) ; Load ret data length from last ctx @@ -530,7 +531,8 @@ opRETURNDATACOPY: ; C is secured to be less than 32 bits after calling saveMem ;(C+31)/32 C + 31 => A :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - RCX => C + ; Recover secured lastMemLength at C + $ => C :MLOAD(lastMemLength) ; 3*((C+31)/32) ; check out-of-gas GAS - 3 * E => GAS :JMPN(outOfGas) diff --git a/main/opcodes/storage-memory.zkasm b/main/opcodes/storage-memory.zkasm index 63a81da4..0894af81 100644 --- a/main/opcodes/storage-memory.zkasm +++ b/main/opcodes/storage-memory.zkasm @@ -95,7 +95,7 @@ opMSTORE8: ; store lastMemLength for memory expansion gas cost. In case of MSTORE8, always 1 byte 1 :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength] B => A :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - $ => RCX :MLOAD(SP); [value => B] + $ => RCX :MLOAD(SP); [value => B] ; DANGER -> make test ; read from memory position E $ => A :MLOAD(MEM:E) diff --git a/main/process-tx.zkasm b/main/process-tx.zkasm index 88109a84..1997d383 100644 --- a/main/process-tx.zkasm +++ b/main/process-tx.zkasm @@ -368,11 +368,14 @@ readDeployBytecodeCreate: $ => CTX :MLOAD(originCTX) ; check enough bytes to read in memory E - PC - 1 :JMPN(readDeployBytecodeCreateDefault) - $ + PC => E :F_MLOAD(argsOffsetCall) - 1 => C :CALL(MLOADX) ; in: [E: offset, C: length] out: [A: value, E: new offset] + + %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) + $ + PC => A :F_MLOAD(argsOffsetCall), CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] + C * %MEM_ALIGN_OFFSET + %MEM_ALIGN_SIZE => C + $ => A :MLOAD(MEM:E) + $ => B :MLOAD(MEM:E+1) + $ => A, RR :MEM_ALIGN_RD $ => CTX :MLOAD(currentCTX) - 31 => D :CALL(SHRarith) ; in: [A: value, D: #bytes to right shift] out: [A: shifted result] - A => RR $${eventLog(onOpcode(RR))} PC + 1 => PC :JMP(@mapping_opcodes + RR) diff --git a/main/utils.zkasm b/main/utils.zkasm index 88bf6262..da27ec8b 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -124,11 +124,11 @@ __MSTOREX_afterSave: $0{E > 0xFFFFFFFF ? -1:E} => A :JMPN(__errorEmore32bits) E :ASSERT,JMP_GE(%MAX_MEM_EXPANSION_BYTES, errorMLOADMSTORE) - $0{E / 32} => RR :JMPN(failAssert) + $0{E / 32} => RR :JMPN(failAssertMstoreX) ; RR = 32 bits positive value $BYTE{E%32} => RCX,A - RCX :JMP_GT(31, failAssert) + RCX :JMP_GT(31, failAssertMstoreX) ; E === 32 * RR + A (RCX) ; E - 32 * RR === A @@ -196,11 +196,11 @@ __MLOADX_afterSave: $0{E > 0xFFFFFFFF ? -1:E} => A :JMPN(__errorEmore32bits) E :ASSERT,JMP_GE(%MAX_MEM_EXPANSION_BYTES, errorMLOADMSTORE) - $0{E / 32} => RR :JMPN(failAssert) + $0{E / 32} => RR :JMPN(failAssertMloadX) ; RR = 32 bits positive value $BYTE{E%32} => RCX,A - RCX :JMP_GT(31, failAssert) + RCX :JMP_GT(31, failAssertMloadX) ; E === 32 * RR + A (RCX) ; E - 32 * RR === A @@ -298,7 +298,7 @@ computeGasSendCall: ; C = [c7, c6, ..., c0] ; JMPN instruction assures c0 is within the range [0, 2**32 - 1] - ${GAS >> 6} => C :JMPN(failAssert) + ${GAS >> 6} => C :JMPN(failAssertComputeGasSendCall) ; We secure D to be less than 32 bits with $0{} $0{GAS & 0x3f} => D @@ -307,7 +307,7 @@ computeGasSendCall: ; that equals the field ; Since e0 is assured to be less than 32 bits, c0 * 64 + d0 could not overflow the field C * 64 + D :ASSERT - 0x3f - D :JMPN(failAssert) ; D is less than 32 bits, we can use JMPN + 0x3f - D :JMPN(failAssertComputeGasSendCall) ; D is less than 32 bits, we can use JMPN GAS - C => A ; gasCall can be more than 32 bits, obtained from stack @@ -356,7 +356,7 @@ saveMemGAS: ; E = [e7, e6, ..., e0] ; JMPN instruction assures e0 is within the range [0, 2**32 - 1] - ${A >> 5} => E :JMPN(failAssert) + ${A >> 5} => E :JMPN(failAssertSaveMemGAS) $0{A & 0x1f} => D ; since D is assured to be less than 0x20 @@ -364,7 +364,7 @@ saveMemGAS: ; that equals the field ; Since e0 is assured to be less than 32 bits, e0 * 32 + d0 could not overflow the field E * 32 + D :ASSERT - 0x1f - D :JMPN(failAssert) ; D is less than 32 bits, we can use JMPN + 0x1f - D :JMPN(failAssertSaveMemGAS) ; D is less than 32 bits, we can use JMPN ; memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) in A ; ${E*E/512} + 3*E=> A @@ -705,8 +705,8 @@ offsetUtil: ; E = [e7, e6, ..., e0] ; JMPN instruction assures e0 is within the range [0, 2**32 - 1] - ${A >> 5} => E :JMPN(failAssert) - $0{A & 0x1F} => C :JMP_GT(0x1F, failAssert); C is 32 bits, If C is greater than 31 (remainder), it is an error + ${A >> 5} => E :JMPN(failAssertOffsetUtil) + $0{A & 0x1F} => C :JMP_GT(0x1F, failAssertOffsetUtil); C is 32 bits, If C is greater than 31 (remainder), it is an error ; since C is assured to be less than 0x20 ; it is enforced that [e7, e6, ..., e1] are 0 since there is no value multiplied by 32 @@ -1134,7 +1134,7 @@ utilMULMOD: ; 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) + $ => A :ADD,JMPC(failAssertMulMod) $ :MLOAD(mulArithOverflowValue), ASSERT, JMP(utilMULMODend) mulModNoKH: @@ -1224,7 +1224,24 @@ expADend: ;@info function to force a failed assert failAssert: A - 1 :ASSERT - +failAssertInvalidForkId: + A - 1 :ASSERT +failAssertMstoreX: + A - 1 :ASSERT +failAssertMloadX: + A - 1 :ASSERT +failAssertComputeGasSendCall: + A - 1 :ASSERT +failAssertSaveMemGAS: + A - 1 :ASSERT +failAssertOffsetUtil: + A - 1 :ASSERT +failAssertMulMod: + A - 1 :ASSERT +failAssertModexp: + A - 1 :ASSERT +failAssertEcrecover: + A - 1 :ASSERT VAR GLOBAL tmpZkPCComputeMerkleProof ;@info Computes merkle root with from currentL1InfoTreeRoot, currentL1InfoTreeIndex and siblings ;@out C: merkle tree root