zkevm-rom 0.0.1-security → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of zkevm-rom might be problematic. Click here for more details.
- package/.eslintrc.js +33 -0
- package/.github/CODEOWNERS +14 -0
- package/.github/ISSUE_TEMPLATE/bug.yml +38 -0
- package/.github/ISSUE_TEMPLATE/feature.yml +26 -0
- package/.github/ISSUE_TEMPLATE/question.yml +26 -0
- package/.github/workflows/main.yaml +40 -0
- package/LICENSE +636 -0
- package/README.md +23 -5
- package/audits/Hexens_Polygon_zkEVM_PUBLIC_27.02.23.pdf +0 -0
- package/audits/Polygon-zkEVM-Public-v1.1-verichains-19-03-2024.pdf +0 -0
- package/audits/zkEVM-ROM-upgrade-1-Spearbit-30-May.pdf +0 -0
- package/audits/zkEVM-ROM-upgrade-2-Spearbit-21-August.pdf +0 -0
- package/audits/zkEVM-engagement-1-Spearbit-27-March.pdf +0 -0
- package/audits/zkEVM-engagement-2-Spearbit-27-March.pdf +0 -0
- package/audits/zkEVM-engagement-3-Spearbit-6-April.pdf +0 -0
- package/counters/README.md +45 -0
- package/counters/counters-executor.js +80 -0
- package/counters/countersConstants.zkasm +370 -0
- package/counters/endIncludes.zkasm +18 -0
- package/counters/initIncludes.zkasm +2 -0
- package/counters/tests/MLOAD32.zkasm +27 -0
- package/counters/tests/MLOADX.zkasm +30 -0
- package/counters/tests/MSTORE32.zkasm +32 -0
- package/counters/tests/MSTOREX.zkasm +36 -0
- package/counters/tests/SHLarith.zkasm +28 -0
- package/counters/tests/SHLarithBit.zkasm +28 -0
- package/counters/tests/SHRarith.zkasm +28 -0
- package/counters/tests/SHRarithBit.zkasm +28 -0
- package/counters/tests/abs.zkasm +29 -0
- package/counters/tests/addBatchHashByteByByte.zkasm +31 -0
- package/counters/tests/computeGasSendCall.zkasm +30 -0
- package/counters/tests/divArith.zkasm +27 -0
- package/counters/tests/expAD.zkasm +30 -0
- package/counters/tests/getLenBits.zkasm +30 -0
- package/counters/tests/getLenBytes.zkasm +32 -0
- package/counters/tests/isEmptyAccount.zkasm +30 -0
- package/counters/tests/mulARITH.zkasm +28 -0
- package/counters/tests/offsetUtil.zkasm +29 -0
- package/counters/tests/opADDMOD.zkasm +28 -0
- package/counters/tests/opAdd.zkasm +27 -0
- package/counters/tests/opBLOCKHASH.zkasm +28 -0
- package/counters/tests/opCALL.zkasm +41 -0
- package/counters/tests/opCALLCODE.zkasm +41 -0
- package/counters/tests/opCALLDATACOPY.zkasm +28 -0
- package/counters/tests/opCALLDATALOAD.zkasm +27 -0
- package/counters/tests/opCODECOPY.zkasm +28 -0
- package/counters/tests/opCREATE.zkasm +35 -0
- package/counters/tests/opCREATE2.zkasm +35 -0
- package/counters/tests/opDELEGATECALL.zkasm +35 -0
- package/counters/tests/opDIV.zkasm +27 -0
- package/counters/tests/opEXP.zkasm +29 -0
- package/counters/tests/opEXTCODECOPY.zkasm +29 -0
- package/counters/tests/opMOD.zkasm +27 -0
- package/counters/tests/opMUL.zkasm +27 -0
- package/counters/tests/opMULMOD.zkasm +28 -0
- package/counters/tests/opRETURN.zkasm +32 -0
- package/counters/tests/opRETURNDATACOPY.zkasm +29 -0
- package/counters/tests/opREVERT.zkasm +32 -0
- package/counters/tests/opSDIV.zkasm +28 -0
- package/counters/tests/opSHA3.zkasm +28 -0
- package/counters/tests/opSIGNEXTEND.zkasm +27 -0
- package/counters/tests/opSMOD.zkasm +28 -0
- package/counters/tests/opSTATICCALL.zkasm +35 -0
- package/counters/tests/opSUB.zkasm +27 -0
- package/counters/tests/saveMem.zkasm +31 -0
- package/docs/opcode-cost-zk-counters.md +315 -0
- package/docs/usage-ecrecover.md +51 -0
- package/index.js +43 -0
- package/main/block-info.zkasm +204 -0
- package/main/constants.zkasm +145 -0
- package/main/ecrecover/addFpEc.zkasm +31 -0
- package/main/ecrecover/checkSqrtFpEc.zkasm +1558 -0
- package/main/ecrecover/constEc.zkasm +13 -0
- package/main/ecrecover/ecrecover.zkasm +280 -0
- package/main/ecrecover/invFnEc.zkasm +44 -0
- package/main/ecrecover/invFpEc.zkasm +45 -0
- package/main/ecrecover/mulFnEc.zkasm +36 -0
- package/main/ecrecover/mulFpEc.zkasm +36 -0
- package/main/ecrecover/mulPointEc.zkasm +311 -0
- package/main/ecrecover/sqFpEc.zkasm +38 -0
- package/main/ecrecover/sqrtFpEc.zkasm +70 -0
- package/main/end.zkasm +4 -0
- package/main/l2-tx-hash.zkasm +159 -0
- package/main/load-change-l2-block-utils.zkasm +11 -0
- package/main/load-change-l2-block.zkasm +28 -0
- package/main/load-tx-rlp-utils.zkasm +72 -0
- package/main/load-tx-rlp.zkasm +431 -0
- package/main/main.zkasm +237 -0
- package/main/map-opcodes.zkasm +274 -0
- package/main/modexp/array_lib/array_add_AGTB.zkasm +123 -0
- package/main/modexp/array_lib/array_add_short.zkasm +85 -0
- package/main/modexp/array_lib/array_div.zkasm +215 -0
- package/main/modexp/array_lib/array_div_long.zkasm +284 -0
- package/main/modexp/array_lib/array_div_short.zkasm +222 -0
- package/main/modexp/array_lib/array_mul.zkasm +97 -0
- package/main/modexp/array_lib/array_mul_long.zkasm +156 -0
- package/main/modexp/array_lib/array_mul_short.zkasm +127 -0
- package/main/modexp/array_lib/array_square.zkasm +246 -0
- package/main/modexp/array_lib/unused/array_add.zkasm +100 -0
- package/main/modexp/array_lib/unused/array_is_odd.zkasm +23 -0
- package/main/modexp/array_lib/unused/array_is_one.zkasm +33 -0
- package/main/modexp/array_lib/unused/array_is_zero.zkasm +34 -0
- package/main/modexp/array_lib/unused/array_sub_AGTB.zkasm +111 -0
- package/main/modexp/array_lib/unused/array_unshift.zkasm +37 -0
- package/main/modexp/array_lib/utils/array_compare.zkasm +82 -0
- package/main/modexp/array_lib/utils/array_trim.zkasm +49 -0
- package/main/modexp/constants.zkasm +5 -0
- package/main/modexp/modexp.zkasm +296 -0
- package/main/modexp/modexp_utils.zkasm +230 -0
- package/main/opcodes/arithmetic.zkasm +357 -0
- package/main/opcodes/block.zkasm +163 -0
- package/main/opcodes/calldata-returndata-code.zkasm +619 -0
- package/main/opcodes/comparison.zkasm +446 -0
- package/main/opcodes/context-information.zkasm +169 -0
- package/main/opcodes/create-terminate-context.zkasm +1011 -0
- package/main/opcodes/crypto.zkasm +96 -0
- package/main/opcodes/flow-control.zkasm +126 -0
- package/main/opcodes/logs.zkasm +193 -0
- package/main/opcodes/stack-operations.zkasm +658 -0
- package/main/opcodes/storage-memory.zkasm +313 -0
- package/main/pairings/BN254/addPointBN254.zkasm +245 -0
- package/main/pairings/BN254/ecAdd.zkasm +312 -0
- package/main/pairings/BN254/ecMul.zkasm +159 -0
- package/main/pairings/BN254/escalarMulBN254.zkasm +155 -0
- package/main/pairings/BN254/lineDiffPointsBN254.zkasm +83 -0
- package/main/pairings/BN254/lineSamePointsBN254.zkasm +96 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm +49 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm +236 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm +444 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm +212 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm +228 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm +64 -0
- package/main/pairings/FP12BN254/frob2Fp12BN254.zkasm +80 -0
- package/main/pairings/FP12BN254/frob3Fp12BN254.zkasm +96 -0
- package/main/pairings/FP12BN254/frobFp12BN254.zkasm +96 -0
- package/main/pairings/FP12BN254/inverseFp12BN254.zkasm +289 -0
- package/main/pairings/FP12BN254/mulFp12BN254.zkasm +408 -0
- package/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm +296 -0
- package/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm +291 -0
- package/main/pairings/FP12BN254/squareFp12BN254.zkasm +376 -0
- package/main/pairings/FP2BN254/addFp2BN254.zkasm +19 -0
- package/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm +20 -0
- package/main/pairings/FP2BN254/invFp2BN254.zkasm +66 -0
- package/main/pairings/FP2BN254/mulFp2BN254.zkasm +19 -0
- package/main/pairings/FP2BN254/squareFp2BN254.zkasm +21 -0
- package/main/pairings/FP2BN254/subFp2BN254.zkasm +19 -0
- package/main/pairings/FP4BN254/squareFp4BN254.zkasm +76 -0
- package/main/pairings/FP6BN254/addFp6BN254.zkasm +59 -0
- package/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm +51 -0
- package/main/pairings/FP6BN254/inverseFp6BN254.zkasm +208 -0
- package/main/pairings/FP6BN254/mulFp6BN254.zkasm +201 -0
- package/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm +65 -0
- package/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm +134 -0
- package/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm +128 -0
- package/main/pairings/FP6BN254/squareFp6BN254.zkasm +147 -0
- package/main/pairings/FP6BN254/subFp6BN254.zkasm +59 -0
- package/main/pairings/FPBN254/addFpBN254.zkasm +29 -0
- package/main/pairings/FPBN254/invFpBN254.zkasm +55 -0
- package/main/pairings/FPBN254/mulFpBN254.zkasm +29 -0
- package/main/pairings/FPBN254/reduceFpBN254.zkasm +25 -0
- package/main/pairings/FPBN254/squareFpBN254.zkasm +31 -0
- package/main/pairings/FPBN254/subFpBN254.zkasm +36 -0
- package/main/pairings/FRBN254/reduceFrBN254.zkasm +25 -0
- package/main/pairings/constants.zkasm +62 -0
- package/main/pairings/ecPairing.zkasm +244 -0
- package/main/pairings/finalExpBN254.zkasm +2095 -0
- package/main/pairings/halfPairingBN254.zkasm +428 -0
- package/main/pairings/loopLengthBN254.zkasm +75 -0
- package/main/pairings/millerLoopBN254.zkasm +741 -0
- package/main/pairings/pairingBN254.zkasm +481 -0
- package/main/pairings/unused/addFp12BN254.zkasm +130 -0
- package/main/pairings/unused/expByXCycloFp12BN254.zkasm +411 -0
- package/main/pairings/unused/expFp12BN254.zkasm +333 -0
- package/main/pairings/unused/subFp12BN254.zkasm +130 -0
- package/main/pairings/unused/xPseudoBinDecompBN254.zkasm +68 -0
- package/main/pairings/utilsTests/expCycloFp12BN254.zkasm +334 -0
- package/main/precompiled/end.zkasm +42 -0
- package/main/precompiled/identity.zkasm +99 -0
- package/main/precompiled/pre-ecAdd.zkasm +84 -0
- package/main/precompiled/pre-ecMul.zkasm +82 -0
- package/main/precompiled/pre-ecPairing.zkasm +72 -0
- package/main/precompiled/pre-ecrecover.zkasm +71 -0
- package/main/precompiled/pre-modexp.zkasm +367 -0
- package/main/precompiled/pre-sha2-256.zkasm +125 -0
- package/main/precompiled/revert-precompiled.zkasm +25 -0
- package/main/precompiled/selector.zkasm +77 -0
- package/main/process-change-l2-block.zkasm +147 -0
- package/main/process-tx.zkasm +587 -0
- package/main/tables/2-exp.zkasm +260 -0
- package/main/touched.zkasm +118 -0
- package/main/utils.zkasm +2335 -0
- package/main/vars.zkasm +117 -0
- package/package.json +62 -3
- package/test/bytes-length.zkasm +39 -0
- package/test/ecrecover.zkasm +538 -0
- package/test/lt4-test.zkasm +38 -0
- package/test/mstorex.zkasm +191 -0
- package/test/opcalldatacopy.ignore.zkasm +331 -0
- package/test/performance/read-push.zkasm +71 -0
- package/test/read-push.zkasm +304 -0
- package/test/testArrayArith.zkasm +1099 -0
- package/test/testArrayUtils.zkasm +335 -0
- package/test/testCycloFp12ArithBN254.zkasm +548 -0
- package/test/testEcAdd.zkasm +252 -0
- package/test/testEcMul.zkasm +231 -0
- package/test/testEcPairing.zkasm +436 -0
- package/test/testFinalExpBn254.zkasm +139 -0
- package/test/testFp12ArithBN254.zkasm +692 -0
- package/test/testFp2ArithBN254.zkasm +185 -0
- package/test/testFp4ArithBN254.zkasm +128 -0
- package/test/testFp6ArithBN254.zkasm +260 -0
- package/test/testFpArithBN254.zkasm +159 -0
- package/test/testFrArithBN254.zkasm +113 -0
- package/test/testHalfPairingBN254.zkasm +285 -0
- package/test/testModExp.zkasm +586 -0
- package/test/testModExpReturn.zkasm +81 -0
- package/test/testPairingBN254.zkasm +463 -0
- package/test/testPointArithBN254.zkasm +270 -0
- package/test/testSHA256.zkasm +27 -0
- package/test/touched-assert.zkasm +59 -0
- package/test/utils-expAD.zkasm +48 -0
- package/test/utils-getLenBytes.zkasm +36 -0
- package/tools/audit-tools/registry-op-checker.js +71 -0
- package/tools/get-not-used-labels.js +31 -0
- package/tools/helpers/helpers.js +47 -0
- package/tools/modexp-utils/README.md +5 -0
- package/tools/modexp-utils/modexp-test-gen.js +168 -0
- package/tools/modexp-utils/modexp-test-int.sage +37 -0
- package/tools/parallel-testing/checker.sh +6 -0
- package/tools/parallel-testing/gen-parallel-tests.js +78 -0
- package/tools/parallel-testing/parallel-tests-sample/sample.test.js +136 -0
- package/tools/run-tests-zkasm.js +83 -0
@@ -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
|