diff --git a/.github/workflows/ci_zkevm.yml b/.github/workflows/ci_zkevm.yml index 5ccdb74f274..ae760de484c 100644 --- a/.github/workflows/ci_zkevm.yml +++ b/.github/workflows/ci_zkevm.yml @@ -98,6 +98,7 @@ jobs: /usr/local/bin/yq -i '.args.data_availability_mode = "rollup"' cdk-erigon-sequencer-params.yml /usr/local/bin/yq -i '.args.cdk_erigon_node_image = "cdk-erigon:local"' cdk-erigon-sequencer-params.yml /usr/local/bin/yq -i '.args.zkevm_bridge_service_image = "hermeznetwork/zkevm-bridge-service:v0.5.0-RC8"' cdk-erigon-sequencer-params.yml + sed -i '/zkevm\.sequencer-initial-fork-id/d' ./templates/cdk-erigon/config-sequencer.yaml - name: Deploy Kurtosis CDK package working-directory: ./kurtosis-cdk @@ -161,6 +162,9 @@ jobs: cd ci_logs kurtosis service logs cdk-v1 cdk-erigon-node-001 --all > cdk-erigon-node-001.log kurtosis service logs cdk-v1 cdk-erigon-sequencer-001 --all > cdk-erigon-sequencer-001.log + kurtosis service logs cdk-v1 zkevm-agglayer-001 --all > zkevm-agglayer-001.log + kurtosis service logs cdk-v1 zkevm-prover-001 --all > zkevm-prover-001.log + kurtosis service logs cdk-v1 zkevm-executor-pless-001 --all > zkevm-executor-pless-001.log - name: Upload logs if: failure() diff --git a/.github/workflows/hourly-env-checker.yml b/.github/workflows/hourly-env-checker.yml new file mode 100644 index 00000000000..e25edadbe71 --- /dev/null +++ b/.github/workflows/hourly-env-checker.yml @@ -0,0 +1,37 @@ +name: Hourly - Envs Checker + +on: + schedule: + - cron: '0 * * * *' # hourly + workflow_dispatch: + +jobs: + test-node: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + include: + - name: "Integration 5 - Legacy" + network: "integration-5" + rpc: "http://34.175.214.161:8505" + - name: "Integration 5 - Erigon RPC" + network: "integration-5" + rpc: "http://34.175.214.161:8500" + - name: "Integration 5 - Erigon Sequencer" + network: "integration-5" + rpc: "http://34.175.214.161:8005" + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.20' + + - name: Build Go application + run: go build -o check_node + + - name: Run tests + run: ./check_node -rpcURL=${{ matrix.rpc }} -nodeName=${{ matrix.name }} \ No newline at end of file diff --git a/.github/workflows/nightly-ansible.yml b/.github/workflows/nightly-ansible.yml index bcac15eca30..a74367a7988 100644 --- a/.github/workflows/nightly-ansible.yml +++ b/.github/workflows/nightly-ansible.yml @@ -8,18 +8,18 @@ on: jobs: build: runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: - include: - - name: "Integration 5" - rpc_url: "http://34.175.214.161:8500" - eth_address: "0x41BB6960a5156aC29d6e9E04273837AD19d6691A" - secret_name: "NETWORK5_PRIVATE_KEY" - log_file: "/tmp/rpc-tests.d/evm-rpc-tests.log" - work_dir: "/tmp/rpc-tests.d" - max_block_size: "25000000" - legacy_flag: "--legacy" - block_interval: "12" + include: + - name: "integration-5" + rpc_url: "http://34.175.214.161:8500" + eth_address: "0x41BB6960a5156aC29d6e9E04273837AD19d6691A" + secret_name: "NETWORK5_PRIVATE_KEY" + - name: "cdk-1" + rpc_url: "http://34.175.214.161:8020" + eth_address: "0x673df8221611aD1f714053b82c4F9E2b0867CcC6" + secret_name: "CDK_1_PRIVATE_KEY" steps: - name: Checkout repository @@ -33,13 +33,8 @@ jobs: RPC_URL: ${{ matrix.rpc_url }} PRIVATE_KEY: ${{ secrets[matrix.secret_name] }} ETH_ADDRESS: ${{ matrix.eth_address }} - LOG_FILE: ${{ matrix.log_file }} - WORK_DIR: ${{ matrix.work_dir }} - MAX_BLOCK_SIZE: ${{ matrix.max_block_size }} - LEGACY_FLAG: ${{ matrix.legacy_flag }} - BLOCK_INTERVAL: ${{ matrix.block_interval }} run: | - cd zk/tests/ansible/evm-rpc-tests && docker-compose up --build + cd zk/tests/ansible/evm-rpc-tests && docker compose build --quiet && docker compose up --exit-code-from ansible - name: Upload logs uses: actions/upload-artifact@v3 diff --git a/.github/workflows/nightly-bridge-erc20.yml b/.github/workflows/nightly-bridge-erc20.yml index 38ee266fb7b..858bbc2de13 100644 --- a/.github/workflows/nightly-bridge-erc20.yml +++ b/.github/workflows/nightly-bridge-erc20.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Clone bridge repository - run: git clone --recurse-submodules -j8 https://github.com/0xPolygonHermez/zkevm-bridge-service.git -b develop bridge + run: git clone --recurse-submodules -j8 https://github.com/0xPolygonHermez/zkevm-bridge-service.git -b feature/test_bridge_messages_real_netowrk bridge - name: Build docker image run: | @@ -35,6 +35,8 @@ jobs: mkdir tmp cat < ./tmp/test.toml TestAddrPrivate= "${{ secrets[matrix.l1_pk_secret_name] }}" + TestL1AddrPrivate="${{ secrets[matrix.l1_pk_secret_name] }}" + TestL2AddrPrivate="${{ secrets[matrix.l1_pk_secret_name] }}" [ConnectionConfig] L1NodeURL="${{ matrix.l1_ep }}" L2NodeURL="${{ matrix.l2_ep }}" diff --git a/.github/workflows/nightly-bridge-msg.yml b/.github/workflows/nightly-bridge-msg.yml new file mode 100644 index 00000000000..7d41b63bde9 --- /dev/null +++ b/.github/workflows/nightly-bridge-msg.yml @@ -0,0 +1,48 @@ +name: Nightly - BridgeMessage + +on: + schedule: + - cron: '0 1 * * *' # run at 1am + workflow_dispatch: + +jobs: + build-and-run: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - profile_name: "network5" + l1_ep: "https://rpc.eu-central-1.gateway.fm/v4/ethereum/non-archival/sepolia" + l2_ep: "http://34.175.214.161:8500" + bridge_ep: "http://34.175.214.161:8085" + l1_pk_secret_name: "L1_SEPOLIA_FUNDED_PRIVATE_KEY" + l2_pk_secret_name: "NETWORK5_PRIVATE_KEY" + bridge_addr: "0xb566BE17B22404BD46F389030ec5592F8ffAde12" + + steps: + - name: Clone bridge repository + run: git clone --recurse-submodules -j8 https://github.com/0xPolygonHermez/zkevm-bridge-service.git -b feature/test_bridge_messages_real_netowrk bridge + + - name: Build docker image + run: | + cd bridge + make build-docker-e2e-real_network + + - name: Run test ERC20 Bridge + run: | + #!/bin/bash + cd bridge + mkdir tmp + cat < ./tmp/test.toml + TestAddrPrivate= "${{ secrets[matrix.l1_pk_secret_name] }}" + TestL1AddrPrivate="${{ secrets[matrix.l1_pk_secret_name] }}" + TestL2AddrPrivate="${{ secrets[matrix.l1_pk_secret_name] }}" + [ConnectionConfig] + L1NodeURL="${{ matrix.l1_ep }}" + L2NodeURL="${{ matrix.l2_ep }}" + BridgeURL="${{ matrix.bridge_ep }}" + L1BridgeAddr="${{ matrix.bridge_addr }}" + L2BridgeAddr="${{ matrix.bridge_addr }}" + EOF + docker run --volume "./tmp/:/config/" --env BRIDGE_TEST_CONFIG_FILE=/config/test.toml bridge-e2e-realnetwork-msg + \ No newline at end of file diff --git a/.github/workflows/nightly-l1-recovery.yml b/.github/workflows/nightly-l1-recovery.yml index 05efbd59412..b521ad14373 100644 --- a/.github/workflows/nightly-l1-recovery.yml +++ b/.github/workflows/nightly-l1-recovery.yml @@ -23,4 +23,4 @@ jobs: - name: Run Docker Compose working-directory: ./zk/tests/nightly-l1-recovery - run: docker compose -f docker-compose-nightly.yml up --build --exit-code-from=block-checker + run: docker compose build --quiet && docker compose up --exit-code-from=block-checker diff --git a/.github/workflows/nightly-node-compare.yml b/.github/workflows/nightly-node-compare.yml index a9848fd466b..b0c45a21754 100644 --- a/.github/workflows/nightly-node-compare.yml +++ b/.github/workflows/nightly-node-compare.yml @@ -8,7 +8,7 @@ on: jobs: compare-blocks: runs-on: ubuntu-latest - + continue-on-error: true strategy: matrix: nodes: diff --git a/.github/workflows/nightly-rpc-batch-compare.yml b/.github/workflows/nightly-rpc-batch-compare.yml new file mode 100644 index 00000000000..e79cc817e01 --- /dev/null +++ b/.github/workflows/nightly-rpc-batch-compare.yml @@ -0,0 +1,33 @@ +name: Nightly - RPC Batch Compare + +on: + schedule: + - cron: '0 23 * * *' + workflow_dispatch: + + +jobs: + run-rpc-batch-compare: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + include: + - name: bali + legacy: "https://rpc.zkevm-internal.com" + erigon: "https://rpc.internal.zkevm-rpc.com" + - name: integration5 + legacy: "http://34.175.214.161:8505" + erigon: "http://34.175.214.161:8500" + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.20' + + - name: Run RPC Batch Compare + run: go run ./zk/debug_tools/rpc-batch-compare -erigon="${{ matrix.erigon }}" -legacy="${{ matrix.legacy }}" -skip=100 -offset=1 diff --git a/Makefile b/Makefile index 49b829110e1..92fecdb4d4b 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ DOCKER := $(shell command -v docker 2> /dev/null) GIT_COMMIT ?= $(shell git rev-list -1 HEAD) GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) -GIT_TAG ?= $(shell git describe --tags '--match=v*' --dirty 2>/dev/null || echo "untagged") +GIT_TAG ?= $(shell git describe --all) ERIGON_USER ?= erigon # if using volume-mounting data dir, then must exist on host OS DOCKER_UID ?= $(shell id -u) diff --git a/README.md b/README.md index 9c322b82eb3..64da5d6fe4a 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,6 @@ Sequencer specific config: - `zkevm.executor-urls`: A csv list of the executor URLs. These will be used in a round robbin fashion by the sequencer - `zkevm.executor-strict`: Defaulted to true, but can be set to false when running the sequencer without verifications (use with extreme caution) - `zkevm.witness-full`: Defaulted to true. Controls whether the full or partial witness is used with the executor. -- `zkevm.sequencer-initial-fork-id`: The fork id to start the network with. Resource Utilisation config: - `zkevm.smt-regenerate-in-memory`: As documented above, allows SMT regeneration in memory if machine has enough RAM, for a speedup in initial sync. diff --git a/cmd/integration/commands/stages_zkevm.go b/cmd/integration/commands/stages_zkevm.go index 49fadc02d93..92332de1d06 100644 --- a/cmd/integration/commands/stages_zkevm.go +++ b/cmd/integration/commands/stages_zkevm.go @@ -103,6 +103,7 @@ func newSyncZk(ctx context.Context, db kv.RwDB) (consensus.Engine, *vm.Config, * nil, nil, nil, + nil, ) } else { stages = stages2.NewDefaultZkStages( diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b628aa63f17..80484a42f57 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -501,11 +501,6 @@ var ( Usage: "Regenerate the SMT in memory (requires a lot of RAM for most chains)", Value: false, } - SequencerInitialForkId = cli.Uint64Flag{ - Name: "zkevm.sequencer-initial-fork-id", - Usage: "The initial fork id to launch the sequencer with", - Value: 8, - } SequencerBlockSealTime = cli.StringFlag{ Name: "zkevm.sequencer-block-seal-time", Usage: "Block seal time. Defaults to 6s", diff --git a/core/vm/evm.go b/core/vm/evm.go index 59f92ecdff9..495ecf7c911 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -61,6 +61,10 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err return evm.interpreter.Run(contract, input, readOnly) } +func runZk(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { + return evm.interpreter.RunZk(contract, input, readOnly) +} + // EVM is the Ethereum Virtual Machine base object and provides // the necessary tools to run a contract on the given state with // the provided context. It should be noted that any error diff --git a/core/vm/evm_zkevm.go b/core/vm/evm_zkevm.go index c4d4a37d284..755833c89b2 100644 --- a/core/vm/evm_zkevm.go +++ b/core/vm/evm_zkevm.go @@ -155,7 +155,7 @@ func (evm *EVM) createZkEvm(caller ContractRef, codeAndHash *codeAndHash, gas ui return nil, address, gas, nil } - ret, err = run(evm, contract, nil, false) + ret, err = runZk(evm, contract, nil, false) // EIP-170: Contract code size limit if err == nil && evm.chainRules.IsSpuriousDragon && len(ret) > params.MaxCodeSize { @@ -336,7 +336,7 @@ func (evm *EVM) call_zkevm(typ OpCode, caller ContractRef, addr libcommon.Addres if typ == STATICCALL { readOnly = true } - ret, err = run(evm, contract, input, readOnly) + ret, err = runZk(evm, contract, input, readOnly) gas = contract.Gas } // When an error was returned by the EVM or when setting the creation code diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index c718fbc007f..c3815b056bb 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -83,6 +83,8 @@ type Interpreter interface { // the return byte-slice and an error if one occurred. Run(contract *Contract, input []byte, static bool) ([]byte, error) + RunZk(contract *Contract, input []byte, static bool) ([]byte, error) + // `Depth` returns the current call stack's depth. Depth() int } diff --git a/core/vm/interpreter_zkevm.go b/core/vm/interpreter_zkevm.go index 5ffdaf160dd..a8a321eb638 100644 --- a/core/vm/interpreter_zkevm.go +++ b/core/vm/interpreter_zkevm.go @@ -2,6 +2,8 @@ package vm import ( "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon-lib/common/math" + "github.com/ledgerwatch/erigon/core/vm/stack" "github.com/ledgerwatch/log/v3" ) @@ -76,3 +78,164 @@ func NewZKEVMInterpreter(evm *EVM, cfg ZkConfig) *EVMInterpreter { jt: jt, } } + +func (in *EVMInterpreter) RunZk(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { + // Don't bother with the execution if there's no code. + if len(contract.Code) == 0 { + return nil, nil + } + + // Increment the call depth which is restricted to 1024 + in.depth++ + defer in.decrementDepth() + + // Make sure the readOnly is only set if we aren't in readOnly yet. + // This makes also sure that the readOnly flag isn't removed for child calls. + if readOnly && !in.readOnly { + in.readOnly = true + defer func() { in.readOnly = false }() + } + + // Reset the previous call's return data. It's unimportant to preserve the old buffer + // as every returning call will return new data anyway. + in.returnData = nil + + var ( + op OpCode // current opcode + mem = pool.Get().(*Memory) + locStack = stack.New() + callContext = &ScopeContext{ + Memory: mem, + Stack: locStack, + Contract: contract, + } + // For optimisation reason we're using uint64 as the program counter. + // It's theoretically possible to go above 2^64. The YP defines the PC + // to be uint256. Practically much less so feasible. + _pc = uint64(0) // program counter + pc = &_pc // program counter + cost uint64 + // copies used by tracer + pcCopy uint64 // needed for the deferred Tracer + gasCopy uint64 // for Tracer to log gas remaining before execution + logged bool // deferred Tracer should ignore already logged steps + res []byte // result of the opcode execution function + ) + + // Don't move this deferrred function, it's placed before the capturestate-deferred method, + // so that it get's executed _after_: the capturestate needs the stacks before + // they are returned to the pools + mem.Reset() + defer pool.Put(mem) + defer stack.ReturnNormalStack(locStack) + contract.Input = input + + // this defer is the only one difference between original erigon Run and RunZk + // it should be placed before the capturestate-deferred method, + // so that it get's executed _after_: the capturestate needs the stacks before + defer func() { + if ret != nil || err == nil { + return + } + + // execute the operation in case of SLOAD | SSTORE + // the actual result of this operation does not matter because it will be reverted anyway, because err != nil + // we implement it this way in order execution to be identical to tracing + if op == SLOAD || op == SSTORE { + // we can safely use pc here instead of pcCopy, + // because pc and pcCopy can be different only if the main loop finishes normally without error + // but is it finishes normally without error then "ret" != nil and the .execute below will never be invoked at all + in.jt[op].execute(pc, in, callContext) + } + }() + + if in.cfg.Debug { + defer func() { + if err != nil { + if !logged { + in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.depth, err) //nolint:errcheck + } else { + in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.depth, err) + } + } + }() + } + + // The Interpreter main run loop (contextual). This loop runs until either an + // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during + // the execution of one of the operations or until the done flag is set by the + // parent context. + steps := 0 + for { + steps++ + if steps%1000 == 0 && in.evm.Cancelled() { + break + } + if in.cfg.Debug { + // Capture pre-execution values for tracing. + logged, pcCopy, gasCopy = false, _pc, contract.Gas + } + // Get the operation from the jump table and validate the stack to ensure there are + // enough stack items available to perform the operation. + op = contract.GetOp(_pc) + operation := in.jt[op] + cost = operation.constantGas // For tracing + // Validate stack + if sLen := locStack.Len(); sLen < operation.numPop { + return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.numPop} + } else if sLen > operation.maxStack { + return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} + } + if !contract.UseGas(cost) { + return nil, ErrOutOfGas + } + if operation.dynamicGas != nil { + // All ops with a dynamic memory usage also has a dynamic gas cost. + var memorySize uint64 + // calculate the new memory size and expand the memory to fit + // the operation + // Memory check needs to be done prior to evaluating the dynamic gas portion, + // to detect calculation overflows + if operation.memorySize != nil { + memSize, overflow := operation.memorySize(locStack) + if overflow { + return nil, ErrGasUintOverflow + } + // memory is expanded in words of 32 bytes. Gas + // is also calculated in words. + if memorySize, overflow = math.SafeMul(ToWordSize(memSize), 32); overflow { + return nil, ErrGasUintOverflow + } + } + // Consume the gas and return an error if not enough gas is available. + // cost is explicitly set so that the capture state defer method can get the proper cost + var dynamicCost uint64 + dynamicCost, err = operation.dynamicGas(in.evm, contract, locStack, mem, memorySize) + cost += dynamicCost // for tracing + if err != nil || !contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } + if memorySize > 0 { + mem.Resize(memorySize) + } + } + if in.cfg.Debug { + in.cfg.Tracer.CaptureState(_pc, op, gasCopy, cost, callContext, in.returnData, in.depth, err) //nolint:errcheck + logged = true + } + // execute the operation + res, err = operation.execute(pc, in, callContext) + + if err != nil { + break + } + _pc++ + } + + if err == errStopToken { + err = nil // clear stop token error + } + + ret = append(ret, res...) + return +} diff --git a/core/vm/mock_vm.go b/core/vm/mock_vm.go index de0a632f454..864628d9090 100644 --- a/core/vm/mock_vm.go +++ b/core/vm/mock_vm.go @@ -62,6 +62,10 @@ func (evm *testVM) Run(_ *Contract, _ []byte, readOnly bool) (ret []byte, err er return } +func (evm *testVM) RunZk(_ *Contract, _ []byte, readOnly bool) (ret []byte, err error) { + return evm.Run(nil, nil, readOnly) +} + func (evm *testVM) Depth() int { return 0 } diff --git a/core/vm/zk_batch_counters.go b/core/vm/zk_batch_counters.go index e43b1be879a..6a30d899ab6 100644 --- a/core/vm/zk_batch_counters.go +++ b/core/vm/zk_batch_counters.go @@ -18,9 +18,10 @@ type BatchCounterCollector struct { blockCount int forkId uint16 unlimitedCounters bool + addonCounters *Counters } -func NewBatchCounterCollector(smtMaxLevel int, forkId uint16, mcpReduction float64, unlimitedCounters bool) *BatchCounterCollector { +func NewBatchCounterCollector(smtMaxLevel int, forkId uint16, mcpReduction float64, unlimitedCounters bool, addonCounters *Counters) *BatchCounterCollector { smtLevels := calculateSmtLevels(smtMaxLevel, 0, mcpReduction) smtLevelsForTransaction := calculateSmtLevels(smtMaxLevel, 32, mcpReduction) return &BatchCounterCollector{ @@ -30,6 +31,7 @@ func NewBatchCounterCollector(smtMaxLevel int, forkId uint16, mcpReduction float blockCount: 0, forkId: forkId, unlimitedCounters: unlimitedCounters, + addonCounters: addonCounters, } } @@ -158,7 +160,16 @@ func (bcc *BatchCounterCollector) NewCounters() Counters { // rlp level counters and execution level counters func (bcc *BatchCounterCollector) CombineCollectors(verifyMerkleProof bool) (Counters, error) { // combine all the counters we have so far + + // if we have external coutners use them, otherwise create new + // this is used when sequencer starts mid batch and we need the already comulated counters combined := bcc.NewCounters() + if bcc.addonCounters != nil { + for k, v := range *bcc.addonCounters { + combined[k].used = v.used + combined[k].remaining -= v.used + } + } if err := bcc.processBatchLevelData(); err != nil { return nil, err @@ -208,3 +219,44 @@ func (bcc *BatchCounterCollector) CombineCollectors(verifyMerkleProof bool) (Cou return combined, nil } + +// CombineCollectors takes the batch level data from all transactions and combines these counters with each transactions' +// rlp level counters and execution level counters +// this one returns the counters as they are so far, without adding processBatchLevelData, processChangeL2Block and decodeChangeL2BlockTx +// used to save batch counter progress without adding the said counters twice +func (bcc *BatchCounterCollector) CombineCollectorsNoChanges(verifyMerkleProof bool) Counters { + // combine all the counters we have so far + + // if we have external coutners use them, otherwise create new + // this is used when sequencer starts mid batch and we need the already comulated counters + combined := bcc.NewCounters() + if bcc.addonCounters != nil { + for k, v := range *bcc.addonCounters { + combined[k].used = v.used + combined[k].remaining -= v.used + } + } + if bcc.l2DataCollector != nil { + for k, v := range bcc.l2DataCollector.Counters() { + combined[k].used += v.used + combined[k].remaining -= v.used + } + } + + for _, tx := range bcc.transactions { + for k, v := range tx.rlpCounters.counters { + combined[k].used += v.used + combined[k].remaining -= v.used + } + for k, v := range tx.executionCounters.counters { + combined[k].used += v.used + combined[k].remaining -= v.used + } + for k, v := range tx.processingCounters.counters { + combined[k].used += v.used + combined[k].remaining -= v.used + } + } + + return combined +} diff --git a/core/vm/zk_counters.go b/core/vm/zk_counters.go index 702a4169e46..d67db2497aa 100644 --- a/core/vm/zk_counters.go +++ b/core/vm/zk_counters.go @@ -69,6 +69,14 @@ func (c *Counter) AsMap() map[string]int { type Counters map[CounterKey]*Counter +func NewCountersFromUsedMap(used map[string]int) *Counters { + res := Counters{} + for k, v := range used { + res[CounterKey(k)] = &Counter{used: v} + } + return &res +} + func (c Counters) UsedAsString() string { res := fmt.Sprintf("[SHA: %v]", c[SHA].used) res += fmt.Sprintf("[A: %v]", c[A].used) diff --git a/core/vm/zk_counters_limits.go b/core/vm/zk_counters_limits.go index f3615f2f926..70b64d6d6be 100644 --- a/core/vm/zk_counters_limits.go +++ b/core/vm/zk_counters_limits.go @@ -7,16 +7,9 @@ import ( ) var ( - defaultTotalSteps = 1 << 23 - defaultCounterLimits = counterLimits{ - totalSteps: defaultTotalSteps, - arith: defaultTotalSteps >> 5, - binary: defaultTotalSteps >> 4, - memAlign: defaultTotalSteps >> 5, - keccaks: int(math.Floor(float64(defaultTotalSteps)/155286) * 44), - padding: int(math.Floor(float64(defaultTotalSteps) / 56)), - poseidon: int(math.Floor(float64(defaultTotalSteps) / 30)), - } + defaultTotalSteps = 1 << 23 + forkId10TotalSteps = 1 << 24 + forkId11TotalSteps = 1 << 25 unlimitedCounters = counterLimits{ totalSteps: math.MaxInt32, @@ -26,6 +19,7 @@ var ( keccaks: math.MaxInt32, padding: math.MaxInt32, poseidon: math.MaxInt32, + sha256: math.MaxInt32, } ) @@ -80,9 +74,33 @@ func createCountrsByLimits(c counterLimits) *Counters { // tp ne used on next forkid counters func getCounterLimits(forkId uint16) *Counters { - if forkId <= uint16(zk_consts.ForkID9Elderberry2) { - return createCountrsByLimits(defaultCounterLimits) + totalSteps := getTotalSteps(forkId) + + counterLimits := counterLimits{ + totalSteps: totalSteps, + arith: totalSteps >> 5, + binary: totalSteps >> 4, + memAlign: totalSteps >> 5, + keccaks: int(math.Floor(float64(totalSteps)/155286) * 44), + padding: int(math.Floor(float64(totalSteps) / 56)), + poseidon: int(math.Floor(float64(totalSteps) / 30)), + sha256: int(math.Floor(float64(totalSteps-1)/31488)) * 7, + } + + return createCountrsByLimits(counterLimits) +} + +func getTotalSteps(forkId uint16) int { + var totalSteps int + + switch forkId { + case uint16(zk_consts.ForkID10): + totalSteps = forkId10TotalSteps + case uint16(zk_consts.ForkID11): + totalSteps = forkId11TotalSteps + default: + totalSteps = defaultTotalSteps } - return createCountrsByLimits(defaultCounterLimits) + return totalSteps } diff --git a/docs/nightly.html b/docs/nightly.html index 8877f429c3e..f17ad5f27d1 100644 --- a/docs/nightly.html +++ b/docs/nightly.html @@ -65,8 +65,11 @@

Nightly GitHub Actions Status