@zkasm/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 @zkasm/zkevm-rom might be problematic. Click here for more details.

Files changed (232) hide show
  1. package/.eslintrc.js +33 -0
  2. package/.github/CODEOWNERS +14 -0
  3. package/.github/ISSUE_TEMPLATE/bug.yml +38 -0
  4. package/.github/ISSUE_TEMPLATE/feature.yml +26 -0
  5. package/.github/ISSUE_TEMPLATE/question.yml +26 -0
  6. package/.github/workflows/main.yaml +40 -0
  7. package/LICENSE +636 -0
  8. package/README.md +23 -5
  9. package/audits/Hexens_Polygon_zkEVM_PUBLIC_27.02.23.pdf +0 -0
  10. package/audits/Polygon-zkEVM-Public-v1.1-verichains-19-03-2024.pdf +0 -0
  11. package/audits/zkEVM-ROM-upgrade-1-Spearbit-30-May.pdf +0 -0
  12. package/audits/zkEVM-ROM-upgrade-2-Spearbit-21-August.pdf +0 -0
  13. package/audits/zkEVM-engagement-1-Spearbit-27-March.pdf +0 -0
  14. package/audits/zkEVM-engagement-2-Spearbit-27-March.pdf +0 -0
  15. package/audits/zkEVM-engagement-3-Spearbit-6-April.pdf +0 -0
  16. package/counters/README.md +45 -0
  17. package/counters/counters-executor.js +80 -0
  18. package/counters/countersConstants.zkasm +370 -0
  19. package/counters/endIncludes.zkasm +18 -0
  20. package/counters/initIncludes.zkasm +2 -0
  21. package/counters/tests/MLOAD32.zkasm +27 -0
  22. package/counters/tests/MLOADX.zkasm +30 -0
  23. package/counters/tests/MSTORE32.zkasm +32 -0
  24. package/counters/tests/MSTOREX.zkasm +36 -0
  25. package/counters/tests/SHLarith.zkasm +28 -0
  26. package/counters/tests/SHLarithBit.zkasm +28 -0
  27. package/counters/tests/SHRarith.zkasm +28 -0
  28. package/counters/tests/SHRarithBit.zkasm +28 -0
  29. package/counters/tests/abs.zkasm +29 -0
  30. package/counters/tests/addBatchHashByteByByte.zkasm +31 -0
  31. package/counters/tests/computeGasSendCall.zkasm +30 -0
  32. package/counters/tests/divArith.zkasm +27 -0
  33. package/counters/tests/expAD.zkasm +30 -0
  34. package/counters/tests/getLenBits.zkasm +30 -0
  35. package/counters/tests/getLenBytes.zkasm +32 -0
  36. package/counters/tests/isEmptyAccount.zkasm +30 -0
  37. package/counters/tests/mulARITH.zkasm +28 -0
  38. package/counters/tests/offsetUtil.zkasm +29 -0
  39. package/counters/tests/opADDMOD.zkasm +28 -0
  40. package/counters/tests/opAdd.zkasm +27 -0
  41. package/counters/tests/opBLOCKHASH.zkasm +28 -0
  42. package/counters/tests/opCALL.zkasm +41 -0
  43. package/counters/tests/opCALLCODE.zkasm +41 -0
  44. package/counters/tests/opCALLDATACOPY.zkasm +28 -0
  45. package/counters/tests/opCALLDATALOAD.zkasm +27 -0
  46. package/counters/tests/opCODECOPY.zkasm +28 -0
  47. package/counters/tests/opCREATE.zkasm +35 -0
  48. package/counters/tests/opCREATE2.zkasm +35 -0
  49. package/counters/tests/opDELEGATECALL.zkasm +35 -0
  50. package/counters/tests/opDIV.zkasm +27 -0
  51. package/counters/tests/opEXP.zkasm +29 -0
  52. package/counters/tests/opEXTCODECOPY.zkasm +29 -0
  53. package/counters/tests/opMOD.zkasm +27 -0
  54. package/counters/tests/opMUL.zkasm +27 -0
  55. package/counters/tests/opMULMOD.zkasm +28 -0
  56. package/counters/tests/opRETURN.zkasm +32 -0
  57. package/counters/tests/opRETURNDATACOPY.zkasm +29 -0
  58. package/counters/tests/opREVERT.zkasm +32 -0
  59. package/counters/tests/opSDIV.zkasm +28 -0
  60. package/counters/tests/opSHA3.zkasm +28 -0
  61. package/counters/tests/opSIGNEXTEND.zkasm +27 -0
  62. package/counters/tests/opSMOD.zkasm +28 -0
  63. package/counters/tests/opSTATICCALL.zkasm +35 -0
  64. package/counters/tests/opSUB.zkasm +27 -0
  65. package/counters/tests/saveMem.zkasm +31 -0
  66. package/docs/opcode-cost-zk-counters.md +315 -0
  67. package/docs/usage-ecrecover.md +51 -0
  68. package/index.js +43 -0
  69. package/main/block-info.zkasm +204 -0
  70. package/main/constants.zkasm +145 -0
  71. package/main/ecrecover/addFpEc.zkasm +31 -0
  72. package/main/ecrecover/checkSqrtFpEc.zkasm +1558 -0
  73. package/main/ecrecover/constEc.zkasm +13 -0
  74. package/main/ecrecover/ecrecover.zkasm +280 -0
  75. package/main/ecrecover/invFnEc.zkasm +44 -0
  76. package/main/ecrecover/invFpEc.zkasm +45 -0
  77. package/main/ecrecover/mulFnEc.zkasm +36 -0
  78. package/main/ecrecover/mulFpEc.zkasm +36 -0
  79. package/main/ecrecover/mulPointEc.zkasm +311 -0
  80. package/main/ecrecover/sqFpEc.zkasm +38 -0
  81. package/main/ecrecover/sqrtFpEc.zkasm +70 -0
  82. package/main/end.zkasm +4 -0
  83. package/main/l2-tx-hash.zkasm +159 -0
  84. package/main/load-change-l2-block-utils.zkasm +11 -0
  85. package/main/load-change-l2-block.zkasm +28 -0
  86. package/main/load-tx-rlp-utils.zkasm +72 -0
  87. package/main/load-tx-rlp.zkasm +431 -0
  88. package/main/main.zkasm +237 -0
  89. package/main/map-opcodes.zkasm +274 -0
  90. package/main/modexp/array_lib/array_add_AGTB.zkasm +123 -0
  91. package/main/modexp/array_lib/array_add_short.zkasm +85 -0
  92. package/main/modexp/array_lib/array_div.zkasm +215 -0
  93. package/main/modexp/array_lib/array_div_long.zkasm +284 -0
  94. package/main/modexp/array_lib/array_div_short.zkasm +222 -0
  95. package/main/modexp/array_lib/array_mul.zkasm +97 -0
  96. package/main/modexp/array_lib/array_mul_long.zkasm +156 -0
  97. package/main/modexp/array_lib/array_mul_short.zkasm +127 -0
  98. package/main/modexp/array_lib/array_square.zkasm +246 -0
  99. package/main/modexp/array_lib/unused/array_add.zkasm +100 -0
  100. package/main/modexp/array_lib/unused/array_is_odd.zkasm +23 -0
  101. package/main/modexp/array_lib/unused/array_is_one.zkasm +33 -0
  102. package/main/modexp/array_lib/unused/array_is_zero.zkasm +34 -0
  103. package/main/modexp/array_lib/unused/array_sub_AGTB.zkasm +111 -0
  104. package/main/modexp/array_lib/unused/array_unshift.zkasm +37 -0
  105. package/main/modexp/array_lib/utils/array_compare.zkasm +82 -0
  106. package/main/modexp/array_lib/utils/array_trim.zkasm +49 -0
  107. package/main/modexp/constants.zkasm +5 -0
  108. package/main/modexp/modexp.zkasm +296 -0
  109. package/main/modexp/modexp_utils.zkasm +230 -0
  110. package/main/opcodes/arithmetic.zkasm +357 -0
  111. package/main/opcodes/block.zkasm +163 -0
  112. package/main/opcodes/calldata-returndata-code.zkasm +619 -0
  113. package/main/opcodes/comparison.zkasm +446 -0
  114. package/main/opcodes/context-information.zkasm +169 -0
  115. package/main/opcodes/create-terminate-context.zkasm +1011 -0
  116. package/main/opcodes/crypto.zkasm +96 -0
  117. package/main/opcodes/flow-control.zkasm +126 -0
  118. package/main/opcodes/logs.zkasm +193 -0
  119. package/main/opcodes/stack-operations.zkasm +658 -0
  120. package/main/opcodes/storage-memory.zkasm +313 -0
  121. package/main/pairings/BN254/addPointBN254.zkasm +245 -0
  122. package/main/pairings/BN254/ecAdd.zkasm +312 -0
  123. package/main/pairings/BN254/ecMul.zkasm +159 -0
  124. package/main/pairings/BN254/escalarMulBN254.zkasm +155 -0
  125. package/main/pairings/BN254/lineDiffPointsBN254.zkasm +83 -0
  126. package/main/pairings/BN254/lineSamePointsBN254.zkasm +96 -0
  127. package/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm +49 -0
  128. package/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm +236 -0
  129. package/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm +444 -0
  130. package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm +212 -0
  131. package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm +228 -0
  132. package/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm +64 -0
  133. package/main/pairings/FP12BN254/frob2Fp12BN254.zkasm +80 -0
  134. package/main/pairings/FP12BN254/frob3Fp12BN254.zkasm +96 -0
  135. package/main/pairings/FP12BN254/frobFp12BN254.zkasm +96 -0
  136. package/main/pairings/FP12BN254/inverseFp12BN254.zkasm +289 -0
  137. package/main/pairings/FP12BN254/mulFp12BN254.zkasm +408 -0
  138. package/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm +296 -0
  139. package/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm +291 -0
  140. package/main/pairings/FP12BN254/squareFp12BN254.zkasm +376 -0
  141. package/main/pairings/FP2BN254/addFp2BN254.zkasm +19 -0
  142. package/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm +20 -0
  143. package/main/pairings/FP2BN254/invFp2BN254.zkasm +66 -0
  144. package/main/pairings/FP2BN254/mulFp2BN254.zkasm +19 -0
  145. package/main/pairings/FP2BN254/squareFp2BN254.zkasm +21 -0
  146. package/main/pairings/FP2BN254/subFp2BN254.zkasm +19 -0
  147. package/main/pairings/FP4BN254/squareFp4BN254.zkasm +76 -0
  148. package/main/pairings/FP6BN254/addFp6BN254.zkasm +59 -0
  149. package/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm +51 -0
  150. package/main/pairings/FP6BN254/inverseFp6BN254.zkasm +208 -0
  151. package/main/pairings/FP6BN254/mulFp6BN254.zkasm +201 -0
  152. package/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm +65 -0
  153. package/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm +134 -0
  154. package/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm +128 -0
  155. package/main/pairings/FP6BN254/squareFp6BN254.zkasm +147 -0
  156. package/main/pairings/FP6BN254/subFp6BN254.zkasm +59 -0
  157. package/main/pairings/FPBN254/addFpBN254.zkasm +29 -0
  158. package/main/pairings/FPBN254/invFpBN254.zkasm +55 -0
  159. package/main/pairings/FPBN254/mulFpBN254.zkasm +29 -0
  160. package/main/pairings/FPBN254/reduceFpBN254.zkasm +25 -0
  161. package/main/pairings/FPBN254/squareFpBN254.zkasm +31 -0
  162. package/main/pairings/FPBN254/subFpBN254.zkasm +36 -0
  163. package/main/pairings/FRBN254/reduceFrBN254.zkasm +25 -0
  164. package/main/pairings/constants.zkasm +62 -0
  165. package/main/pairings/ecPairing.zkasm +244 -0
  166. package/main/pairings/finalExpBN254.zkasm +2095 -0
  167. package/main/pairings/halfPairingBN254.zkasm +428 -0
  168. package/main/pairings/loopLengthBN254.zkasm +75 -0
  169. package/main/pairings/millerLoopBN254.zkasm +741 -0
  170. package/main/pairings/pairingBN254.zkasm +481 -0
  171. package/main/pairings/unused/addFp12BN254.zkasm +130 -0
  172. package/main/pairings/unused/expByXCycloFp12BN254.zkasm +411 -0
  173. package/main/pairings/unused/expFp12BN254.zkasm +333 -0
  174. package/main/pairings/unused/subFp12BN254.zkasm +130 -0
  175. package/main/pairings/unused/xPseudoBinDecompBN254.zkasm +68 -0
  176. package/main/pairings/utilsTests/expCycloFp12BN254.zkasm +334 -0
  177. package/main/precompiled/end.zkasm +42 -0
  178. package/main/precompiled/identity.zkasm +99 -0
  179. package/main/precompiled/pre-ecAdd.zkasm +84 -0
  180. package/main/precompiled/pre-ecMul.zkasm +82 -0
  181. package/main/precompiled/pre-ecPairing.zkasm +72 -0
  182. package/main/precompiled/pre-ecrecover.zkasm +71 -0
  183. package/main/precompiled/pre-modexp.zkasm +367 -0
  184. package/main/precompiled/pre-sha2-256.zkasm +125 -0
  185. package/main/precompiled/revert-precompiled.zkasm +25 -0
  186. package/main/precompiled/selector.zkasm +77 -0
  187. package/main/process-change-l2-block.zkasm +147 -0
  188. package/main/process-tx.zkasm +587 -0
  189. package/main/tables/2-exp.zkasm +260 -0
  190. package/main/touched.zkasm +118 -0
  191. package/main/utils.zkasm +2335 -0
  192. package/main/vars.zkasm +117 -0
  193. package/package.json +62 -3
  194. package/test/bytes-length.zkasm +39 -0
  195. package/test/ecrecover.zkasm +538 -0
  196. package/test/lt4-test.zkasm +38 -0
  197. package/test/mstorex.zkasm +191 -0
  198. package/test/opcalldatacopy.ignore.zkasm +331 -0
  199. package/test/performance/read-push.zkasm +71 -0
  200. package/test/read-push.zkasm +304 -0
  201. package/test/testArrayArith.zkasm +1099 -0
  202. package/test/testArrayUtils.zkasm +335 -0
  203. package/test/testCycloFp12ArithBN254.zkasm +548 -0
  204. package/test/testEcAdd.zkasm +252 -0
  205. package/test/testEcMul.zkasm +231 -0
  206. package/test/testEcPairing.zkasm +436 -0
  207. package/test/testFinalExpBn254.zkasm +139 -0
  208. package/test/testFp12ArithBN254.zkasm +692 -0
  209. package/test/testFp2ArithBN254.zkasm +185 -0
  210. package/test/testFp4ArithBN254.zkasm +128 -0
  211. package/test/testFp6ArithBN254.zkasm +260 -0
  212. package/test/testFpArithBN254.zkasm +159 -0
  213. package/test/testFrArithBN254.zkasm +113 -0
  214. package/test/testHalfPairingBN254.zkasm +285 -0
  215. package/test/testModExp.zkasm +586 -0
  216. package/test/testModExpReturn.zkasm +81 -0
  217. package/test/testPairingBN254.zkasm +463 -0
  218. package/test/testPointArithBN254.zkasm +270 -0
  219. package/test/testSHA256.zkasm +27 -0
  220. package/test/touched-assert.zkasm +59 -0
  221. package/test/utils-expAD.zkasm +48 -0
  222. package/test/utils-getLenBytes.zkasm +36 -0
  223. package/tools/audit-tools/registry-op-checker.js +71 -0
  224. package/tools/get-not-used-labels.js +31 -0
  225. package/tools/helpers/helpers.js +47 -0
  226. package/tools/modexp-utils/README.md +5 -0
  227. package/tools/modexp-utils/modexp-test-gen.js +168 -0
  228. package/tools/modexp-utils/modexp-test-int.sage +37 -0
  229. package/tools/parallel-testing/checker.sh +6 -0
  230. package/tools/parallel-testing/gen-parallel-tests.js +78 -0
  231. package/tools/parallel-testing/parallel-tests-sample/sample.test.js +136 -0
  232. package/tools/run-tests-zkasm.js +83 -0
@@ -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