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,619 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* @link [https://www.evm.codes/#35?fork=berlin]
|
4
|
+
* @zk-counters
|
5
|
+
* - 1 binary
|
6
|
+
* - 100 steps
|
7
|
+
* @process-opcode
|
8
|
+
* - stack input: [offset]
|
9
|
+
* - stack output: [data(offset)]
|
10
|
+
*/
|
11
|
+
opCALLDATALOAD:
|
12
|
+
; checks zk-counters
|
13
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
14
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
15
|
+
|
16
|
+
; check stack underflow
|
17
|
+
SP - 1 => SP :JMPN(stackUnderflow)
|
18
|
+
; check out-of-gas
|
19
|
+
GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
|
20
|
+
; return 0 for contract creation
|
21
|
+
$ :MLOAD(isCreateContract), JMPNZ(CALLDATALOADreturn0)
|
22
|
+
$ => A :MLOAD(SP); [offset => A]
|
23
|
+
$ => B :MLOAD(txCalldataLen)
|
24
|
+
; if offset is not lower than calldata length, return 0.
|
25
|
+
; This check is also done at `readFromCalldataOffset` but we do it here with a binary to be sure offset is lower than 32 bits
|
26
|
+
$ :LT,JMPNC(CALLDATALOADreturn0)
|
27
|
+
32 :MSTORE(readXFromCalldataLength)
|
28
|
+
A :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataOffset: result value]
|
29
|
+
$ => A :MLOAD(readXFromCalldataResult)
|
30
|
+
A :MSTORE(SP++), JMP(readCode); [data(offset) => SP]
|
31
|
+
|
32
|
+
CALLDATALOADreturn0:
|
33
|
+
0 :MSTORE(SP++), JMP(readCode); [0 => SP]
|
34
|
+
|
35
|
+
/**
|
36
|
+
* @link [https://www.evm.codes/#36?fork=berlin]
|
37
|
+
* @zk-counters
|
38
|
+
* - 100 steps
|
39
|
+
* @process-opcode
|
40
|
+
* - stack input: []
|
41
|
+
* - stack output: [size]
|
42
|
+
*/
|
43
|
+
opCALLDATASIZE:
|
44
|
+
; checks zk-counters
|
45
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
46
|
+
; check out-of-gas
|
47
|
+
GAS-%GAS_QUICK_STEP => GAS :JMPN(outOfGas)
|
48
|
+
; return 0 for contract creation
|
49
|
+
$ :MLOAD(isCreateContract), JMPNZ(opCALLDATASIZEdep)
|
50
|
+
$ => B :MLOAD(txCalldataLen)
|
51
|
+
B :MSTORE(SP++); [size => SP]
|
52
|
+
; check stack overflow
|
53
|
+
%MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
|
54
|
+
|
55
|
+
opCALLDATASIZEdep:
|
56
|
+
0 :MSTORE(SP++); [0 => SP]
|
57
|
+
; check stack overflow
|
58
|
+
%MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
|
59
|
+
|
60
|
+
VAR GLOBAL auxDestOffset
|
61
|
+
VAR GLOBAL calldataCopyOffset ; current calldatacopy offset
|
62
|
+
VAR GLOBAL auxOffset ; original calldatacopy offset
|
63
|
+
VAR GLOBAL numLastBytes
|
64
|
+
/**
|
65
|
+
* @link [https://www.evm.codes/#37?fork=berlin]
|
66
|
+
* @zk-counters
|
67
|
+
* - 100 steps
|
68
|
+
* - 2 binary
|
69
|
+
* @process-opcode
|
70
|
+
* - stack input: [destOffset, offset, size]
|
71
|
+
* - stack output: []
|
72
|
+
*/
|
73
|
+
opCALLDATACOPY:
|
74
|
+
; checks zk-counters
|
75
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
76
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
77
|
+
; check stack underflow
|
78
|
+
SP - 3 => SP :JMPN(stackUnderflow)
|
79
|
+
$ => E :MLOAD(SP+2); [destOffset => E]
|
80
|
+
$ => B :MLOAD(SP+1); [offset => B]
|
81
|
+
B :MSTORE(auxOffset)
|
82
|
+
B :MSTORE(calldataCopyOffset)
|
83
|
+
$ => C :MLOAD(SP); [size => C]
|
84
|
+
C :MSTORE(numLastBytes)
|
85
|
+
; store lastMemOffset for memory expansion gas cost
|
86
|
+
E :MSTORE(lastMemOffset)
|
87
|
+
; store lastMemLength for memory expansion gas cost
|
88
|
+
C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
|
89
|
+
; check out-of-gas
|
90
|
+
GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
|
91
|
+
;${3*((C+31)/32)}
|
92
|
+
;(C+31)/32 => A
|
93
|
+
C+31 => A
|
94
|
+
:CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
|
95
|
+
GAS - 3*E => GAS :JMPN(outOfGas)
|
96
|
+
; Recover destOffset at E
|
97
|
+
$ => E :MLOAD(lastMemOffset)
|
98
|
+
; Recover size at C
|
99
|
+
$ => C :MLOAD(lastMemLength)
|
100
|
+
; If is a calldataCopy called from codeCopy, copy code from calldata allocation, else if is a create contract, return 0
|
101
|
+
$ :MLOAD(isCalldataCopyFromCodeCopy), JMPNZ(continueOpCalldatacopyFromCodeCopy)
|
102
|
+
$ :MLOAD(isCreateContract), JMPNZ(opCALLDATACOPY0, continueOpCalldatacopy)
|
103
|
+
continueOpCalldatacopyFromCodeCopy:
|
104
|
+
0 :MSTORE(isCalldataCopyFromCodeCopy)
|
105
|
+
continueOpCalldatacopy:
|
106
|
+
B => A
|
107
|
+
$ => B :MLOAD(txCalldataLen); less than 2**32 bytes (calldata). Enforced by memory expansion gas cost & smart contract batchL2DataHash
|
108
|
+
; if offset is not lower than calldata length, return 0
|
109
|
+
; This check is also done at `readFromCalldataOffset` but we do it here with a binary to be sure offset is lower than 32 bits
|
110
|
+
$ :LT,JMPNC(opCALLDATACOPY0)
|
111
|
+
B => A
|
112
|
+
$ => B :MLOAD(auxOffset)
|
113
|
+
B + C => B
|
114
|
+
32 :MSTORE(readXFromCalldataLength)
|
115
|
+
; if txCalldataLen < (offset + size) --> opCALLDATACOPYX0
|
116
|
+
$ :LT,JMPC(opCALLDATACOPYX0)
|
117
|
+
$ => B :MLOAD(auxOffset),JMP(opCALLDATACOPYloop)
|
118
|
+
|
119
|
+
opCALLDATACOPYX0:
|
120
|
+
$ => C :MLOAD(txCalldataLen)
|
121
|
+
$ => B :MLOAD(auxOffset)
|
122
|
+
C - B => C :MSTORE(numLastBytes)
|
123
|
+
|
124
|
+
opCALLDATACOPYloop:
|
125
|
+
; checks zk-counters
|
126
|
+
%MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep)
|
127
|
+
; finish loop
|
128
|
+
C :JMPZ(opCALLDATACOPYcheckLen)
|
129
|
+
; copy last bytes
|
130
|
+
C - 32 :JMPN(opCALLDATACOPYfinal)
|
131
|
+
B + 32 :MSTORE(calldataCopyOffset)
|
132
|
+
B :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
|
133
|
+
$ => A :MLOAD(readXFromCalldataResult)
|
134
|
+
A :MSTORE(bytesToStore)
|
135
|
+
$ => A :MLOAD(lastMemOffset)
|
136
|
+
; checks zk-counters
|
137
|
+
%MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign)
|
138
|
+
; Store 32 bytes from calldata to memory
|
139
|
+
:CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
|
140
|
+
E :MSTORE(auxDestOffset)
|
141
|
+
$ => A :MLOAD(MEM:E)
|
142
|
+
$ => B :MLOAD(MEM:E+1)
|
143
|
+
${memAlignWR_W0(A,mem.bytesToStore,C)} => D ; no trust calculate W0
|
144
|
+
${memAlignWR_W1(B,mem.bytesToStore,C)} => E ; no trust calculate W1
|
145
|
+
$ :MEM_ALIGN_WR,MLOAD(bytesToStore)
|
146
|
+
E => A
|
147
|
+
$ => E :MLOAD(auxDestOffset)
|
148
|
+
D :MSTORE(MEM:E) ; write W0
|
149
|
+
A :MSTORE(MEM:E+1) ; write W1
|
150
|
+
; recover stack pointer
|
151
|
+
$ => C :MLOAD(numLastBytes)
|
152
|
+
C - 32 => C :MSTORE(numLastBytes)
|
153
|
+
$ => E :MLOAD(lastMemOffset)
|
154
|
+
E + 32 => E :MSTORE(lastMemOffset)
|
155
|
+
$ => B :MLOAD(calldataCopyOffset), JMP(opCALLDATACOPYloop)
|
156
|
+
|
157
|
+
opCALLDATACOPYfinal:
|
158
|
+
; copy last bytes
|
159
|
+
C :MSTORE(readXFromCalldataLength)
|
160
|
+
$ => D :MLOAD(calldataCopyOffset)
|
161
|
+
D :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
|
162
|
+
$ => A :MLOAD(readXFromCalldataResult)
|
163
|
+
|
164
|
+
; set bytesToStore with value to use in MSTORE
|
165
|
+
A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
|
166
|
+
:JMP(opCALLDATACOPYcheckLen)
|
167
|
+
|
168
|
+
opCALLDATACOPY0:
|
169
|
+
C :JMPZ(opCALLDATACOPYend)
|
170
|
+
32 - C :JMPN(opCALLDATACOPY320)
|
171
|
+
; set bytesToStore with value to use in MSTORE
|
172
|
+
0 :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
|
173
|
+
:JMP(opCALLDATACOPYend)
|
174
|
+
|
175
|
+
opCALLDATACOPY320:
|
176
|
+
; set bytesToStore with value to use in MSTORE
|
177
|
+
0 :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
|
178
|
+
C - 32 => C :JMP(opCALLDATACOPY0)
|
179
|
+
|
180
|
+
opCALLDATACOPYcheckLen:
|
181
|
+
; fill missing values with 0 (size > calldata)
|
182
|
+
$ => C :MLOAD(lastMemLength)
|
183
|
+
$ => A :MLOAD(txCalldataLen)
|
184
|
+
$ => B :MLOAD(auxOffset)
|
185
|
+
C - A + B => C :JMPN(opCALLDATACOPYend, opCALLDATACOPY0)
|
186
|
+
|
187
|
+
|
188
|
+
opCALLDATACOPYend:
|
189
|
+
:JMP(readCode)
|
190
|
+
|
191
|
+
/**
|
192
|
+
* @link [https://www.evm.codes/#38?fork=berlin]
|
193
|
+
* @zk-counters
|
194
|
+
* - %MAX_CNT_POSEIDON_SLOAD_SSTORE poseidon
|
195
|
+
* - 30 steps
|
196
|
+
* @process-opcode
|
197
|
+
* - stack input: []
|
198
|
+
* - stack output: [size]
|
199
|
+
*/
|
200
|
+
opCODESIZE:
|
201
|
+
; checks zk-counters
|
202
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
|
203
|
+
%MAX_CNT_STEPS - STEP - 30 :JMPN(outOfCountersStep)
|
204
|
+
; check out-of-gas
|
205
|
+
GAS-%GAS_QUICK_STEP => GAS :JMPN(outOfGas)
|
206
|
+
; if is create, get size from calldata
|
207
|
+
$ => A :MLOAD(isCreateContract), JMPNZ(opCODESIZEdep)
|
208
|
+
; else, from storage
|
209
|
+
$ => A :MLOAD(txDestAddr)
|
210
|
+
; set key for smt bytecode length query
|
211
|
+
%SMT_KEY_SC_LENGTH => B
|
212
|
+
0 => C
|
213
|
+
$ => A :SLOAD
|
214
|
+
A :MSTORE(SP++); [size => SP]
|
215
|
+
; check stack overflow
|
216
|
+
%MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
|
217
|
+
|
218
|
+
opCODESIZEdep:
|
219
|
+
$ => B :MLOAD(txCalldataLen)
|
220
|
+
B :MSTORE(SP++); [size => SP]
|
221
|
+
; check stack overflow
|
222
|
+
%MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
|
223
|
+
|
224
|
+
VAR GLOBAL memOffset
|
225
|
+
VAR GLOBAL remainingBytes
|
226
|
+
VAR GLOBAL previousValue
|
227
|
+
VAR GLOBAL codecopyHashId
|
228
|
+
VAR GLOBAL codecopyBytecodeLength
|
229
|
+
VAR GLOBAL memInteger
|
230
|
+
; Flag to check if the calldataCopy function is being called from the codecopy function
|
231
|
+
VAR CTX isCalldataCopyFromCodeCopy
|
232
|
+
/**
|
233
|
+
* @link [https://www.evm.codes/#39?fork=berlin]
|
234
|
+
* @zk-counters
|
235
|
+
* - dynamic binary: 2 * size
|
236
|
+
* - dynamic mem align: 2 * size
|
237
|
+
* - dynamic poseidon: %MAX_CNT_POSEIDON_SLOAD_SSTORE * 2 * size
|
238
|
+
* - dynamic steps: 100 * size
|
239
|
+
* @process-opcode
|
240
|
+
* - stack input: [destOffset, offset, size]
|
241
|
+
* - stack output: []
|
242
|
+
*/
|
243
|
+
opCODECOPY:
|
244
|
+
;Check counters
|
245
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
246
|
+
; if is a create, copy from calldata
|
247
|
+
$ => A :MLOAD(isCreateContract), JMPZ(continueOpCODECOPY)
|
248
|
+
1 :MSTORE(isCalldataCopyFromCodeCopy), JMP(opCALLDATACOPY)
|
249
|
+
continueOpCODECOPY:
|
250
|
+
; check stack underflow
|
251
|
+
SP - 3 => SP :JMPN(stackUnderflow)
|
252
|
+
$ => C :MLOAD(SP+2); [destOffset => C]
|
253
|
+
$ => D :MLOAD(SP+1); [offset => D]
|
254
|
+
$ => E :MLOAD(SP); [size => E]
|
255
|
+
; store lastMemOffset for memory expansion gas cost
|
256
|
+
C :MSTORE(lastMemOffset)
|
257
|
+
; store lastMemLength for memory expansion gas cost
|
258
|
+
; compute memory expansion gas cost
|
259
|
+
E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
|
260
|
+
; check out-of-gas
|
261
|
+
GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
|
262
|
+
;${3*((E+31)/32)}
|
263
|
+
E+31 => A
|
264
|
+
;(E+31)/32
|
265
|
+
A :MSTORE(arithA)
|
266
|
+
32 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
267
|
+
$ => A :MLOAD(arithRes1)
|
268
|
+
; Mul operation with Arith
|
269
|
+
; 3*((E+31)/32)
|
270
|
+
3 :MSTORE(arithA)
|
271
|
+
A :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB]
|
272
|
+
$ => A :MLOAD(arithRes1)
|
273
|
+
|
274
|
+
GAS - A => GAS :JMPN(outOfGas)
|
275
|
+
|
276
|
+
|
277
|
+
; if offset is above data len, length => offset
|
278
|
+
D => A
|
279
|
+
$ => B :MLOAD(bytecodeLength)
|
280
|
+
$ :LT, JMPC(opCODECOPY2)
|
281
|
+
B => A
|
282
|
+
|
283
|
+
opCODECOPY2:
|
284
|
+
; init vars for copy the code
|
285
|
+
A => HASHPOS
|
286
|
+
$ => D :MLOAD(contractHashId)
|
287
|
+
; set hashId to get bytes from
|
288
|
+
D :MSTORE(codecopyHashId)
|
289
|
+
; set contract bytecode length
|
290
|
+
B :MSTORE(codecopyBytecodeLength)
|
291
|
+
C :MSTORE(memOffset)
|
292
|
+
E :MSTORE(remainingBytes)
|
293
|
+
|
294
|
+
opCODECOPYloopInit:
|
295
|
+
; checks zk-counters
|
296
|
+
%MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - E :JMPN(outOfCountersMemalign)
|
297
|
+
|
298
|
+
opCODECOPYloop:
|
299
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
300
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
301
|
+
|
302
|
+
$ => B :MLOAD(remainingBytes), JMPZ(readCode)
|
303
|
+
$ => A :MLOAD(memOffset), CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
|
304
|
+
E :MSTORE(memInteger)
|
305
|
+
; read M0 previous value
|
306
|
+
$ => A :MLOAD(MEM:E)
|
307
|
+
A :MSTORE(previousValue), CALL(opCODECOPYLoadBytes); in:[codecopyBytecodeLength, codecopyHashId] out: [B: readByte]
|
308
|
+
$ => A :MLOAD(previousValue)
|
309
|
+
${memAlignWR8_W0(A,B,C)} => D ; no trust calculate W0
|
310
|
+
B :MEM_ALIGN_WR8 ; only use LSB of B, rest of bytes could be non zero
|
311
|
+
$ => E :MLOAD(memInteger)
|
312
|
+
D :MSTORE(MEM:E) ; write W0
|
313
|
+
; update vars loop
|
314
|
+
$ => B :MLOAD(remainingBytes)
|
315
|
+
B - 1 => B ; decrease 1 byte from length
|
316
|
+
B :MSTORE(remainingBytes)
|
317
|
+
$ => A :MLOAD(memOffset)
|
318
|
+
A + 1 => A ; increment offset to write the next byte
|
319
|
+
A :MSTORE(memOffset), JMP(opCODECOPYloop)
|
320
|
+
|
321
|
+
|
322
|
+
; @info Load 0 if read bytecode position is above bytecode length
|
323
|
+
opCODECOPYLoadBytes:
|
324
|
+
0 => A
|
325
|
+
$ => B :MLOAD(codecopyBytecodeLength)
|
326
|
+
$ :EQ, JMPC(readZero)
|
327
|
+
HASHPOS => A
|
328
|
+
$ :LT, JMPC(readValueBytecode)
|
329
|
+
readZero:
|
330
|
+
0 => B :RETURN
|
331
|
+
readValueBytecode:
|
332
|
+
$ => E :MLOAD(codecopyHashId)
|
333
|
+
; read value to write in memory
|
334
|
+
$ => B :HASHP1(E), RETURN
|
335
|
+
|
336
|
+
/**
|
337
|
+
* @link [https://www.evm.codes/#3B?fork=berlin]
|
338
|
+
* @zk-counters
|
339
|
+
* - 100 steps
|
340
|
+
* - %MAX_CNT_POSEIDON_SLOAD_SSTORE poseidon
|
341
|
+
* @process-opcode
|
342
|
+
* - stack input: [address]
|
343
|
+
* - stack output: [size]
|
344
|
+
*/
|
345
|
+
opEXTCODESIZE:
|
346
|
+
; checks zk-counters
|
347
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
348
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
|
349
|
+
; check stack underflow
|
350
|
+
SP - 1 => SP :JMPN(stackUnderflow)
|
351
|
+
$ => A :MLOAD(SP), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
|
352
|
+
:CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
|
353
|
+
; check out-of-gas
|
354
|
+
GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
|
355
|
+
; set key for smt smart contract length query
|
356
|
+
%SMT_KEY_SC_LENGTH => B
|
357
|
+
0 => C
|
358
|
+
$ => A :SLOAD
|
359
|
+
A :MSTORE(SP++), JMP(readCode); [size => SP]
|
360
|
+
|
361
|
+
; read hash smt
|
362
|
+
; put 32 by 32 bytes in the hashP
|
363
|
+
; assert bytes with hash smt
|
364
|
+
|
365
|
+
; read byte from hashP and copy into memory
|
366
|
+
; over length => set 0's
|
367
|
+
VAR GLOBAL tmpContractHashId
|
368
|
+
VAR GLOBAL tmpContractLength
|
369
|
+
/**
|
370
|
+
* @link [https://www.evm.codes/#51?fork=berlin]
|
371
|
+
* @zk-counters
|
372
|
+
* - dynamic: 100
|
373
|
+
* - dynamic poseidon: %MAX_CNT_POSEIDON_SLOAD_SSTORE + f(size)
|
374
|
+
* @process-opcode
|
375
|
+
* - stack input: [address, destOffset, offset, size]
|
376
|
+
* - stack output: []
|
377
|
+
*/
|
378
|
+
opEXTCODECOPY:
|
379
|
+
; checks zk-counters
|
380
|
+
%MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep)
|
381
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
382
|
+
|
383
|
+
; check stack underflow
|
384
|
+
SP - 4 => SP :JMPN(stackUnderflow)
|
385
|
+
$ => A :MLOAD(SP+3), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
|
386
|
+
:CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
|
387
|
+
|
388
|
+
; check out-of-gas
|
389
|
+
GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
|
390
|
+
:CALL(opEXTCODECOPYLoadBytecode)
|
391
|
+
$ => C :MLOAD(SP+2); [destOffset => C]
|
392
|
+
$ => D :MLOAD(SP+1); [offset => D]
|
393
|
+
$ => E :MLOAD(SP); [size => E]
|
394
|
+
|
395
|
+
; store lastMemOffset for memory expansion gas cost
|
396
|
+
C :MSTORE(lastMemOffset)
|
397
|
+
|
398
|
+
; store lastMemLength for memory expansion gas cost
|
399
|
+
; compute memory expansion gas cost
|
400
|
+
E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
|
401
|
+
|
402
|
+
; check out-of-gas
|
403
|
+
;${3*((E+31)/32)}
|
404
|
+
E+31 => A
|
405
|
+
;(E+31)/32
|
406
|
+
A :MSTORE(arithA)
|
407
|
+
32 :MSTORE(arithB)
|
408
|
+
:CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
409
|
+
$ => A :MLOAD(arithRes1)
|
410
|
+
; Mul operation with Arith
|
411
|
+
; 3*((E+31)/32)
|
412
|
+
3 :MSTORE(arithA)
|
413
|
+
A :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB]
|
414
|
+
$ => A :MLOAD(arithRes1)
|
415
|
+
; check out-of-gas
|
416
|
+
GAS - A => GAS :JMPN(outOfGas)
|
417
|
+
; if offset is above data len, length => offset
|
418
|
+
D => A
|
419
|
+
$ => B :MLOAD(tmpContractLength)
|
420
|
+
$ :LT, JMPC(opEXTCODECOPY2)
|
421
|
+
B => A
|
422
|
+
|
423
|
+
opEXTCODECOPY2:
|
424
|
+
; init vars for copy the code
|
425
|
+
A => HASHPOS
|
426
|
+
$ => D :MLOAD(tmpContractHashId)
|
427
|
+
D :MSTORE(codecopyHashId) ; set hashId to get bytes from
|
428
|
+
B :MSTORE(codecopyBytecodeLength) ; set contract bytecode length
|
429
|
+
C :MSTORE(memOffset)
|
430
|
+
E :MSTORE(remainingBytes), JMP(opCODECOPYloopInit)
|
431
|
+
|
432
|
+
VAR GLOBAL tmpZkPCext
|
433
|
+
opEXTCODECOPYLoadBytecode:
|
434
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
|
435
|
+
; set key for smt smart contract length query
|
436
|
+
%SMT_KEY_SC_LENGTH => B
|
437
|
+
0 => C
|
438
|
+
$ => D :SLOAD
|
439
|
+
; if length is 0, nothing to check
|
440
|
+
; after the implementation of EIP170, the maximum bytecode size is 24.576 bytes, less than 2**32
|
441
|
+
D :MSTORE(tmpContractLength), JMPZ(opEXTCODECOPYCheckHashEnd)
|
442
|
+
|
443
|
+
; check poseidon counters
|
444
|
+
; 56 is the value used by the prover to increment poseidon counters depending on the hash length
|
445
|
+
RR :MSTORE(tmpZkPCext)
|
446
|
+
D + 1 :MSTORE(arithA)
|
447
|
+
56 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
448
|
+
$ => RR :MLOAD(tmpZkPCext)
|
449
|
+
$ => B :MLOAD(arithRes1)
|
450
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE - 1 - B :JMPN(outOfCountersPoseidon)
|
451
|
+
%MAX_CNT_PADDING_PG - CNT_PADDING_PG - 1 - B :JMPN(outOfCountersPadding)
|
452
|
+
|
453
|
+
; set key for smt smart contract code query
|
454
|
+
%SMT_KEY_SC_CODE => B
|
455
|
+
0 => C
|
456
|
+
$ => A :SLOAD
|
457
|
+
|
458
|
+
; get a new hashPId
|
459
|
+
$ => E :MLOAD(nextHashPId)
|
460
|
+
E :MSTORE(tmpContractHashId)
|
461
|
+
E + 1 :MSTORE(nextHashPId)
|
462
|
+
|
463
|
+
; load contract bytecode
|
464
|
+
A :HASHPDIGEST(E)
|
465
|
+
opEXTCODECOPYCheckHashEnd:
|
466
|
+
:RETURN
|
467
|
+
|
468
|
+
/**
|
469
|
+
* @link [https://www.evm.codes/#3D?fork=berlin]
|
470
|
+
* @zk-counters
|
471
|
+
* - 1 binary
|
472
|
+
* - 20 steps
|
473
|
+
* @process-opcode
|
474
|
+
* - stack input: []
|
475
|
+
* - stack output: [size]
|
476
|
+
*/
|
477
|
+
opRETURNDATASIZE:
|
478
|
+
; checks zk-counters
|
479
|
+
%MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
|
480
|
+
%MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
|
481
|
+
|
482
|
+
; check out-of-gas
|
483
|
+
GAS - %GAS_QUICK_STEP => GAS :JMPN(outOfGas)
|
484
|
+
; Load ret data length from last ctx
|
485
|
+
$ => B :MLOAD(retDataCTX)
|
486
|
+
; if no retDataCTX(0), retDataLength = 0
|
487
|
+
0 => A
|
488
|
+
$ :EQ, JMPC(endOpRETURNDATASIZE)
|
489
|
+
B => CTX
|
490
|
+
$ => A :MLOAD(retDataLength)
|
491
|
+
; Restore current context
|
492
|
+
$ => CTX :MLOAD(currentCTX)
|
493
|
+
|
494
|
+
endOpRETURNDATASIZE:
|
495
|
+
A :MSTORE(SP++); [size => SP]
|
496
|
+
; check stack overflow
|
497
|
+
%MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
|
498
|
+
|
499
|
+
/**
|
500
|
+
* @link [https://www.evm.codes/#3E?fork=berlin]
|
501
|
+
* @zk-counters
|
502
|
+
* - 2 binary
|
503
|
+
* - dynamic steps: 400 + 100 * size
|
504
|
+
* @process-opcode
|
505
|
+
* - stack input: [destOffset, offset, size]
|
506
|
+
* - stack output: []
|
507
|
+
*/
|
508
|
+
opRETURNDATACOPY:
|
509
|
+
; checks zk-counters
|
510
|
+
%MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
|
511
|
+
%MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
|
512
|
+
; check stack underflow
|
513
|
+
SP - 3 => SP :JMPN(stackUnderflow)
|
514
|
+
; check out-of-gas
|
515
|
+
GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
|
516
|
+
|
517
|
+
$ => D :MLOAD(SP+2); [destOffset => D]
|
518
|
+
$ => E :MLOAD(SP+1); [offset => E]
|
519
|
+
$ => C :MLOAD(SP); [size => C]
|
520
|
+
; store lastMemOffset for memory expansion gas cost
|
521
|
+
D :MSTORE(lastMemOffset)
|
522
|
+
; store lastMemLength for memory expansion gas cost
|
523
|
+
C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
|
524
|
+
; if retDataCTX is 0, end opcode execution
|
525
|
+
$ => B :MLOAD(retDataCTX)
|
526
|
+
0 => A
|
527
|
+
$ :EQ, JMPC(opRETURNDATACOPYEmpty)
|
528
|
+
|
529
|
+
; Load ret data length from last ctx
|
530
|
+
B => CTX
|
531
|
+
E => B
|
532
|
+
|
533
|
+
$ => A :MLOAD(retDataLength)
|
534
|
+
$ => E :MLOAD(retDataOffset)
|
535
|
+
$ => CTX :MLOAD(currentCTX)
|
536
|
+
; A is retDataLength
|
537
|
+
; B is offset
|
538
|
+
$ :LT, JMPC(outOfGas)
|
539
|
+
; if retDataLength < offset + size -> OOG
|
540
|
+
A - B - C :JMPN(outOfGas)
|
541
|
+
|
542
|
+
; E ret data offset (memory pointer) of last context, B offset in return data that want to retrieve
|
543
|
+
E + B => B ; memory pointer where start to copy memory
|
544
|
+
;${3*((C+31)/32)}
|
545
|
+
C+31 => A
|
546
|
+
;(C+31)/32
|
547
|
+
A :MSTORE(arithA)
|
548
|
+
32 :MSTORE(arithB)
|
549
|
+
:CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
|
550
|
+
$ => A :MLOAD(arithRes1)
|
551
|
+
; Mul operation with Arith
|
552
|
+
; 3*((C+31)/32)
|
553
|
+
3 :MSTORE(arithA)
|
554
|
+
A :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB]
|
555
|
+
$ => A :MLOAD(arithRes1)
|
556
|
+
; check out-of-gas
|
557
|
+
GAS - A => GAS :JMPN(outOfGas)
|
558
|
+
|
559
|
+
opRETURNDATACOPYloop:
|
560
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
561
|
+
C :JMPZ(readCode)
|
562
|
+
C - 32 :JMPN(opRETURNDATACOPYfinal)
|
563
|
+
B => E
|
564
|
+
; Load memory from last context used
|
565
|
+
$ => CTX :MLOAD(retDataCTX), CALL(MLOAD32); in: [E: offset] out: [A: value, E: new offset]
|
566
|
+
; save new offset at B
|
567
|
+
; Save memory to the current context
|
568
|
+
$ => CTX :MLOAD(currentCTX)
|
569
|
+
E => B
|
570
|
+
D => E
|
571
|
+
; set bytesToStore with value to use in MSTORE
|
572
|
+
A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
|
573
|
+
E => D
|
574
|
+
C - 32 => C :JMP(opRETURNDATACOPYloop)
|
575
|
+
|
576
|
+
opRETURNDATACOPYfinal:
|
577
|
+
B => E
|
578
|
+
; Load memory from last context used
|
579
|
+
$ => CTX :MLOAD(retDataCTX), CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset]
|
580
|
+
; save memory to the current context
|
581
|
+
$ => CTX :MLOAD(currentCTX)
|
582
|
+
E => B ; offset retDataCTX
|
583
|
+
D => E ; offset current CTX
|
584
|
+
; set bytesToStore with value to use in MSTORE
|
585
|
+
A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
|
586
|
+
:JMP(readCode)
|
587
|
+
|
588
|
+
opRETURNDATACOPYEmpty:
|
589
|
+
; offset return data + len return data must be 0
|
590
|
+
E => A
|
591
|
+
C => B
|
592
|
+
$ => B :ADD, JMPC(outOfGas)
|
593
|
+
0 => A
|
594
|
+
$ :EQ, JMPC(readCode, outOfGas)
|
595
|
+
|
596
|
+
/**
|
597
|
+
* @link [https://www.evm.codes/#3F?fork=berlin]
|
598
|
+
* @zk-counters
|
599
|
+
* - 100 steps
|
600
|
+
* - %MAX_CNT_POSEIDON_SLOAD_SSTORE poseidon
|
601
|
+
* @process-opcode
|
602
|
+
* - stack input: [address]
|
603
|
+
* - stack output: [hash]
|
604
|
+
*/
|
605
|
+
opEXTCODEHASH:
|
606
|
+
; checks zk-counters
|
607
|
+
%MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
|
608
|
+
%MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
|
609
|
+
; check stack underflow
|
610
|
+
SP - 1 => SP :JMPN(stackUnderflow)
|
611
|
+
$ => A :MLOAD(SP), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
|
612
|
+
:CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
|
613
|
+
; check out-of-gas
|
614
|
+
GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
|
615
|
+
; set key for smt smart contract code hash query
|
616
|
+
%SMT_KEY_SC_CODE => B
|
617
|
+
0 => C
|
618
|
+
$ => A :SLOAD
|
619
|
+
A :MSTORE(SP++), JMP(readCode); [hash => SP]
|