Skip to content

Commit

Permalink
Optimizations III
Browse files Browse the repository at this point in the history
  • Loading branch information
ignasirv committed Apr 29, 2024
1 parent 6ad29f2 commit bccc5c2
Show file tree
Hide file tree
Showing 15 changed files with 69 additions and 50 deletions.
4 changes: 1 addition & 3 deletions main/constants.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
CONST %MEM_ALIGN_LITTLE_ENDIAN = 2**14
2 changes: 1 addition & 1 deletion main/ecrecover/dblScalarMulSecp256k1.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
; ------------------------------


Expand Down
1 change: 0 additions & 1 deletion main/load-tx-rlp-utils.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions main/load-tx-rlp.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion main/main.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion main/modexp/array_lib/array_add_AGTB.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 8 additions & 8 deletions main/modexp/array_lib/array_div_long.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions main/modexp/array_lib/array_div_short.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand Down
8 changes: 4 additions & 4 deletions main/modexp/array_lib/array_div_two.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion main/modexp/array_lib/array_mul_long.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion main/modexp/array_lib/array_mul_two.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 6 additions & 4 deletions main/opcodes/calldata-returndata-code.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion main/opcodes/storage-memory.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
11 changes: 7 additions & 4 deletions main/process-tx.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
41 changes: 29 additions & 12 deletions main/utils.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -356,15 +356,15 @@ 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
; it is enforced that [e7, e6, ..., e1] are 0 since there is no value multiplied by 32
; 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit bccc5c2

Please sign in to comment.