diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..d41a52fa4c2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +**/*_test.go +**/*.a +**/*.dylib +**/*.o +**/*.dSYM + +build +tests/testdata +cmd/prometheus +vendor + +cache.db +.git diff --git a/.github/workflows/ci_zkevm.yml b/.github/workflows/ci_zkevm.yml index ae760de484c..5a423e79ef1 100644 --- a/.github/workflows/ci_zkevm.yml +++ b/.github/workflows/ci_zkevm.yml @@ -138,7 +138,8 @@ jobs: cd bridge mkdir tmp cat < ./tmp/test.toml - TestAddrPrivate= "0x12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625" + TestL1AddrPrivate="0x12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625" + TestL2AddrPrivate="0x12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625" [ConnectionConfig] L1NodeURL="${ETH_RPC_URL}" L2NodeURL="${L2_RPC_URL}" diff --git a/.github/workflows/hourly-env-checker.yml b/.github/workflows/hourly-env-checker.yml index e25edadbe71..3688c027ab4 100644 --- a/.github/workflows/hourly-env-checker.yml +++ b/.github/workflows/hourly-env-checker.yml @@ -6,21 +6,8 @@ on: workflow_dispatch: jobs: - test-node: + run-checks: 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 @@ -30,8 +17,6 @@ jobs: 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 + - name: Run checks + working-directory: ./zk/debug_tools/env-checker + run: go run main.go -envFile envs.json \ No newline at end of file diff --git a/.github/workflows/nightly-bridge-erc20.yml b/.github/workflows/nightly-bridge-erc20.yml index 858bbc2de13..238c9c19c93 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 feature/test_bridge_messages_real_netowrk bridge + run: git clone --recurse-submodules -j8 https://github.com/0xPolygonHermez/zkevm-bridge-service.git -b feature/test_bridge_messages_real_network-v2 bridge - name: Build docker image run: | diff --git a/.github/workflows/nightly-bridge-msg.yml b/.github/workflows/nightly-bridge-msg.yml index 7d41b63bde9..949874e1493 100644 --- a/.github/workflows/nightly-bridge-msg.yml +++ b/.github/workflows/nightly-bridge-msg.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 feature/test_bridge_messages_real_netowrk bridge + run: git clone --recurse-submodules -j8 https://github.com/0xPolygonHermez/zkevm-bridge-service.git -b develop bridge - name: Build docker image run: | diff --git a/cmd/hack/rpc_cache/main.go b/cmd/hack/rpc_cache/main.go index 104ef310d90..91a3746ba39 100644 --- a/cmd/hack/rpc_cache/main.go +++ b/cmd/hack/rpc_cache/main.go @@ -180,7 +180,6 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { } url, _ := url2.Parse(endpoint) - fmt.Println("Fetching from upstream", url.Host) resp, err := http.Post(endpoint, "application/json", bytes.NewBuffer(body)) if err != nil { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 80484a42f57..d8f4033572e 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -646,6 +646,11 @@ var ( Usage: "The URL of the data availability service", Value: "", } + DebugTimers = cli.BoolFlag{ + Name: "debug.timers", + Usage: "Enable debug timers", + Value: false, + } DebugNoSync = cli.BoolFlag{ Name: "debug.no-sync", Usage: "Disable syncing", diff --git a/core/blockchain_zkevm.go b/core/blockchain_zkevm.go index a1a38f39ef4..e73bacc7eea 100644 --- a/core/blockchain_zkevm.go +++ b/core/blockchain_zkevm.go @@ -118,41 +118,8 @@ func ExecuteBlockEphemerallyZk( vmConfig.Tracer = nil } - //[hack]TODO: remove this after bug is fixed - localReceipt := *receipt - if !chainConfig.IsForkID8Elderberry(blockNum) && errors.Is(execResult.Err, vm.ErrUnsupportedPrecompile) { - localReceipt.Status = 1 - } - - // forkid8 the poststate is empty - // forkid8 also fixed the bugs with logs and cumulative gas used - if !chainConfig.IsForkID8Elderberry(blockNum) { - // the stateroot in the transactions that comes from the datastream - // is the one after smart contract writes so it can't be used - // but since pre forkid7 blocks have 1 tx only, we can use the block root - if chainConfig.IsForkID7Etrog(blockNum) { - // receipt root holds the intermediate stateroot after the tx - intermediateState, err := roHermezDb.GetIntermediateTxStateRoot(blockNum, tx.Hash()) - if err != nil { - return nil, err - } - receipt.PostState = intermediateState.Bytes() - } else { - receipt.PostState = header.Root.Bytes() - } - - //[hack] log0 pre forkid8 are not included in the rpc logs - // also pre forkid8 comulative gas used is same as gas used - var fixedLogs types.Logs - for _, l := range receipt.Logs { - if len(l.Topics) == 0 && len(l.Data) == 0 { - continue - } - fixedLogs = append(fixedLogs, l) - } - receipt.Logs = fixedLogs - receipt.CumulativeGasUsed = receipt.GasUsed - } + localReceipt := CreateReceiptForBlockInfoTree(receipt, chainConfig, blockNum, execResult) + ProcessReceiptForBlockExecution(receipt, roHermezDb, chainConfig, blockNum, header, tx) if err != nil { if !vmConfig.StatelessExec { @@ -182,7 +149,7 @@ func ExecuteBlockEphemerallyZk( txInfos = append(txInfos, blockinfo.ExecutedTxInfo{ Tx: tx, - Receipt: &localReceipt, + Receipt: localReceipt, EffectiveGasPrice: effectiveGasPricePercentage, Signer: &txSender, }) @@ -361,3 +328,51 @@ func FinalizeBlockExecutionWithHistoryWrite( return newBlock, newTxs, newReceipt, nil } + +func CreateReceiptForBlockInfoTree(receipt *types.Receipt, chainConfig *chain.Config, blockNum uint64, execResult *ExecutionResult) *types.Receipt { + // [hack]TODO: remove this after bug is fixed + localReceipt := receipt.Clone() + if !chainConfig.IsForkID8Elderberry(blockNum) && errors.Is(execResult.Err, vm.ErrUnsupportedPrecompile) { + localReceipt.Status = 1 + } + + return localReceipt +} + +func ProcessReceiptForBlockExecution(receipt *types.Receipt, roHermezDb state.ReadOnlyHermezDb, chainConfig *chain.Config, blockNum uint64, header *types.Header, tx types.Transaction) error { + // forkid8 the poststate is empty + // forkid8 also fixed the bugs with logs and cumulative gas used + if !chainConfig.IsForkID8Elderberry(blockNum) { + // the stateroot in the transactions that comes from the datastream + // is the one after smart contract writes so it can't be used + // but since pre forkid7 blocks have 1 tx only, we can use the block root + if chainConfig.IsForkID7Etrog(blockNum) { + // receipt root holds the intermediate stateroot after the tx + intermediateState, err := roHermezDb.GetIntermediateTxStateRoot(blockNum, tx.Hash()) + if err != nil { + return err + } + receipt.PostState = intermediateState.Bytes() + } else { + receipt.PostState = header.Root.Bytes() + } + + //[hack] log0 pre forkid8 are not included in the rpc logs + // also pre forkid8 comulative gas used is same as gas used + var fixedLogs types.Logs + for _, l := range receipt.Logs { + if len(l.Topics) == 0 && len(l.Data) == 0 { + continue + } + fixedLogs = append(fixedLogs, l) + } + receipt.Logs = fixedLogs + receipt.CumulativeGasUsed = receipt.GasUsed + } + + for _, l := range receipt.Logs { + l.ApplyPaddingToLogsData(chainConfig.IsForkID8Elderberry(blockNum), chainConfig.IsForkID12Banana(blockNum)) + } + + return nil +} diff --git a/core/types/log_zkevm.go b/core/types/log_zkevm.go new file mode 100644 index 00000000000..7195fab257a --- /dev/null +++ b/core/types/log_zkevm.go @@ -0,0 +1,123 @@ +package types + +import ( + "encoding/hex" + + libcommon "github.com/ledgerwatch/erigon-lib/common" +) + +func (_this *Log) Clone() *Log { + address := libcommon.Address{} + copy(address[:], _this.Address[:]) + + topics := make([]libcommon.Hash, len(_this.Topics)) + for i, t := range _this.Topics { + copy(topics[i][:], t[:]) + } + + data := make([]byte, len(_this.Data)) + copy(data, _this.Data) + + txHash := libcommon.Hash{} + copy(txHash[:], _this.TxHash[:]) + + blockHash := libcommon.Hash{} + copy(blockHash[:], _this.BlockHash[:]) + + return &Log{ + Address: address, + Topics: topics, + Data: data, + BlockNumber: _this.BlockNumber, + TxHash: txHash, + TxIndex: _this.TxIndex, + BlockHash: blockHash, + Index: _this.Index, + Removed: _this.Removed, + } +} + +func (_this *Log) ApplyPaddingToLogsData(isForkId8, isForkId12 bool) { + d := _this.Data + mSize := len(d) + + if isForkId8 && !isForkId12 { + d = applyHexPadBug(d, mSize) + } else { + // [zkEvm] fill 0 at the end + lenMod32 := mSize & 31 + if lenMod32 != 0 { + d = append(d, make([]byte, 32-lenMod32)...) + } + } + + _this.Data = d +} + +func applyHexPadBug(d []byte, msInt int) []byte { + fullMs := msInt + + var dLastWord []byte + if len(d) <= 32 { + dLastWord = append(d, make([]byte, 32-len(d))...) + d = []byte{} + } else { + dLastWord, msInt = getLastWordBytes(d, fullMs) + d = d[:len(d)-len(dLastWord)] + } + + dataHex := hex.EncodeToString(dLastWord) + + dataHex = appendZeros(dataHex, 64) + + for len(dataHex) > 0 && dataHex[0] == '0' { + dataHex = dataHex[1:] + } + + if len(dataHex) < msInt*2 { + dataHex = prependZeros(dataHex, msInt*2) + } + outputStr := takeFirstN(dataHex, msInt*2) + op, _ := hex.DecodeString(outputStr) // there error is always nil here, because we prepare outputStr to have even length + d = append(d, op...) + d = d[:fullMs] + + return d +} + +func getLastWordBytes(data []byte, originalMsInt int) ([]byte, int) { + wordLength := 32 + dataLength := len(data) + + remainderLength := dataLength % wordLength + if remainderLength == 0 { + return data[dataLength-wordLength:], 32 + } + + toRemove := dataLength / wordLength + + msInt := originalMsInt - (toRemove * wordLength) + + return data[dataLength-remainderLength:], msInt +} + +func prependZeros(data string, size int) string { + for len(data) < size { + data = "0" + data + } + return data +} + +func takeFirstN(data string, n int) string { + if len(data) < n { + return data + } + return data[:n] +} + +func appendZeros(dataHex string, targetLength int) string { + for len(dataHex) < targetLength { + dataHex += "0" + } + return dataHex +} diff --git a/core/types/log_zkevm_test.go b/core/types/log_zkevm_test.go new file mode 100644 index 00000000000..e71b4aa9bab --- /dev/null +++ b/core/types/log_zkevm_test.go @@ -0,0 +1,69 @@ +package types + +import ( + "testing" + + "encoding/hex" + + "github.com/ledgerwatch/erigon/common" +) + +func TestApplyHexPadBug(t *testing.T) { + type testScenario struct { + data string + mSize int + expected string + } + + scenarios := map[string]testScenario{ + "cardona-bug-block-3177498": { + data: "0x010203", + mSize: 3, + expected: "102030", + }, + "singleByteHexWithoutBug": { + data: "0x11", + mSize: 1, + expected: "11", + }, + "another": { + data: "0x100000000000000000000000000000000000000000000000000000000000000", + mSize: 1, + expected: "10", + }, + "another1": { + data: "0x1020000000000000000000000000000000000000000000000000000000000", + mSize: 3, + expected: "102000", + }, + "cardona-897048": { + data: "0x0000000000000000000000000000000000000000000000000000000000000001", + mSize: 32, + expected: "0000000000000000000000000000000000000000000000000000000000000001", + }, + "cardona-896194": { + data: "0x0000000000000000000000000000000000000000000000010000000000001e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009af3049dd15616fd627a35563b5282bea5c32e2000000000000000000000000000000000000000000000000000005af3107a4000", + mSize: 160, + expected: "0000000000000000000000000000000000000000000000010000000000001e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009af3049dd15616fd627a35563b5282bea5c32e2000000000000000000000000000000000000000000000000000005af3107a4000", + }, + "cardona-3816917": { + data: "0x0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f", + mSize: 60, + expected: "0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f010230405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0", + }, + } + + for name, scenario := range scenarios { + t.Run(name, func(t *testing.T) { + d := common.FromHex(scenario.data) + + result := applyHexPadBug(d, scenario.mSize) + + resultHex := hex.EncodeToString(result) + + if resultHex != scenario.expected { + t.Errorf("Expected %s but got %s", scenario.expected, resultHex) + } + }) + } +} diff --git a/core/types/receipt_zkevm.go b/core/types/receipt_zkevm.go index 5b9c3759b27..719748e6439 100644 --- a/core/types/receipt_zkevm.go +++ b/core/types/receipt_zkevm.go @@ -21,10 +21,49 @@ import ( "math/big" "github.com/ledgerwatch/erigon-lib/common" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/crypto" ) +func (_this *Receipt) Clone() *Receipt { + postState := make([]byte, len(_this.PostState)) + copy(postState, _this.PostState) + + bloom := Bloom{} + copy(bloom[:], _this.Bloom[:]) + + logs := make(Logs, len(_this.Logs)) + for i, l := range _this.Logs { + logs[i] = l.Clone() + } + + txHash := libcommon.Hash{} + copy(txHash[:], _this.TxHash[:]) + + contractAddress := libcommon.Address{} + copy(contractAddress[:], _this.ContractAddress[:]) + + blockHash := libcommon.Hash{} + copy(blockHash[:], _this.BlockHash[:]) + + BlockNumber := big.NewInt(0).Set(_this.BlockNumber) + + return &Receipt{ + Type: _this.Type, + PostState: postState, + Status: _this.Status, + CumulativeGasUsed: _this.CumulativeGasUsed, + Bloom: bloom, + Logs: logs, + TxHash: txHash, + ContractAddress: contractAddress, + BlockHash: blockHash, + BlockNumber: BlockNumber, + TransactionIndex: _this.TransactionIndex, + } +} + // DeriveFields fills the receipts with their computed fields based on consensus // data and contextual infos like containing block and transactions. func (r Receipts) DeriveFields_zkEvm(forkId8BlockNum uint64, hash common.Hash, number uint64, txs Transactions, senders []common.Address) error { diff --git a/core/vm/instructions_zkevm.go b/core/vm/instructions_zkevm.go index 63b0e86b547..dae26a2b685 100644 --- a/core/vm/instructions_zkevm.go +++ b/core/vm/instructions_zkevm.go @@ -1,7 +1,6 @@ package vm import ( - "encoding/hex" "math/big" "github.com/holiman/uint256" @@ -169,47 +168,6 @@ func makeLog_zkevm(size int, logIndexPerTx bool) executionFunc { d := scope.Memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64())) - forkBlock := uint64(0) - if interpreter.evm.ChainConfig().ForkID88ElderberryBlock != nil { - forkBlock = interpreter.VM.evm.ChainConfig().ForkID88ElderberryBlock.Uint64() - } - blockNo := interpreter.VM.evm.Context.BlockNumber - - // [hack] APPLY BUG ONLY ABOVE FORKID9 - if forkBlock == 0 || blockNo < forkBlock { - // [zkEvm] fill 0 at the end - dataLen := len(d) - lenMod32 := dataLen & 31 - if lenMod32 != 0 { - d = append(d, make([]byte, 32-lenMod32)...) - } - } else { - // bug start - /* - \ / - (o)(o) - / \ - \ / - \ / - \/ - */ - var err error - - d, err = applyHexPadBug(d, int(mSize.Uint64()), blockNo) - if err != nil { - return nil, err - } - /* - \ / - (o)(o) - / \ - \ / - \ / - \/ - */ - // bug end - } - log := types.Log{ Address: scope.Contract.Address(), Topics: topics, @@ -228,86 +186,6 @@ func makeLog_zkevm(size int, logIndexPerTx bool) executionFunc { } } -func applyHexPadBug(d []byte, msInt int, blockNo uint64) ([]byte, error) { - fullMs := msInt - - var dLastWord []byte - if len(d) <= 32 { - dLastWord = append(d, make([]byte, 32-len(d))...) - d = []byte{} - } else { - dLastWord, msInt = getLastWordBytes(d, fullMs) - d = d[:len(d)-len(dLastWord)] - } - - dataHex := hex.EncodeToString(dLastWord) - - dataHex = appendZeros(dataHex, 64) - - for len(dataHex) > 0 && dataHex[0] == '0' { - dataHex = dataHex[1:] - } - - if len(dataHex) < msInt*2 { - dataHex = prependZeros(dataHex, msInt*2) - } - outputStr := takeFirstN(dataHex, msInt*2) - - op, err := hex.DecodeString(outputStr) - if err != nil { - return nil, err - } - d = append(d, op...) - - d = d[:fullMs] - - return d, nil -} - -func min(a, b uint64) uint64 { - if a < b { - return a - } - return b -} - -func getLastWordBytes(data []byte, originalMsInt int) ([]byte, int) { - wordLength := 32 - dataLength := len(data) - - remainderLength := dataLength % wordLength - if remainderLength == 0 { - return data[dataLength-wordLength:], 32 - } - - toRemove := dataLength / wordLength - - msInt := originalMsInt - (toRemove * wordLength) - - return data[dataLength-remainderLength:], msInt -} - -func prependZeros(data string, size int) string { - for len(data) < size { - data = "0" + data - } - return data -} - -func takeFirstN(data string, n int) string { - if len(data) < n { - return data - } - return data[:n] -} - -func appendZeros(dataHex string, targetLength int) string { - for len(dataHex) < targetLength { - dataHex += "0" - } - return dataHex -} - func opCreate_zkevm(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { if interpreter.readOnly { return nil, ErrWriteProtection diff --git a/core/vm/instructions_zkevm_test.go b/core/vm/instructions_zkevm_test.go index 01642e841e1..3f28ade4240 100644 --- a/core/vm/instructions_zkevm_test.go +++ b/core/vm/instructions_zkevm_test.go @@ -5,8 +5,6 @@ import ( "math/big" "testing" - "encoding/hex" - "github.com/holiman/uint256" "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" @@ -18,69 +16,6 @@ import ( "github.com/ledgerwatch/erigon/params" ) -func TestApplyHexPadBug(t *testing.T) { - type testScenario struct { - data string - mSize int - expected string - } - - scenarios := map[string]testScenario{ - "cardona-bug-block-3177498": { - data: "0x010203", - mSize: 3, - expected: "102030", - }, - "singleByteHexWithoutBug": { - data: "0x11", - mSize: 1, - expected: "11", - }, - "another": { - data: "0x100000000000000000000000000000000000000000000000000000000000000", - mSize: 1, - expected: "10", - }, - "another1": { - data: "0x1020000000000000000000000000000000000000000000000000000000000", - mSize: 3, - expected: "102000", - }, - "cardona-897048": { - data: "0x0000000000000000000000000000000000000000000000000000000000000001", - mSize: 32, - expected: "0000000000000000000000000000000000000000000000000000000000000001", - }, - "cardona-896194": { - data: "0x0000000000000000000000000000000000000000000000010000000000001e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009af3049dd15616fd627a35563b5282bea5c32e2000000000000000000000000000000000000000000000000000005af3107a4000", - mSize: 160, - expected: "0000000000000000000000000000000000000000000000010000000000001e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009af3049dd15616fd627a35563b5282bea5c32e2000000000000000000000000000000000000000000000000000005af3107a4000", - }, - "cardona-3816917": { - data: "0x0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f", - mSize: 60, - expected: "0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f010230405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0", - }, - } - - for name, scenario := range scenarios { - t.Run(name, func(t *testing.T) { - d := common.FromHex(scenario.data) - - result, err := applyHexPadBug(d, scenario.mSize, 0) - if err != nil { - t.Fatalf("Error in applyHexPadBug: %v", err) - } - - resultHex := hex.EncodeToString(result) - - if resultHex != scenario.expected { - t.Errorf("Expected %s but got %s", scenario.expected, resultHex) - } - }) - } -} - func TestBlockhashV2(t *testing.T) { gethashFn := func(bn uint64) libcommon.Hash { diff --git a/core/vm/zk_batch_counters.go b/core/vm/zk_batch_counters.go index 6a30d899ab6..5640ef2c93a 100644 --- a/core/vm/zk_batch_counters.go +++ b/core/vm/zk_batch_counters.go @@ -4,7 +4,6 @@ import ( "fmt" "math" - "github.com/ledgerwatch/erigon/zk/tx" "github.com/ledgerwatch/log/v3" ) @@ -89,11 +88,12 @@ func (bcc *BatchCounterCollector) StartNewBlock(verifyMerkleProof bool) (bool, e func (bcc *BatchCounterCollector) processBatchLevelData() error { totalEncodedTxLength := 0 for _, t := range bcc.transactions { - encoded, err := tx.TransactionToL2Data(t.transaction, bcc.forkId, tx.MaxEffectivePercentage) + l2Data, err := t.GetL2DataCache() if err != nil { return err } - totalEncodedTxLength += len(encoded) + + totalEncodedTxLength += len(l2Data) } // simulate adding in the changeL2Block transactions diff --git a/core/vm/zk_counters_limits.go b/core/vm/zk_counters_limits.go index 70b64d6d6be..fa04353c173 100644 --- a/core/vm/zk_counters_limits.go +++ b/core/vm/zk_counters_limits.go @@ -6,6 +6,9 @@ import ( zk_consts "github.com/ledgerwatch/erigon-lib/chain" ) +const stepDeduction = 200 +const baseSafetyPercentage float64 = 0.05 + var ( defaultTotalSteps = 1 << 23 forkId10TotalSteps = 1 << 24 @@ -21,6 +24,11 @@ var ( poseidon: math.MaxInt32, sha256: math.MaxInt32, } + + safetyPercentages = map[uint16]float64{ + uint16(zk_consts.ForkID10): 0.025, + uint16(zk_consts.ForkID11): 0.0125, + } ) type counterLimits struct { @@ -77,14 +85,14 @@ func getCounterLimits(forkId uint16) *Counters { 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, + totalSteps: applyDeduction(forkId, totalSteps), + arith: applyDeduction(forkId, totalSteps>>5), + binary: applyDeduction(forkId, totalSteps>>4), + memAlign: applyDeduction(forkId, totalSteps>>5), + keccaks: applyDeduction(forkId, int(math.Floor(float64(totalSteps)/155286)*44)), + padding: applyDeduction(forkId, int(math.Floor(float64(totalSteps)/56))), + poseidon: applyDeduction(forkId, int(math.Floor(float64(totalSteps)/30))), + sha256: applyDeduction(forkId, int(math.Floor(float64(totalSteps-1)/31488))*7), } return createCountrsByLimits(counterLimits) @@ -102,5 +110,19 @@ func getTotalSteps(forkId uint16) int { totalSteps = defaultTotalSteps } + // we need to remove some steps as these will always be used during batch execution + totalSteps -= stepDeduction + return totalSteps } + +func applyDeduction(fork uint16, input int) int { + deduction, found := safetyPercentages[fork] + if !found { + deduction = baseSafetyPercentage + } + asFloat := float64(input) + reduction := asFloat * deduction + newValue := asFloat - reduction + return int(math.Ceil(newValue)) +} diff --git a/core/vm/zk_transaction_counters.go b/core/vm/zk_transaction_counters.go index 34fd8b0155b..468e4e8fbb1 100644 --- a/core/vm/zk_transaction_counters.go +++ b/core/vm/zk_transaction_counters.go @@ -17,6 +17,7 @@ type TransactionCounter struct { processingCounters *CounterCollector smtLevels int forkId uint16 + l2DataCache []byte } func NewTransactionCounter(transaction types.Transaction, smtMaxLevel int, forkId uint16, mcpReduction float64, shouldCountersBeUnlimited bool) *TransactionCounter { @@ -49,17 +50,36 @@ func NewTransactionCounter(transaction types.Transaction, smtMaxLevel int, forkI } func (tc *TransactionCounter) Clone() *TransactionCounter { + var l2DataCacheCopy []byte + if tc.l2DataCache != nil { + l2DataCacheCopy = make([]byte, len(tc.l2DataCache)) + copy(l2DataCacheCopy, tc.l2DataCache) + } + return &TransactionCounter{ transaction: tc.transaction, rlpCounters: tc.rlpCounters.Clone(), executionCounters: tc.executionCounters.Clone(), processingCounters: tc.processingCounters.Clone(), smtLevels: tc.smtLevels, + l2DataCache: l2DataCacheCopy, + } +} + +func (tc *TransactionCounter) GetL2DataCache() ([]byte, error) { + if tc.l2DataCache == nil { + data, err := tx.TransactionToL2Data(tc.transaction, 8, tx.MaxEffectivePercentage) + if err != nil { + return data, err + } + + tc.l2DataCache = data } + return tc.l2DataCache, nil } func (tc *TransactionCounter) CalculateRlp() error { - raw, err := tx.TransactionToL2Data(tc.transaction, 8, tx.MaxEffectivePercentage) + raw, err := tc.GetL2DataCache() if err != nil { return err } @@ -128,8 +148,7 @@ func (tc *TransactionCounter) CalculateRlp() error { v, r, s := tc.transaction.RawSignatureValues() v = tx.GetDecodedV(tc.transaction, v) - err = collector.ecRecover(v, r, s, false) - if err != nil { + if err := collector.ecRecover(v, r, s, false); err != nil { return err } diff --git a/docs/nightly.html b/docs/nightly.html index f17ad5f27d1..6d0244c7bf8 100644 --- a/docs/nightly.html +++ b/docs/nightly.html @@ -3,7 +3,7 @@ - Nightly GitHub Actions Status + Actions Status -

Nightly GitHub Actions Status

-
+

Actions Status

+ + +
Data Age: Calculating...
+
+ + + + + + + + + + + + + +
WorkflowStatusConclusionRun Time (min)Started AtUpdated AtLink