diff --git a/main/constants.zkasm b/main/constants.zkasm index d66a2570..22cfef6d 100644 --- a/main/constants.zkasm +++ b/main/constants.zkasm @@ -77,6 +77,7 @@ CONST %SHA2_256_GAS = 60 ; sha256 static gas CONST %SHA2_256_WORD_GAS = 12 ; sha256 word gas CONST %KECCAK_GAS = 30 ; Once per KECCAK256 operation. CONST %KECCAK_WORD_GAS = 6 ; Once per word of the KECCAK256 operation's data. +CONST %P256VERIFY_GAS = 3450 ; p256verify gas price CONST %LOG_GAS = 375 ; Per LOG* operation. CONST %LOG_TOPIC_GAS = 375 ; Per LOG topic operation. CONST %JUMP_DEST_GAS = 1 ; Once per JUMPDEST operation. @@ -89,6 +90,7 @@ CONST %CREATE_GAS = 32000 CONST %CREATE_2_GAS = 32000 CONST %SENDALL_GAS = 5000 CONST %LOG_DATA_GAS = 8 + ; sstore CONST %SSTORE_ENTRY_EIP_2200_GAS = 2300 ; Minimum gas required to be present for an SSTORE call, not consumed CONST %SSTORE_SET_EIP_2200_GAS = 20000 ; Once per SSTORE operation from clean zero to non-zero diff --git a/main/precompiled/pre-ecrecover.zkasm b/main/precompiled/pre-ecrecover.zkasm index ba2eb694..44fc52b3 100644 --- a/main/precompiled/pre-ecrecover.zkasm +++ b/main/precompiled/pre-ecrecover.zkasm @@ -9,6 +9,9 @@ * - stack output: [publicAddress] */ funcECRECOVER: + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + ; Move balances if value > 0 just before executing the contract CALL $ => B :MLOAD(txValue) 0 => A diff --git a/main/precompiled/pre-p256verify.zkasm b/main/precompiled/pre-p256verify.zkasm new file mode 100644 index 00000000..92948dbf --- /dev/null +++ b/main/precompiled/pre-p256verify.zkasm @@ -0,0 +1,79 @@ +/** + * @link [https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md] + * @zk-counters + * - dynamic steps: + * - dynamic arith: + * - dynamic binary: + * @process-precompiled + * - stack input: [hash, r, s, x, y] + * - stack output: [success] +*/ + +funcP256VERIFY: + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + + ; Move balances if value > 0 just before executing the contract CALL + $ => B :MLOAD(txValue) + 0 => A + zkPC+2 => RR + $ :LT, JMPC(moveBalances) + + GAS - %P256VERIFY_GAS => GAS :JMPN(outOfGas) ; gas static = 3450 + ; read data stored in calldata + ; read hash [32 bytes] + 32 :MSTORE(readXFromCalldataLength) + 0 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + ; read r [32 bytes] + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => B :MLOAD(readXFromCalldataResult) + ; read s [32 bytes] + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => C :MLOAD(readXFromCalldataResult) + ; read x [32 bytes] + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => D :MLOAD(readXFromCalldataResult) + ; read y [32 bytes] + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => E :MLOAD(readXFromCalldataResult), CALL(p256verify) ;in: [A: hash, B: r, C: s, D: x, E: y], out: [A: result, B: result_code] + B :JMPNZ(endP256VERIFYFail) + A :JMPZ(preEndP256VERIFY) + + ; write result p256verify into memory + 0 => E + A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + + ; prepare return data + 0 :MSTORE(retDataOffset) + 32 :MSTORE(retDataLength) + $ => A :MLOAD(originCTX), JMPZ(handleGas) + ; set retDataCTX + $ => B :MLOAD(currentCTX) + A => CTX + B :MSTORE(retDataCTX) + B => CTX + + ; write result p256verify into previous context memory + $ => C :MLOAD(retCallLength), JMPZ(preEndP256VERIFY) + $ => E :MLOAD(retCallOffset) + + ; p256verify result is in bytesToStore + C - 32 :JMPN(continueP256VERIFY) + 32 => C + +continueP256VERIFY: + $ => CTX :MLOAD(originCTX), CALL(MSTOREX) ; in: [bytesToStore, E: offset, C: length] out: [E: new offset] + :JMP(endP256VERIFY) + +endP256VERIFYFail: + $ => A :MLOAD(originCTX), JMPZ(handleGas) + A => CTX + 0 :MSTORE(retDataCTX) + CTX :MSTORE(currentCTX), JMP(preEnd) + +preEndP256VERIFY: + $ => CTX :MLOAD(originCTX) + +endP256VERIFY: + CTX :MSTORE(currentCTX), JMP(preEnd) diff --git a/main/precompiled/selector.zkasm b/main/precompiled/selector.zkasm index c81a55e0..9f36292b 100644 --- a/main/precompiled/selector.zkasm +++ b/main/precompiled/selector.zkasm @@ -6,6 +6,8 @@ INCLUDE "pre-ecMul.zkasm" INCLUDE "pre-ecPairing.zkasm" INCLUDE "pre-modexp.zkasm" INCLUDE "pre-sha2-256.zkasm" +INCLUDE "pre-p256verify.zkasm" +INCLUDE "../p256verify/p256verify.zkasm" INCLUDE "../pairings/constants.zkasm" INCLUDE "../pairings/BN254/ecAdd.zkasm" INCLUDE "../pairings/BN254/ecMul.zkasm" @@ -74,4 +76,7 @@ selectorPrecompiled: A - 7 :JMPN(funcEcAdd) A - 8 :JMPN(funcEcMul) A - 9 :JMPN(funcEcPairing) - A - 10 :JMPN(revertPrecompiled) ;:JMPN(BLAKE2F) \ No newline at end of file + A - 10 :JMPN(revertPrecompiled) ;:JMPN(BLAKE2F) + +selectorPrecompiledP256Verify: + :JMP(funcP256VERIFY) \ No newline at end of file diff --git a/main/process-tx.zkasm b/main/process-tx.zkasm index 696eaa44..761a7292 100644 --- a/main/process-tx.zkasm +++ b/main/process-tx.zkasm @@ -201,7 +201,6 @@ endCalldataIntrinsicGas: ;; F - Check transaction type ;;;;;;;;;;;;;;;;;; txType: - ; Compute deployment address if create contract operation $ => A :MLOAD(isCreateContract), JMPNZ(getContractAddress) $ => A :MLOAD(txDestAddr) @@ -210,8 +209,10 @@ txType: ; Check zero address since zero address is not a precompiled contract 0 => B $ :EQ, JMPC(callContract) + 0x100 => B + $ :EQ, JMPC(selectorPrecompiledP256Verify) 10 => B - $ :LT,JMPC(selectorPrecompiled, callContract) + $ :LT, JMPC(selectorPrecompiled, callContract) ;;;;;;;;;;;;;;;;;; ;; F.2 - Deploy contract diff --git a/main/touched.zkasm b/main/touched.zkasm index 32b82c67..b7c42794 100644 --- a/main/touched.zkasm +++ b/main/touched.zkasm @@ -36,6 +36,8 @@ isColdAddress: ; if address is a precompiled considered as warm address 10 => B $ :LT, JMPC(finishColdPrecompiled) + 0x100 => B + $ :EQ, JMPC(finishColdPrecompiled) checkWarmed: ; save current state root & load touched root diff --git a/package.json b/package.json index bf7e1503..87f83a2c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test:zkasm": "node tools/run-tests-zkasm.js ./test --helpers ../main/helper.js", "eslint": "npx eslint tools/**.js && npx eslint counters/counters-executor.js", "eslint:fix": "npx eslint tools/**.js --fix && npx eslint counters/counters-executor.js --fix", - "test:gen": "node tools/parallel-testing/gen-parallel-tests.js", + "test:gen": "node tools/parallel-testing/gen-parallel-tests.js --skipVCounters", "test:start": "npx mocha --jobs $NUM_CPUS --timeout 0 --max-old-space-size=8192 --parallel \"tools/parallel-testing/parallel-tests/*.test.js\"", "report:free-inputs": "node tools/audit-tools/free-inputs-checker.js", "report:registry-op": "node tools/audit-tools/registry-op-checker.js" @@ -44,8 +44,8 @@ }, "devDependencies": { "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v8.0.0-fork.12", - "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs#develop-durian", - "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#feature/fork-13", + "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs#fix/secp256r1-dbl", + "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#feature/add-rip7212", "chai": "^4.3.6", "chalk": "^3.0.0", "eslint": "^8.25.0",