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.

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,85 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;;
3
+ ;; array_add_short:
4
+ ;; in:
5
+ ;; · C ∈ [1, 32], the len of inA
6
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
7
+ ;; · inB ∈ [0, 2²⁵⁶ - 1], the second input
8
+ ;;
9
+ ;; output:
10
+ ;; · out = inA + inB, with len(out) <= C + 1
11
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
+
13
+ ; function array_add_short(a: bigint[], b: bigint, base: bigint): bigint[] {
14
+ ; const alen = a.length;
15
+ ; let result = new Array<bigint>(alen);
16
+ ; let sum = 0n;
17
+ ; let carry = b;
18
+ ; for (let i = 0; i < alen; i++) {
19
+ ; sum = a[i] + carry;
20
+ ; carry = sum >= base ? 1n : 0n;
21
+ ; out[i] = sum - carry * base;
22
+ ; }
23
+
24
+ ; if (carry === 1n) {
25
+ ; result.push(carry);
26
+ ; }
27
+ ; return result;
28
+ ; }
29
+
30
+ VAR GLOBAL array_add_short_inA[%ARRAY_MAX_LEN]
31
+ VAR GLOBAL array_add_short_inB
32
+ VAR GLOBAL array_add_short_out[%ARRAY_MAX_LEN_PLUS_ONE]
33
+ VAR GLOBAL array_add_short_len_inA
34
+ VAR GLOBAL array_add_short_len_out
35
+
36
+ VAR GLOBAL array_add_short_carry
37
+
38
+ VAR GLOBAL array_add_short_RR
39
+
40
+ array_add_short:
41
+ %MAX_CNT_BINARY - CNT_BINARY - C :JMPN(outOfCountersBinary)
42
+ %MAX_CNT_STEPS - STEP - 5 - 10*C - 8 :JMPN(outOfCountersStep)
43
+
44
+ RR :MSTORE(array_add_short_RR)
45
+
46
+ C :MSTORE(array_add_short_len_inA)
47
+
48
+ 0 => E ; index in loops
49
+ $ => A :MLOAD(array_add_short_inB)
50
+ A :MSTORE(array_add_short_carry)
51
+
52
+ array_add_short_loopZero2inA:
53
+ ; The result will be stored as D·base + C
54
+
55
+ 0 => D ; reset the carry chunk
56
+
57
+ ; a[i] + carry, where a[i] ∈ [0,base-1]:
58
+ ; · If i = 0, then carry = inB and then the number cannot be GT base + (base - 2), two chunks
59
+ ; · Otherwise, the number cannot be GT base, two chunks
60
+ $ => A :MLOAD(array_add_short_inA + E)
61
+ $ => B :MLOAD(array_add_short_carry)
62
+ $ => C :ADD, JMPNC(__array_add_short_continue_1)
63
+ 1 => D
64
+ __array_add_short_continue_1:
65
+
66
+ C :MSTORE(array_add_short_out + E)
67
+ D :MSTORE(array_add_short_carry)
68
+
69
+ E + 1 => E,A
70
+ $ => B :MLOAD(array_add_short_len_inA)
71
+ B - A :JMPZ(array_add_short_check_carry, array_add_short_loopZero2inA)
72
+
73
+ array_add_short_check_carry:
74
+ D => A
75
+ A :JMPZ(__array_add_short_continue_2)
76
+ ; In this case, the carry = 1 and we should append it to the result
77
+ 1 :MSTORE(array_add_short_out + E)
78
+ E + 1 :MSTORE(array_add_short_len_out)
79
+ :JMP(array_add_short_end)
80
+ __array_add_short_continue_2:
81
+ E :MSTORE(array_add_short_len_out)
82
+
83
+ array_add_short_end:
84
+ $ => RR :MLOAD(array_add_short_RR)
85
+ :RETURN
@@ -0,0 +1,215 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed;
3
+ ;; POST: The quotient and remainder are trimmed.
4
+ ;;
5
+ ;; array_div:
6
+ ;; in:
7
+ ;; · C ∈ [1, 32], the len of inA
8
+ ;; · D ∈ [1, 32], the len of inB
9
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
10
+ ;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array
11
+ ;;
12
+ ;; output:
13
+ ;; · [quo,rem] = [inA / inB, inA % inB], with len(quo) <= C - D + 1, len(rem) <= D
14
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
+
16
+ ; function array_div(a: bigint[], b: bigint[], base: bigint): bigint[] {
17
+ ; if (a === [0n]) {
18
+ ; if (b === [0n]) {
19
+ ; throw new Error("Division by zero");
20
+ ; }
21
+ ; return [0n, 0n];
22
+ ; } else if (b === [0n]) {
23
+ ; throw new Error("Division by zero");
24
+ ; }
25
+ ;
26
+ ; if (a === b) {
27
+ ; return [1n, 0n];
28
+ ; } else if (a < b) {
29
+ ; return [0n, a];
30
+ ; }
31
+ ;
32
+ ; if (b.length === 1) {
33
+ ; return array_div_short(a, b, base);
34
+ ; }
35
+ ; return array_div_long(a, b, base);
36
+ ; }
37
+
38
+ VAR GLOBAL array_div_inA[%ARRAY_MAX_LEN]
39
+ VAR GLOBAL array_div_inB[%ARRAY_MAX_LEN]
40
+ VAR GLOBAL array_div_quo[%ARRAY_MAX_LEN]
41
+ VAR GLOBAL array_div_rem[%ARRAY_MAX_LEN]
42
+
43
+ VAR GLOBAL array_div_len_inA
44
+ VAR GLOBAL array_div_len_inB
45
+ VAR GLOBAL array_div_len_quo
46
+ VAR GLOBAL array_div_len_rem
47
+
48
+ VAR GLOBAL array_div_RR
49
+
50
+ ; ERROR CODES (B)
51
+ ; 0 - no error
52
+ ; 1 - inB is zero
53
+
54
+ array_div:
55
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
56
+ %MAX_CNT_STEPS - STEP - 12 - 3*C - 3*D - 1 :JMPN(outOfCountersStep)
57
+
58
+ RR :MSTORE(array_div_RR)
59
+
60
+ C :MSTORE(array_div_len_inA)
61
+ D :MSTORE(array_div_len_inB)
62
+
63
+ ; Let's cover the edge cases
64
+ 1 => B
65
+ ; 1] Is C == 1 and inA == 0?
66
+ C - B :JMPNZ(__array_div_inA_continue)
67
+ $ => A :MLOAD(array_div_inA)
68
+ $ :LT, JMPC(array_div_inA_is_zero)
69
+ __array_div_inA_continue:
70
+
71
+ ; 2] Is D == 1 and inB == 0?
72
+ D - B :JMPNZ(__array_div_inB_continue_1)
73
+ $ => A :MLOAD(array_div_inB)
74
+ $ :LT, JMPC(array_div_inB_is_zero)
75
+ __array_div_inB_continue_1:
76
+
77
+ ; 3] Check if inA = inB or inA < inB
78
+ C - 1 => RR
79
+ D - 1 => E
80
+ array_div_compare_inA:
81
+ $ => A :MLOAD(array_div_inA + RR)
82
+ A :MSTORE(array_compare_inA + RR)
83
+ RR - 1 => RR :JMPN(array_div_compare_inB, array_div_compare_inA)
84
+
85
+ array_div_compare_inB:
86
+ $ => A :MLOAD(array_div_inB + E)
87
+ A :MSTORE(array_compare_inB + E)
88
+ E - 1 => E :JMPN(array_div_compare, array_div_compare_inB)
89
+
90
+ array_div_compare:
91
+ :CALL(array_compare)
92
+
93
+ %MAX_CNT_STEPS - STEP - 5 - 3*C - 3*D - 1 :JMPN(outOfCountersStep)
94
+
95
+ $ => A :MLOAD(array_compare_result), JMPZ(array_div_prep_inALTinB)
96
+ A - 1 :JMPZ(array_div_same_input)
97
+ ; From here, inA > inB
98
+
99
+ C - 1 => RR
100
+ D - 1 => E
101
+ D - 1 :JMPZ(array_div_inA_to_div_short, array_div_inA_to_div_long); worst case is div long
102
+
103
+ ; Begin of edge cases
104
+ array_div_inA_is_zero:
105
+ ;Is D == 1 and inB == 0? 0/0 is undefined
106
+ D - B :JMPNZ(__array_div_inB_continue_2)
107
+ $ => A :MLOAD(array_div_inB)
108
+ $ :LT, JMPC(array_div_inB_is_zero)
109
+ __array_div_inB_continue_2:
110
+ ; From here, inB != 0
111
+
112
+ ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1
113
+ 0 :MSTORE(array_div_quo)
114
+ 0 :MSTORE(array_div_rem)
115
+ 1 :MSTORE(array_div_len_quo)
116
+ 1 :MSTORE(array_div_len_rem)
117
+ 0 => B :JMP(array_div_end)
118
+
119
+ array_div_inB_is_zero:
120
+ ; Error, you cannot divide by 0
121
+ 1 => B :JMP(array_div_end)
122
+
123
+ array_div_same_input:
124
+ 1 :MSTORE(array_div_quo)
125
+ 0 :MSTORE(array_div_rem)
126
+ 1 :MSTORE(array_div_len_quo)
127
+ 1 :MSTORE(array_div_len_rem)
128
+ 0 => B :JMP(array_div_end)
129
+
130
+ array_div_prep_inALTinB:
131
+ C :MSTORE(array_div_len_rem)
132
+ 1 :MSTORE(array_div_len_quo)
133
+
134
+ %MAX_CNT_STEPS - STEP - 1 - 4*C - 2 :JMPN(outOfCountersStep)
135
+
136
+ C - 1 => RR
137
+ array_div_inALTinB:
138
+ $ => A :MLOAD(array_div_inA + RR)
139
+ A :MSTORE(array_div_rem + RR)
140
+ RR - 1 => RR :JMPN(array_div_inALTinB_before_end, array_div_inALTinB)
141
+
142
+ array_div_inALTinB_before_end:
143
+ 0 :MSTORE(array_div_quo)
144
+ 0 => B :JMP(array_div_end)
145
+ ; End of edge cases
146
+
147
+ ; Long
148
+ array_div_inA_to_div_long:
149
+ $ => A :MLOAD(array_div_inA + RR)
150
+ A :MSTORE(array_div_long_inA + RR)
151
+ RR - 1 => RR :JMPN(array_div_inB_to_div_long, array_div_inA_to_div_long)
152
+
153
+ array_div_inB_to_div_long:
154
+ $ => A :MLOAD(array_div_inB + E)
155
+ A :MSTORE(array_div_long_inB + E)
156
+ E - 1 => E :JMPN(array_div_compute_long, array_div_inB_to_div_long)
157
+
158
+ array_div_compute_long:
159
+ :CALL(array_div_long)
160
+
161
+ %MAX_CNT_STEPS - STEP - 7 :JMPN(outOfCountersStep)
162
+
163
+ $ => C :MLOAD(array_div_long_len_quo)
164
+ $ => D :MLOAD(array_div_long_len_rem)
165
+ C :MSTORE(array_div_len_quo)
166
+ D :MSTORE(array_div_len_rem)
167
+ C - 1 => RR
168
+ D - 1 => E
169
+
170
+ %MAX_CNT_STEPS - STEP - 3*C - 3*D - 2 :JMPN(outOfCountersStep)
171
+
172
+ array_div_assign_long_quo:
173
+ $ => A :MLOAD(array_div_long_quo + RR)
174
+ A :MSTORE(array_div_quo + RR)
175
+ RR - 1 => RR :JMPN(array_div_assign_long_rem, array_div_assign_long_quo)
176
+
177
+ array_div_assign_long_rem:
178
+ $ => A :MLOAD(array_div_long_rem + E)
179
+ A :MSTORE(array_div_rem + E)
180
+ E - 1 => E :JMPN(array_div_end, array_div_assign_long_rem)
181
+
182
+ ; Short
183
+ array_div_inA_to_div_short:
184
+ $ => A :MLOAD(array_div_inA + RR)
185
+ A :MSTORE(array_div_short_inA + RR)
186
+ RR - 1 => RR :JMPN(array_div_inB_to_div_short, array_div_inA_to_div_short)
187
+
188
+ array_div_inB_to_div_short:
189
+ $ => A :MLOAD(array_div_inB)
190
+ A :MSTORE(array_div_short_inB)
191
+
192
+ array_div_compute_short:
193
+ :CALL(array_div_short)
194
+
195
+ %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep)
196
+
197
+ $ => C :MLOAD(array_div_short_len_quo)
198
+ C :MSTORE(array_div_len_quo)
199
+ 1 :MSTORE(array_div_len_rem)
200
+ C - 1 => RR
201
+
202
+ %MAX_CNT_STEPS - STEP - 3*C - 4 :JMPN(outOfCountersStep)
203
+
204
+ array_div_assign_short_quo:
205
+ $ => A :MLOAD(array_div_short_quo + RR)
206
+ A :MSTORE(array_div_quo + RR)
207
+ RR - 1 => RR :JMPN(array_div_assign_short_rem, array_div_assign_short_quo)
208
+
209
+ array_div_assign_short_rem:
210
+ $ => A :MLOAD(array_div_short_rem)
211
+ A :MSTORE(array_div_rem)
212
+
213
+ array_div_end:
214
+ $ => RR :MLOAD(array_div_RR)
215
+ :RETURN
@@ -0,0 +1,284 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed.
3
+ ;; POST: The quotient and remainder are trimmed.
4
+ ;;
5
+ ;; array_div_long:
6
+ ;; in:
7
+ ;; · C ∈ [1, 32], the len of inA
8
+ ;; · D ∈ [1, 32], the len of inB
9
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
10
+ ;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array
11
+ ;;
12
+ ;; output:
13
+ ;; · [quo,rem] = [inA / inB, inA % inB], with len(quo) <= C - D + 1, len(rem) <= D
14
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
+
16
+ ; function array_div_long(a: bigint[], b: bigint[], base: bigint): bigint[] {
17
+ ; if (a === [0n]) {
18
+ ; if (b === [0n]) {
19
+ ; throw new Error("Division by zero");
20
+ ; }
21
+ ; return [0n, 0n];
22
+ ; } else if (b === [0n]) {
23
+ ; throw new Error("Division by zero");
24
+ ; }
25
+ ;
26
+ ; if (a === b) {
27
+ ; return [1n, 0n];
28
+ ; } else if (a < b) {
29
+ ; return [0n, a];
30
+ ; }
31
+ ; }
32
+
33
+ ; NOTE: This function receives the actual result from the helper (avoiding the need of computing divisions);
34
+ ; checks the correctness of the result and returns the result to the caller
35
+
36
+ VAR GLOBAL array_div_long_inA[%ARRAY_MAX_LEN]
37
+ VAR GLOBAL array_div_long_inB[%ARRAY_MAX_LEN]
38
+ VAR GLOBAL array_div_long_quo[%ARRAY_MAX_LEN]
39
+ VAR GLOBAL array_div_long_rem[%ARRAY_MAX_LEN]
40
+
41
+ VAR GLOBAL array_div_long_len_inA
42
+ VAR GLOBAL array_div_long_len_inB
43
+ VAR GLOBAL array_div_long_len_quo
44
+ VAR GLOBAL array_div_long_len_rem
45
+
46
+ VAR GLOBAL array_div_long_RR
47
+
48
+ ; ERROR CODES (B)
49
+ ; 0 - no error
50
+ ; 1 - inB is zero
51
+
52
+ array_div_long:
53
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
54
+ %MAX_CNT_STEPS - STEP - 12 - 3*C - 3*D - 1 :JMPN(outOfCountersStep)
55
+
56
+ RR :MSTORE(array_div_long_RR)
57
+
58
+ C :MSTORE(array_div_long_len_inA)
59
+ D :MSTORE(array_div_long_len_inB)
60
+
61
+ ; Let's cover the edge cases
62
+ 1 => B
63
+ ; 1] Is C == 1 and inA == 0?
64
+ C - B :JMPNZ(__array_div_long_inA_continue)
65
+ $ => A :MLOAD(array_div_long_inA)
66
+ $ :LT, JMPC(array_div_long_inA_is_zero)
67
+ __array_div_long_inA_continue:
68
+
69
+ ; 2] Is D == 1 and inB == 0?
70
+ D - B :JMPNZ(__array_div_long_inB_continue_1)
71
+ $ => A :MLOAD(array_div_long_inB)
72
+ $ :LT, JMPC(array_div_long_inB_is_zero)
73
+ __array_div_long_inB_continue_1:
74
+
75
+ ; 3] Check if inA = inB or inA < inB
76
+ C - 1 => RR
77
+ D - 1 => E
78
+ array_div_long_compare_inA1:
79
+ $ => A :MLOAD(array_div_long_inA + RR)
80
+ A :MSTORE(array_compare_inA + RR)
81
+ RR - 1 => RR :JMPN(array_div_long_compare_inB1, array_div_long_compare_inA1)
82
+
83
+ array_div_long_compare_inB1:
84
+ $ => A :MLOAD(array_div_long_inB + E)
85
+ A :MSTORE(array_compare_inB + E)
86
+ E - 1 => E :JMPN(array_div_long_compare1, array_div_long_compare_inB1)
87
+
88
+ array_div_long_compare1:
89
+ :CALL(array_compare)
90
+
91
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
92
+ %MAX_CNT_STEPS - STEP - 12 - 4*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep)
93
+
94
+ $ => A :MLOAD(array_compare_result), JMPZ(array_div_long_prep_inALTinB)
95
+ A - 1 :JMPZ(array_div_long_same_input)
96
+ ; From here, inA > inB
97
+
98
+ ; Strategy: Divide outside and check the result inside
99
+ $${MPdiv(addr.array_div_long_inA,mem.array_div_long_len_inA,addr.array_div_long_inB,mem.array_div_long_len_inB)}
100
+
101
+ :JMP(array_div_long_prepare_mul_quo_inB)
102
+
103
+ ; Begin of edge cases
104
+ array_div_long_inA_is_zero:
105
+ ; Is D == 1 and inB == 0? 0/0 is undefined
106
+ D - B :JMPNZ(__array_div_long_inB_continue_2)
107
+ $ => A :MLOAD(array_div_long_inB)
108
+ $ :LT, JMPC(array_div_long_inB_is_zero)
109
+ __array_div_long_inB_continue_2:
110
+ ; From here, inA == 0 and inB != 0
111
+
112
+ ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1
113
+ 0 :MSTORE(array_div_long_quo)
114
+ 0 :MSTORE(array_div_long_rem)
115
+ 1 :MSTORE(array_div_long_len_quo)
116
+ 1 :MSTORE(array_div_long_len_rem)
117
+ 0 => B :JMP(array_div_long_end)
118
+
119
+ array_div_long_inB_is_zero:
120
+ ; Error, you cannot divide by 0
121
+ 1 => B :JMP(array_div_long_end)
122
+
123
+ array_div_long_same_input:
124
+ ; if inA = inB, then return [1, 0] and len(q) = 1, len(r) = 1
125
+ 1 :MSTORE(array_div_long_quo)
126
+ 0 :MSTORE(array_div_long_rem)
127
+ 1 :MSTORE(array_div_long_len_quo)
128
+ 1 :MSTORE(array_div_long_len_rem)
129
+ 0 => B :JMP(array_div_long_end)
130
+
131
+ array_div_long_prep_inALTinB:
132
+ ; if inA < inB, then return [0, inA] and len(q) = 1, len(r) = C
133
+ 1 :MSTORE(array_div_long_len_quo)
134
+ C :MSTORE(array_div_long_len_rem)
135
+
136
+ %MAX_CNT_STEPS - STEP - 1 - 3*C - 2 :JMPN(outOfCountersStep)
137
+
138
+ C - 1 => RR
139
+ array_div_long_inALTinB:
140
+ $ => A :MLOAD(array_div_long_inA + RR)
141
+ A :MSTORE(array_div_long_rem + RR)
142
+ RR - 1 => RR :JMPN(array_div_long_inALTinB_before_end, array_div_long_inALTinB)
143
+
144
+ array_div_long_inALTinB_before_end:
145
+ 0 :MSTORE(array_div_long_quo)
146
+ 0 => B :JMP(array_div_long_end)
147
+ ; End of edge cases
148
+
149
+ array_div_long_prepare_mul_quo_inB:
150
+ $0{receiveLenQuotient()} => C
151
+
152
+ ; The received length must be between 1 and %ARRAY_MAX_LEN
153
+ C - 1 => RR :JMPN(failAssert) ; If C = 0, then fail
154
+ %ARRAY_MAX_LEN - C :JMPN(failAssert) ; If C > %ARRAY_MAX_LEN, then fail
155
+ ; From here, 1 <= C <= %ARRAY_MAX_LEN
156
+
157
+ ; To avoid non-determinism, we must ensure that the quotient is trimmed
158
+ ; i.e., that its last chunk is not 0
159
+ ${receiveQuotientChunk(RR)} => A
160
+ 0 => B
161
+ 0 :EQ
162
+ ; From here, the quotient is trimmed
163
+
164
+ C :MSTORE(array_div_long_len_quo)
165
+ $ => D :MLOAD(array_div_long_len_inB)
166
+ C - 1 => RR
167
+ D - 1 => E
168
+
169
+ ; save the first non-zero chunk of quo
170
+ A :MSTORE(array_div_long_quo + RR)
171
+ A :MSTORE(array_mul_inA + RR)
172
+ RR - 1 => RR :JMPN(array_div_long_inB_to_mul)
173
+
174
+ array_div_long_quo_to_mul:
175
+ ${receiveQuotientChunk(RR)} => A
176
+ A :MSTORE(array_div_long_quo + RR)
177
+ A :MSTORE(array_mul_inA + RR)
178
+ RR - 1 => RR :JMPN(array_div_long_inB_to_mul, array_div_long_quo_to_mul)
179
+
180
+ array_div_long_inB_to_mul:
181
+ $ => A :MLOAD(array_div_long_inB + E)
182
+ A :MSTORE(array_mul_inB + E)
183
+ E - 1 => E :JMPN(array_div_long_mul_quo_inB, array_div_long_inB_to_mul)
184
+
185
+ array_div_long_mul_quo_inB:
186
+ :CALL(array_mul)
187
+
188
+ $ => D :MLOAD(array_div_long_len_inB)
189
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
190
+ %MAX_CNT_STEPS - STEP - 8 - 3*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep)
191
+
192
+ ; Check the remainder
193
+ $0{receiveLenRemainder()} => D
194
+
195
+ ; 1] The received length must be between 1 and %ARRAY_MAX_LEN
196
+ D - 1 => E :JMPN(failAssert) ; If D = 0, then fail
197
+ %ARRAY_MAX_LEN - D :JMPN(failAssert) ; If D > %ARRAY_MAX_LEN, then fail
198
+ ; From here, 1 <= D <= %ARRAY_MAX_LEN
199
+
200
+ ; 2] To avoid non-determinism, we must ensure that the remainder is trimmed
201
+ ; i.e., that its last chunk is not 0
202
+ ${receiveRemainderChunk(E)} => A
203
+ 0 => B
204
+ 0 :EQ
205
+ ; From here, the remainder is trimmed
206
+
207
+ ; 3] Finally, we must ensure that the remainder is lower than inB
208
+ $ => C :MLOAD(array_div_long_len_inB)
209
+ C - 1 => RR
210
+ D - 1 => E
211
+
212
+ ; save the first non-zero chunk of rem
213
+ A :MSTORE(array_compare_inB + E)
214
+ E - 1 => E :JMPN(array_div_long_compare_inB2)
215
+
216
+ array_div_long_compare_rem:
217
+ ${receiveRemainderChunk(E)} => A
218
+ A :MSTORE(array_compare_inB + E)
219
+ E - 1 => E :JMPN(array_div_long_compare_inB2, array_div_long_compare_rem)
220
+
221
+ array_div_long_compare_inB2:
222
+ $ => A :MLOAD(array_div_long_inB + RR)
223
+ A :MSTORE(array_compare_inA + RR)
224
+ RR - 1 => RR :JMPN(array_div_long_compare2, array_div_long_compare_inB2)
225
+
226
+ array_div_long_compare2:
227
+ :CALL(array_compare)
228
+
229
+ %MAX_CNT_STEPS - STEP - 5 - 3*%ARRAY_MAX_LEN - 4*%ARRAY_MAX_LEN - 1 :JMPN(outOfCountersStep)
230
+
231
+ 2 :MLOAD(array_compare_result)
232
+
233
+ D :MSTORE(array_div_long_len_rem)
234
+
235
+ ; prepare output and remainder to be added
236
+ $ => C :MLOAD(array_mul_len_out)
237
+ C - 1 => RR
238
+ D - 1 => E
239
+
240
+ array_div_long_res_to_add:
241
+ $ => A :MLOAD(array_mul_out + RR)
242
+ A :MSTORE(array_add_AGTB_inA + RR)
243
+ RR - 1 => RR :JMPN(array_div_long_rem_to_add, array_div_long_res_to_add)
244
+
245
+ array_div_long_rem_to_add:
246
+ $ => A :MLOAD(array_compare_inB + E) ; Load the remainder used in the comparison
247
+ A :MSTORE(array_div_long_rem + E)
248
+ A :MSTORE(array_add_AGTB_inB + E)
249
+ E - 1 => E :JMPN(array_div_long_add_res_rem, array_div_long_rem_to_add)
250
+
251
+ array_div_long_add_res_rem:
252
+ :CALL(array_add_AGTB)
253
+
254
+ %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep)
255
+
256
+ ; prepare next
257
+ $ => C :MLOAD(array_add_AGTB_len_out)
258
+ $ => D :MLOAD(array_div_long_len_inA)
259
+ C - 1 => RR
260
+ D - 1 => E
261
+
262
+ %MAX_CNT_STEPS - STEP - 3*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep)
263
+
264
+ array_div_long_compare_inA2:
265
+ $ => A :MLOAD(array_add_AGTB_out + RR)
266
+ A :MSTORE(array_compare_inA + RR)
267
+ RR - 1 => RR :JMPN(array_div_long_compare_inB3, array_div_long_compare_inA2)
268
+
269
+ array_div_long_compare_inB3:
270
+ $ => A :MLOAD(array_div_long_inA + E)
271
+ A :MSTORE(array_compare_inB + E)
272
+ E - 1 => E :JMPN(array_div_long_compare3, array_div_long_compare_inB3)
273
+
274
+ array_div_long_compare3:
275
+ :CALL(array_compare)
276
+
277
+ %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep)
278
+
279
+ 1 :MLOAD(array_compare_result)
280
+ 0 => B
281
+
282
+ array_div_long_end:
283
+ $ => RR :MLOAD(array_div_long_RR)
284
+ :RETURN