zkevm-rom 0.0.1-security → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of zkevm-rom might be problematic. Click here for more details.
- package/.eslintrc.js +33 -0
- package/.github/CODEOWNERS +14 -0
- package/.github/ISSUE_TEMPLATE/bug.yml +38 -0
- package/.github/ISSUE_TEMPLATE/feature.yml +26 -0
- package/.github/ISSUE_TEMPLATE/question.yml +26 -0
- package/.github/workflows/main.yaml +40 -0
- package/LICENSE +636 -0
- package/README.md +23 -5
- package/audits/Hexens_Polygon_zkEVM_PUBLIC_27.02.23.pdf +0 -0
- package/audits/Polygon-zkEVM-Public-v1.1-verichains-19-03-2024.pdf +0 -0
- package/audits/zkEVM-ROM-upgrade-1-Spearbit-30-May.pdf +0 -0
- package/audits/zkEVM-ROM-upgrade-2-Spearbit-21-August.pdf +0 -0
- package/audits/zkEVM-engagement-1-Spearbit-27-March.pdf +0 -0
- package/audits/zkEVM-engagement-2-Spearbit-27-March.pdf +0 -0
- package/audits/zkEVM-engagement-3-Spearbit-6-April.pdf +0 -0
- package/counters/README.md +45 -0
- package/counters/counters-executor.js +80 -0
- package/counters/countersConstants.zkasm +370 -0
- package/counters/endIncludes.zkasm +18 -0
- package/counters/initIncludes.zkasm +2 -0
- package/counters/tests/MLOAD32.zkasm +27 -0
- package/counters/tests/MLOADX.zkasm +30 -0
- package/counters/tests/MSTORE32.zkasm +32 -0
- package/counters/tests/MSTOREX.zkasm +36 -0
- package/counters/tests/SHLarith.zkasm +28 -0
- package/counters/tests/SHLarithBit.zkasm +28 -0
- package/counters/tests/SHRarith.zkasm +28 -0
- package/counters/tests/SHRarithBit.zkasm +28 -0
- package/counters/tests/abs.zkasm +29 -0
- package/counters/tests/addBatchHashByteByByte.zkasm +31 -0
- package/counters/tests/computeGasSendCall.zkasm +30 -0
- package/counters/tests/divArith.zkasm +27 -0
- package/counters/tests/expAD.zkasm +30 -0
- package/counters/tests/getLenBits.zkasm +30 -0
- package/counters/tests/getLenBytes.zkasm +32 -0
- package/counters/tests/isEmptyAccount.zkasm +30 -0
- package/counters/tests/mulARITH.zkasm +28 -0
- package/counters/tests/offsetUtil.zkasm +29 -0
- package/counters/tests/opADDMOD.zkasm +28 -0
- package/counters/tests/opAdd.zkasm +27 -0
- package/counters/tests/opBLOCKHASH.zkasm +28 -0
- package/counters/tests/opCALL.zkasm +41 -0
- package/counters/tests/opCALLCODE.zkasm +41 -0
- package/counters/tests/opCALLDATACOPY.zkasm +28 -0
- package/counters/tests/opCALLDATALOAD.zkasm +27 -0
- package/counters/tests/opCODECOPY.zkasm +28 -0
- package/counters/tests/opCREATE.zkasm +35 -0
- package/counters/tests/opCREATE2.zkasm +35 -0
- package/counters/tests/opDELEGATECALL.zkasm +35 -0
- package/counters/tests/opDIV.zkasm +27 -0
- package/counters/tests/opEXP.zkasm +29 -0
- package/counters/tests/opEXTCODECOPY.zkasm +29 -0
- package/counters/tests/opMOD.zkasm +27 -0
- package/counters/tests/opMUL.zkasm +27 -0
- package/counters/tests/opMULMOD.zkasm +28 -0
- package/counters/tests/opRETURN.zkasm +32 -0
- package/counters/tests/opRETURNDATACOPY.zkasm +29 -0
- package/counters/tests/opREVERT.zkasm +32 -0
- package/counters/tests/opSDIV.zkasm +28 -0
- package/counters/tests/opSHA3.zkasm +28 -0
- package/counters/tests/opSIGNEXTEND.zkasm +27 -0
- package/counters/tests/opSMOD.zkasm +28 -0
- package/counters/tests/opSTATICCALL.zkasm +35 -0
- package/counters/tests/opSUB.zkasm +27 -0
- package/counters/tests/saveMem.zkasm +31 -0
- package/docs/opcode-cost-zk-counters.md +315 -0
- package/docs/usage-ecrecover.md +51 -0
- package/index.js +43 -0
- package/main/block-info.zkasm +204 -0
- package/main/constants.zkasm +145 -0
- package/main/ecrecover/addFpEc.zkasm +31 -0
- package/main/ecrecover/checkSqrtFpEc.zkasm +1558 -0
- package/main/ecrecover/constEc.zkasm +13 -0
- package/main/ecrecover/ecrecover.zkasm +280 -0
- package/main/ecrecover/invFnEc.zkasm +44 -0
- package/main/ecrecover/invFpEc.zkasm +45 -0
- package/main/ecrecover/mulFnEc.zkasm +36 -0
- package/main/ecrecover/mulFpEc.zkasm +36 -0
- package/main/ecrecover/mulPointEc.zkasm +311 -0
- package/main/ecrecover/sqFpEc.zkasm +38 -0
- package/main/ecrecover/sqrtFpEc.zkasm +70 -0
- package/main/end.zkasm +4 -0
- package/main/l2-tx-hash.zkasm +159 -0
- package/main/load-change-l2-block-utils.zkasm +11 -0
- package/main/load-change-l2-block.zkasm +28 -0
- package/main/load-tx-rlp-utils.zkasm +72 -0
- package/main/load-tx-rlp.zkasm +431 -0
- package/main/main.zkasm +237 -0
- package/main/map-opcodes.zkasm +274 -0
- package/main/modexp/array_lib/array_add_AGTB.zkasm +123 -0
- package/main/modexp/array_lib/array_add_short.zkasm +85 -0
- package/main/modexp/array_lib/array_div.zkasm +215 -0
- package/main/modexp/array_lib/array_div_long.zkasm +284 -0
- package/main/modexp/array_lib/array_div_short.zkasm +222 -0
- package/main/modexp/array_lib/array_mul.zkasm +97 -0
- package/main/modexp/array_lib/array_mul_long.zkasm +156 -0
- package/main/modexp/array_lib/array_mul_short.zkasm +127 -0
- package/main/modexp/array_lib/array_square.zkasm +246 -0
- package/main/modexp/array_lib/unused/array_add.zkasm +100 -0
- package/main/modexp/array_lib/unused/array_is_odd.zkasm +23 -0
- package/main/modexp/array_lib/unused/array_is_one.zkasm +33 -0
- package/main/modexp/array_lib/unused/array_is_zero.zkasm +34 -0
- package/main/modexp/array_lib/unused/array_sub_AGTB.zkasm +111 -0
- package/main/modexp/array_lib/unused/array_unshift.zkasm +37 -0
- package/main/modexp/array_lib/utils/array_compare.zkasm +82 -0
- package/main/modexp/array_lib/utils/array_trim.zkasm +49 -0
- package/main/modexp/constants.zkasm +5 -0
- package/main/modexp/modexp.zkasm +296 -0
- package/main/modexp/modexp_utils.zkasm +230 -0
- package/main/opcodes/arithmetic.zkasm +357 -0
- package/main/opcodes/block.zkasm +163 -0
- package/main/opcodes/calldata-returndata-code.zkasm +619 -0
- package/main/opcodes/comparison.zkasm +446 -0
- package/main/opcodes/context-information.zkasm +169 -0
- package/main/opcodes/create-terminate-context.zkasm +1011 -0
- package/main/opcodes/crypto.zkasm +96 -0
- package/main/opcodes/flow-control.zkasm +126 -0
- package/main/opcodes/logs.zkasm +193 -0
- package/main/opcodes/stack-operations.zkasm +658 -0
- package/main/opcodes/storage-memory.zkasm +313 -0
- package/main/pairings/BN254/addPointBN254.zkasm +245 -0
- package/main/pairings/BN254/ecAdd.zkasm +312 -0
- package/main/pairings/BN254/ecMul.zkasm +159 -0
- package/main/pairings/BN254/escalarMulBN254.zkasm +155 -0
- package/main/pairings/BN254/lineDiffPointsBN254.zkasm +83 -0
- package/main/pairings/BN254/lineSamePointsBN254.zkasm +96 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm +49 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm +236 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm +444 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm +212 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm +228 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm +64 -0
- package/main/pairings/FP12BN254/frob2Fp12BN254.zkasm +80 -0
- package/main/pairings/FP12BN254/frob3Fp12BN254.zkasm +96 -0
- package/main/pairings/FP12BN254/frobFp12BN254.zkasm +96 -0
- package/main/pairings/FP12BN254/inverseFp12BN254.zkasm +289 -0
- package/main/pairings/FP12BN254/mulFp12BN254.zkasm +408 -0
- package/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm +296 -0
- package/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm +291 -0
- package/main/pairings/FP12BN254/squareFp12BN254.zkasm +376 -0
- package/main/pairings/FP2BN254/addFp2BN254.zkasm +19 -0
- package/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm +20 -0
- package/main/pairings/FP2BN254/invFp2BN254.zkasm +66 -0
- package/main/pairings/FP2BN254/mulFp2BN254.zkasm +19 -0
- package/main/pairings/FP2BN254/squareFp2BN254.zkasm +21 -0
- package/main/pairings/FP2BN254/subFp2BN254.zkasm +19 -0
- package/main/pairings/FP4BN254/squareFp4BN254.zkasm +76 -0
- package/main/pairings/FP6BN254/addFp6BN254.zkasm +59 -0
- package/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm +51 -0
- package/main/pairings/FP6BN254/inverseFp6BN254.zkasm +208 -0
- package/main/pairings/FP6BN254/mulFp6BN254.zkasm +201 -0
- package/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm +65 -0
- package/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm +134 -0
- package/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm +128 -0
- package/main/pairings/FP6BN254/squareFp6BN254.zkasm +147 -0
- package/main/pairings/FP6BN254/subFp6BN254.zkasm +59 -0
- package/main/pairings/FPBN254/addFpBN254.zkasm +29 -0
- package/main/pairings/FPBN254/invFpBN254.zkasm +55 -0
- package/main/pairings/FPBN254/mulFpBN254.zkasm +29 -0
- package/main/pairings/FPBN254/reduceFpBN254.zkasm +25 -0
- package/main/pairings/FPBN254/squareFpBN254.zkasm +31 -0
- package/main/pairings/FPBN254/subFpBN254.zkasm +36 -0
- package/main/pairings/FRBN254/reduceFrBN254.zkasm +25 -0
- package/main/pairings/constants.zkasm +62 -0
- package/main/pairings/ecPairing.zkasm +244 -0
- package/main/pairings/finalExpBN254.zkasm +2095 -0
- package/main/pairings/halfPairingBN254.zkasm +428 -0
- package/main/pairings/loopLengthBN254.zkasm +75 -0
- package/main/pairings/millerLoopBN254.zkasm +741 -0
- package/main/pairings/pairingBN254.zkasm +481 -0
- package/main/pairings/unused/addFp12BN254.zkasm +130 -0
- package/main/pairings/unused/expByXCycloFp12BN254.zkasm +411 -0
- package/main/pairings/unused/expFp12BN254.zkasm +333 -0
- package/main/pairings/unused/subFp12BN254.zkasm +130 -0
- package/main/pairings/unused/xPseudoBinDecompBN254.zkasm +68 -0
- package/main/pairings/utilsTests/expCycloFp12BN254.zkasm +334 -0
- package/main/precompiled/end.zkasm +42 -0
- package/main/precompiled/identity.zkasm +99 -0
- package/main/precompiled/pre-ecAdd.zkasm +84 -0
- package/main/precompiled/pre-ecMul.zkasm +82 -0
- package/main/precompiled/pre-ecPairing.zkasm +72 -0
- package/main/precompiled/pre-ecrecover.zkasm +71 -0
- package/main/precompiled/pre-modexp.zkasm +367 -0
- package/main/precompiled/pre-sha2-256.zkasm +125 -0
- package/main/precompiled/revert-precompiled.zkasm +25 -0
- package/main/precompiled/selector.zkasm +77 -0
- package/main/process-change-l2-block.zkasm +147 -0
- package/main/process-tx.zkasm +587 -0
- package/main/tables/2-exp.zkasm +260 -0
- package/main/touched.zkasm +118 -0
- package/main/utils.zkasm +2335 -0
- package/main/vars.zkasm +117 -0
- package/package.json +62 -3
- package/test/bytes-length.zkasm +39 -0
- package/test/ecrecover.zkasm +538 -0
- package/test/lt4-test.zkasm +38 -0
- package/test/mstorex.zkasm +191 -0
- package/test/opcalldatacopy.ignore.zkasm +331 -0
- package/test/performance/read-push.zkasm +71 -0
- package/test/read-push.zkasm +304 -0
- package/test/testArrayArith.zkasm +1099 -0
- package/test/testArrayUtils.zkasm +335 -0
- package/test/testCycloFp12ArithBN254.zkasm +548 -0
- package/test/testEcAdd.zkasm +252 -0
- package/test/testEcMul.zkasm +231 -0
- package/test/testEcPairing.zkasm +436 -0
- package/test/testFinalExpBn254.zkasm +139 -0
- package/test/testFp12ArithBN254.zkasm +692 -0
- package/test/testFp2ArithBN254.zkasm +185 -0
- package/test/testFp4ArithBN254.zkasm +128 -0
- package/test/testFp6ArithBN254.zkasm +260 -0
- package/test/testFpArithBN254.zkasm +159 -0
- package/test/testFrArithBN254.zkasm +113 -0
- package/test/testHalfPairingBN254.zkasm +285 -0
- package/test/testModExp.zkasm +586 -0
- package/test/testModExpReturn.zkasm +81 -0
- package/test/testPairingBN254.zkasm +463 -0
- package/test/testPointArithBN254.zkasm +270 -0
- package/test/testSHA256.zkasm +27 -0
- package/test/touched-assert.zkasm +59 -0
- package/test/utils-expAD.zkasm +48 -0
- package/test/utils-getLenBytes.zkasm +36 -0
- package/tools/audit-tools/registry-op-checker.js +71 -0
- package/tools/get-not-used-labels.js +31 -0
- package/tools/helpers/helpers.js +47 -0
- package/tools/modexp-utils/README.md +5 -0
- package/tools/modexp-utils/modexp-test-gen.js +168 -0
- package/tools/modexp-utils/modexp-test-int.sage +37 -0
- package/tools/parallel-testing/checker.sh +6 -0
- package/tools/parallel-testing/gen-parallel-tests.js +78 -0
- package/tools/parallel-testing/parallel-tests-sample/sample.test.js +136 -0
- package/tools/run-tests-zkasm.js +83 -0
package/main/utils.zkasm
ADDED
@@ -0,0 +1,2335 @@
|
|
1
|
+
; @info Get absolute value and sign
|
2
|
+
; @in A => number to convert
|
3
|
+
; @out A => Absolute value of A
|
4
|
+
; @out B => Sign of A [1 if negative, 0 positive]
|
5
|
+
abs:
|
6
|
+
; check zk-counters
|
7
|
+
%MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
|
8
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
9
|
+
0 => B
|
10
|
+
; if is negative, change sign
|
11
|
+
$ => B :SLT, JMPC(absIsNeg)
|
12
|
+
:RETURN
|
13
|
+
|
14
|
+
absIsNeg:
|
15
|
+
A => B
|
16
|
+
0 => A
|
17
|
+
; 0 - (-A) = A
|
18
|
+
$ => A :SUB
|
19
|
+
1 => B :RETURN
|
20
|
+
|
21
|
+
VAR GLOBAL tmpVarBgetLen
|
22
|
+
VAR GLOBAL tmpVarCgetLen
|
23
|
+
VAR GLOBAL tmpVarDgetLen
|
24
|
+
VAR GLOBAL tmpZkPCgetLen
|
25
|
+
; @info byte length of B
|
26
|
+
; @in B => number
|
27
|
+
; @out A => bytes length
|
28
|
+
getLenBytes:
|
29
|
+
; checks zk-counters
|
30
|
+
%MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
|
31
|
+
; store current registries
|
32
|
+
RR :MSTORE(tmpZkPCgetLen)
|
33
|
+
B :MSTORE(tmpVarBgetLen)
|
34
|
+
C :MSTORE(tmpVarCgetLen)
|
35
|
+
D :MSTORE(tmpVarDgetLen)
|
36
|
+
; set C as counter to 0
|
37
|
+
0 => C
|
38
|
+
B => A
|
39
|
+
|
40
|
+
getLenBytesLoop:
|
41
|
+
; checks zk-counters
|
42
|
+
%MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep)
|
43
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
44
|
+
|
45
|
+
0 => B
|
46
|
+
; if A is zero, finish counter
|
47
|
+
$ :EQ,JMPC(getLenEnd)
|
48
|
+
; right shift one byte
|
49
|
+
1 => D
|
50
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
51
|
+
; increase counter
|
52
|
+
C + 1 => C :JMP(getLenBytesLoop)
|
53
|
+
|
54
|
+
getLenEnd:
|
55
|
+
; counter to A
|
56
|
+
C => A
|
57
|
+
; recover registries
|
58
|
+
$ => B :MLOAD(tmpVarBgetLen)
|
59
|
+
$ => C :MLOAD(tmpVarCgetLen)
|
60
|
+
$ => RR :MLOAD(tmpZkPCgetLen)
|
61
|
+
$ => D :MLOAD(tmpVarDgetLen), RETURN
|
62
|
+
|
63
|
+
; @info bits length of B
|
64
|
+
; @in B => number
|
65
|
+
; @out A => bits length
|
66
|
+
getLenBits:
|
67
|
+
; checks zk-counters
|
68
|
+
%MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
|
69
|
+
; store current registries
|
70
|
+
RR :MSTORE(tmpZkPCgetLen)
|
71
|
+
B :MSTORE(tmpVarBgetLen)
|
72
|
+
C :MSTORE(tmpVarCgetLen)
|
73
|
+
D :MSTORE(tmpVarDgetLen)
|
74
|
+
; set C as counter to 0
|
75
|
+
0 => C
|
76
|
+
B => A
|
77
|
+
|
78
|
+
getLenBitsLoop:
|
79
|
+
; checks zk-counters
|
80
|
+
%MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep)
|
81
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
82
|
+
0 => B
|
83
|
+
; if B is zero, finish counter
|
84
|
+
$ :EQ,JMPC(getLenBitsEnd)
|
85
|
+
; divide value by 2
|
86
|
+
A :MSTORE(arithA)
|
87
|
+
2 :MSTORE(arithB)
|
88
|
+
zkPC+1 => RR :JMP(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
89
|
+
$ => A :MLOAD(arithRes1)
|
90
|
+
; increase counter
|
91
|
+
C + 1 => C :JMP(getLenBitsLoop)
|
92
|
+
|
93
|
+
getLenBitsEnd:
|
94
|
+
; counter to A
|
95
|
+
C => A
|
96
|
+
; recover registries
|
97
|
+
$ => B :MLOAD(tmpVarBgetLen)
|
98
|
+
$ => C :MLOAD(tmpVarCgetLen)
|
99
|
+
$ => RR :MLOAD(tmpZkPCgetLen)
|
100
|
+
$ => D :MLOAD(tmpVarDgetLen), RETURN
|
101
|
+
|
102
|
+
VAR GLOBAL tmpVarAmstore
|
103
|
+
VAR GLOBAL tmpVarBmstore
|
104
|
+
VAR GLOBAL tmpVarCmstore
|
105
|
+
VAR GLOBAL tmpVarDmstore
|
106
|
+
VAR GLOBAL tmpVarEmstore
|
107
|
+
VAR GLOBAL tmpZkPCmstore
|
108
|
+
|
109
|
+
VAR GLOBAL bytesToStore
|
110
|
+
VAR GLOBAL isMSTOREX
|
111
|
+
; @info save value to memory < 32 bytes with offset
|
112
|
+
; @in bytesToStore => bytes to store in memory
|
113
|
+
; @in E => offset
|
114
|
+
; @in C => length
|
115
|
+
; @out E => new offset
|
116
|
+
MSTOREX:
|
117
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
118
|
+
C :JMPZ(endMSTOREX)
|
119
|
+
32 - C :JMPN(errorMLOADMSTORE)
|
120
|
+
32 - C - 1 :JMPN(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
|
121
|
+
1 :MSTORE(isMSTOREX)
|
122
|
+
|
123
|
+
; @info save value to memory 32 bytes with offset
|
124
|
+
; @in bytesToStore => bytes to store in memory
|
125
|
+
; @in E => offset
|
126
|
+
; @out E => new offset
|
127
|
+
MSTORE32:
|
128
|
+
; checks zk-counters
|
129
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
130
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
131
|
+
%MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign)
|
132
|
+
; store current registries
|
133
|
+
RR :MSTORE(tmpZkPCmstore)
|
134
|
+
A :MSTORE(tmpVarAmstore)
|
135
|
+
B :MSTORE(tmpVarBmstore)
|
136
|
+
C :MSTORE(tmpVarCmstore)
|
137
|
+
D :MSTORE(tmpVarDmstore)
|
138
|
+
; check offset is lower than max memory
|
139
|
+
E => A
|
140
|
+
%MAX_MEM_EXPANSION_BYTES => B
|
141
|
+
$ :LT,JMPC(initMSTORE, errorMLOADMSTORE)
|
142
|
+
|
143
|
+
initMSTORE:
|
144
|
+
zkPC+1 => RR :JMP(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
|
145
|
+
; is storing <32 bytes, jump to store last bytes or finish if 0 bytes left
|
146
|
+
$ => B :MLOAD(isMSTOREX), JMPZ(finalMSTORE)
|
147
|
+
; if C has value, offset != 0
|
148
|
+
C :JMPNZ(MSTOREX2)
|
149
|
+
$ => C :MLOAD(tmpVarCmstore)
|
150
|
+
; load bytes to store
|
151
|
+
$ => A :MLOAD(bytesToStore)
|
152
|
+
32 - C => D
|
153
|
+
; shift bytes to store
|
154
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
155
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
156
|
+
A => B
|
157
|
+
; load from memory
|
158
|
+
$ => A :MLOAD(MEM:E)
|
159
|
+
32 - D => D
|
160
|
+
; shift loaded bytes
|
161
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
162
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
163
|
+
A + B :MSTORE(bytesToStore)
|
164
|
+
A + B => A
|
165
|
+
0 => C :JMP(finalMSTORE)
|
166
|
+
|
167
|
+
; used if bytesToStore.length < 32 && offset != 0
|
168
|
+
MSTOREX2:
|
169
|
+
$ => D :MLOAD(tmpVarCmstore)
|
170
|
+
C + D => D
|
171
|
+
32 - D :JMPN(MSTOREX3)
|
172
|
+
; if bytesToStore.length < 32 && memory to load is allocated in two different slots
|
173
|
+
; load memory from slot E
|
174
|
+
$ => A :MLOAD(MEM:E)
|
175
|
+
; shift loaded memory from slot E
|
176
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
177
|
+
$ => D :MLOAD(tmpVarCmstore)
|
178
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
179
|
+
A => B
|
180
|
+
; load memory from slot E+1
|
181
|
+
$ => A :MLOAD(MEM:E+1)
|
182
|
+
32 - C => D
|
183
|
+
; right shift loaded memory from slot E+1
|
184
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
185
|
+
; join both results
|
186
|
+
A + B => B
|
187
|
+
$ => A :MLOAD(bytesToStore)
|
188
|
+
$ => D :MLOAD(tmpVarCmstore)
|
189
|
+
32 - D => D
|
190
|
+
; shift bytes to store
|
191
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
192
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
193
|
+
; append loaded bytes from concurrent slots
|
194
|
+
A + B => A :MSTORE(bytesToStore)
|
195
|
+
:JMP(finalMSTORE)
|
196
|
+
|
197
|
+
; used if bytesToStore.length < 32 && memory to load is allocated in one slot
|
198
|
+
MSTOREX3:
|
199
|
+
D - 32 => D
|
200
|
+
; load memory from slot E+1
|
201
|
+
$ => A :MLOAD(MEM:E+1)
|
202
|
+
; shift bytes to store
|
203
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
204
|
+
$ => D :MLOAD(tmpVarCmstore)
|
205
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
206
|
+
; join both results
|
207
|
+
A => B
|
208
|
+
$ => A :MLOAD(bytesToStore)
|
209
|
+
$ => D :MLOAD(tmpVarCmstore)
|
210
|
+
32 - D => D
|
211
|
+
; shift bytes to store
|
212
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
213
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
214
|
+
; append loaded bytes from concurrent slots
|
215
|
+
A + B => A :MSTORE(bytesToStore)
|
216
|
+
|
217
|
+
finalMSTORE:
|
218
|
+
C :JMPNZ(memAlignOptionMSTORE)
|
219
|
+
$ => A :MLOAD(bytesToStore)
|
220
|
+
A :MSTORE(MEM:E)
|
221
|
+
E*32 => E
|
222
|
+
$ :MLOAD(isMSTOREX),JMPZ(offsetMSTORE32)
|
223
|
+
$ => C :MLOAD(tmpVarCmstore)
|
224
|
+
E + C => E
|
225
|
+
0 :MSTORE(isMSTOREX),JMP(endMSTORE)
|
226
|
+
|
227
|
+
memAlignOptionMSTORE:
|
228
|
+
E :MSTORE(tmpVarEmstore)
|
229
|
+
|
230
|
+
$ => A :MLOAD(MEM:E)
|
231
|
+
$ => B :MLOAD(MEM:E+1)
|
232
|
+
|
233
|
+
${memAlignWR_W0(A,mem.bytesToStore,C)} => D ; no trust calculate W0
|
234
|
+
${memAlignWR_W1(B,mem.bytesToStore,C)} => E ; no trust calculate W1
|
235
|
+
$ :MEM_ALIGN_WR,MLOAD(bytesToStore)
|
236
|
+
E => A
|
237
|
+
$ => E :MLOAD(tmpVarEmstore)
|
238
|
+
D :MSTORE(MEM:E) ; write W0
|
239
|
+
A :MSTORE(MEM:E+1) ; write W1
|
240
|
+
E*32 + C => E
|
241
|
+
$ => A :MLOAD(isMSTOREX), JMPZ(offsetMSTORE32)
|
242
|
+
$ => C :MLOAD(tmpVarCmstore)
|
243
|
+
E + C => E
|
244
|
+
0 :MSTORE(isMSTOREX), JMP(endMSTORE)
|
245
|
+
|
246
|
+
offsetMSTORE32:
|
247
|
+
E + 32 => E
|
248
|
+
|
249
|
+
endMSTORE:
|
250
|
+
$ => A :MLOAD(tmpVarAmstore)
|
251
|
+
$ => B :MLOAD(tmpVarBmstore)
|
252
|
+
$ => C :MLOAD(tmpVarCmstore)
|
253
|
+
$ => RR :MLOAD(tmpZkPCmstore)
|
254
|
+
$ => D :MLOAD(tmpVarDmstore), RETURN
|
255
|
+
endMSTOREX:
|
256
|
+
:RETURN
|
257
|
+
|
258
|
+
VAR GLOBAL tmpVarAmload
|
259
|
+
VAR GLOBAL tmpVarBmload
|
260
|
+
VAR GLOBAL tmpVarCmload
|
261
|
+
VAR GLOBAL tmpVarDmload
|
262
|
+
VAR GLOBAL tmpVarEmload
|
263
|
+
VAR GLOBAL tmpZkPCmload
|
264
|
+
|
265
|
+
VAR GLOBAL isMLOADX
|
266
|
+
; @info get value from memory (< 32 bytes)
|
267
|
+
; @in E => offset
|
268
|
+
; @in C => length
|
269
|
+
; @out A => value
|
270
|
+
; @out E => new offset
|
271
|
+
MLOADX:
|
272
|
+
; check zk-counters
|
273
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
274
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
275
|
+
%MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign)
|
276
|
+
|
277
|
+
32 - C :JMPN(errorMLOADMSTORE)
|
278
|
+
32 - C - 1 :JMPN(MLOAD32)
|
279
|
+
1 :MSTORE(isMLOADX)
|
280
|
+
|
281
|
+
; @info get value from memory (32 bytes)
|
282
|
+
; @in E => offset
|
283
|
+
; @out A => value
|
284
|
+
; @out E => new offset
|
285
|
+
MLOAD32:
|
286
|
+
; check zk-counters
|
287
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
288
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
289
|
+
%MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign)
|
290
|
+
; store current registries
|
291
|
+
RR :MSTORE(tmpZkPCmload)
|
292
|
+
B :MSTORE(tmpVarBmload)
|
293
|
+
C :MSTORE(tmpVarCmload)
|
294
|
+
D :MSTORE(tmpVarDmload)
|
295
|
+
; check offset is lower than max memory
|
296
|
+
E => A
|
297
|
+
%MAX_MEM_EXPANSION_BYTES => B
|
298
|
+
$ :LT,JMPC(initMLOAD, errorMLOADMSTORE)
|
299
|
+
|
300
|
+
initMLOAD:
|
301
|
+
:CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
|
302
|
+
; if C has value, bytes split in two memory slots
|
303
|
+
C :JMPNZ(memAlignOptionMLOAD)
|
304
|
+
; load memory from one slot
|
305
|
+
$ => A :MLOAD(MEM:E)
|
306
|
+
$ => B :MLOAD(isMLOADX)
|
307
|
+
E*32 => E
|
308
|
+
B :JMPZ(offsetMLOAD32, sliceA)
|
309
|
+
|
310
|
+
memAlignOptionMLOAD:
|
311
|
+
$ => A :MLOAD(MEM:E)
|
312
|
+
$ => B :MLOAD(MEM:E+1)
|
313
|
+
; get memory value
|
314
|
+
$ => A :MEM_ALIGN_RD
|
315
|
+
E*32 + C => E
|
316
|
+
$ => B :MLOAD(isMLOADX)
|
317
|
+
B :JMPZ(offsetMLOAD32)
|
318
|
+
|
319
|
+
sliceA:
|
320
|
+
; if is mloadx, slice the result by the length
|
321
|
+
$ => C :MLOAD(tmpVarCmload)
|
322
|
+
32 - C => D
|
323
|
+
zkPC+1 => RR :JMP(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
324
|
+
zkPC+1 => RR :JMP(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result]
|
325
|
+
0 :MSTORE(isMLOADX)
|
326
|
+
E + C => E :JMP(endMLOAD)
|
327
|
+
|
328
|
+
offsetMLOAD32:
|
329
|
+
E + 32 => E
|
330
|
+
|
331
|
+
endMLOAD:
|
332
|
+
; restore stored values
|
333
|
+
$ => B :MLOAD(tmpVarBmload)
|
334
|
+
$ => C :MLOAD(tmpVarCmload)
|
335
|
+
$ => RR :MLOAD(tmpZkPCmload)
|
336
|
+
$ => D :MLOAD(tmpVarDmload), RETURN
|
337
|
+
|
338
|
+
errorMLOADMSTORE:
|
339
|
+
:JMP(outOfGas)
|
340
|
+
|
341
|
+
VAR GLOBAL tmpVarAemptyAcc
|
342
|
+
VAR GLOBAL tmpVarBemptyAcc
|
343
|
+
VAR GLOBAL tmpVarCemptyAcc
|
344
|
+
VAR GLOBAL tmpVarDemptyAcc
|
345
|
+
|
346
|
+
; @info check account is empty ( balance == nonce == code == 0x )
|
347
|
+
; @in E => address
|
348
|
+
; @out E => isEmpty => 1 = true, 0 = false
|
349
|
+
isEmptyAccount:
|
350
|
+
; check zk-counters
|
351
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
352
|
+
%MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary)
|
353
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*3 :JMPN(outOfCountersPoseidon)
|
354
|
+
|
355
|
+
; store current registries
|
356
|
+
A :MSTORE(tmpVarAemptyAcc)
|
357
|
+
B :MSTORE(tmpVarBemptyAcc)
|
358
|
+
C :MSTORE(tmpVarCemptyAcc)
|
359
|
+
D :MSTORE(tmpVarDemptyAcc)
|
360
|
+
|
361
|
+
E => A
|
362
|
+
; read balance
|
363
|
+
; set key for smt balance query.
|
364
|
+
%SMT_KEY_BALANCE => B
|
365
|
+
0 => C
|
366
|
+
$ => B :SLOAD
|
367
|
+
; balance in A
|
368
|
+
0 => A
|
369
|
+
; if balance is not zero, is not empty
|
370
|
+
$ :LT,JMPC(isNotEmptyAccount)
|
371
|
+
; check nonce
|
372
|
+
E => A
|
373
|
+
; set key for smt nonce query
|
374
|
+
%SMT_KEY_NONCE => B
|
375
|
+
; nonce in B
|
376
|
+
$ => B :SLOAD
|
377
|
+
0 => A
|
378
|
+
; if nonce is not zero, is not empty
|
379
|
+
$ :LT,JMPC(isNotEmptyAccount)
|
380
|
+
; read bytecode
|
381
|
+
E => A
|
382
|
+
; set key for smt smart contract query
|
383
|
+
%SMT_KEY_SC_CODE => B
|
384
|
+
; sc in B
|
385
|
+
$ => B :SLOAD
|
386
|
+
0 => A
|
387
|
+
; if code is not zero, is not empty
|
388
|
+
$ :LT,JMPC(isNotEmptyAccount)
|
389
|
+
1 => E :JMP(ISEMPTYEnd)
|
390
|
+
|
391
|
+
isNotEmptyAccount:
|
392
|
+
0 => E :JMP(ISEMPTYEnd)
|
393
|
+
|
394
|
+
ISEMPTYEnd:
|
395
|
+
; recover registries
|
396
|
+
$ => A :MLOAD(tmpVarAemptyAcc)
|
397
|
+
$ => B :MLOAD(tmpVarBemptyAcc)
|
398
|
+
$ => C :MLOAD(tmpVarCemptyAcc)
|
399
|
+
$ => D :MLOAD(tmpVarDemptyAcc), RETURN
|
400
|
+
|
401
|
+
VAR GLOBAL tmpVarBcompGas
|
402
|
+
VAR GLOBAL tmpVarCcompGas
|
403
|
+
VAR GLOBAL tmpVarDcompGas
|
404
|
+
VAR GLOBAL tmpVarEcompGas
|
405
|
+
|
406
|
+
; @info Compute gas to send to call following EIP 150
|
407
|
+
; @in gasCall: gas sent to call
|
408
|
+
; @out A => min( requested_gas , all_but_one_64th(63/64) )
|
409
|
+
computeGasSendCall:
|
410
|
+
; check zk-counters
|
411
|
+
%MAX_CNT_STEPS - STEP - 30 :JMPN(outOfCountersStep)
|
412
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
413
|
+
; save tmp vars
|
414
|
+
B :MSTORE(tmpVarBcompGas)
|
415
|
+
C :MSTORE(tmpVarCcompGas)
|
416
|
+
D :MSTORE(tmpVarDcompGas)
|
417
|
+
E :MSTORE(tmpVarEcompGas)
|
418
|
+
|
419
|
+
; compute all_but_one_64th gas
|
420
|
+
GAS => A
|
421
|
+
|
422
|
+
; C = [c7, c6, ..., c0]
|
423
|
+
; JMPN instruction assures c0 is within the range [0, 2**32 - 1]
|
424
|
+
${GAS >> 6} => C :JMPN(failAssert)
|
425
|
+
${GAS & 0x3f} => D
|
426
|
+
|
427
|
+
; since D is assured to be less than 0x40
|
428
|
+
; it is enforced that [c7, c6, ..., c1] are 0 since there is no value multiplied by 64
|
429
|
+
; that equals the field
|
430
|
+
; Since e0 is assured to be less than 32 bits, c0 * 64 + d0 could not overflow the field
|
431
|
+
C * 64 + D :ASSERT
|
432
|
+
D => A
|
433
|
+
0x40 => B
|
434
|
+
$ :LT,JMPNC(failAssert)
|
435
|
+
GAS - C => A
|
436
|
+
$ => B :MLOAD(gasCall)
|
437
|
+
; gas_sent_with_call = min(requested_gas, all_but_one_64th)
|
438
|
+
$ :LT,JMPC(computeGasSendCallEnd)
|
439
|
+
; gas to substract
|
440
|
+
B => A
|
441
|
+
|
442
|
+
computeGasSendCallEnd:
|
443
|
+
; restore stored values
|
444
|
+
$ => B :MLOAD(tmpVarBcompGas)
|
445
|
+
$ => C :MLOAD(tmpVarCcompGas)
|
446
|
+
$ => D :MLOAD(tmpVarDcompGas)
|
447
|
+
$ => E :MLOAD(tmpVarEcompGas), RETURN
|
448
|
+
|
449
|
+
VAR GLOBAL tmpVarAsaveMem
|
450
|
+
VAR GLOBAL tmpVarBsaveMem
|
451
|
+
VAR GLOBAL tmpVarCsaveMem
|
452
|
+
VAR GLOBAL tmpVarDsaveMem
|
453
|
+
VAR GLOBAL tmpVarEsaveMem
|
454
|
+
VAR GLOBAL tmpZkPCsaveMem
|
455
|
+
; @info compute memory expansion gas cost
|
456
|
+
; @in: lastMemOffset: offset to copy bytes
|
457
|
+
; @in: lastMemLength: size of the bytes to copy
|
458
|
+
saveMem:
|
459
|
+
; check zk-counters
|
460
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
461
|
+
%MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary)
|
462
|
+
RR :MSTORE(tmpZkPCsaveMem)
|
463
|
+
A :MSTORE(tmpVarAsaveMem)
|
464
|
+
B :MSTORE(tmpVarBsaveMem)
|
465
|
+
C :MSTORE(tmpVarCsaveMem)
|
466
|
+
D :MSTORE(tmpVarDsaveMem)
|
467
|
+
E :MSTORE(tmpVarEsaveMem)
|
468
|
+
$ => A :MLOAD(lastMemLength)
|
469
|
+
; If no len, no memory expansion
|
470
|
+
0 => B
|
471
|
+
$ :EQ, JMPC(saveMemEnd)
|
472
|
+
$ => B :MLOAD(lastMemOffset)
|
473
|
+
; If the binary has a carry, means the mem expansion is very big. We can jump to oog directly
|
474
|
+
; offset + length in B
|
475
|
+
$ => B :ADD, JMPC(outOfGas)
|
476
|
+
; check new memory length is lower than 2**22 - 31 - 1 (max supported memory expansion for %TX_GAS_LIMIT of gas)
|
477
|
+
%MAX_MEM_EXPANSION_BYTES => A
|
478
|
+
$ :LT,JMPC(outOfGas)
|
479
|
+
|
480
|
+
|
481
|
+
; load old memory length, if is greater than new memory length, no expansion cost
|
482
|
+
$ => A :MLOAD(memLength)
|
483
|
+
$ :LT, JMPC(saveMemGAS, saveMemEnd)
|
484
|
+
|
485
|
+
saveMemGAS:
|
486
|
+
; store new memory length
|
487
|
+
B :MSTORE(memLength)
|
488
|
+
B => E
|
489
|
+
; memory_size_word = (memory_byte_size + 31) / 32 in E
|
490
|
+
; ${(B+31)/32} => E
|
491
|
+
E + 31 => A
|
492
|
+
|
493
|
+
; E = [e7, e6, ..., e0]
|
494
|
+
; JMPN instruction assures e0 is within the range [0, 2**32 - 1]
|
495
|
+
${A >> 5} => E :JMPN(failAssert)
|
496
|
+
${A & 0x1f} => D
|
497
|
+
|
498
|
+
; since D is assured to be less than 0x20
|
499
|
+
; it is enforced that [e7, e6, ..., e1] are 0 since there is no value multiplied by 32
|
500
|
+
; that equals the field
|
501
|
+
; Since e0 is assured to be less than 32 bits, e0 * 32 + d0 could not overflow the field
|
502
|
+
E * 32 + D :ASSERT
|
503
|
+
D => A
|
504
|
+
0x20 => B
|
505
|
+
$ :LT,JMPNC(failAssert)
|
506
|
+
; memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) in A
|
507
|
+
; ${E*E/512} + 3*E=> A
|
508
|
+
E :MSTORE(arithA)
|
509
|
+
E :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB, mulFlagOverflow: value overflow, mulArithOverflowFlag: set to 1 if operation causes overflow]
|
510
|
+
$ => C :MLOAD(arithRes1)
|
511
|
+
$ :MLOAD(mulArithOverflowFlag), JMPNZ(outOfGas)
|
512
|
+
C :MSTORE(arithA)
|
513
|
+
512 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
514
|
+
$ => A :MLOAD(arithRes1)
|
515
|
+
A + 3*E => A
|
516
|
+
$ => B :MLOAD(lastMemoryExpansionCost)
|
517
|
+
A :MSTORE(lastMemoryExpansionCost)
|
518
|
+
; memory_expansion_cost = new_memory_cost - last_memory_cost
|
519
|
+
A - B => A
|
520
|
+
; update new gas
|
521
|
+
GAS - A => GAS :JMPN(outOfGas)
|
522
|
+
|
523
|
+
saveMemEnd:
|
524
|
+
; restore stored values
|
525
|
+
$ => A :MLOAD(tmpVarAsaveMem)
|
526
|
+
$ => B :MLOAD(tmpVarBsaveMem)
|
527
|
+
$ => C :MLOAD(tmpVarCsaveMem)
|
528
|
+
$ => D :MLOAD(tmpVarDsaveMem)
|
529
|
+
$ => RR :MLOAD(tmpZkPCsaveMem)
|
530
|
+
$ => E :MLOAD(tmpVarEsaveMem), RETURN
|
531
|
+
|
532
|
+
VAR GLOBAL tmpVarAArith
|
533
|
+
VAR GLOBAL tmpVarBArith
|
534
|
+
VAR GLOBAL tmpVarCArith
|
535
|
+
VAR GLOBAL tmpVarDArith
|
536
|
+
VAR GLOBAL tmpVarEArith
|
537
|
+
VAR GLOBAL tmpZkPCArith
|
538
|
+
VAR GLOBAL arithA
|
539
|
+
VAR GLOBAL arithB
|
540
|
+
VAR GLOBAL arithRes1
|
541
|
+
VAR GLOBAL arithRes2
|
542
|
+
|
543
|
+
VAR GLOBAL addArithOverflow
|
544
|
+
; @info binary addition
|
545
|
+
; @in: arithA: addend value
|
546
|
+
; @in: arithB: addend value
|
547
|
+
; @out: arithRes1: arithA + arithB
|
548
|
+
addARITH:
|
549
|
+
|
550
|
+
RR :MSTORE(tmpZkPCArith), CALL(storeTmp)
|
551
|
+
$ => A :MLOAD(arithA)
|
552
|
+
$ => B :MLOAD(arithB)
|
553
|
+
$ => E :ADD, MSTORE(arithRes1), JMPC(setAddArithOverflow)
|
554
|
+
0 :MSTORE(addArithOverflow), JMP(finishAddArith)
|
555
|
+
|
556
|
+
setAddArithOverflow:
|
557
|
+
1 :MSTORE(addArithOverflow)
|
558
|
+
|
559
|
+
finishAddArith:
|
560
|
+
$ => RR :MLOAD(tmpZkPCArith), JMP(loadTmp)
|
561
|
+
|
562
|
+
; @info binary subtraction
|
563
|
+
; @in: arithA: minuend value
|
564
|
+
; @in: arithB: subtrahend value
|
565
|
+
; @out: arithRes1: arithA - arithB
|
566
|
+
subARITH:
|
567
|
+
|
568
|
+
RR :MSTORE(tmpZkPCArith),CALL(storeTmp)
|
569
|
+
$ => A :MLOAD(arithA)
|
570
|
+
$ => B :MLOAD(arithB)
|
571
|
+
$ => A :SUB,MSTORE(arithRes1)
|
572
|
+
$ => RR :MLOAD(tmpZkPCArith),JMP(loadTmp)
|
573
|
+
|
574
|
+
VAR GLOBAL mulArithOverflowValue
|
575
|
+
VAR GLOBAL mulArithOverflowFlag
|
576
|
+
; @info arithmetic multiplication
|
577
|
+
; @in: arithA: multiplier value
|
578
|
+
; @in: arithB: multiplicand value
|
579
|
+
; @out: arithRes1: product of multiplication arithA * arithB
|
580
|
+
; @out: mulArithOverflowValue: overflow value
|
581
|
+
; @out: mulArithOverflowFlag: set to 1 if operation causes overflow
|
582
|
+
mulARITH:
|
583
|
+
; check zk-counters
|
584
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
585
|
+
%MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith)
|
586
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
587
|
+
|
588
|
+
RR :MSTORE(tmpZkPCArith), CALL(storeTmp)
|
589
|
+
$ => A :MLOAD(arithA)
|
590
|
+
$ => B :MLOAD(arithB)
|
591
|
+
0 => C
|
592
|
+
$${var _mulArith = A * B}
|
593
|
+
${_mulArith >> 256} => D
|
594
|
+
${_mulArith} => E :ARITH
|
595
|
+
|
596
|
+
E :MSTORE(arithRes1)
|
597
|
+
D :MSTORE(mulArithOverflowValue)
|
598
|
+
D => A
|
599
|
+
0 => B
|
600
|
+
$ :EQ,JMPNC(setMulArithOverflow)
|
601
|
+
0 :MSTORE(mulArithOverflowFlag), JMP(finishMulArith)
|
602
|
+
|
603
|
+
setMulArithOverflow:
|
604
|
+
1 :MSTORE(mulArithOverflowFlag)
|
605
|
+
|
606
|
+
finishMulArith:
|
607
|
+
$ => RR :MLOAD(tmpZkPCArith),JMP(loadTmp)
|
608
|
+
|
609
|
+
; @info arithmetic division
|
610
|
+
; @in: arithA: dividend value
|
611
|
+
; @in: arithB: divisor value
|
612
|
+
; @out: arithRes1: quotient of division arithA / arithB
|
613
|
+
; @out: arithRes2: remainder of division arithA % arithB
|
614
|
+
divARITH:
|
615
|
+
; check zk-counters
|
616
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
617
|
+
%MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary)
|
618
|
+
%MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith)
|
619
|
+
|
620
|
+
RR :MSTORE(tmpZkPCArith), CALL(storeTmp)
|
621
|
+
$ => E :MLOAD(arithA)
|
622
|
+
$ => A :MLOAD(arithB)
|
623
|
+
; Check denominator(A) is not zero
|
624
|
+
0 => B
|
625
|
+
$ :EQ, JMPC(zeroDiv)
|
626
|
+
|
627
|
+
; Check if divisor (E) is smaller than denominator E < A
|
628
|
+
A => C ; store temporally A in C
|
629
|
+
E => A ; divisor
|
630
|
+
C => B ; denominator
|
631
|
+
$ :LT, JMPC(divisorSmallerDiv)
|
632
|
+
C => A
|
633
|
+
|
634
|
+
${E%A} => C ; remainder
|
635
|
+
${E/A} => B
|
636
|
+
0 => D
|
637
|
+
E :ARITH
|
638
|
+
|
639
|
+
B :MSTORE(arithRes1)
|
640
|
+
C :MSTORE(arithRes2)
|
641
|
+
|
642
|
+
; check divisor > remainder
|
643
|
+
A => B ; divisor
|
644
|
+
C => A ; remainder
|
645
|
+
$ => A :LT
|
646
|
+
1 :ASSERT,CALL(loadTmp)
|
647
|
+
$ => RR :MLOAD(tmpZkPCArith)
|
648
|
+
:RETURN
|
649
|
+
|
650
|
+
zeroDiv:
|
651
|
+
0 :MSTORE(arithRes1)
|
652
|
+
0 :MSTORE(arithRes2), CALL(loadTmp)
|
653
|
+
$ => RR :MLOAD(tmpZkPCArith)
|
654
|
+
:RETURN
|
655
|
+
|
656
|
+
divisorSmallerDiv:
|
657
|
+
0 :MSTORE(arithRes1)
|
658
|
+
E :MSTORE(arithRes2), CALL(loadTmp)
|
659
|
+
$ => RR :MLOAD(tmpZkPCArith)
|
660
|
+
:RETURN
|
661
|
+
|
662
|
+
loadTmp:
|
663
|
+
$ => A :MLOAD(tmpVarAArith)
|
664
|
+
$ => B :MLOAD(tmpVarBArith)
|
665
|
+
$ => C :MLOAD(tmpVarCArith)
|
666
|
+
$ => D :MLOAD(tmpVarDArith)
|
667
|
+
$ => E :MLOAD(tmpVarEArith), RETURN
|
668
|
+
|
669
|
+
storeTmp:
|
670
|
+
A :MSTORE(tmpVarAArith)
|
671
|
+
B :MSTORE(tmpVarBArith)
|
672
|
+
C :MSTORE(tmpVarCArith)
|
673
|
+
D :MSTORE(tmpVarDArith)
|
674
|
+
E :MSTORE(tmpVarEArith), RETURN
|
675
|
+
|
676
|
+
VAR GLOBAL tmpSHXZkPC
|
677
|
+
VAR GLOBAL tmpSHXZkPC2
|
678
|
+
|
679
|
+
VAR GLOBAL tmpVarBSHX
|
680
|
+
VAR GLOBAL tmpVarCSHX
|
681
|
+
VAR GLOBAL tmpVarDSHX
|
682
|
+
VAR GLOBAL tmpVarESHX
|
683
|
+
|
684
|
+
VAR GLOBAL result
|
685
|
+
;@info Shift right D bytes to A
|
686
|
+
;@in A - (A >> D)
|
687
|
+
;@in D - (A >> D) D bytes
|
688
|
+
;@out A - A >> D => A
|
689
|
+
SHRarith:
|
690
|
+
; check zk-counters
|
691
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
692
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
693
|
+
%MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith)
|
694
|
+
|
695
|
+
RR :MSTORE(tmpSHXZkPC2)
|
696
|
+
B :MSTORE(tmpVarBSHX)
|
697
|
+
C :MSTORE(tmpVarCSHX)
|
698
|
+
D :MSTORE(tmpVarDSHX)
|
699
|
+
E :MSTORE(tmpVarESHX)
|
700
|
+
; E init number
|
701
|
+
A => E
|
702
|
+
; A bytes
|
703
|
+
D => A
|
704
|
+
; B = 8 (1 byte = 8 bits)
|
705
|
+
8 => B
|
706
|
+
0 => C
|
707
|
+
0 => D
|
708
|
+
; A * B = op --> D = op (D bits)
|
709
|
+
${A*B} => D :ARITH
|
710
|
+
; A init number
|
711
|
+
E => A :JMP(SHRarithinit)
|
712
|
+
|
713
|
+
;@in A - (A >> D)
|
714
|
+
;@in D - (A >> D) D bits
|
715
|
+
;@out A - A >> D => A
|
716
|
+
SHRarithBit:
|
717
|
+
; check zk-counters
|
718
|
+
%MAX_CNT_STEPS - STEP - 30 :JMPN(outOfCountersStep)
|
719
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
720
|
+
RR :MSTORE(tmpSHXZkPC2)
|
721
|
+
B :MSTORE(tmpVarBSHX)
|
722
|
+
C :MSTORE(tmpVarCSHX)
|
723
|
+
D :MSTORE(tmpVarDSHX)
|
724
|
+
E :MSTORE(tmpVarESHX)
|
725
|
+
|
726
|
+
SHRarithinit:
|
727
|
+
0 => B
|
728
|
+
; if A == 0 --> no shift
|
729
|
+
$ :EQ,JMPC(SHRarithfinal)
|
730
|
+
; E init number
|
731
|
+
A => E
|
732
|
+
; B bits
|
733
|
+
D => B
|
734
|
+
255 => A
|
735
|
+
; A < B, 255 < bits
|
736
|
+
$ :LT,JMPC(SHRarith0)
|
737
|
+
D => RR
|
738
|
+
E => A :MSTORE(arithA)
|
739
|
+
:CALL(@exp_num + RR); out:[B: 2**RR]
|
740
|
+
B :MSTORE(arithB),CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
741
|
+
$ => A :MLOAD(arithRes1),JMP(SHRarithfinal)
|
742
|
+
|
743
|
+
SHRarith0:
|
744
|
+
0 => A
|
745
|
+
|
746
|
+
SHRarithfinal:
|
747
|
+
$ => B :MLOAD(tmpVarBSHX)
|
748
|
+
$ => C :MLOAD(tmpVarCSHX)
|
749
|
+
$ => D :MLOAD(tmpVarDSHX)
|
750
|
+
$ => RR :MLOAD(tmpSHXZkPC2)
|
751
|
+
$ => E :MLOAD(tmpVarESHX), RETURN
|
752
|
+
|
753
|
+
;@info Shift left D bytes to A
|
754
|
+
;@in A - (A << D)
|
755
|
+
;@in D - (A << D) D bytes
|
756
|
+
;@out A - A << D => A
|
757
|
+
SHLarith:
|
758
|
+
; check zk-counters
|
759
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
760
|
+
%MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary)
|
761
|
+
%MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith)
|
762
|
+
RR :MSTORE(tmpSHXZkPC2)
|
763
|
+
B :MSTORE(tmpVarBSHX)
|
764
|
+
C :MSTORE(tmpVarCSHX)
|
765
|
+
D :MSTORE(tmpVarDSHX)
|
766
|
+
E :MSTORE(tmpVarESHX)
|
767
|
+
; E init number
|
768
|
+
A => E
|
769
|
+
; A bytes
|
770
|
+
D => A
|
771
|
+
8 => B
|
772
|
+
0 => C, D
|
773
|
+
; D = A * 8, D bits
|
774
|
+
${A*B} => D :ARITH
|
775
|
+
; A init number
|
776
|
+
E => A
|
777
|
+
:JMP(SHLarithinit)
|
778
|
+
SHLarithBit:
|
779
|
+
; check zk-counters
|
780
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
781
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
782
|
+
%MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith)
|
783
|
+
RR :MSTORE(tmpSHXZkPC2)
|
784
|
+
B :MSTORE(tmpVarBSHX)
|
785
|
+
C :MSTORE(tmpVarCSHX)
|
786
|
+
D :MSTORE(tmpVarDSHX)
|
787
|
+
E :MSTORE(tmpVarESHX)
|
788
|
+
|
789
|
+
SHLarithinit:
|
790
|
+
; E init number
|
791
|
+
A => E
|
792
|
+
0 => A
|
793
|
+
; D --> B bits
|
794
|
+
D => B
|
795
|
+
; if D == 0 --> no shift
|
796
|
+
$ :EQ,JMPC(SHLarithfinal)
|
797
|
+
255 => A
|
798
|
+
; A < B, 255 < bits
|
799
|
+
$ :LT,JMPC(SHLarith0)
|
800
|
+
|
801
|
+
D => RR
|
802
|
+
; A init number and calculate B = 2**D
|
803
|
+
E => A :CALL(@exp_num + RR); out:[B: 2**RR]
|
804
|
+
; E = init number * 2**D (result)
|
805
|
+
${A*B} => E
|
806
|
+
E :MSTORE(result)
|
807
|
+
; D = 256 - D
|
808
|
+
256 - D => D, RR
|
809
|
+
B => C :CALL(@exp_num + RR); out:[B: 2**RR]
|
810
|
+
${A/B} => D
|
811
|
+
C => B
|
812
|
+
0 => C
|
813
|
+
E :ARITH, JMP(SHLarithfinal)
|
814
|
+
|
815
|
+
SHLarith0:
|
816
|
+
0 => E
|
817
|
+
:JMP(SHLarithfinal)
|
818
|
+
|
819
|
+
SHLarithfinal:
|
820
|
+
E => A
|
821
|
+
$ => B :MLOAD(tmpVarBSHX)
|
822
|
+
$ => C :MLOAD(tmpVarCSHX)
|
823
|
+
$ => D :MLOAD(tmpVarDSHX)
|
824
|
+
$ => RR :MLOAD(tmpSHXZkPC2)
|
825
|
+
$ => E :MLOAD(tmpVarESHX), RETURN
|
826
|
+
|
827
|
+
; out of counters full tracer event trigger
|
828
|
+
outOfCountersStep:
|
829
|
+
$${eventLog(onError, OOCS)} :JMP(handleBatchError)
|
830
|
+
outOfCountersKeccak:
|
831
|
+
$${eventLog(onError, OOCK)} :JMP(handleBatchError)
|
832
|
+
outOfCountersBinary:
|
833
|
+
$${eventLog(onError, OOCB)} :JMP(handleBatchError)
|
834
|
+
outOfCountersMemalign:
|
835
|
+
$${eventLog(onError, OOCM)} :JMP(handleBatchError)
|
836
|
+
outOfCountersArith:
|
837
|
+
$${eventLog(onError, OOCA)} :JMP(handleBatchError)
|
838
|
+
outOfCountersPadding:
|
839
|
+
$${eventLog(onError, OOCPA)} :JMP(handleBatchError)
|
840
|
+
outOfCountersPoseidon:
|
841
|
+
$${eventLog(onError, OOCPO)} :JMP(handleBatchError)
|
842
|
+
outOfCountersSha256:
|
843
|
+
$${eventLog(onError, OOCSH)} :JMP(handleBatchError)
|
844
|
+
invalidChangeL2BlockLimitTimestamp:
|
845
|
+
$${eventLog(onError, invalid_change_l2_block_limit_timestamp)} :JMP(handleBatchError)
|
846
|
+
invalidChangeL2BlockMinTimestamp:
|
847
|
+
$${eventLog(onError, invalid_change_l2_block_min_timestamp)} :JMP(handleBatchError)
|
848
|
+
invalidL1InfoTreeIndex:
|
849
|
+
$${eventLog(onError, invalid_l1_info_tree_index)} :JMP(handleBatchError)
|
850
|
+
outOfGas:
|
851
|
+
$${eventLog(onError, OOG)} :JMP(handleError)
|
852
|
+
invalidJump:
|
853
|
+
$${eventLog(onError, invalidJump)} :JMP(handleError)
|
854
|
+
invalidOpcode:
|
855
|
+
$${eventLog(onError, invalidOpcode)} :JMP(handleError)
|
856
|
+
stackUnderflow:
|
857
|
+
$${eventLog(onError, underflow)} :JMP(handleError)
|
858
|
+
stackOverflow:
|
859
|
+
$${eventLog(onError, overflow)} :JMP(handleError)
|
860
|
+
deployAddressCollision:
|
861
|
+
$${eventLog(onError, invalidAddressCollision)} :JMP(handleError)
|
862
|
+
invalidStaticTx:
|
863
|
+
$${eventLog(onError, invalidStaticTx)} :JMP(handleError)
|
864
|
+
invalidCodeSize:
|
865
|
+
$${eventLog(onError, invalidCodeSize)} :JMP(handleError)
|
866
|
+
invalidCodeStartsEF:
|
867
|
+
$${eventLog(onError, invalidCodeStartsEF)} :JMP(handleError)
|
868
|
+
|
869
|
+
handleError:
|
870
|
+
%MAX_CNT_STEPS - STEP - 500 :JMPN(outOfCountersStep)
|
871
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
872
|
+
;revert all state changes
|
873
|
+
$ => SR :MLOAD(initSR), CALL(revertTouched)
|
874
|
+
:CALL(revertBlockInfoTree)
|
875
|
+
|
876
|
+
$ => A :MLOAD(originCTX), JMPZ(errorAtFirstContext)
|
877
|
+
A => CTX
|
878
|
+
; Add return data context value to origin context
|
879
|
+
; Clear return data context
|
880
|
+
0 :MSTORE(retDataCTX)
|
881
|
+
CTX :MSTORE(currentCTX)
|
882
|
+
$ => GAS :MLOAD(gasCTX)
|
883
|
+
$ => SP :MLOAD(lastSP)
|
884
|
+
$ => PC :MLOAD(lastPC)
|
885
|
+
0 :MSTORE(SP++), JMP(readCode)
|
886
|
+
|
887
|
+
handleBatchError:
|
888
|
+
; restore init state root and finish batch
|
889
|
+
$ => SR :MLOAD(batchSR)
|
890
|
+
; if batch error is triggered while parsing the RLP, it jumps to 'appendTxsInit'
|
891
|
+
; to fill the missing bytes to complete 'batchDataHash'
|
892
|
+
$ :MLOAD(isLoadingRLP),JMPNZ(appendTxsInit)
|
893
|
+
$${eventLog(onFinishTx)} :JMP(finalizeBatch)
|
894
|
+
|
895
|
+
errorAtFirstContext:
|
896
|
+
; Set tx status to failure
|
897
|
+
0 :MSTORE(txStatus)
|
898
|
+
;save Root and jump to send gas to sequencer
|
899
|
+
0 :MSTORE(gasRefund)
|
900
|
+
;remaining gas = 0
|
901
|
+
0 => GAS :JMP(sendGasSeq)
|
902
|
+
|
903
|
+
VAR GLOBAL tmpVarAoffsetUtil
|
904
|
+
VAR GLOBAL tmpVarBoffsetUtil
|
905
|
+
;Get offset/32 & offset%32
|
906
|
+
;@in A offset (offset is assumed to be less than %MAX_MEM_EXPANSION_BYTES)
|
907
|
+
;@out E offset/32
|
908
|
+
;@out C offset%32
|
909
|
+
offsetUtil:
|
910
|
+
%MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
|
911
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
912
|
+
A :MSTORE(tmpVarAoffsetUtil)
|
913
|
+
B :MSTORE(tmpVarBoffsetUtil)
|
914
|
+
|
915
|
+
; E = [e7, e6, ..., e0]
|
916
|
+
; JMPN instruction assures e0 is within the range [0, 2**32 - 1]
|
917
|
+
${A >> 5} => E :JMPN(failAssert)
|
918
|
+
${A & 0x1F} => C
|
919
|
+
|
920
|
+
; since C is assured to be less than 0x20
|
921
|
+
; it is enforced that [e7, e6, ..., e1] are 0 since there is no value multiplied by 32
|
922
|
+
; that equals the field
|
923
|
+
; Since e0 is assured to be less than 32 bits, e0 * 32 + c0 could not overflow the field
|
924
|
+
E * 32 + C :ASSERT
|
925
|
+
C => A
|
926
|
+
0x20 => B
|
927
|
+
$ :LT,JMPNC(failAssert)
|
928
|
+
|
929
|
+
$ => A :MLOAD(tmpVarAoffsetUtil)
|
930
|
+
$ => B :MLOAD(tmpVarBoffsetUtil), RETURN
|
931
|
+
|
932
|
+
;@info: move balances between two accounts
|
933
|
+
;@in: txSrcAddr: source address
|
934
|
+
;@in: storageAddr: destination address
|
935
|
+
;@in: txValue: transaction value
|
936
|
+
moveBalances:
|
937
|
+
;;;;;;;;
|
938
|
+
; evmCALL (Move Balances)
|
939
|
+
;;;;;;;;
|
940
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
941
|
+
%MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary)
|
942
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 :JMPN(outOfCountersPoseidon)
|
943
|
+
;Check if is a delegate call
|
944
|
+
$ => A :MLOAD(isDelegateCall), JMPNZ(endMoveBalances)
|
945
|
+
; Decrement source balance
|
946
|
+
$ => A :MLOAD(txSrcAddr)
|
947
|
+
; set key for smt balance query
|
948
|
+
%SMT_KEY_BALANCE => B
|
949
|
+
0 => C
|
950
|
+
; Balance in A
|
951
|
+
$ => A :SLOAD
|
952
|
+
; value in B
|
953
|
+
$ => B :MLOAD(txValue)
|
954
|
+
; Check has enough balance to pay the value. In case not, means we are in a CALL/CALLCODE
|
955
|
+
$ :LT,JMPC(invalidCall)
|
956
|
+
; sourceBalance - value in D
|
957
|
+
$ => D :SUB
|
958
|
+
; update source balance
|
959
|
+
$ => A :MLOAD(txSrcAddr)
|
960
|
+
; set key for smt balance query
|
961
|
+
%SMT_KEY_BALANCE => B
|
962
|
+
$ => SR :SSTORE
|
963
|
+
; Increment destination balance
|
964
|
+
$ => A :MLOAD(storageAddr)
|
965
|
+
; set key for smt balance query
|
966
|
+
%SMT_KEY_BALANCE => B
|
967
|
+
; Balance in A
|
968
|
+
$ => A :SLOAD
|
969
|
+
$ => B :MLOAD(txValue)
|
970
|
+
$ => D :ADD
|
971
|
+
$ => A :MLOAD(storageAddr)
|
972
|
+
; set key for smt balance query
|
973
|
+
%SMT_KEY_BALANCE => B
|
974
|
+
0 => C
|
975
|
+
$ => SR :SSTORE
|
976
|
+
endMoveBalances:
|
977
|
+
:RETURN
|
978
|
+
|
979
|
+
invalidCall:
|
980
|
+
; return to origin context
|
981
|
+
$ => SR :MLOAD(initSR)
|
982
|
+
$ => A :MLOAD(originCTX)
|
983
|
+
0 => B
|
984
|
+
; if last context, finish tx
|
985
|
+
$ :EQ,JMPC(handleGas)
|
986
|
+
A => CTX
|
987
|
+
0 :MSTORE(retDataCTX)
|
988
|
+
CTX :MSTORE(currentCTX)
|
989
|
+
$ => A :MLOAD(gasCTX)
|
990
|
+
GAS + A => GAS
|
991
|
+
$ => SP :MLOAD(lastSP)
|
992
|
+
$ => PC :MLOAD(lastPC)
|
993
|
+
0 :MSTORE(SP++), JMP(readCode)
|
994
|
+
|
995
|
+
VAR GLOBAL pushBytes
|
996
|
+
VAR GLOBAL pushBytes_RR
|
997
|
+
; @info Read bytes opcode PUSHX
|
998
|
+
; @internalParam {numBlocks} 4 bytes blocks to read
|
999
|
+
; @internalParam {leftBytes} remaining bytes
|
1000
|
+
; @in D,E => bytes to read (1..32)
|
1001
|
+
; @out E => value read
|
1002
|
+
|
1003
|
+
readPush:
|
1004
|
+
:JMP(@readPush+E) ;0
|
1005
|
+
readPush1:
|
1006
|
+
PC => HASHPOS :JMP(_readPush1) ;1
|
1007
|
+
readPush2:
|
1008
|
+
PC => HASHPOS :JMP(_readPush2) ;2
|
1009
|
+
readPush3:
|
1010
|
+
PC => HASHPOS :JMP(_readPush3) ;3
|
1011
|
+
readPush4:
|
1012
|
+
PC => HASHPOS :JMP(_readPush4) ;4
|
1013
|
+
readPush5:
|
1014
|
+
PC => HASHPOS :JMP(_readPushX) ;5
|
1015
|
+
readPush6:
|
1016
|
+
PC => HASHPOS :JMP(_readPushX) ;6
|
1017
|
+
readPush7:
|
1018
|
+
PC => HASHPOS :JMP(_readPushX) ;7
|
1019
|
+
readPush8:
|
1020
|
+
PC => HASHPOS :JMP(_readPushX) ;8
|
1021
|
+
readPush9:
|
1022
|
+
PC => HASHPOS :JMP(_readPushX) ;9
|
1023
|
+
readPush10:
|
1024
|
+
PC => HASHPOS :JMP(_readPushX) ;10
|
1025
|
+
readPush11:
|
1026
|
+
PC => HASHPOS :JMP(_readPushX) ;11
|
1027
|
+
readPush12:
|
1028
|
+
PC => HASHPOS :JMP(_readPushX) ;12
|
1029
|
+
readPush13:
|
1030
|
+
PC => HASHPOS :JMP(_readPushX) ;13
|
1031
|
+
readPush14:
|
1032
|
+
PC => HASHPOS :JMP(_readPushX) ;14
|
1033
|
+
readPush15:
|
1034
|
+
PC => HASHPOS :JMP(_readPushX) ;15
|
1035
|
+
readPush16:
|
1036
|
+
PC => HASHPOS :JMP(_readPushX) ;16
|
1037
|
+
readPush17:
|
1038
|
+
PC => HASHPOS :JMP(_readPushX) ;17
|
1039
|
+
readPush18:
|
1040
|
+
PC => HASHPOS :JMP(_readPushX) ;18
|
1041
|
+
readPush19:
|
1042
|
+
PC => HASHPOS :JMP(_readPushX) ;19
|
1043
|
+
readPush20:
|
1044
|
+
PC => HASHPOS :JMP(_readPushX) ;20
|
1045
|
+
readPush21:
|
1046
|
+
PC => HASHPOS :JMP(_readPushX) ;21
|
1047
|
+
readPush22:
|
1048
|
+
PC => HASHPOS :JMP(_readPushX) ;22
|
1049
|
+
readPush23:
|
1050
|
+
PC => HASHPOS :JMP(_readPushX) ;23
|
1051
|
+
readPush24:
|
1052
|
+
PC => HASHPOS :JMP(_readPushX) ;24
|
1053
|
+
readPush25:
|
1054
|
+
PC => HASHPOS :JMP(_readPushX) ;25
|
1055
|
+
readPush26:
|
1056
|
+
PC => HASHPOS :JMP(_readPushX) ;26
|
1057
|
+
readPush27:
|
1058
|
+
PC => HASHPOS :JMP(_readPushX) ;27
|
1059
|
+
readPush28:
|
1060
|
+
PC => HASHPOS :JMP(_readPushX) ;28
|
1061
|
+
readPush29:
|
1062
|
+
PC => HASHPOS :JMP(_readPushX) ;29
|
1063
|
+
readPush30:
|
1064
|
+
PC => HASHPOS :JMP(_readPushX) ;30
|
1065
|
+
readPush31:
|
1066
|
+
PC => HASHPOS :JMP(_readPushX) ;31
|
1067
|
+
readPush32:
|
1068
|
+
PC => HASHPOS :JMP(_readPush32) ;32
|
1069
|
+
|
1070
|
+
_readPush1:
|
1071
|
+
$ => E :MLOAD(contractHashId)
|
1072
|
+
$ => E :HASHP1(E),RETURN
|
1073
|
+
|
1074
|
+
_readPush2:
|
1075
|
+
$ => E :MLOAD(contractHashId)
|
1076
|
+
$ => C :HASHP1(E)
|
1077
|
+
$ => E :HASHP1(E)
|
1078
|
+
C * 256 + E => E :RETURN
|
1079
|
+
|
1080
|
+
_readPush3:
|
1081
|
+
$ => E :MLOAD(contractHashId)
|
1082
|
+
$ => A :HASHP1(E)
|
1083
|
+
$ => C :HASHP1(E)
|
1084
|
+
$ => E :HASHP1(E)
|
1085
|
+
A * 2**16 + C * 2**8 + E => E :RETURN
|
1086
|
+
|
1087
|
+
_readPush4:
|
1088
|
+
$ => E :MLOAD(contractHashId)
|
1089
|
+
$ => A :HASHP1(E)
|
1090
|
+
$ => B :HASHP1(E)
|
1091
|
+
$ => C :HASHP1(E)
|
1092
|
+
$ => E :HASHP1(E)
|
1093
|
+
A * 2**24 + B * 2**16 + C * 2**8 + E => E :RETURN
|
1094
|
+
|
1095
|
+
_readPush32:
|
1096
|
+
$ => E :MLOAD(contractHashId)
|
1097
|
+
|
1098
|
+
$ => B :HASHP1(E)
|
1099
|
+
$ => RCX :HASHP1(E)
|
1100
|
+
$ => D :HASHP1(E)
|
1101
|
+
$ => A :HASHP1(E)
|
1102
|
+
2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1103
|
+
|
1104
|
+
; 28 bytes
|
1105
|
+
|
1106
|
+
$ => B :HASHP1(E)
|
1107
|
+
$ => RCX :HASHP1(E)
|
1108
|
+
$ => D :HASHP1(E)
|
1109
|
+
$ => A :HASHP1(E)
|
1110
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1111
|
+
|
1112
|
+
; 24 bytes
|
1113
|
+
|
1114
|
+
$ => B :HASHP1(E)
|
1115
|
+
$ => RCX :HASHP1(E)
|
1116
|
+
$ => D :HASHP1(E)
|
1117
|
+
$ => A :HASHP1(E)
|
1118
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1119
|
+
|
1120
|
+
; 20 bytes
|
1121
|
+
|
1122
|
+
$ => B :HASHP1(E)
|
1123
|
+
$ => RCX :HASHP1(E)
|
1124
|
+
$ => D :HASHP1(E)
|
1125
|
+
$ => A :HASHP1(E)
|
1126
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1127
|
+
|
1128
|
+
; 16 bytes
|
1129
|
+
|
1130
|
+
$ => B :HASHP1(E)
|
1131
|
+
$ => RCX :HASHP1(E)
|
1132
|
+
$ => D :HASHP1(E)
|
1133
|
+
$ => A :HASHP1(E)
|
1134
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1135
|
+
|
1136
|
+
; 12 bytes
|
1137
|
+
|
1138
|
+
$ => B :HASHP1(E)
|
1139
|
+
$ => RCX :HASHP1(E)
|
1140
|
+
$ => D :HASHP1(E)
|
1141
|
+
$ => A :HASHP1(E)
|
1142
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1143
|
+
|
1144
|
+
; 8 bytes
|
1145
|
+
|
1146
|
+
$ => B :HASHP1(E)
|
1147
|
+
$ => RCX :HASHP1(E)
|
1148
|
+
$ => D :HASHP1(E)
|
1149
|
+
$ => A :HASHP1(E)
|
1150
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1151
|
+
|
1152
|
+
; 4 bytes
|
1153
|
+
|
1154
|
+
$ => B :HASHP1(E)
|
1155
|
+
$ => RCX :HASHP1(E)
|
1156
|
+
$ => D :HASHP1(E)
|
1157
|
+
$ => A :HASHP1(E)
|
1158
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => E
|
1159
|
+
|
1160
|
+
32 => D :RETURN
|
1161
|
+
|
1162
|
+
_readPushX:
|
1163
|
+
D :MSTORE(pushBytes)
|
1164
|
+
$ => B :MLOAD(contractHashId)
|
1165
|
+
|
1166
|
+
readPushBytes:
|
1167
|
+
B => E :JMP(@readPushBytes + E)
|
1168
|
+
|
1169
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_1)
|
1170
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_2)
|
1171
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_3)
|
1172
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_4)
|
1173
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_5)
|
1174
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_6)
|
1175
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_7)
|
1176
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_8)
|
1177
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_9)
|
1178
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_10)
|
1179
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_11)
|
1180
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_12)
|
1181
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_13)
|
1182
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_14)
|
1183
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_15)
|
1184
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_16)
|
1185
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_17)
|
1186
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_18)
|
1187
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_19)
|
1188
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_20)
|
1189
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_21)
|
1190
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_22)
|
1191
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_23)
|
1192
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_24)
|
1193
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_25)
|
1194
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_26)
|
1195
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_27)
|
1196
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_28)
|
1197
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_29)
|
1198
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_30)
|
1199
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_31)
|
1200
|
+
0 => RCX, B, D, A, C :JMP(readPushBytes_32)
|
1201
|
+
|
1202
|
+
readPushBytes_32:
|
1203
|
+
$ => B :HASHP1(E)
|
1204
|
+
readPushBytes_31:
|
1205
|
+
$ => RCX :HASHP1(E)
|
1206
|
+
readPushBytes_30:
|
1207
|
+
$ => D :HASHP1(E)
|
1208
|
+
readPushBytes_29:
|
1209
|
+
$ => A :HASHP1(E)
|
1210
|
+
2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1211
|
+
|
1212
|
+
readPushBytes_28:
|
1213
|
+
$ => B :HASHP1(E)
|
1214
|
+
readPushBytes_27:
|
1215
|
+
$ => RCX :HASHP1(E)
|
1216
|
+
readPushBytes_26:
|
1217
|
+
$ => D :HASHP1(E)
|
1218
|
+
readPushBytes_25:
|
1219
|
+
$ => A :HASHP1(E)
|
1220
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1221
|
+
|
1222
|
+
readPushBytes_24:
|
1223
|
+
$ => B :HASHP1(E)
|
1224
|
+
readPushBytes_23:
|
1225
|
+
$ => RCX :HASHP1(E)
|
1226
|
+
readPushBytes_22:
|
1227
|
+
$ => D :HASHP1(E)
|
1228
|
+
readPushBytes_21:
|
1229
|
+
$ => A :HASHP1(E)
|
1230
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1231
|
+
|
1232
|
+
readPushBytes_20:
|
1233
|
+
$ => B :HASHP1(E)
|
1234
|
+
readPushBytes_19:
|
1235
|
+
$ => RCX :HASHP1(E)
|
1236
|
+
readPushBytes_18:
|
1237
|
+
$ => D :HASHP1(E)
|
1238
|
+
readPushBytes_17:
|
1239
|
+
$ => A :HASHP1(E)
|
1240
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1241
|
+
|
1242
|
+
readPushBytes_16:
|
1243
|
+
$ => B :HASHP1(E)
|
1244
|
+
readPushBytes_15:
|
1245
|
+
$ => RCX :HASHP1(E)
|
1246
|
+
readPushBytes_14:
|
1247
|
+
$ => D :HASHP1(E)
|
1248
|
+
readPushBytes_13:
|
1249
|
+
$ => A :HASHP1(E)
|
1250
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1251
|
+
|
1252
|
+
readPushBytes_12:
|
1253
|
+
$ => B :HASHP1(E)
|
1254
|
+
readPushBytes_11:
|
1255
|
+
$ => RCX :HASHP1(E)
|
1256
|
+
readPushBytes_10:
|
1257
|
+
$ => D :HASHP1(E)
|
1258
|
+
readPushBytes_9:
|
1259
|
+
$ => A :HASHP1(E)
|
1260
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1261
|
+
|
1262
|
+
readPushBytes_8:
|
1263
|
+
$ => B :HASHP1(E)
|
1264
|
+
readPushBytes_7:
|
1265
|
+
$ => RCX :HASHP1(E)
|
1266
|
+
readPushBytes_6:
|
1267
|
+
$ => D :HASHP1(E)
|
1268
|
+
readPushBytes_5:
|
1269
|
+
$ => A :HASHP1(E)
|
1270
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => C
|
1271
|
+
|
1272
|
+
readPushBytes_4:
|
1273
|
+
$ => B :HASHP1(E)
|
1274
|
+
readPushBytes_3:
|
1275
|
+
$ => RCX :HASHP1(E)
|
1276
|
+
readPushBytes_2:
|
1277
|
+
$ => D :HASHP1(E)
|
1278
|
+
readPushBytes_1:
|
1279
|
+
$ => A :HASHP1(E)
|
1280
|
+
ROTL_C + 2**24 * B + 2**16 * RCX + 2**8 * D + A => E
|
1281
|
+
|
1282
|
+
$ => D :MLOAD(pushBytes), RETURN
|
1283
|
+
|
1284
|
+
VAR GLOBAL tmpVarDaddB
|
1285
|
+
VAR GLOBAL tmpVarBaddB
|
1286
|
+
VAR GLOBAL tmpZkPCaddB
|
1287
|
+
VAR GLOBAL auxBytes
|
1288
|
+
|
1289
|
+
;@info: adds data to batchHashdata byte by byte
|
1290
|
+
;@in: A: bytes to add
|
1291
|
+
;@in D: bytes length
|
1292
|
+
addBatchHashByteByByte:
|
1293
|
+
%MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep)
|
1294
|
+
RR :MSTORE(tmpZkPCaddB)
|
1295
|
+
A :MSTORE(auxBytes)
|
1296
|
+
D :MSTORE(tmpVarDaddB)
|
1297
|
+
B :MSTORE(tmpVarBaddB)
|
1298
|
+
1 => D
|
1299
|
+
|
1300
|
+
utilsAddBatchHashBytebyByteLoop:
|
1301
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
1302
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
1303
|
+
32 - D => D
|
1304
|
+
$ => A :MLOAD(auxBytes), CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
1305
|
+
; get last byte in A
|
1306
|
+
0xFFn => B
|
1307
|
+
$ => A :AND
|
1308
|
+
D => B
|
1309
|
+
; add last byte to batchHashData
|
1310
|
+
1 => D :CALL(addBatchHashData); in:[D: length of the hash]
|
1311
|
+
; check loop
|
1312
|
+
B => D
|
1313
|
+
; D + 1 => D, we set 33 instead of 32 to earn 1 step
|
1314
|
+
33 - D => D
|
1315
|
+
$ => B :MLOAD(tmpVarDaddB)
|
1316
|
+
D - B - 1 :JMPN(utilsAddBatchHashBytebyByteLoop)
|
1317
|
+
$ => B :MLOAD(tmpVarBaddB)
|
1318
|
+
$ => RR :MLOAD(tmpZkPCaddB)
|
1319
|
+
:RETURN
|
1320
|
+
|
1321
|
+
VAR GLOBAL startsWithEF
|
1322
|
+
VAR GLOBAL tmpVarAEF
|
1323
|
+
VAR GLOBAL tmpVarBEF
|
1324
|
+
VAR GLOBAL tmpVarCEF
|
1325
|
+
VAR GLOBAL tmpVarDEF
|
1326
|
+
VAR GLOBAL tmpVarEEF
|
1327
|
+
VAR GLOBAL tmpZkPCEF
|
1328
|
+
; @info check bytecode first byte != 0xEF as defined in EIP-3541 (https://eips.ethereum.org/EIPS/eip-3541)
|
1329
|
+
; @internalParam {memOffset} memory offset to read bytes from
|
1330
|
+
; @internalParam {startsWithEF} flag to indicate if first deployed byte on the bytecode is 0xEF
|
1331
|
+
checkBytecodeStartsEF:
|
1332
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
1333
|
+
; save temporary registers
|
1334
|
+
A :MSTORE(tmpVarAEF)
|
1335
|
+
B :MSTORE(tmpVarBEF)
|
1336
|
+
C :MSTORE(tmpVarCEF)
|
1337
|
+
D :MSTORE(tmpVarDEF)
|
1338
|
+
E :MSTORE(tmpVarEEF)
|
1339
|
+
RR :MSTORE(tmpZkPCEF)
|
1340
|
+
|
1341
|
+
; set flag to 0
|
1342
|
+
0 :MSTORE(startsWithEF)
|
1343
|
+
|
1344
|
+
; check length
|
1345
|
+
$ :MLOAD(memSizeLinearPoseidon),JMPZ(checkBytecodeStartsEFend)
|
1346
|
+
|
1347
|
+
; load memOffset
|
1348
|
+
$ => E :MLOAD(memOffsetLinearPoseidon)
|
1349
|
+
|
1350
|
+
; get 1 byte from memory
|
1351
|
+
1 => C :CALL(MLOADX) ; in: [E: offset, C: length] out: [A: value , E: new offset]
|
1352
|
+
31 => D :CALL(SHRarith) ; in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
1353
|
+
|
1354
|
+
; check if byte read is equal to 0xEF
|
1355
|
+
%BYTECODE_STARTS_EF - A :JMPNZ(checkBytecodeStartsEFend)
|
1356
|
+
1 :MSTORE(startsWithEF)
|
1357
|
+
|
1358
|
+
checkBytecodeStartsEFend:
|
1359
|
+
; set back tmp registers
|
1360
|
+
$ => RR :MLOAD(tmpZkPCEF)
|
1361
|
+
$ => A :MLOAD(tmpVarAEF)
|
1362
|
+
$ => B :MLOAD(tmpVarBEF)
|
1363
|
+
$ => C :MLOAD(tmpVarCEF)
|
1364
|
+
$ => D :MLOAD(tmpVarDEF)
|
1365
|
+
$ => E :MLOAD(tmpVarEEF), RETURN
|
1366
|
+
|
1367
|
+
VAR GLOBAL tmpVarAhashP
|
1368
|
+
VAR GLOBAL tmpVarBhashP
|
1369
|
+
VAR GLOBAL tmpVarChashP
|
1370
|
+
VAR GLOBAL tmpVarEhashP
|
1371
|
+
VAR GLOBAL tmpZkPChashP
|
1372
|
+
VAR GLOBAL memOffsetLinearPoseidon
|
1373
|
+
VAR GLOBAL memSizeLinearPoseidon
|
1374
|
+
; @info Computes hash bytecode from memory bytes
|
1375
|
+
; @internalParam {memOffset} memory offset to read bytes from
|
1376
|
+
; @internalParam {memSize} memory size to read bytes from
|
1377
|
+
; @out D => resulting linear poseidon
|
1378
|
+
hashPoseidonLinearFromMemory:
|
1379
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
1380
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
1381
|
+
A :MSTORE(tmpVarAhashP)
|
1382
|
+
B :MSTORE(tmpVarBhashP)
|
1383
|
+
C :MSTORE(tmpVarChashP)
|
1384
|
+
E :MSTORE(tmpVarEhashP)
|
1385
|
+
RR :MSTORE(tmpZkPChashP)
|
1386
|
+
$ => E :MLOAD(memOffsetLinearPoseidon)
|
1387
|
+
$ => C :MLOAD(memSizeLinearPoseidon)
|
1388
|
+
0 => D
|
1389
|
+
C :JMPZ(hashPoseidonReturn)
|
1390
|
+
; check poseidon counters
|
1391
|
+
; 56 is the value used by the prover to increment poseidon counters depending on the hash length
|
1392
|
+
C :MSTORE(arithA)
|
1393
|
+
56 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
1394
|
+
$ => B :MLOAD(arithRes1)
|
1395
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 1 - B :JMPN(outOfCountersPoseidon)
|
1396
|
+
%MAX_CNT_PADDING_PG - CNT_PADDING_PG - 1 - B :JMPN(outOfCountersPadding)
|
1397
|
+
|
1398
|
+
; get a new hashPId
|
1399
|
+
$ => B :MLOAD(nextHashPId)
|
1400
|
+
B :MSTORE(tmpContractHashId)
|
1401
|
+
B + 1 :MSTORE(nextHashPId)
|
1402
|
+
32 => D
|
1403
|
+
0 => HASHPOS
|
1404
|
+
|
1405
|
+
hashPoseidonLoop:
|
1406
|
+
%MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep)
|
1407
|
+
|
1408
|
+
C :JMPZ(hashPoseidonEnd)
|
1409
|
+
C - 32 :JMPN(hashPoseidonFinal)
|
1410
|
+
:CALL(MLOAD32)
|
1411
|
+
E => B
|
1412
|
+
$ => E :MLOAD(tmpContractHashId)
|
1413
|
+
A :HASHP(E)
|
1414
|
+
B => E
|
1415
|
+
C - 32 => C :JMP(hashPoseidonLoop)
|
1416
|
+
|
1417
|
+
|
1418
|
+
hashPoseidonFinal:
|
1419
|
+
:CALL(MLOADX)
|
1420
|
+
32 - C => D :CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result]
|
1421
|
+
$ => E :MLOAD(tmpContractHashId)
|
1422
|
+
C => D
|
1423
|
+
A :HASHP(E)
|
1424
|
+
|
1425
|
+
hashPoseidonEnd:
|
1426
|
+
$ => E :MLOAD(tmpContractHashId)
|
1427
|
+
HASHPOS :HASHPLEN(E)
|
1428
|
+
$ => D :HASHPDIGEST(E)
|
1429
|
+
|
1430
|
+
hashPoseidonReturn:
|
1431
|
+
$ => RR :MLOAD(tmpZkPChashP)
|
1432
|
+
$ => A :MLOAD(tmpVarAhashP)
|
1433
|
+
$ => B :MLOAD(tmpVarBhashP)
|
1434
|
+
$ => C :MLOAD(tmpVarChashP)
|
1435
|
+
$ => E :MLOAD(tmpVarEhashP), RETURN
|
1436
|
+
|
1437
|
+
VAR GLOBAL tmpVarBmask
|
1438
|
+
; @info Mask address to 20 bytes
|
1439
|
+
; @in A => address not masked
|
1440
|
+
; @out A => masked address
|
1441
|
+
maskAddress:
|
1442
|
+
%MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep)
|
1443
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
1444
|
+
B :MSTORE(tmpVarBmask)
|
1445
|
+
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B
|
1446
|
+
$ => A :AND
|
1447
|
+
$ => B :MLOAD(tmpVarBmask), RETURN
|
1448
|
+
|
1449
|
+
VAR GLOBAL tmpVarAmulmod
|
1450
|
+
VAR GLOBAL tmpVarBmulmod
|
1451
|
+
VAR GLOBAL tmpVarDmulmod
|
1452
|
+
VAR GLOBAL tmpVarEmulmod
|
1453
|
+
VAR GLOBAL tmpZkPCmulmod
|
1454
|
+
; @info (A*B)%C => C
|
1455
|
+
; @in A
|
1456
|
+
; @in B
|
1457
|
+
; @in C
|
1458
|
+
; @out C
|
1459
|
+
utilMULMOD:
|
1460
|
+
; checks zk-counters
|
1461
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
1462
|
+
%MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary)
|
1463
|
+
%MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith)
|
1464
|
+
|
1465
|
+
RR :MSTORE(tmpZkPCmulmod)
|
1466
|
+
A :MSTORE(tmpVarAmulmod)
|
1467
|
+
B :MSTORE(tmpVarBmulmod)
|
1468
|
+
D :MSTORE(tmpVarDmulmod)
|
1469
|
+
E :MSTORE(tmpVarEmulmod)
|
1470
|
+
|
1471
|
+
; The following approach will be followed in order to verify the mulmod operation
|
1472
|
+
; A * B + 0 = D*2^256 + E
|
1473
|
+
; K * N + mulModResult = D*2^256 + E
|
1474
|
+
|
1475
|
+
; Since the k can be bigger than 2²⁵⁶ and therefore does not fit in a register, we split it in the
|
1476
|
+
; most significant and less significant part:
|
1477
|
+
|
1478
|
+
; (k.l + k.h * 2²⁵⁶) * N + mulModResult = (D1 + D2) * 2²⁵⁶ + E
|
1479
|
+
; And divide this operation in 2 which fits in 2²⁵⁶ digits
|
1480
|
+
|
1481
|
+
;k.l * N + mulModResult = D1 * 2²⁵⁶ + E
|
1482
|
+
;k.h * 2²⁵⁶ * N = D2 * 2²⁵⁶ --> k.h * N = D2
|
1483
|
+
|
1484
|
+
; Mul operation with Arith
|
1485
|
+
$${var _mulMod = A * B}
|
1486
|
+
A :MSTORE(arithA)
|
1487
|
+
; here we perform the: A * B + 0 = D*2^256 + E
|
1488
|
+
; result is stored in: arithRes1(E) and mulArithOverflowValue(D)
|
1489
|
+
B :MSTORE(arithB), CALL(mulARITH)
|
1490
|
+
C => A
|
1491
|
+
; Check if modulus is 0 or 1
|
1492
|
+
2 => B
|
1493
|
+
$ :LT, JMPC(zeroOneMod)
|
1494
|
+
; Now we will try to perform the following equation:
|
1495
|
+
; (k.l + k.h * 2²⁵⁶) * N + mulModResult = (D1 + D2) * 2²⁵⁶ + E
|
1496
|
+
|
1497
|
+
${(_mulMod / C) >> 256} => B ; k.h
|
1498
|
+
; We can jump with Js, because later it's all verified by the ARITH
|
1499
|
+
; the two paths must be mutually exclusive.
|
1500
|
+
; mulModNoKH: if kh is non zero, not found a solution only with kl
|
1501
|
+
${cond(B == 0)} :JMPN(mulModNoKH)
|
1502
|
+
|
1503
|
+
; in case of malicious prover, check that B was different of zero to
|
1504
|
+
; avoid dual path.
|
1505
|
+
0 => A
|
1506
|
+
0 :EQ ; assert B != 0
|
1507
|
+
|
1508
|
+
; Since there's k.h we will split the equation in those 2
|
1509
|
+
;k.l * N + mulModResult = D1 * 2²⁵⁶ + E
|
1510
|
+
;k.h * 2²⁵⁶ * N = D2 * 2²⁵⁶ --> k.h * N = D2
|
1511
|
+
|
1512
|
+
; k.h * N = D2
|
1513
|
+
; B * A + 0 = 0 * 2²⁵⁶ + E
|
1514
|
+
; D2 must be less than 2²⁵⁶
|
1515
|
+
C => A ; Modulus
|
1516
|
+
0 => C, D
|
1517
|
+
${B * A} => E :MSTORE(tmpVarDmulmod), ARITH ; D2
|
1518
|
+
|
1519
|
+
; k.l * N + mulModResult = D1 * 2²⁵⁶ + E
|
1520
|
+
; B * A + C = D*2^256 + E
|
1521
|
+
; remember that:
|
1522
|
+
; result of mul is stored in: arithRes1(E) and mulArithOverflowValue(D)
|
1523
|
+
|
1524
|
+
${(_mulMod / A) % (1 << 256)} => B ; k.l
|
1525
|
+
${_mulMod % A} => C ; mulModResult
|
1526
|
+
${(B * A + C) >> 256} => D ; D1
|
1527
|
+
$ :MLOAD(arithRes1), ARITH
|
1528
|
+
|
1529
|
+
; Finally we need to assert the following:
|
1530
|
+
; N>resultModulus
|
1531
|
+
; D1 + D2 = D
|
1532
|
+
; N>resultModulus ; LT; ASSERT
|
1533
|
+
A => B ; modulus
|
1534
|
+
C => A ; mulModResult
|
1535
|
+
$ => A :LT
|
1536
|
+
1 :ASSERT
|
1537
|
+
|
1538
|
+
; Assert D1 + D2 = D ; ADD ;ASSERT
|
1539
|
+
D => A ; D1
|
1540
|
+
$ => B :MLOAD(tmpVarDmulmod) ;D2
|
1541
|
+
|
1542
|
+
; verify no carry, because D = D1 + D2 must be less than 2**256
|
1543
|
+
; to pass arithmetic equation A * B + C = D * 2**256 + op
|
1544
|
+
$ => A :ADD,JMPC(failAssert)
|
1545
|
+
$ :MLOAD(mulArithOverflowValue), ASSERT, JMP(utilMULMODend)
|
1546
|
+
|
1547
|
+
mulModNoKH:
|
1548
|
+
; if theres no K.h the equation is simplified as:
|
1549
|
+
; K * N + mulModResult = D*2^256 + E
|
1550
|
+
; B * A + C = D*2^256 + E
|
1551
|
+
|
1552
|
+
C => A ; Modulus on A
|
1553
|
+
${(_mulMod / A)} => B ; k
|
1554
|
+
${_mulMod % A} => C ; mulModResult
|
1555
|
+
$ => D :MLOAD(mulArithOverflowValue)
|
1556
|
+
$ :MLOAD(arithRes1), ARITH
|
1557
|
+
|
1558
|
+
A => B ; modulus
|
1559
|
+
C => A ; mulModResult
|
1560
|
+
$ => A :LT
|
1561
|
+
1 :ASSERT, JMP(utilMULMODend)
|
1562
|
+
|
1563
|
+
zeroOneMod:
|
1564
|
+
0 => C
|
1565
|
+
|
1566
|
+
utilMULMODend:
|
1567
|
+
$ => A :MLOAD(tmpVarAmulmod)
|
1568
|
+
$ => B :MLOAD(tmpVarBmulmod)
|
1569
|
+
$ => D :MLOAD(tmpVarDmulmod)
|
1570
|
+
$ => RR :MLOAD(tmpZkPCmulmod)
|
1571
|
+
$ => E :MLOAD(tmpVarEmulmod), RETURN
|
1572
|
+
|
1573
|
+
VAR GLOBAL tmpVarBexp
|
1574
|
+
VAR GLOBAL tmpVarCexp
|
1575
|
+
VAR GLOBAL tmpVarEexp
|
1576
|
+
VAR GLOBAL tmpZkPCexp
|
1577
|
+
|
1578
|
+
;@info exp(A,D) --> A^D
|
1579
|
+
;@in A, D => A^D
|
1580
|
+
;@out A => result
|
1581
|
+
expAD:
|
1582
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
1583
|
+
%MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
|
1584
|
+
RR :MSTORE(tmpZkPCexp)
|
1585
|
+
B :MSTORE(tmpVarBexp)
|
1586
|
+
C :MSTORE(tmpVarCexp)
|
1587
|
+
E :MSTORE(tmpVarEexp)
|
1588
|
+
;E base
|
1589
|
+
A => E
|
1590
|
+
;B exp
|
1591
|
+
D => B
|
1592
|
+
0 => A
|
1593
|
+
;if exp == 0 --> expAD0
|
1594
|
+
$ :EQ,JMPC(expAD0)
|
1595
|
+
;A base
|
1596
|
+
E => A
|
1597
|
+
0 => B
|
1598
|
+
;if base == 0 --> expA0D
|
1599
|
+
$ :EQ,JMPC(expA0D)
|
1600
|
+
1 => C
|
1601
|
+
D => B :CALL(getLenBits) ;A exp bits length
|
1602
|
+
|
1603
|
+
; check zk-counters on each loop (A loops)
|
1604
|
+
; - 3 ARITH: 1 in divARITH + 1 in 2*mulARITH
|
1605
|
+
; - 5 BINARIES: 5 in divARITH
|
1606
|
+
; - 100 steps (rounded up): 37 in divARITH + 11 in 2*mulARITH + 18 self
|
1607
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2*A :JMPN(outOfCountersBinary)
|
1608
|
+
%MAX_CNT_STEPS - STEP - 50*A :JMPN(outOfCountersStep)
|
1609
|
+
|
1610
|
+
expADloop:
|
1611
|
+
;A exp
|
1612
|
+
D => A
|
1613
|
+
0 => B
|
1614
|
+
;if exp == 0 --> expADend
|
1615
|
+
$ :EQ,JMPC(expADend)
|
1616
|
+
A :MSTORE(arithA)
|
1617
|
+
;divARITH --> exp/2
|
1618
|
+
2 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
1619
|
+
;D = exp/2
|
1620
|
+
$ => D :MLOAD(arithRes1)
|
1621
|
+
;A = exp%2 (0 or 1)
|
1622
|
+
$ => A :MLOAD(arithRes2)
|
1623
|
+
0 => B
|
1624
|
+
;if exp%2 == 0 --> expADloop0
|
1625
|
+
$ :EQ,JMPC(expADloop0)
|
1626
|
+
E :MSTORE(arithA)
|
1627
|
+
;mulARITH --> E*C
|
1628
|
+
C :MSTORE(arithB), CALL(mulARITH)
|
1629
|
+
;C = E*C (acc = bp*acc)
|
1630
|
+
$ => C :MLOAD(arithRes1)
|
1631
|
+
|
1632
|
+
expADloop0:
|
1633
|
+
E :MSTORE(arithA)
|
1634
|
+
;mulARITH --> E*E
|
1635
|
+
E :MSTORE(arithB), CALL(mulARITH)
|
1636
|
+
;E = E*E (bp = bp*bp)
|
1637
|
+
$ => E :MLOAD(arithRes1), JMP(expADloop)
|
1638
|
+
;if base == 0, result0
|
1639
|
+
expA0D:
|
1640
|
+
0 => C
|
1641
|
+
0 => D :JMP(expADend)
|
1642
|
+
;if exp == 0, result 1
|
1643
|
+
expAD0:
|
1644
|
+
1 => C
|
1645
|
+
0 => D
|
1646
|
+
|
1647
|
+
expADend:
|
1648
|
+
C => A
|
1649
|
+
$ => B :MLOAD(tmpVarBexp)
|
1650
|
+
$ => C :MLOAD(tmpVarCexp)
|
1651
|
+
$ => RR :MLOAD(tmpZkPCexp)
|
1652
|
+
$ => E :MLOAD(tmpVarEexp), RETURN
|
1653
|
+
|
1654
|
+
;@info function to force a failed assert
|
1655
|
+
failAssert:
|
1656
|
+
1 => A
|
1657
|
+
2 :ASSERT
|
1658
|
+
|
1659
|
+
VAR GLOBAL tmpZkPCVerifyMerkleProof
|
1660
|
+
;@info verifies L1Info data with sibilings
|
1661
|
+
;@in A: ger
|
1662
|
+
;@in B: blockhashL1
|
1663
|
+
;@in C: timestamp
|
1664
|
+
verifyMerkleProof:
|
1665
|
+
; check zk-counters
|
1666
|
+
$ => E :MLOAD(cntKeccakPreProcess)
|
1667
|
+
|
1668
|
+
; 1 keccak for the leaf and 32 for the L1InfoTree
|
1669
|
+
%MAX_CNT_KECCAK_F - CNT_KECCAK_F - E - 33 :JMPN(outOfCountersKeccak)
|
1670
|
+
; 7 steps at most per bit + 21 statics
|
1671
|
+
%MAX_CNT_STEPS - STEP - 7 * 32 - 25 :JMPN(outOfCountersStep)
|
1672
|
+
; check binaries
|
1673
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
1674
|
+
|
1675
|
+
RR :MSTORE(tmpZkPCVerifyMerkleProof)
|
1676
|
+
0 :MSTORE(isL1InfoDataZero)
|
1677
|
+
|
1678
|
+
;;;;;;;;;;;;;;;;;;;;;
|
1679
|
+
;; compute leaf value
|
1680
|
+
;;;;;;;;;;;;;;;;;;;;;
|
1681
|
+
|
1682
|
+
; new keccak address
|
1683
|
+
$ => E :MLOAD(lastHashKIdUsed)
|
1684
|
+
E + 1 => E :MSTORE(lastHashKIdUsed)
|
1685
|
+
|
1686
|
+
; add gerL1InfoTree (32 bytes)
|
1687
|
+
0 => HASHPOS
|
1688
|
+
32 => D
|
1689
|
+
A :HASHK(E)
|
1690
|
+
|
1691
|
+
; add blockHashL1 (32 bytes)
|
1692
|
+
B :HASHK(E)
|
1693
|
+
|
1694
|
+
; add timestamp (8 bytes)
|
1695
|
+
8 => D
|
1696
|
+
C :HASHK(E)
|
1697
|
+
|
1698
|
+
; compute l1InfoTree Leaf value
|
1699
|
+
HASHPOS :HASHKLEN(E)
|
1700
|
+
$ => C, A :HASHKDIGEST(E) ; initial value
|
1701
|
+
; allow to set value to all zeroes if all its values are zero
|
1702
|
+
%L1_INFO_DATA_ZERO => B
|
1703
|
+
$ :EQ, JMPNC(continueVerifyMerkleProof)
|
1704
|
+
1 :MSTORE(isL1InfoDataZero)
|
1705
|
+
0 => C
|
1706
|
+
|
1707
|
+
continueVerifyMerkleProof:
|
1708
|
+
; initialization registers for smt verify
|
1709
|
+
0 => D, A
|
1710
|
+
|
1711
|
+
$ => B :MLOAD(indexL1InfoTree)
|
1712
|
+
|
1713
|
+
; prepare new hash
|
1714
|
+
$ => E :MLOAD(lastHashKIdUsed)
|
1715
|
+
E + 1 => E :MSTORE(lastHashKIdUsed)
|
1716
|
+
32 => D
|
1717
|
+
|
1718
|
+
; - Start loop 32 levels:
|
1719
|
+
; - provide each 'indexL1InfoTree' bit to either hash left/right the merkle tree nodes
|
1720
|
+
; - compute linear combination of 'indexL1InfoTree' bits to match the 'indexL1InfoTree' itself at the end of the loop
|
1721
|
+
|
1722
|
+
; BIT 0
|
1723
|
+
0 => HASHPOS
|
1724
|
+
${B & 0x00000001} :JMPZ(hashLeft0)
|
1725
|
+
|
1726
|
+
hashRight0:
|
1727
|
+
${getSmtProof(mem.indexL1InfoTree, 0)} :HASHK(E+0)
|
1728
|
+
C :HASHK(E+0)
|
1729
|
+
A + 0x00000001 => A :JMP(hashBranchEnd0)
|
1730
|
+
|
1731
|
+
hashLeft0:
|
1732
|
+
C :HASHK(E+0)
|
1733
|
+
${getSmtProof(mem.indexL1InfoTree, 0)} :HASHK(E+0)
|
1734
|
+
|
1735
|
+
hashBranchEnd0:
|
1736
|
+
HASHPOS :HASHKLEN(E+0)
|
1737
|
+
$ => C :HASHKDIGEST(E+0)
|
1738
|
+
|
1739
|
+
; BIT 1
|
1740
|
+
0 => HASHPOS
|
1741
|
+
${B & 0x00000002} :JMPZ(hashLeft1)
|
1742
|
+
|
1743
|
+
hashRight1:
|
1744
|
+
${getSmtProof(mem.indexL1InfoTree, 1)} :HASHK(E+1)
|
1745
|
+
C :HASHK(E+1)
|
1746
|
+
A + 0x00000002 => A :JMP(hashBranchEnd1)
|
1747
|
+
|
1748
|
+
hashLeft1:
|
1749
|
+
C :HASHK(E+1)
|
1750
|
+
${getSmtProof(mem.indexL1InfoTree, 1)} :HASHK(E+1)
|
1751
|
+
|
1752
|
+
hashBranchEnd1:
|
1753
|
+
HASHPOS :HASHKLEN(E+1)
|
1754
|
+
$ => C :HASHKDIGEST(E+1)
|
1755
|
+
|
1756
|
+
; BIT 2
|
1757
|
+
0 => HASHPOS
|
1758
|
+
${B & 0x00000004} :JMPZ(hashLeft2)
|
1759
|
+
|
1760
|
+
hashRight2:
|
1761
|
+
${getSmtProof(mem.indexL1InfoTree, 2)} :HASHK(E+2)
|
1762
|
+
C :HASHK(E+2)
|
1763
|
+
A + 0x00000004 => A :JMP(hashBranchEnd2)
|
1764
|
+
|
1765
|
+
hashLeft2:
|
1766
|
+
C :HASHK(E+2)
|
1767
|
+
${getSmtProof(mem.indexL1InfoTree, 2)} :HASHK(E+2)
|
1768
|
+
|
1769
|
+
hashBranchEnd2:
|
1770
|
+
HASHPOS :HASHKLEN(E+2)
|
1771
|
+
$ => C :HASHKDIGEST(E+2)
|
1772
|
+
|
1773
|
+
; BIT 3
|
1774
|
+
0 => HASHPOS
|
1775
|
+
${B & 0x00000008} :JMPZ(hashLeft3)
|
1776
|
+
|
1777
|
+
hashRight3:
|
1778
|
+
${getSmtProof(mem.indexL1InfoTree, 3)} :HASHK(E+3)
|
1779
|
+
C :HASHK(E+3)
|
1780
|
+
A + 0x00000008 => A :JMP(hashBranchEnd3)
|
1781
|
+
|
1782
|
+
hashLeft3:
|
1783
|
+
C :HASHK(E+3)
|
1784
|
+
${getSmtProof(mem.indexL1InfoTree, 3)} :HASHK(E+3)
|
1785
|
+
|
1786
|
+
hashBranchEnd3:
|
1787
|
+
HASHPOS :HASHKLEN(E+3)
|
1788
|
+
$ => C :HASHKDIGEST(E+3)
|
1789
|
+
|
1790
|
+
; BIT 4
|
1791
|
+
0 => HASHPOS
|
1792
|
+
${B & 0x00000010} :JMPZ(hashLeft4)
|
1793
|
+
|
1794
|
+
hashRight4:
|
1795
|
+
${getSmtProof(mem.indexL1InfoTree, 4)} :HASHK(E+4)
|
1796
|
+
C :HASHK(E+4)
|
1797
|
+
A + 0x00000010 => A :JMP(hashBranchEnd4)
|
1798
|
+
|
1799
|
+
hashLeft4:
|
1800
|
+
C :HASHK(E+4)
|
1801
|
+
${getSmtProof(mem.indexL1InfoTree, 4)} :HASHK(E+4)
|
1802
|
+
|
1803
|
+
hashBranchEnd4:
|
1804
|
+
HASHPOS :HASHKLEN(E+4)
|
1805
|
+
$ => C :HASHKDIGEST(E+4)
|
1806
|
+
|
1807
|
+
; BIT 5
|
1808
|
+
0 => HASHPOS
|
1809
|
+
${B & 0x00000020} :JMPZ(hashLeft5)
|
1810
|
+
|
1811
|
+
hashRight5:
|
1812
|
+
${getSmtProof(mem.indexL1InfoTree, 5)} :HASHK(E+5)
|
1813
|
+
C :HASHK(E+5)
|
1814
|
+
A + 0x00000020 => A :JMP(hashBranchEnd5)
|
1815
|
+
|
1816
|
+
hashLeft5:
|
1817
|
+
C :HASHK(E+5)
|
1818
|
+
${getSmtProof(mem.indexL1InfoTree, 5)} :HASHK(E+5)
|
1819
|
+
|
1820
|
+
hashBranchEnd5:
|
1821
|
+
HASHPOS :HASHKLEN(E+5)
|
1822
|
+
$ => C :HASHKDIGEST(E+5)
|
1823
|
+
|
1824
|
+
; BIT 6
|
1825
|
+
0 => HASHPOS
|
1826
|
+
${B & 0x00000040} :JMPZ(hashLeft6)
|
1827
|
+
|
1828
|
+
hashRight6:
|
1829
|
+
${getSmtProof(mem.indexL1InfoTree, 6)} :HASHK(E+6)
|
1830
|
+
C :HASHK(E+6)
|
1831
|
+
A + 0x00000040 => A :JMP(hashBranchEnd6)
|
1832
|
+
|
1833
|
+
hashLeft6:
|
1834
|
+
C :HASHK(E+6)
|
1835
|
+
${getSmtProof(mem.indexL1InfoTree, 6)} :HASHK(E+6)
|
1836
|
+
|
1837
|
+
hashBranchEnd6:
|
1838
|
+
HASHPOS :HASHKLEN(E+6)
|
1839
|
+
$ => C :HASHKDIGEST(E+6)
|
1840
|
+
|
1841
|
+
; BIT 7
|
1842
|
+
0 => HASHPOS
|
1843
|
+
${B & 0x00000080} :JMPZ(hashLeft7)
|
1844
|
+
|
1845
|
+
hashRight7:
|
1846
|
+
${getSmtProof(mem.indexL1InfoTree, 7)} :HASHK(E+7)
|
1847
|
+
C :HASHK(E+7)
|
1848
|
+
A + 0x00000080 => A :JMP(hashBranchEnd7)
|
1849
|
+
|
1850
|
+
hashLeft7:
|
1851
|
+
C :HASHK(E+7)
|
1852
|
+
${getSmtProof(mem.indexL1InfoTree, 7)} :HASHK(E+7)
|
1853
|
+
|
1854
|
+
hashBranchEnd7:
|
1855
|
+
HASHPOS :HASHKLEN(E+7)
|
1856
|
+
$ => C :HASHKDIGEST(E+7)
|
1857
|
+
|
1858
|
+
; BIT 8
|
1859
|
+
0 => HASHPOS
|
1860
|
+
${B & 0x00000100} :JMPZ(hashLeft8)
|
1861
|
+
|
1862
|
+
hashRight8:
|
1863
|
+
${getSmtProof(mem.indexL1InfoTree, 8)} :HASHK(E+8)
|
1864
|
+
C :HASHK(E+8)
|
1865
|
+
A + 0x00000100 => A :JMP(hashBranchEnd8)
|
1866
|
+
|
1867
|
+
hashLeft8:
|
1868
|
+
C :HASHK(E+8)
|
1869
|
+
${getSmtProof(mem.indexL1InfoTree, 8)} :HASHK(E+8)
|
1870
|
+
|
1871
|
+
hashBranchEnd8:
|
1872
|
+
HASHPOS :HASHKLEN(E+8)
|
1873
|
+
$ => C :HASHKDIGEST(E+8)
|
1874
|
+
|
1875
|
+
; BIT 9
|
1876
|
+
0 => HASHPOS
|
1877
|
+
${B & 0x00000200} :JMPZ(hashLeft9)
|
1878
|
+
|
1879
|
+
hashRight9:
|
1880
|
+
${getSmtProof(mem.indexL1InfoTree, 9)} :HASHK(E+9)
|
1881
|
+
C :HASHK(E+9)
|
1882
|
+
A + 0x00000200 => A :JMP(hashBranchEnd9)
|
1883
|
+
|
1884
|
+
hashLeft9:
|
1885
|
+
C :HASHK(E+9)
|
1886
|
+
${getSmtProof(mem.indexL1InfoTree, 9)} :HASHK(E+9)
|
1887
|
+
|
1888
|
+
hashBranchEnd9:
|
1889
|
+
HASHPOS :HASHKLEN(E+9)
|
1890
|
+
$ => C :HASHKDIGEST(E+9)
|
1891
|
+
|
1892
|
+
; BIT 10
|
1893
|
+
0 => HASHPOS
|
1894
|
+
${B & 0x00000400} :JMPZ(hashLeft10)
|
1895
|
+
|
1896
|
+
hashRight10:
|
1897
|
+
${getSmtProof(mem.indexL1InfoTree, 10)} :HASHK(E+10)
|
1898
|
+
C :HASHK(E+10)
|
1899
|
+
A + 0x00000400 => A :JMP(hashBranchEnd10)
|
1900
|
+
|
1901
|
+
hashLeft10:
|
1902
|
+
C :HASHK(E+10)
|
1903
|
+
${getSmtProof(mem.indexL1InfoTree, 10)} :HASHK(E+10)
|
1904
|
+
|
1905
|
+
hashBranchEnd10:
|
1906
|
+
HASHPOS :HASHKLEN(E+10)
|
1907
|
+
$ => C :HASHKDIGEST(E+10)
|
1908
|
+
|
1909
|
+
; BIT 11
|
1910
|
+
0 => HASHPOS
|
1911
|
+
${B & 0x00000800} :JMPZ(hashLeft11)
|
1912
|
+
|
1913
|
+
hashRight11:
|
1914
|
+
${getSmtProof(mem.indexL1InfoTree, 11)} :HASHK(E+11)
|
1915
|
+
C :HASHK(E+11)
|
1916
|
+
A + 0x00000800 => A :JMP(hashBranchEnd11)
|
1917
|
+
|
1918
|
+
hashLeft11:
|
1919
|
+
C :HASHK(E+11)
|
1920
|
+
${getSmtProof(mem.indexL1InfoTree, 11)} :HASHK(E+11)
|
1921
|
+
|
1922
|
+
hashBranchEnd11:
|
1923
|
+
HASHPOS :HASHKLEN(E+11)
|
1924
|
+
$ => C :HASHKDIGEST(E+11)
|
1925
|
+
|
1926
|
+
|
1927
|
+
; BIT 12
|
1928
|
+
0 => HASHPOS
|
1929
|
+
${B & 0x00001000} :JMPZ(hashLeft12)
|
1930
|
+
|
1931
|
+
hashRight12:
|
1932
|
+
${getSmtProof(mem.indexL1InfoTree, 12)} :HASHK(E+12)
|
1933
|
+
C :HASHK(E+12)
|
1934
|
+
A + 0x00001000 => A :JMP(hashBranchEnd12)
|
1935
|
+
|
1936
|
+
hashLeft12:
|
1937
|
+
C :HASHK(E+12)
|
1938
|
+
${getSmtProof(mem.indexL1InfoTree, 12)} :HASHK(E+12)
|
1939
|
+
|
1940
|
+
hashBranchEnd12:
|
1941
|
+
HASHPOS :HASHKLEN(E+12)
|
1942
|
+
$ => C :HASHKDIGEST(E+12)
|
1943
|
+
|
1944
|
+
; BIT 13
|
1945
|
+
0 => HASHPOS
|
1946
|
+
${B & 0x00002000} :JMPZ(hashLeft13)
|
1947
|
+
|
1948
|
+
hashRight13:
|
1949
|
+
${getSmtProof(mem.indexL1InfoTree, 13)} :HASHK(E+13)
|
1950
|
+
C :HASHK(E+13)
|
1951
|
+
A + 0x00002000 => A :JMP(hashBranchEnd13)
|
1952
|
+
|
1953
|
+
hashLeft13:
|
1954
|
+
C :HASHK(E+13)
|
1955
|
+
${getSmtProof(mem.indexL1InfoTree, 13)} :HASHK(E+13)
|
1956
|
+
|
1957
|
+
hashBranchEnd13:
|
1958
|
+
HASHPOS :HASHKLEN(E+13)
|
1959
|
+
$ => C :HASHKDIGEST(E+13)
|
1960
|
+
|
1961
|
+
; BIT 14
|
1962
|
+
0 => HASHPOS
|
1963
|
+
${B & 0x00004000} :JMPZ(hashLeft14)
|
1964
|
+
|
1965
|
+
hashRight14:
|
1966
|
+
${getSmtProof(mem.indexL1InfoTree, 14)} :HASHK(E+14)
|
1967
|
+
C :HASHK(E+14)
|
1968
|
+
A + 0x00004000 => A :JMP(hashBranchEnd14)
|
1969
|
+
|
1970
|
+
hashLeft14:
|
1971
|
+
C :HASHK(E+14)
|
1972
|
+
${getSmtProof(mem.indexL1InfoTree, 14)} :HASHK(E+14)
|
1973
|
+
|
1974
|
+
hashBranchEnd14:
|
1975
|
+
HASHPOS :HASHKLEN(E+14)
|
1976
|
+
$ => C :HASHKDIGEST(E+14)
|
1977
|
+
|
1978
|
+
; BIT 15
|
1979
|
+
0 => HASHPOS
|
1980
|
+
${B & 0x00008000} :JMPZ(hashLeft15)
|
1981
|
+
|
1982
|
+
hashRight15:
|
1983
|
+
${getSmtProof(mem.indexL1InfoTree, 15)} :HASHK(E+15)
|
1984
|
+
C :HASHK(E+15)
|
1985
|
+
A + 0x00008000 => A :JMP(hashBranchEnd15)
|
1986
|
+
|
1987
|
+
hashLeft15:
|
1988
|
+
C :HASHK(E+15)
|
1989
|
+
${getSmtProof(mem.indexL1InfoTree, 15)} :HASHK(E+15)
|
1990
|
+
|
1991
|
+
hashBranchEnd15:
|
1992
|
+
HASHPOS :HASHKLEN(E+15)
|
1993
|
+
$ => C :HASHKDIGEST(E+15)
|
1994
|
+
|
1995
|
+
; BIT 16
|
1996
|
+
0 => HASHPOS
|
1997
|
+
${B & 0x00010000} :JMPZ(hashLeft16)
|
1998
|
+
|
1999
|
+
hashRight16:
|
2000
|
+
${getSmtProof(mem.indexL1InfoTree, 16)} :HASHK(E+16)
|
2001
|
+
C :HASHK(E+16)
|
2002
|
+
A + 0x00010000 => A :JMP(hashBranchEnd16)
|
2003
|
+
|
2004
|
+
hashLeft16:
|
2005
|
+
C :HASHK(E+16)
|
2006
|
+
${getSmtProof(mem.indexL1InfoTree, 16)} :HASHK(E+16)
|
2007
|
+
|
2008
|
+
hashBranchEnd16:
|
2009
|
+
HASHPOS :HASHKLEN(E+16)
|
2010
|
+
$ => C :HASHKDIGEST(E+16)
|
2011
|
+
|
2012
|
+
; BIT 17
|
2013
|
+
0 => HASHPOS
|
2014
|
+
${B & 0x00020000} :JMPZ(hashLeft17)
|
2015
|
+
|
2016
|
+
hashRight17:
|
2017
|
+
${getSmtProof(mem.indexL1InfoTree, 17)} :HASHK(E+17)
|
2018
|
+
C :HASHK(E+17)
|
2019
|
+
A + 0x00020000 => A :JMP(hashBranchEnd17)
|
2020
|
+
|
2021
|
+
hashLeft17:
|
2022
|
+
C :HASHK(E+17)
|
2023
|
+
${getSmtProof(mem.indexL1InfoTree, 17)} :HASHK(E+17)
|
2024
|
+
|
2025
|
+
hashBranchEnd17:
|
2026
|
+
HASHPOS :HASHKLEN(E+17)
|
2027
|
+
$ => C :HASHKDIGEST(E+17)
|
2028
|
+
|
2029
|
+
; BIT 18
|
2030
|
+
0 => HASHPOS
|
2031
|
+
${B & 0x00040000} :JMPZ(hashLeft18)
|
2032
|
+
|
2033
|
+
hashRight18:
|
2034
|
+
${getSmtProof(mem.indexL1InfoTree, 18)} :HASHK(E+18)
|
2035
|
+
C :HASHK(E+18)
|
2036
|
+
A + 0x00040000 => A :JMP(hashBranchEnd18)
|
2037
|
+
|
2038
|
+
hashLeft18:
|
2039
|
+
C :HASHK(E+18)
|
2040
|
+
${getSmtProof(mem.indexL1InfoTree, 18)} :HASHK(E+18)
|
2041
|
+
|
2042
|
+
hashBranchEnd18:
|
2043
|
+
HASHPOS :HASHKLEN(E+18)
|
2044
|
+
$ => C :HASHKDIGEST(E+18)
|
2045
|
+
|
2046
|
+
; BIT 19
|
2047
|
+
0 => HASHPOS
|
2048
|
+
${B & 0x00080000} :JMPZ(hashLeft19)
|
2049
|
+
|
2050
|
+
hashRight19:
|
2051
|
+
${getSmtProof(mem.indexL1InfoTree, 19)} :HASHK(E+19)
|
2052
|
+
C :HASHK(E+19)
|
2053
|
+
A + 0x00080000 => A :JMP(hashBranchEnd19)
|
2054
|
+
|
2055
|
+
hashLeft19:
|
2056
|
+
C :HASHK(E+19)
|
2057
|
+
${getSmtProof(mem.indexL1InfoTree, 19)} :HASHK(E+19)
|
2058
|
+
|
2059
|
+
hashBranchEnd19:
|
2060
|
+
HASHPOS :HASHKLEN(E+19)
|
2061
|
+
$ => C :HASHKDIGEST(E+19)
|
2062
|
+
|
2063
|
+
; BIT 20
|
2064
|
+
0 => HASHPOS
|
2065
|
+
${B & 0x00100000} :JMPZ(hashLeft20)
|
2066
|
+
|
2067
|
+
hashRight20:
|
2068
|
+
${getSmtProof(mem.indexL1InfoTree, 20)} :HASHK(E+20)
|
2069
|
+
C :HASHK(E+20)
|
2070
|
+
A + 0x00100000 => A :JMP(hashBranchEnd20)
|
2071
|
+
|
2072
|
+
hashLeft20:
|
2073
|
+
C :HASHK(E+20)
|
2074
|
+
${getSmtProof(mem.indexL1InfoTree, 20)} :HASHK(E+20)
|
2075
|
+
|
2076
|
+
hashBranchEnd20:
|
2077
|
+
HASHPOS :HASHKLEN(E+20)
|
2078
|
+
$ => C :HASHKDIGEST(E+20)
|
2079
|
+
|
2080
|
+
; BIT 21
|
2081
|
+
0 => HASHPOS
|
2082
|
+
${B & 0x00200000} :JMPZ(hashLeft21)
|
2083
|
+
|
2084
|
+
hashRight21:
|
2085
|
+
${getSmtProof(mem.indexL1InfoTree, 21)} :HASHK(E+21)
|
2086
|
+
C :HASHK(E+21)
|
2087
|
+
A + 0x00200000 => A :JMP(hashBranchEnd21)
|
2088
|
+
|
2089
|
+
hashLeft21:
|
2090
|
+
C :HASHK(E+21)
|
2091
|
+
${getSmtProof(mem.indexL1InfoTree, 21)} :HASHK(E+21)
|
2092
|
+
|
2093
|
+
hashBranchEnd21:
|
2094
|
+
HASHPOS :HASHKLEN(E+21)
|
2095
|
+
$ => C :HASHKDIGEST(E+21)
|
2096
|
+
|
2097
|
+
; BIT 22
|
2098
|
+
0 => HASHPOS
|
2099
|
+
${B & 0x00400000} :JMPZ(hashLeft22)
|
2100
|
+
|
2101
|
+
hashRight22:
|
2102
|
+
${getSmtProof(mem.indexL1InfoTree, 22)} :HASHK(E+22)
|
2103
|
+
C :HASHK(E+22)
|
2104
|
+
A + 0x00400000 => A :JMP(hashBranchEnd22)
|
2105
|
+
|
2106
|
+
hashLeft22:
|
2107
|
+
C :HASHK(E+22)
|
2108
|
+
${getSmtProof(mem.indexL1InfoTree, 22)} :HASHK(E+22)
|
2109
|
+
|
2110
|
+
hashBranchEnd22:
|
2111
|
+
HASHPOS :HASHKLEN(E+22)
|
2112
|
+
$ => C :HASHKDIGEST(E+22)
|
2113
|
+
|
2114
|
+
; BIT 23
|
2115
|
+
0 => HASHPOS
|
2116
|
+
${B & 0x00800000} :JMPZ(hashLeft23)
|
2117
|
+
|
2118
|
+
hashRight23:
|
2119
|
+
${getSmtProof(mem.indexL1InfoTree, 23)} :HASHK(E+23)
|
2120
|
+
C :HASHK(E+23)
|
2121
|
+
A + 0x00800000 => A :JMP(hashBranchEnd23)
|
2122
|
+
|
2123
|
+
hashLeft23:
|
2124
|
+
C :HASHK(E+23)
|
2125
|
+
${getSmtProof(mem.indexL1InfoTree, 23)} :HASHK(E+23)
|
2126
|
+
|
2127
|
+
hashBranchEnd23:
|
2128
|
+
HASHPOS :HASHKLEN(E+23)
|
2129
|
+
$ => C :HASHKDIGEST(E+23)
|
2130
|
+
|
2131
|
+
; BIT 24
|
2132
|
+
0 => HASHPOS
|
2133
|
+
${B & 0x01000000} :JMPZ(hashLeft24)
|
2134
|
+
|
2135
|
+
hashRight24:
|
2136
|
+
${getSmtProof(mem.indexL1InfoTree, 24)} :HASHK(E+24)
|
2137
|
+
C :HASHK(E+24)
|
2138
|
+
A + 0x01000000 => A :JMP(hashBranchEnd24)
|
2139
|
+
|
2140
|
+
hashLeft24:
|
2141
|
+
C :HASHK(E+24)
|
2142
|
+
${getSmtProof(mem.indexL1InfoTree, 24)} :HASHK(E+24)
|
2143
|
+
|
2144
|
+
hashBranchEnd24:
|
2145
|
+
HASHPOS :HASHKLEN(E+24)
|
2146
|
+
$ => C :HASHKDIGEST(E+24)
|
2147
|
+
|
2148
|
+
; BIT 25
|
2149
|
+
0 => HASHPOS
|
2150
|
+
${B & 0x02000000} :JMPZ(hashLeft25)
|
2151
|
+
|
2152
|
+
hashRight25:
|
2153
|
+
${getSmtProof(mem.indexL1InfoTree, 25)} :HASHK(E+25)
|
2154
|
+
C :HASHK(E+25)
|
2155
|
+
A + 0x02000000 => A :JMP(hashBranchEnd25)
|
2156
|
+
|
2157
|
+
hashLeft25:
|
2158
|
+
C :HASHK(E+25)
|
2159
|
+
${getSmtProof(mem.indexL1InfoTree, 25)} :HASHK(E+25)
|
2160
|
+
|
2161
|
+
hashBranchEnd25:
|
2162
|
+
HASHPOS :HASHKLEN(E+25)
|
2163
|
+
$ => C :HASHKDIGEST(E+25)
|
2164
|
+
|
2165
|
+
; BIT 26
|
2166
|
+
0 => HASHPOS
|
2167
|
+
${B & 0x04000000} :JMPZ(hashLeft26)
|
2168
|
+
|
2169
|
+
hashRight26:
|
2170
|
+
${getSmtProof(mem.indexL1InfoTree, 26)} :HASHK(E+26)
|
2171
|
+
C :HASHK(E+26)
|
2172
|
+
A + 0x04000000 => A :JMP(hashBranchEnd26)
|
2173
|
+
|
2174
|
+
hashLeft26:
|
2175
|
+
C :HASHK(E+26)
|
2176
|
+
${getSmtProof(mem.indexL1InfoTree, 26)} :HASHK(E+26)
|
2177
|
+
|
2178
|
+
hashBranchEnd26:
|
2179
|
+
HASHPOS :HASHKLEN(E+26)
|
2180
|
+
$ => C :HASHKDIGEST(E+26)
|
2181
|
+
|
2182
|
+
; BIT 27
|
2183
|
+
0 => HASHPOS
|
2184
|
+
${B & 0x08000000} :JMPZ(hashLeft27)
|
2185
|
+
|
2186
|
+
hashRight27:
|
2187
|
+
${getSmtProof(mem.indexL1InfoTree, 27)} :HASHK(E+27)
|
2188
|
+
C :HASHK(E+27)
|
2189
|
+
A + 0x08000000 => A :JMP(hashBranchEnd27)
|
2190
|
+
|
2191
|
+
hashLeft27:
|
2192
|
+
C :HASHK(E+27)
|
2193
|
+
${getSmtProof(mem.indexL1InfoTree, 27)} :HASHK(E+27)
|
2194
|
+
|
2195
|
+
hashBranchEnd27:
|
2196
|
+
HASHPOS :HASHKLEN(E+27)
|
2197
|
+
$ => C :HASHKDIGEST(E+27)
|
2198
|
+
|
2199
|
+
; BIT 28
|
2200
|
+
0 => HASHPOS
|
2201
|
+
${B & 0x10000000} :JMPZ(hashLeft28)
|
2202
|
+
|
2203
|
+
hashRight28:
|
2204
|
+
${getSmtProof(mem.indexL1InfoTree, 28)} :HASHK(E+28)
|
2205
|
+
C :HASHK(E+28)
|
2206
|
+
A + 0x10000000 => A :JMP(hashBranchEnd28)
|
2207
|
+
|
2208
|
+
hashLeft28:
|
2209
|
+
C :HASHK(E+28)
|
2210
|
+
${getSmtProof(mem.indexL1InfoTree, 28)} :HASHK(E+28)
|
2211
|
+
|
2212
|
+
hashBranchEnd28:
|
2213
|
+
HASHPOS :HASHKLEN(E+28)
|
2214
|
+
$ => C :HASHKDIGEST(E+28)
|
2215
|
+
|
2216
|
+
; BIT 29
|
2217
|
+
0 => HASHPOS
|
2218
|
+
${B & 0x20000000} :JMPZ(hashLeft29)
|
2219
|
+
|
2220
|
+
hashRight29:
|
2221
|
+
${getSmtProof(mem.indexL1InfoTree, 29)} :HASHK(E+29)
|
2222
|
+
C :HASHK(E+29)
|
2223
|
+
A + 0x20000000 => A :JMP(hashBranchEnd29)
|
2224
|
+
|
2225
|
+
hashLeft29:
|
2226
|
+
C :HASHK(E+29)
|
2227
|
+
${getSmtProof(mem.indexL1InfoTree, 29)} :HASHK(E+29)
|
2228
|
+
|
2229
|
+
hashBranchEnd29:
|
2230
|
+
HASHPOS :HASHKLEN(E+29)
|
2231
|
+
$ => C :HASHKDIGEST(E+29)
|
2232
|
+
|
2233
|
+
; BIT 30
|
2234
|
+
0 => HASHPOS
|
2235
|
+
${B & 0x40000000} :JMPZ(hashLeft30)
|
2236
|
+
|
2237
|
+
hashRight30:
|
2238
|
+
${getSmtProof(mem.indexL1InfoTree, 30)} :HASHK(E+30)
|
2239
|
+
C :HASHK(E+30)
|
2240
|
+
A + 0x40000000 => A :JMP(hashBranchEnd30)
|
2241
|
+
|
2242
|
+
hashLeft30:
|
2243
|
+
C :HASHK(E+30)
|
2244
|
+
${getSmtProof(mem.indexL1InfoTree, 30)} :HASHK(E+30)
|
2245
|
+
|
2246
|
+
hashBranchEnd30:
|
2247
|
+
HASHPOS :HASHKLEN(E+30)
|
2248
|
+
$ => C :HASHKDIGEST(E+30)
|
2249
|
+
|
2250
|
+
; BIT 31
|
2251
|
+
0 => HASHPOS
|
2252
|
+
${B & 0x80000000} :JMPZ(hashLeft31)
|
2253
|
+
|
2254
|
+
hashRight31:
|
2255
|
+
${getSmtProof(mem.indexL1InfoTree, 31)} :HASHK(E+31)
|
2256
|
+
C :HASHK(E+31)
|
2257
|
+
A + 0x80000000 => A :JMP(hashBranchEnd31)
|
2258
|
+
|
2259
|
+
hashLeft31:
|
2260
|
+
C :HASHK(E+31)
|
2261
|
+
${getSmtProof(mem.indexL1InfoTree, 31)} :HASHK(E+31)
|
2262
|
+
|
2263
|
+
hashBranchEnd31:
|
2264
|
+
HASHPOS :HASHKLEN(E+31)
|
2265
|
+
$ => C :HASHKDIGEST(E+31)
|
2266
|
+
|
2267
|
+
; verify linear combination of 'indexL1InfoTree'
|
2268
|
+
B :ASSERT
|
2269
|
+
E + 31 => E :MSTORE(lastHashKIdUsed)
|
2270
|
+
|
2271
|
+
|
2272
|
+
verifyMerkleProofEnd:
|
2273
|
+
$ => A :MLOAD(l1InfoRoot)
|
2274
|
+
C :ASSERT
|
2275
|
+
$ :MLOAD(isL1InfoDataZero), JMPNZ(invalidL1InfoTreeIndex)
|
2276
|
+
|
2277
|
+
verifyMerkleProofReturn:
|
2278
|
+
$ => RR :MLOAD(tmpZkPCVerifyMerkleProof)
|
2279
|
+
:RETURN
|
2280
|
+
|
2281
|
+
VAR GLOBAL tmpZkPCreadXFromOffset
|
2282
|
+
VAR GLOBAL readXFromCalldataOffset
|
2283
|
+
VAR GLOBAL readXFromCalldataLength
|
2284
|
+
VAR GLOBAL readXFromCalldataResult
|
2285
|
+
VAR GLOBAL tmpVarAReadXFromOffset
|
2286
|
+
VAR GLOBAL tmpVarBReadXFromOffset
|
2287
|
+
VAR GLOBAL tmpVarCReadXFromOffset
|
2288
|
+
VAR GLOBAL tmpVarDReadXFromOffset
|
2289
|
+
VAR GLOBAL tmpVarEReadXFromOffset
|
2290
|
+
; @info Reads {readXFromCalldataOffset} bytes (max 32) from a given offset in calldata memory. If offset or offset + length exceeds txCalldataLen, zeros are added
|
2291
|
+
; @internalParam {readXFromCalldataOffset} offset to read from calldata
|
2292
|
+
; @internalParam {readXFromCalldataLength} length to read from calldata
|
2293
|
+
; @returns {readXFromCalldataResult} bytes read from calldata
|
2294
|
+
readFromCalldataOffset:
|
2295
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
2296
|
+
RR :MSTORE(tmpZkPCreadXFromOffset)
|
2297
|
+
A :MSTORE(tmpVarAReadXFromOffset)
|
2298
|
+
B :MSTORE(tmpVarBReadXFromOffset)
|
2299
|
+
C :MSTORE(tmpVarCReadXFromOffset)
|
2300
|
+
E :MSTORE(tmpVarEReadXFromOffset)
|
2301
|
+
$ => A :MLOAD(txCalldataLen), JMPZ(return0FromCalldata)
|
2302
|
+
$ => B :MLOAD(calldataOffset)
|
2303
|
+
$ => C :MLOAD(readXFromCalldataLength)
|
2304
|
+
$ => E :MLOAD(readXFromCalldataOffset)
|
2305
|
+
A - E - 1 :JMPN(return0FromCalldata) ; If offset >= txCalldataLen, return 0
|
2306
|
+
; if readOffset + readLength > txCalldataLen, readLength = txCalldataLen - readOffset
|
2307
|
+
E + C - A :JMPN(dontLimitLength)
|
2308
|
+
A - E => C
|
2309
|
+
|
2310
|
+
dontLimitLength:
|
2311
|
+
$ => CTX :MLOAD(calldataCTX) ; get calldata context
|
2312
|
+
B + E => E :CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset]
|
2313
|
+
$ => CTX :MLOAD(currentCTX)
|
2314
|
+
A :MSTORE(readXFromCalldataResult), JMP(readFromCalldataOffsetEnd)
|
2315
|
+
|
2316
|
+
return0FromCalldata:
|
2317
|
+
0 :MSTORE(readXFromCalldataResult)
|
2318
|
+
|
2319
|
+
readFromCalldataOffsetEnd:
|
2320
|
+
$ => RR :MLOAD(tmpZkPCreadXFromOffset)
|
2321
|
+
$ => A :MLOAD(tmpVarAReadXFromOffset)
|
2322
|
+
$ => B :MLOAD(tmpVarBReadXFromOffset)
|
2323
|
+
$ => C :MLOAD(tmpVarCReadXFromOffset)
|
2324
|
+
$ => E :MLOAD(tmpVarEReadXFromOffset), RETURN
|
2325
|
+
|
2326
|
+
; @info store calldata pointer to read calldata
|
2327
|
+
saveCalldataPointer:
|
2328
|
+
%MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep)
|
2329
|
+
; load data: previous CTX & argsOffsetCall
|
2330
|
+
$ => A, CTX :MLOAD(originCTX)
|
2331
|
+
$ => B :MLOAD(argsOffsetCall)
|
2332
|
+
; move to current CTX and store data
|
2333
|
+
$ => CTX :MLOAD(currentCTX)
|
2334
|
+
A :MSTORE(calldataCTX)
|
2335
|
+
B :MSTORE(calldataOffset), RETURN
|