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,246 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; POST: out is trimmed
3
+ ;;
4
+ ;; array_square:
5
+ ;; in:
6
+ ;; · C ∈ [1, 32], the len of in
7
+ ;; · in ∈ [0, 2²⁵⁶- 1]^C, the input array
8
+ ;;
9
+ ;; output:
10
+ ;; · out = in², with len(out) <= 2·C
11
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
+
13
+ ; function array_square(a: bigint[], base: bigint): bigint[] {
14
+ ; let len = a.length;
15
+ ; let out = new Array<bigint>(2*len).fill(0n);
16
+ ; let product: bigint;
17
+ ; let carry: bigint;
18
+ ; for (let i = 0; i < len; i++) {
19
+ ; carry = 0n - a[i] * a[i];
20
+ ; for (var j = i; j < len; j++) {
21
+ ; product = 2n * (a[i] * a[j]) + out[i+j] + carry;
22
+ ; carry = product / base;
23
+
24
+ ; out[i+j] = product - carry * base;
25
+ ; }
26
+ ; out[i + len] = carry;
27
+ ; }
28
+ ; trim(out);
29
+ ; return out;
30
+ ; }
31
+
32
+ ; Matrix visualization: https://hackmd.io/C9KQPGoaSICStIQQFweBlw?view
33
+
34
+ VAR GLOBAL array_square_in[%ARRAY_MAX_LEN]
35
+ VAR GLOBAL array_square_out[%ARRAY_MAX_LEN_DOUBLED]
36
+ VAR GLOBAL array_square_len_in
37
+ VAR GLOBAL array_square_len_out
38
+
39
+ VAR GLOBAL array_square_carry_chunk_1
40
+ VAR GLOBAL array_square_carry_chunk_2
41
+ VAR GLOBAL array_square_carry_sign ; 0 if negative, 1 if positive
42
+ VAR GLOBAL array_square_chunk_3
43
+ VAR GLOBAL array_square_aiaj_chunk_2
44
+ VAR GLOBAL array_square_out_chunk_2
45
+
46
+ VAR GLOBAL array_square_RR
47
+
48
+ array_square:
49
+ %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith)
50
+ %MAX_CNT_STEPS - STEP - 7 :JMPN(outOfCountersStep)
51
+
52
+ C => A,B
53
+ 0 => C,D
54
+ ${A*A} => E :ARITH
55
+ A => C
56
+ ; E holds C*C
57
+
58
+ %MAX_CNT_BINARY - CNT_BINARY - 9*E :JMPN(outOfCountersBinary)
59
+ %MAX_CNT_ARITH - CNT_ARITH - 1 - 2*E :JMPN(outOfCountersArith)
60
+ %MAX_CNT_STEPS - STEP - 5 - 2*C - 68*E - 2 :JMPN(outOfCountersStep)
61
+
62
+ RR :MSTORE(array_square_RR)
63
+
64
+ C :MSTORE(array_square_len_in)
65
+ C + C :MSTORE(array_square_len_out)
66
+
67
+ 0 :MSTORE(array_square_chunk_3) ; initialize the third chunk
68
+ 0 :MSTORE(array_square_out_chunk_2) ; initialize the second chunk of out
69
+
70
+ 0 => RCX,RR ; first and second indexes in loops
71
+ C + C - 1 => E
72
+ array_square_clean_out:
73
+ 0 :MSTORE(array_square_out + E)
74
+ E - 1 => E :JMPN(array_square_ai_times_ai, array_square_clean_out)
75
+
76
+ ; Begin of branching
77
+ ; We perform subtraction of a value with three chunks
78
+ ; Therefore, the subtraction can produce carry until the highest chunk
79
+ ; e.g. (base² + y) - (y+1) = 0
80
+ array_square_is_negative_1:
81
+ $ => C :SUB, JMPNC(__return_array_square_is_negative_1)
82
+ ;-----------------
83
+ D => A
84
+ 1 => B
85
+ $ => D :SUB, JMPNC(__return_array_square_is_negative_1)
86
+ 0 :MSTORE(array_square_chunk_3)
87
+ :JMP(__return_array_square_is_negative_1)
88
+ ;-----------------
89
+
90
+
91
+ array_square_is_negative_2:
92
+ $ => D :SUB, JMPNC(__return_array_square_is_negative_2)
93
+ ;-----------------
94
+ 0 :MSTORE(array_square_chunk_3)
95
+ :JMP(__return_array_square_is_negative_2)
96
+ ;-----------------
97
+
98
+ array_square_loop_index_check:
99
+ ; out[i + len] = carry
100
+ $ => A :MLOAD(array_square_carry_chunk_1)
101
+ RCX + B => E
102
+ A :MSTORE(array_square_out + E)
103
+
104
+ $ => A :MLOAD(array_square_carry_chunk_2)
105
+ A :MSTORE(array_square_out_chunk_2)
106
+
107
+ ; update indices
108
+ RCX + 1 => RCX,RR,A
109
+ B - A :JMPZ(array_square_prep_trim_in) ; This subtraction is safe
110
+ ; End of branching
111
+
112
+ array_square_ai_times_ai:
113
+ ; carry = 0 - a[i]·a[i]
114
+ ; a[i]·a[i], where a[i] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks
115
+ $ => A,B :MLOAD(array_square_in + RR)
116
+ 0 => C
117
+ $${var _arraySquare_aiai = A*B}
118
+ ${_arraySquare_aiai >> 256} => D
119
+ ${_arraySquare_aiai} => E :ARITH
120
+ E :MSTORE(array_square_carry_chunk_1)
121
+ D :MSTORE(array_square_carry_chunk_2)
122
+ 0 :MSTORE(array_square_carry_sign)
123
+
124
+ array_square_loopRR2len:
125
+ ; product = 2·(a[i]·a[j]) + out[i+j] + carry (in the worst case, this is a 3-chunk number)
126
+ ; The result will be stored as array_square_chunk_3·base² + D·base + C
127
+
128
+ ; 1] a[i]·a[j], where a[i],a[j] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks
129
+ RCX => E
130
+ $ => A :MLOAD(array_square_in + E)
131
+ $ => B :MLOAD(array_square_in + RR)
132
+ 0 => C
133
+ $${var _arraySquare_aiaj = A*B}
134
+ ${_arraySquare_aiaj >> 256} => D
135
+ ${_arraySquare_aiaj} => E :ARITH
136
+ D :MSTORE(array_square_aiaj_chunk_2)
137
+
138
+ ; 2] 2·a[i]·a[j]: This number cannot be GT base² + (base - 4)·base + 2, three chunks
139
+ E => A,B
140
+ $ => C :ADD, JMPNC(__array_square_no_carry_continue_1)
141
+ ;-----------------
142
+ ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition
143
+ D => A
144
+ 1 => B
145
+ $ => D :ADD
146
+ ;-----------------
147
+ __array_square_no_carry_continue_1:
148
+ $ => A :MLOAD(array_square_aiaj_chunk_2)
149
+ D => B
150
+ $ => D :ADD, JMPNC(__array_square_no_carry_continue_2)
151
+ ;-----------------
152
+ 1 :MSTORE(array_square_chunk_3)
153
+ ;-----------------
154
+ __array_square_no_carry_continue_2:
155
+
156
+ ; 3] 2·a[i]·a[j] + out[i+j]:
157
+ ; a) j < len-1: This number cannot be GT base² + (base - 3)·base + 1, as out[i+j] < base
158
+ ; b) j == len-1: This number cannot be GT base² + (base - 3)·base + base - 1, as out[i + len] <= base + (base - 3)
159
+ ; In both cases, three chunks
160
+ RCX + RR => E
161
+ $ => A :MLOAD(array_square_out + E)
162
+ C => B
163
+ $ => C :ADD, JMPNC(__array_square_no_carry_continue_3)
164
+ ;-----------------
165
+ ; Since here D ∈ [0, base - 1], there can be carry in the following addition
166
+ D => A
167
+ 1 => B
168
+ $ => D :ADD, JMPNC(__array_square_no_carry_continue_3)
169
+ 1 :MSTORE(array_square_chunk_3)
170
+ ;-----------------
171
+ __array_square_no_carry_continue_3:
172
+
173
+ ; The output can have two chunks only if j == len-1, so we must jump the following block of code if j < len-1
174
+ RR + 1 => A
175
+ $ => B :MLOAD(array_square_len_in)
176
+ B - A :JMPNZ(__array_square_no_carry_continue_4) ; This subtraction is safe
177
+ ; Add the second output chunk
178
+ $ => A :MLOAD(array_square_out_chunk_2)
179
+ D => B
180
+ $ => D :ADD, JMPNC(__array_square_no_carry_continue_4)
181
+ ;-----------------
182
+ 1 :MSTORE(array_square_chunk_3)
183
+ ;-----------------
184
+ __array_square_no_carry_continue_4:
185
+
186
+ ; 4] product = 2·a[i]·a[j] + out[i+j] + carry: This number cannot be GT base² + (base - 2)·base, three chunks
187
+ C => A
188
+ $ => B :MLOAD(array_square_carry_chunk_1)
189
+ $ :MLOAD(array_square_carry_sign), JMPZ(array_square_is_negative_1)
190
+ $ => C :ADD, JMPNC(__array_square_no_carry_continue_5)
191
+ ;-----------------
192
+ ; Since here D ∈ [0, base - 1], there can be carry in the following addition
193
+ D => A
194
+ 1 => B
195
+ $ => D :ADD, JMPNC(__array_square_no_carry_continue_5)
196
+ 1 :MSTORE(array_square_chunk_3)
197
+ ;-----------------
198
+ __array_square_no_carry_continue_5:
199
+ __return_array_square_is_negative_1:
200
+
201
+ D => A
202
+ $ => B :MLOAD(array_square_carry_chunk_2)
203
+ $ :MLOAD(array_square_carry_sign), JMPZ(array_square_is_negative_2)
204
+ $ => D :ADD, JMPNC(__array_square_no_carry_continue_6)
205
+ ;-----------------
206
+ 1 :MSTORE(array_square_chunk_3)
207
+ ;-----------------
208
+ __array_square_no_carry_continue_6:
209
+ __return_array_square_is_negative_2:
210
+
211
+ ; carry = product / base; This number cannot be greater than base + (base - 2)
212
+ D :MSTORE(array_square_carry_chunk_1)
213
+ $ => A :MLOAD(array_square_chunk_3)
214
+ A :MSTORE(array_square_carry_chunk_2)
215
+ 1 :MSTORE(array_square_carry_sign)
216
+
217
+ ; out[i+j] = product - carry·base;
218
+ RCX + RR => E
219
+ C :MSTORE(array_square_out + E)
220
+ 0 :MSTORE(array_square_chunk_3) ; reset the third chunk
221
+
222
+ RR + 1 => RR
223
+ $ => B :MLOAD(array_square_len_in)
224
+ B - RR :JMPZ(array_square_loop_index_check, array_square_loopRR2len) ; This subtraction is safe
225
+
226
+ array_square_prep_trim_in:
227
+ $ => C :MLOAD(array_square_len_out)
228
+
229
+ %MAX_CNT_STEPS - STEP - 1 - 3*C - 1 :JMPN(outOfCountersStep)
230
+
231
+ C - 1 => E
232
+ array_square_trim_in:
233
+ $ => A :MLOAD(array_square_out + E)
234
+ A :MSTORE(array_trim_in + E)
235
+ E - 1 => E :JMPN(array_square_trim, array_square_trim_in)
236
+
237
+ array_square_trim:
238
+ :CALL(array_trim)
239
+
240
+ %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep)
241
+
242
+ C :MSTORE(array_square_len_out)
243
+
244
+ array_square_end:
245
+ $ => RR :MLOAD(array_square_RR)
246
+ :RETURN
@@ -0,0 +1,100 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;;
3
+ ;; array_add:
4
+ ;; in:
5
+ ;; · C ∈ [1, 32], the len of inA
6
+ ;; · D ∈ [1, 32], the len of inB
7
+ ;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array
8
+ ;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array
9
+ ;;
10
+ ;; output:
11
+ ;; · out = inA + inB, with len(out) <= C + 1
12
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
+
14
+ VAR GLOBAL array_add_inA[%ARRAY_MAX_LEN]
15
+ VAR GLOBAL array_add_inB[%ARRAY_MAX_LEN]
16
+ VAR GLOBAL array_add_out[%ARRAY_MAX_LEN_PLUS_ONE]
17
+ VAR GLOBAL array_add_len_inA
18
+ VAR GLOBAL array_add_len_inB
19
+ VAR GLOBAL array_add_len_out
20
+
21
+ VAR GLOBAL array_add_RR
22
+
23
+ array_add:
24
+ RR :MSTORE(array_add_RR)
25
+ C :MSTORE(array_add_len_inA)
26
+ D :MSTORE(array_add_len_inB)
27
+ 0 => RR,E
28
+
29
+ D => A
30
+ C => B
31
+ $ :LT, JMPC(array_add_inA_to_add_AGTB)
32
+
33
+ ; BGTA
34
+ array_add_prep_BGTA:
35
+ C => A
36
+ D => C
37
+ A => D
38
+
39
+ array_add_inA_to_add_BGTA:
40
+ $ => A :MLOAD(array_add_inB + RR)
41
+ A :MSTORE(array_add_AGTB_inA + RR)
42
+ RR + 1 => RR
43
+ RR => A
44
+ D => B
45
+ $ :EQ, JMPC(array_add_inB_to_add_BGTA, array_add_inA_to_add_BGTA)
46
+
47
+ array_add_inB_to_add_BGTA:
48
+ $ => A :MLOAD(array_add_inA + E)
49
+ A :MSTORE(array_add_AGTB_inB + E)
50
+ E + 1 => E
51
+ E => A
52
+ C => B
53
+ $ :EQ, JMPC(array_add_compute_BGTA, array_add_inB_to_add_BGTA)
54
+
55
+ array_add_compute_BGTA:
56
+ :CALL(array_add_AGTB)
57
+ $ => C :MLOAD(array_add_AGTB_len_out)
58
+ C :MSTORE(array_add_len_out)
59
+ 0 => RR
60
+ array_add_assign_BGTA:
61
+ $ => A :MLOAD(array_add_AGTB_out + RR)
62
+ A :MSTORE(array_add_out + RR)
63
+ RR + 1 => RR
64
+ RR => A
65
+ C => B
66
+ $ :EQ, JMPC(array_add_end, array_add_assign_BGTA)
67
+
68
+ ; AGTB
69
+ array_add_inA_to_add_AGTB:
70
+ $ => A :MLOAD(array_add_inA + RR)
71
+ A :MSTORE(array_add_AGTB_inA + RR)
72
+ RR + 1 => RR
73
+ RR => A
74
+ C => B
75
+ $ :EQ, JMPC(array_add_inB_to_add_AGTB, array_add_inA_to_add_AGTB)
76
+
77
+ array_add_inB_to_add_AGTB:
78
+ $ => A :MLOAD(array_add_inB + E)
79
+ A :MSTORE(array_add_AGTB_inB + E)
80
+ E + 1 => E
81
+ E => A
82
+ D => B
83
+ $ :EQ, JMPC(array_add_compute_AGTB, array_add_inB_to_add_AGTB)
84
+
85
+ array_add_compute_AGTB:
86
+ :CALL(array_add_AGTB)
87
+ $ => C :MLOAD(array_add_AGTB_len_out)
88
+ C :MSTORE(array_add_len_out)
89
+ 0 => RR
90
+ array_add_assign_AGTB:
91
+ $ => A :MLOAD(array_add_AGTB_out + RR)
92
+ A :MSTORE(array_add_out + RR)
93
+ RR + 1 => RR
94
+ RR => A
95
+ C => B
96
+ $ :EQ, JMPC(array_add_end, array_add_assign_AGTB)
97
+
98
+ array_add_end:
99
+ $ => RR :MLOAD(array_add_RR)
100
+ :RETURN
@@ -0,0 +1,23 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed.
3
+ ;;
4
+ ;; array_is_odd:
5
+ ;; in:
6
+ ;; · in ∈ [0, 2²⁵⁶ - 1]*, the input array
7
+ ;; output:
8
+ ;; · 1, if in is an odd number
9
+ ;; · 0, otherwise
10
+ ;;
11
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
+
13
+ ; NOTE: The base is 2^256, so I only need to check if the first chunk is odd to conclude that the whole number is odd.
14
+
15
+ VAR GLOBAL array_is_odd_in
16
+ VAR GLOBAL array_is_odd_result
17
+
18
+ array_is_odd:
19
+ $ => A :MLOAD(array_is_odd_in)
20
+ 1 => B
21
+ $ => A :AND
22
+ A :MSTORE(array_is_odd_result)
23
+ :RETURN
@@ -0,0 +1,33 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed.
3
+ ;;
4
+ ;; array_is_one:
5
+ ;; in:
6
+ ;; · C ∈ [1, 32], the len of in
7
+ ;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array
8
+ ;; output:
9
+ ;; · 1, if in = 1
10
+ ;; · 0, otherwise
11
+ ;;
12
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
+
14
+ VAR GLOBAL array_is_one_in
15
+ VAR GLOBAL array_is_one_result
16
+
17
+ array_is_one:
18
+ ; Is C == 1 and in == 1?
19
+ C => A
20
+ 1 => B
21
+ $ :EQ, JMPNC(__array_is_one_continue)
22
+ $ => A :MLOAD(array_is_one_in)
23
+ $ :EQ, JMPC(array_is_one_sure)
24
+ __array_is_one_continue:
25
+
26
+ 0 :MSTORE(array_is_one_result)
27
+ :JMP(array_is_one_end)
28
+
29
+ array_is_one_sure:
30
+ 1 :MSTORE(array_is_one_result)
31
+
32
+ array_is_one_end:
33
+ :RETURN
@@ -0,0 +1,34 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed.
3
+ ;;
4
+ ;; array_is_zero:
5
+ ;; in:
6
+ ;; · C ∈ [1, 32], the len of in
7
+ ;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array
8
+ ;; output:
9
+ ;; · 1, if in = 0
10
+ ;; · 0, otherwise
11
+ ;;
12
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
+
14
+ VAR GLOBAL array_is_zero_in
15
+ VAR GLOBAL array_is_zero_result
16
+
17
+ array_is_zero:
18
+ ; Is C == 1 and in == 0?
19
+ C => A
20
+ 1 => B
21
+ $ :EQ, JMPNC(__array_is_zero_continue)
22
+ 0 => B
23
+ $ => A :MLOAD(array_is_zero_in)
24
+ $ :EQ, JMPC(array_is_zero_sure)
25
+ __array_is_zero_continue:
26
+
27
+ 0 :MSTORE(array_is_zero_result)
28
+ :JMP(array_is_zero_end)
29
+
30
+ array_is_zero_sure:
31
+ 1 :MSTORE(array_is_zero_result)
32
+
33
+ array_is_zero_end:
34
+ :RETURN
@@ -0,0 +1,111 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: inA >= inB
3
+ ;;
4
+ ;; array_sub_AGTB:
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
13
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
+
15
+ VAR GLOBAL array_sub_AGTB_inA[%ARRAY_MAX_LEN]
16
+ VAR GLOBAL array_sub_AGTB_inB[%ARRAY_MAX_LEN]
17
+ VAR GLOBAL array_sub_AGTB_out[%ARRAY_MAX_LEN]
18
+ VAR GLOBAL array_sub_AGTB_len_inA
19
+ VAR GLOBAL array_sub_AGTB_len_inB
20
+
21
+ VAR GLOBAL array_sub_AGTB_carry
22
+
23
+ VAR GLOBAL array_sub_AGTB_RR
24
+
25
+ array_sub_AGTB:
26
+ RR :MSTORE(array_sub_AGTB_RR)
27
+ C :MSTORE(array_sub_AGTB_len_inA)
28
+ D :MSTORE(array_sub_AGTB_len_inB)
29
+
30
+ 0 => E ; index in loops
31
+ 0 :MSTORE(array_sub_AGTB_carry)
32
+ :JMP(array_sub_AGTB_loopZero2inB)
33
+
34
+ array_sub_AGTB_add_carry:
35
+ 1 => D
36
+ :JMP(return_array_sub_AGTB_add_carry)
37
+
38
+ array_sub_AGTB_sub_carry:
39
+ D => A
40
+ 1 => B
41
+ $ :SUB, JMPC(array_sub_AGTB_set_carry_to_1, array_sub_AGTB_set_carry_tp_0)
42
+
43
+ array_sub_AGTB_set_carry_to_1:
44
+ 1 :MSTORE(array_sub_AGTB_carry)
45
+ :JMP(return_array_sub_AGTB_sub_carry)
46
+
47
+ array_sub_AGTB_set_carry_tp_0:
48
+ 0 :MSTORE(array_sub_AGTB_carry)
49
+ :JMP(return_array_sub_AGTB_sub_carry)
50
+
51
+ array_sub_AGTB_loopZero2inB:
52
+ 0 => D ; cleanup
53
+
54
+ ; diff = a[i] - (b[i] + carry)
55
+ $ => A :MLOAD(array_sub_AGTB_inB + E)
56
+ $ => B :MLOAD(array_sub_AGTB_carry)
57
+ $ => C :ADD, JMPC(array_sub_AGTB_add_carry)
58
+ return_array_sub_AGTB_add_carry:
59
+
60
+ $ => A :MLOAD(array_sub_AGTB_inA + E)
61
+ C => B
62
+ $ => C :SUB, JMPC(array_sub_AGTB_sub_carry)
63
+ 0 :MSTORE(array_sub_AGTB_carry)
64
+ return_array_sub_AGTB_sub_carry:
65
+
66
+ C :MSTORE(array_sub_AGTB_out + E)
67
+
68
+ E + 1 => E
69
+ E => A
70
+ $ => B :MLOAD(array_sub_AGTB_len_inB)
71
+ $ :EQ, JMPC(array_sub_AGTB_loop_index_check1, array_sub_AGTB_loopZero2inB)
72
+
73
+ array_sub_AGTB_loop_index_check1:
74
+ E => A
75
+ $ => B :MLOAD(array_sub_AGTB_len_inA)
76
+ $ :EQ, JMPC(array_sub_AGTB_end)
77
+
78
+ array_sub_AGTB_loopInB2InA:
79
+ ; diff = a[i] - carry
80
+ $ => A :MLOAD(array_sub_AGTB_inA + E)
81
+ $ => B :MLOAD(array_sub_AGTB_carry)
82
+ $ => C :SUB, JMPC(array_sub_AGTB_loopInB2InA_cont)
83
+ C :MSTORE(array_sub_AGTB_out + E)
84
+ E + 1 => E
85
+ :JMP(array_sub_AGTB_loop_index_check2)
86
+
87
+ array_sub_AGTB_loopInB2InA_cont:
88
+ C :MSTORE(array_sub_AGTB_out + E)
89
+
90
+ E + 1 => E
91
+ E => A
92
+ $ => B :MLOAD(array_sub_AGTB_len_inA)
93
+ $ :EQ, JMPC(array_sub_AGTB_end, array_sub_AGTB_loopInB2InA)
94
+
95
+ array_sub_AGTB_loop_index_check2:
96
+ E => A
97
+ $ => B :MLOAD(array_sub_AGTB_len_inA)
98
+ $ :EQ, JMPC(array_sub_AGTB_end)
99
+
100
+ array_sub_AGTB_loop_final:
101
+ $ => A :MLOAD(array_sub_AGTB_inA + E)
102
+ A :MSTORE(array_sub_AGTB_out + E)
103
+
104
+ E + 1 => E
105
+ E => A
106
+ $ => B :MLOAD(array_sub_AGTB_len_inA)
107
+ $ :EQ, JMPC(array_sub_AGTB_end, array_sub_AGTB_loop_final)
108
+
109
+ array_sub_AGTB_end:
110
+ $ => RR :MLOAD(array_sub_AGTB_RR)
111
+ :RETURN
@@ -0,0 +1,37 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;;
3
+ ;; array_unshift:
4
+ ;; in:
5
+ ;; · C ∈ [1, 32], the len of in = [in[0], in[1], ..., in[C - 1]]
6
+ ;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array
7
+ ;; · D ∈ [0, 2²⁵⁶ - 1], the element to unshift
8
+ ;;
9
+ ;; output:
10
+ ;; · in = [D, in[0], in[1], ..., in[C - 1]]
11
+ ;; · len = C + 1
12
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
+
14
+ VAR GLOBAL array_unshift_in[%ARRAY_MAX_LEN]
15
+ VAR GLOBAL array_unshift_len
16
+
17
+ VAR GLOBAL array_unshift_RR
18
+
19
+ array_unshift:
20
+ RR :MSTORE(array_unshift_RR)
21
+
22
+ C + 1 :MSTORE(array_unshift_len)
23
+
24
+ C :JMPZ(array_unshift_end)
25
+
26
+ array_unshift_loop:
27
+ C - 1 => E
28
+ $ => A :MLOAD(array_unshift_in + E)
29
+ C => E
30
+ A :MSTORE(array_unshift_in + E)
31
+ C - 1 => C :JMPZ(array_unshift_end)
32
+ :JMP(array_unshift_loop)
33
+
34
+ array_unshift_end:
35
+ D :MSTORE(array_unshift_in)
36
+ $ => RR :MLOAD(array_unshift_RR)
37
+ :RETURN
@@ -0,0 +1,82 @@
1
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
+ ;; PRE: The input arrays have been trimmed.
3
+ ;;
4
+ ;; array_compare:
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
+ ;; · 2, if inA > inB
13
+ ;; · 1, if inA = inB
14
+ ;; · 0, if inA < inB
15
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
+
17
+ ; function array_compare(a: bigint[], b: bigint[]): number {
18
+ ; const alen = a.length;
19
+ ; const blen = b.length;
20
+ ; if (alen !== blen) {
21
+ ; return alen >= blen ? 1 : -1;
22
+ ; }
23
+ ; for (let i = alen - 1; i >= 0; i--) {
24
+ ; if (a[i] !== b[i]) {
25
+ ; return a[i] > b[i] ? 1 : -1;
26
+ ; }
27
+ ; }
28
+ ; return 0;
29
+ ; }
30
+
31
+ ; ----------------------------------
32
+ ; Five possible paths:
33
+ ; · inA > inB and lenA > lenB.
34
+ ; · inA > inB and lenA = lenB.
35
+ ; · inA = inB. (worst case)
36
+ ; · inA < inB and lenA < lenB.
37
+ ; · inA < inB and lenA = lenB.
38
+ ; ----------------------------------
39
+
40
+ VAR GLOBAL array_compare_inA[%ARRAY_MAX_LEN]
41
+ VAR GLOBAL array_compare_inB[%ARRAY_MAX_LEN]
42
+
43
+ VAR GLOBAL array_compare_result
44
+
45
+ VAR GLOBAL array_compare_RR
46
+
47
+ array_compare:
48
+ %MAX_CNT_BINARY - CNT_BINARY - 2*C :JMPN(outOfCountersBinary)
49
+ %MAX_CNT_STEPS - STEP - 4 - 7*C - 4 :JMPN(outOfCountersStep)
50
+
51
+ RR :MSTORE(array_compare_RR)
52
+
53
+ ; Start by comparing the lengths of the arrays
54
+ C - D :JMPN(array_compare_ALTB)
55
+ D - C :JMPN(array_compare_AGTB)
56
+
57
+ C - 1 => E
58
+ array_compare_same_len:
59
+ $ => A :MLOAD(array_compare_inA + E)
60
+ $ => B :MLOAD(array_compare_inB + E)
61
+ $ :LT, JMPC(array_compare_ALTB)
62
+
63
+ $ => A :MLOAD(array_compare_inB + E)
64
+ $ => B :MLOAD(array_compare_inA + E)
65
+ $ :LT, JMPC(array_compare_AGTB)
66
+
67
+ E - 1 => E :JMPN(array_compare_AEQB, array_compare_same_len)
68
+
69
+ array_compare_AGTB:
70
+ 2 :MSTORE(array_compare_result)
71
+ :JMP(array_compare_end)
72
+
73
+ array_compare_AEQB:
74
+ 1 :MSTORE(array_compare_result)
75
+ :JMP(array_compare_end)
76
+
77
+ array_compare_ALTB:
78
+ 0 :MSTORE(array_compare_result)
79
+
80
+ array_compare_end:
81
+ $ => RR :MLOAD(array_compare_RR)
82
+ :RETURN