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,222 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed.
3
+ ;; POST: The quotient is trimmed.
4
+ ;;
5
+ ;; array_div_short:
6
+ ;; in:
7
+ ;; · C ∈ [1, 32], the len of inA
8
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
9
+ ;; · inB ∈ [0, 2²⁵⁶ - 1], the second input
10
+ ;;
11
+ ;; output:
12
+ ;; · [quo,rem] = [inA / inB[0], inA % inB[0]], with len(quo) <= C, len(rem) = 1
13
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
+
15
+ ; function array_div_short(a: bigint[], b: bigint, base: bigint): bigint[] {
16
+ ; if (a === [0n]) {
17
+ ; if (b === 0n) {
18
+ ; throw new Error("Division by zero");
19
+ ; }
20
+ ; return [0n, 0n];
21
+ ; } else if (b === 0n) {
22
+ ; throw new Error("Division by zero");
23
+ ; }
24
+ ;
25
+ ; if (a === b) {
26
+ ; return [1n, 0n];
27
+ ; } else if (a < b) {
28
+ ; return [0n, a];
29
+ ; }
30
+ ; }
31
+
32
+ ; NOTE: This function receives the actual result from the helper (avoiding the need of computing divisions);
33
+ ; checks the correctness of the result and returns the result to the caller
34
+
35
+ VAR GLOBAL array_div_short_inA[%ARRAY_MAX_LEN]
36
+ VAR GLOBAL array_div_short_inB
37
+ VAR GLOBAL array_div_short_quo[%ARRAY_MAX_LEN]
38
+ VAR GLOBAL array_div_short_rem
39
+
40
+ VAR GLOBAL array_div_short_len_inA
41
+ VAR GLOBAL array_div_short_len_quo
42
+
43
+ VAR GLOBAL array_div_short_RR
44
+
45
+ ; ERROR CODES (B)
46
+ ; 0 - no error
47
+ ; 1 - inB is zero
48
+
49
+ array_div_short:
50
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
51
+ %MAX_CNT_STEPS - STEP - 11 - 3*C - 3 :JMPN(outOfCountersStep)
52
+
53
+ RR :MSTORE(array_div_short_RR)
54
+
55
+ C :MSTORE(array_div_short_len_inA)
56
+ C :MSTORE(array_div_short_len_quo)
57
+
58
+ ; Let's cover the edge cases
59
+ 1 => B
60
+ ; 1] Is C == 1 and inA == 0?
61
+ C - B :JMPNZ(__array_div_short_inA_continue)
62
+ $ => A :MLOAD(array_div_short_inA)
63
+ $ :LT, JMPC(array_div_short_inA_is_zero)
64
+ __array_div_short_inA_continue:
65
+
66
+ ; 2] Is inB == 0?
67
+ $ => A :MLOAD(array_div_short_inB)
68
+ $ :LT, JMPC(array_div_short_inB_is_zero)
69
+
70
+ ; Check whether inA = inB or inA < inB
71
+ C - 1 => RR
72
+ 1 => D
73
+ array_div_short_inA_to_compare1:
74
+ $ => A :MLOAD(array_div_short_inA + RR)
75
+ A :MSTORE(array_compare_inA + RR)
76
+ RR - 1 => RR :JMPN(array_div_short_inB_to_compare, array_div_short_inA_to_compare1)
77
+
78
+ array_div_short_inB_to_compare:
79
+ $ => A :MLOAD(array_div_short_inB)
80
+ A :MSTORE(array_compare_inB)
81
+
82
+ array_div_short_compare_inA_inB:
83
+ :CALL(array_compare)
84
+
85
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
86
+ %MAX_CNT_STEPS - STEP - 10 - 4*%ARRAY_MAX_LEN - 3 :JMPN(outOfCountersStep)
87
+
88
+ $ => A :MLOAD(array_compare_result), JMPZ(array_div_short_inALTinB)
89
+ A - 1 :JMPZ(array_div_short_same_input)
90
+ ; From here, inA > inB
91
+
92
+ ; Strategy: Divide outside and check the result inside
93
+ $${MPdiv_short(addr.array_div_short_inA,mem.array_div_short_len_inA,mem.array_div_short_inB)}
94
+
95
+ :JMP(array_div_short_prepare_mul_quo_inB)
96
+
97
+ ; Begin of edge cases
98
+ array_div_short_inA_is_zero:
99
+ ; Is inB == 0? 0/0 is undefined
100
+ $ => A :MLOAD(array_div_short_inB)
101
+ $ :LT, JMPC(array_div_short_inB_is_zero)
102
+ ; From here, inB != 0
103
+
104
+ ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1
105
+ 0 :MSTORE(array_div_short_quo)
106
+ 0 :MSTORE(array_div_short_rem)
107
+ 1 :MSTORE(array_div_short_len_quo)
108
+ 0 => B :JMP(array_div_short_end)
109
+
110
+ array_div_short_inB_is_zero:
111
+ ; Error, you cannot divide by 0
112
+ 1 => B :JMP(array_div_short_end)
113
+
114
+ array_div_short_same_input:
115
+ ; If inA = inB, then the result is [1,0] since inA = 1·inB + 0
116
+ 1 :MSTORE(array_div_short_quo)
117
+ 1 :MSTORE(array_div_short_len_quo)
118
+ 0 :MSTORE(array_div_short_rem)
119
+ 0 => B :JMP(array_div_short_end)
120
+
121
+ array_div_short_inALTinB:
122
+ ; If inA < inB, then the result is [0, inA] since inA = 0·inB + inA
123
+ 0 :MSTORE(array_div_short_quo)
124
+ 1 :MSTORE(array_div_short_len_quo)
125
+ $ => A :MLOAD(array_div_short_inA)
126
+ A :MSTORE(array_div_short_rem)
127
+ 0 => B :JMP(array_div_short_end)
128
+ ; End of edge cases
129
+
130
+ array_div_short_prepare_mul_quo_inB:
131
+ $0{receiveLenQuotient_short()} => C
132
+
133
+ ; The received length must be between 1 and %ARRAY_MAX_LEN
134
+ C - 1 => RR :JMPN(failAssert) ; If C = 0, then fail
135
+ %ARRAY_MAX_LEN - C :JMPN(failAssert) ; If C > %ARRAY_MAX_LEN, then fail
136
+ ; From here, 1 <= C <= %ARRAY_MAX_LEN
137
+
138
+ ; To avoid non-determinism, we must ensure that the quotient is trimmed
139
+ ; i.e., that its last chunk is not 0
140
+ ${receiveQuotientChunk_short(RR)} => A
141
+ 0 => B
142
+ 0 :EQ
143
+ ; From here, the quotient is trimmed
144
+
145
+ C :MSTORE(array_div_short_len_quo)
146
+ C - 1 => RR
147
+
148
+ ; save the first non-zero chunk of quo
149
+ A :MSTORE(array_div_short_quo + RR)
150
+ A :MSTORE(array_mul_short_inA + RR)
151
+ RR - 1 => RR :JMPN(array_div_short_inB_to_mul)
152
+
153
+ array_div_short_quo_to_mul:
154
+ ${receiveQuotientChunk_short(RR)} => A
155
+ A :MSTORE(array_div_short_quo + RR)
156
+ A :MSTORE(array_mul_short_inA + RR)
157
+ RR - 1 => RR :JMPN(array_div_short_inB_to_mul, array_div_short_quo_to_mul)
158
+
159
+ array_div_short_inB_to_mul:
160
+ $ => A :MLOAD(array_div_short_inB)
161
+ A :MSTORE(array_mul_short_inB)
162
+
163
+ array_div_short_mul_quo_inB:
164
+ :CALL(array_mul_short)
165
+
166
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
167
+ %MAX_CNT_STEPS - STEP - 2 - 3*%ARRAY_MAX_LEN - 6 :JMPN(outOfCountersStep)
168
+
169
+ ; prepare next
170
+ $ => C :MLOAD(array_mul_short_len_out)
171
+ C - 1 => RR
172
+
173
+ array_div_short_result_to_add:
174
+ $ => A :MLOAD(array_mul_short_out + RR)
175
+ A :MSTORE(array_add_short_inA + RR)
176
+ RR - 1 => RR :JMPN(array_div_short_rem_to_add, array_div_short_result_to_add)
177
+
178
+ array_div_short_rem_to_add:
179
+ ${receiveRemainderChunk_short()} => A
180
+
181
+ ; We must ensure the the remaider is lower than inB
182
+ $ => B :MLOAD(array_div_short_inB)
183
+ 1 :LT
184
+
185
+ A :MSTORE(array_div_short_rem)
186
+ A :MSTORE(array_add_short_inB)
187
+
188
+ array_div_short_add_result_rem:
189
+ :CALL(array_add_short)
190
+
191
+ %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep)
192
+
193
+ ; prepare next
194
+ $ => C :MLOAD(array_add_short_len_out)
195
+ $ => D :MLOAD(array_div_short_len_inA)
196
+ C - 1 => RR
197
+ D - 1 => E
198
+
199
+ %MAX_CNT_STEPS - STEP - 3*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep)
200
+
201
+ array_div_short_result_to_compare:
202
+ $ => A :MLOAD(array_add_short_out + RR)
203
+ A :MSTORE(array_compare_inA + RR)
204
+ RR - 1 => RR :JMPN(array_div_short_inA_to_compare2, array_div_short_result_to_compare)
205
+
206
+ array_div_short_inA_to_compare2:
207
+ $ => A :MLOAD(array_div_short_inA + E)
208
+ A :MSTORE(array_compare_inB + E)
209
+ E - 1 => E :JMPN(array_div_short_compare_result_inA, array_div_short_inA_to_compare2)
210
+
211
+ array_div_short_compare_result_inA:
212
+ :CALL(array_compare)
213
+
214
+ %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep)
215
+
216
+ 1 :MLOAD(array_compare_result)
217
+
218
+ 0 => B ; error code
219
+
220
+ array_div_short_end:
221
+ $ => RR :MLOAD(array_div_short_RR)
222
+ :RETURN
@@ -0,0 +1,97 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; POST: out is trimmed
3
+ ;;
4
+ ;; array_mul:
5
+ ;; in:
6
+ ;; · C ∈ [1, 32], the len of inA
7
+ ;; · D ∈ [1, 32], the len of inB
8
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
9
+ ;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array
10
+ ;;
11
+ ;; output:
12
+ ;; · out = inA·inB, with len(out) <= C + D
13
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
+
15
+ ; function array_mul(a: bigint[], b: bigint[], base: bigint): bigint[] {
16
+ ; if (b.length === 1) {
17
+ ; return array_mul_short(a, b, base);
18
+ ; }
19
+ ; return array_mul_long(a, b, base);
20
+ ; }
21
+
22
+ VAR GLOBAL array_mul_inA[%ARRAY_MAX_LEN]
23
+ VAR GLOBAL array_mul_inB[%ARRAY_MAX_LEN]
24
+ VAR GLOBAL array_mul_out[%ARRAY_MAX_LEN_DOUBLED]
25
+ VAR GLOBAL array_mul_len_inA
26
+ VAR GLOBAL array_mul_len_inB
27
+ VAR GLOBAL array_mul_len_out
28
+
29
+ VAR GLOBAL array_mul_RR
30
+
31
+ array_mul:
32
+ %MAX_CNT_STEPS - STEP - 6 - 3*C - 3*D - 1 :JMPN(outOfCountersStep)
33
+
34
+ RR :MSTORE(array_mul_RR)
35
+
36
+ C :MSTORE(array_mul_len_inA)
37
+ D :MSTORE(array_mul_len_inB)
38
+
39
+ C - 1 => RR
40
+ D - 1 => E
41
+ D - 1 :JMPZ(array_mul_inA_to_mul_short) ; worst case is mul long
42
+ ; Long
43
+ array_mul_inA_to_mul_long:
44
+ $ => A :MLOAD(array_mul_inA + RR)
45
+ A :MSTORE(array_mul_long_inA + RR)
46
+ RR - 1 => RR :JMPN(array_mul_inB_to_mul_long, array_mul_inA_to_mul_long)
47
+
48
+ array_mul_inB_to_mul_long:
49
+ $ => A :MLOAD(array_mul_inB + E)
50
+ A :MSTORE(array_mul_long_inB + E)
51
+ E - 1 => E :JMPN(array_mul_compute_long, array_mul_inB_to_mul_long)
52
+
53
+ array_mul_compute_long:
54
+ :CALL(array_mul_long)
55
+
56
+ %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep)
57
+
58
+ $ => C :MLOAD(array_mul_long_len_out)
59
+ C :MSTORE(array_mul_len_out)
60
+ C - 1 => RR
61
+
62
+ %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep)
63
+
64
+ array_mul_assign_long:
65
+ $ => A :MLOAD(array_mul_long_out + RR)
66
+ A :MSTORE(array_mul_out + RR)
67
+ RR - 1 => RR :JMPN(array_mul_end, array_mul_assign_long)
68
+
69
+ ; Short
70
+ array_mul_inA_to_mul_short:
71
+ $ => A :MLOAD(array_mul_inA + RR)
72
+ A :MSTORE(array_mul_short_inA + RR)
73
+ RR - 1 => RR :JMPN(array_mul_inB_to_mul_short, array_mul_inA_to_mul_short)
74
+
75
+ array_mul_inB_to_mul_short:
76
+ $ => A :MLOAD(array_mul_inB)
77
+ A :MSTORE(array_mul_short_inB)
78
+
79
+ array_mul_compute_short:
80
+ :CALL(array_mul_short)
81
+
82
+ %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep)
83
+
84
+ $ => C :MLOAD(array_mul_short_len_out)
85
+ C :MSTORE(array_mul_len_out)
86
+ C - 1 => RR
87
+
88
+ %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep)
89
+
90
+ array_mul_assign_short:
91
+ $ => A :MLOAD(array_mul_short_out + RR)
92
+ A :MSTORE(array_mul_out + RR)
93
+ RR - 1 => RR :JMPN(array_mul_end, array_mul_assign_short)
94
+
95
+ array_mul_end:
96
+ $ => RR :MLOAD(array_mul_RR)
97
+ :RETURN
@@ -0,0 +1,156 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: len(inB) >= 2
3
+ ;; POST: out is trimmed
4
+ ;;
5
+ ;; array_mul_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
+ ;; · out = inA·inB, with len(out) <= C + D
14
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
+
16
+ ; function array_mul_long(a: bigint[], b: bigint[], base: bigint): bigint[] {
17
+ ; const alen = a.length;
18
+ ; const blen = b.length;
19
+ ; const len = alen + blen;
20
+ ; const result = new Array<bigint>(len).fill(0n);
21
+ ; let product: bigint;
22
+ ; let carry: bigint;
23
+ ; for (let i = 0; i < alen; i++) {
24
+ ; for (let j = 0; j < blen; j++) {
25
+ ; product = a[i] * b[j] + out[i+j];
26
+ ; carry = product / base;
27
+ ; out[i+j] = product - carry * base;
28
+ ; out[i + j + 1] += carry;
29
+ ; }
30
+ ; }
31
+ ; trim(result);
32
+ ; return result;
33
+ ; }
34
+
35
+ VAR GLOBAL array_mul_long_inA[%ARRAY_MAX_LEN]
36
+ VAR GLOBAL array_mul_long_inB[%ARRAY_MAX_LEN]
37
+ VAR GLOBAL array_mul_long_out[%ARRAY_MAX_LEN_DOUBLED]
38
+ VAR GLOBAL array_mul_long_len_inA
39
+ VAR GLOBAL array_mul_long_len_inB
40
+ VAR GLOBAL array_mul_long_len_out
41
+
42
+ VAR GLOBAL array_mul_long_out_chunk_2
43
+
44
+ VAR GLOBAL array_mul_long_RR
45
+
46
+ array_mul_long:
47
+ %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith)
48
+ %MAX_CNT_STEPS - STEP - 9 :JMPN(outOfCountersStep)
49
+
50
+ C => A
51
+ D => B
52
+ 0 => C,D
53
+ ${A*B} => E :ARITH
54
+ A => C
55
+ B => D
56
+ ; E holds C*D
57
+
58
+ %MAX_CNT_BINARY - CNT_BINARY - 4*E :JMPN(outOfCountersBinary)
59
+ %MAX_CNT_ARITH - CNT_ARITH - E :JMPN(outOfCountersArith)
60
+ %MAX_CNT_STEPS - STEP - 7 - 2*C - 2*D - 33*E - 2 - 3*C - 1 :JMPN(outOfCountersStep)
61
+
62
+ RR :MSTORE(array_mul_long_RR)
63
+
64
+ C :MSTORE(array_mul_long_len_inA)
65
+ D :MSTORE(array_mul_long_len_inB)
66
+ C + D :MSTORE(array_mul_long_len_out)
67
+ 0 :MSTORE(array_mul_long_out_chunk_2) ; initialize the out chunk 2
68
+
69
+ C + D - 1 => E ; auxiliar index
70
+ 0 => RCX ; first index in loops
71
+ 0 => RR ; second index in loops
72
+
73
+ array_mul_long_clean_out:
74
+ 0 :MSTORE(array_mul_long_out + E)
75
+ E - 1 => E :JMPN(array_mul_long_loopZero2inB, array_mul_long_clean_out)
76
+
77
+ ; Begin of branching
78
+ array_mul_long_loop_index_check:
79
+ RCX + 1 => RCX
80
+ $ => B :MLOAD(array_mul_long_len_inA)
81
+ B - RCX :JMPZ(array_mul_long_prep_trim_in)
82
+
83
+ 0 => RR ; reset the second index
84
+ ; End of branching
85
+
86
+ array_mul_long_loopZero2inB:
87
+ ; The result will be stored as D·base + C
88
+
89
+ RCX => E
90
+ ; 1] a[i]·b[j], where a[i],b[j] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks
91
+ $ => A :MLOAD(array_mul_long_inA + E)
92
+ $ => B :MLOAD(array_mul_long_inB + RR)
93
+ 0 => C
94
+ $${var _arrayLongMul_AB = A*B}
95
+ ${_arrayLongMul_AB >> 256} => D
96
+ ${_arrayLongMul_AB} => E :ARITH
97
+
98
+ ; 2] product = a[i]·b[j] + out[i+j], where out[i+j] ∈ [0,base-1]: This number cannot be GT (base - 1)·base, two chunks
99
+ E => A
100
+ RCX + RR => E
101
+ $ => B :MLOAD(array_mul_long_out + E)
102
+ $ => C :ADD, JMPNC(__array_mul_long_no_carry_continue_1)
103
+ ;-----------------
104
+ ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition
105
+ D => A
106
+ 1 => B
107
+ $ => D :ADD
108
+ ;-----------------
109
+ __array_mul_long_no_carry_continue_1:
110
+ $ => A :MLOAD(array_mul_long_out_chunk_2) ; out_chunk_2 ∈ [0,1]
111
+ D => B
112
+ $ => D :ADD ; the number is of two chunks, no carry can be generated here
113
+
114
+ ; NOTE: It cannot happen that a[i]·b[j] + out[i+j] produces carry and out_chunk_2 is 1.
115
+
116
+ ; out[i+j] = product - carry·B
117
+ C :MSTORE(array_mul_long_out + E)
118
+
119
+ ; out[i+j+1] += carry, where carry ∈ [0,base-1]: This number cannot be GT base + (base-3), two chunks
120
+ E + 1 => E
121
+ $ => A :MLOAD(array_mul_long_out + E)
122
+ D => B
123
+ $ => C :ADD, JMPNC(__array_mul_long_no_carry_continue_2)
124
+ ;-----------------
125
+ 1 :MSTORE(array_mul_long_out_chunk_2)
126
+ :JMP(__array_mul_long_carry_continue)
127
+ __array_mul_long_no_carry_continue_2:
128
+ 0 :MSTORE(array_mul_long_out_chunk_2)
129
+ __array_mul_long_carry_continue:
130
+ ;-----------------
131
+
132
+ C :MSTORE(array_mul_long_out + E)
133
+
134
+ RR + 1 => RR
135
+ $ => B :MLOAD(array_mul_long_len_inB)
136
+ B - RR :JMPZ(array_mul_long_loop_index_check, array_mul_long_loopZero2inB)
137
+
138
+ array_mul_long_prep_trim_in:
139
+ $ => C :MLOAD(array_mul_long_len_out)
140
+ C - 1 => E
141
+
142
+ array_mul_long_trim_in:
143
+ $ => A :MLOAD(array_mul_long_out + E)
144
+ A :MSTORE(array_trim_in + E)
145
+ E - 1 => E :JMPN(array_mul_long_trim, array_mul_long_trim_in)
146
+
147
+ array_mul_long_trim:
148
+ :CALL(array_trim)
149
+
150
+ %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep)
151
+
152
+ C :MSTORE(array_mul_long_len_out)
153
+
154
+ array_mul_long_end:
155
+ $ => RR :MLOAD(array_mul_long_RR)
156
+ :RETURN
@@ -0,0 +1,127 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; POST: out is trimmed
3
+ ;;
4
+ ;; array_mul_short:
5
+ ;; in:
6
+ ;; · C ∈ [1, 32], the len of inA
7
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
8
+ ;; · inB ∈ [0, 2²⁵⁶ - 1], the second input
9
+ ;;
10
+ ;; output:
11
+ ;; · out = inA·inB, with len(out) <= C + 1
12
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
+
14
+ ; function array_mul_short(a: bigint[], b: bigint, base: bigint): bigint[] {
15
+ ; const alen = a.length;
16
+ ; const len = alen;
17
+ ; const result = new Array<bigint>(len).fill(0n);
18
+ ; let product: bigint;
19
+ ; let carry = 0n;
20
+ ; let i;
21
+ ; for (i = 0; i < alen; i++) {
22
+ ; product = a[i] * b + carry;
23
+ ; carry = product / base;
24
+ ; out[i] = product - carry * base;
25
+ ; }
26
+
27
+ ; if (carry > 0n) {
28
+ ; result.push(carry);
29
+ ; }
30
+
31
+ ; trim(result);
32
+ ; return result;
33
+ ; }
34
+
35
+ VAR GLOBAL array_mul_short_inA[%ARRAY_MAX_LEN]
36
+ VAR GLOBAL array_mul_short_inB
37
+ VAR GLOBAL array_mul_short_out[%ARRAY_MAX_LEN_PLUS_ONE]
38
+ VAR GLOBAL array_mul_short_len_inA
39
+ VAR GLOBAL array_mul_short_len_out
40
+
41
+ VAR GLOBAL array_mul_short_carry
42
+
43
+ VAR GLOBAL array_mul_short_RR
44
+
45
+ array_mul_short:
46
+ %MAX_CNT_BINARY - CNT_BINARY - 2*C :JMPN(outOfCountersBinary)
47
+ %MAX_CNT_ARITH - CNT_ARITH - C :JMPN(outOfCountersArith)
48
+ %MAX_CNT_STEPS - STEP - 6 - 2*C-2 - 18*C - 6 :JMPN(outOfCountersStep)
49
+
50
+ RR :MSTORE(array_mul_short_RR)
51
+
52
+ C :MSTORE(array_mul_short_len_inA)
53
+ C + 1 :MSTORE(array_mul_short_len_out)
54
+
55
+ C => E ; auxiliar index
56
+ 0 => RCX ; index in loops
57
+ 0 :MSTORE(array_mul_short_carry)
58
+
59
+ array_mul_short_clean_out:
60
+ 0 :MSTORE(array_mul_short_out + E)
61
+ E - 1 => E :JMPN(array_mul_short_loopZero2inA, array_mul_short_clean_out)
62
+
63
+ array_mul_short_loopZero2inA:
64
+ ; The result will be stored as D·base + C
65
+
66
+ RCX => E
67
+ ; 1] a[i] * b, where a[i],b ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks
68
+ $ => A :MLOAD(array_mul_short_inA + E)
69
+ $ => B :MLOAD(array_mul_short_inB)
70
+ 0 => C
71
+ $${var _arrayShortMul_AB = A*B}
72
+ ${_arrayShortMul_AB >> 256} => D
73
+ ${_arrayShortMul_AB} => E :ARITH
74
+
75
+ ; 2] product = a[i] * b + carry, where carry ∈ [0,base-1]: This number cannot be GT (base - 1)·base, two chunks
76
+ E => A
77
+ $ => B :MLOAD(array_mul_short_carry)
78
+ $ => C :ADD, JMPNC(__array_mul_short_no_carry_continue)
79
+ ;-----------------
80
+ ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition
81
+ D => A
82
+ 1 => B
83
+ $ => D :ADD
84
+ ;-----------------
85
+ __array_mul_short_no_carry_continue:
86
+
87
+ ; carry = product / base
88
+ D :MSTORE(array_mul_short_carry)
89
+
90
+ ; out[i] = product - carry·base
91
+ RCX => E
92
+ C :MSTORE(array_mul_short_out + E)
93
+
94
+ RCX + 1 => RCX
95
+ $ => B :MLOAD(array_mul_short_len_inA)
96
+ B - RCX :JMPZ(array_mul_short_carry_check, array_mul_short_loopZero2inA)
97
+
98
+ ; If the last carry > 0, we need to insert it to the output
99
+ array_mul_short_carry_check:
100
+ $ => A :MLOAD(array_mul_short_carry)
101
+ 0 => B
102
+ $ :EQ, JMPC(array_mul_short_prep_trim_in)
103
+
104
+ RCX => E
105
+ A :MSTORE(array_mul_short_out + E)
106
+
107
+ array_mul_short_prep_trim_in:
108
+ $ => C :MLOAD(array_mul_short_len_out)
109
+ C - 1 => E
110
+
111
+ %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep)
112
+
113
+ array_mul_short_trim_in:
114
+ $ => A :MLOAD(array_mul_short_out + E)
115
+ A :MSTORE(array_trim_in + E)
116
+ E - 1 => E :JMPZ(array_mul_short_trim, array_mul_short_trim_in)
117
+
118
+ array_mul_short_trim:
119
+ :CALL(array_trim)
120
+
121
+ %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep)
122
+
123
+ C :MSTORE(array_mul_short_len_out)
124
+
125
+ array_mul_short_end:
126
+ $ => RR :MLOAD(array_mul_short_RR)
127
+ :RETURN