Skip to content

Commit

Permalink
Merge pull request #169 from 0xPolygonHermez/feature/exp-new
Browse files Browse the repository at this point in the history
Update exp
  • Loading branch information
krlosMata authored Nov 14, 2022
2 parents e2bdbcf + bf1c586 commit 2188585
Show file tree
Hide file tree
Showing 7 changed files with 904 additions and 172 deletions.
520 changes: 520 additions & 0 deletions main/2-exp.zkasm

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion main/load-tx-rlp.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ endChainId:
0x8080 => B
$ :EQ,JMPC(sizeVerification)
:JMP(invalidTxRLP)

setPreEIP155Flag:
1 :MSTORE(isPreEIP155)
;; size verification
Expand Down
116 changes: 16 additions & 100 deletions main/opcodes/arithmetic.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ AddModJumpCarry:

$ => A :MLOAD(SP) ; load modulus
2 => B
$ :LT, JMPC(zeroOneMod)
$ :LT, JMPC(zeroOneAddMod)

${_addMod / A} => B ; k: Max should be (2^256 -1) * 2 / 2 --> smaller than 2^256
${_addMod % A} => C ; addModResult
Expand All @@ -235,122 +235,34 @@ AddModJumpCarry:
C :MSTORE(SP++)
:JMP(readCode)

opMULMOD:
%MAX_CNT_ARITH - CNT_ARITH - 3 :JMPN(outOfCountersArith)
%MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary)
%MAX_CNT_STEPS - STEP - 150 :JMPN(outOfCountersStep)
zeroOneAddMod:
0 :MSTORE(SP++)
:JMP(readCode)

opMULMOD:
GAS-8 => GAS :JMPN(outOfGas)
SP - 3 :JMPN(stackUnderflow)
SP - 1 => SP

; 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 divedit in the
; most significan 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
$ => A :MLOAD(SP--)
$ => B :MLOAD(SP--)

; Mul operation with Arith
${var _mulMod = A * B} ; TODO $$
A :MSTORE(arithA)
B :MSTORE(arithB)
; here we perform the: A * B + 0 = D*2^256 + E
; result is stored in: arithRes1(E) and arithOverflow(D)
:CALL(mulARITH)

$ => A :MLOAD(SP) ; Modulus N
; 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
A => C ; modulus on C
${(_mulMod / C) >> 256} => B ; k.h
; We can jump with Js, because later it's all verified by the ARITH
${cond(B == 0)} :JMPN(mulModNoKH)

; 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(tmpVarD), 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 arithOverflow(D)

${(_mulMod / A) % (2 << 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(tmpVarD) ;D2
$ => A :ADD
$ :MLOAD(arithOverflow), ASSERT
$ => C :MLOAD(SP) ; Modulus N
zkPC+1 => RR :JMP(utilMULMOD)

C :MSTORE(SP++)
:JMP(readCode)

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(arithOverflow)
$ :MLOAD(arithRes1), ARITH ; Can this be on the same line of MLOAD?

A => B ; modulus
C => A ; mulModResult
$ => A :LT
1 :ASSERT
C :MSTORE(SP++)
:JMP(readCode)
zeroOneMod:
0 :MSTORE(SP++)
:JMP(readCode)

opEXP: ; //TODO: test exp == 0

%MAX_CNT_ARITH - CNT_ARITH - 512 :JMPN(outOfCountersArith)
%MAX_CNT_BINARY - CNT_BINARY - 1025 :JMPN(outOfCountersBinary)
%MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary)
%MAX_CNT_STEPS - STEP - 120 :JMPN(outOfCountersStep)

SP - 2 :JMPN(stackUnderflow)
SP - 1 => SP
$ => A :MLOAD(SP--)
$ => B :MLOAD(SP)
${exp(A,B)} => A
B => D
zkPC+1 => RR :JMP(expAD)
A :MSTORE(SP++)
1024 - SP :JMPN(stackOverflow)
:CALL(getLenBytes)
Expand All @@ -369,8 +281,12 @@ opSIGNEXTEND: ; following this impl https://github.com/ethereumjs/ethereumjs-mon
30 => A
$ :LT, JMPC(opSIGNEXTENDEnd); if signByte is 31 or more, means basically let the number as it is
; TODO we could divide this opcode in a table with constants, only 31 cases
B * 8 + 7 => B ; B is less than 31, no need for binary
${exp(2, B)} => A ; signBit TODO table for shifting + multipliyng
B * 8 + 7 => D ; B is less than 31, no need for binary
D*2 => RR
zkPC+2 :MSTORE(tmpSHXZkPC)
:JMP(@exp_num + RR) ; signBit TODO table for shifting + multipliyng
B => A
$ => D :MLOAD(SP) ; number to convert

;Store mask
1 => B
Expand Down
3 changes: 3 additions & 0 deletions main/opcodes/flow-control.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ checkJumpDest:
$ => A :MLOAD(isCreateContract)
-A :JMPN(checkJumpDestDeployment)
PC => HASHPOS
HASHPOS => B
$ => A :MLOAD(bytecodeLength)
$ :LT,JMPC(invalidJump)
; set number of bytes to hashP at D
1 => D
; get hashP address pointer where contract bytecode is stored
Expand Down
1 change: 1 addition & 0 deletions main/process-tx.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ INCLUDE "map-opcodes.zkasm"
INCLUDE "precompiled/selector.zkasm"
INCLUDE "ecrecover/ecrecover.zkasm"
INCLUDE "touched.zkasm"
INCLUDE "2-exp.zkasm"

; Blocks process txs
; A - Verify ecdsa signature
Expand Down
Loading

0 comments on commit 2188585

Please sign in to comment.