From ff2d6d0284cf6ee5f464c3221df97ecfab471cb2 Mon Sep 17 00:00:00 2001 From: galaio <12880651+galaio@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:58:56 +0800 Subject: [PATCH] txdag: support write & read TxDAG from file; (#9) txdag: record txdag metrics; txdag: opt txdag flag name; Co-authored-by: galaio --- cmd/geth/main.go | 2 + cmd/utils/flags.go | 21 ++++++ core/blockchain.go | 123 ++++++++++++++++++++++++++++--- core/blockchain_insert.go | 2 +- core/blockchain_test.go | 32 ++++++++ core/parallel_state_processor.go | 30 ++++++-- core/state/statedb.go | 11 +++ core/state_processor.go | 26 ++++--- core/types/dag.go | 5 +- core/types/dag_test.go | 3 +- core/types/mvstates.go | 5 +- eth/backend.go | 3 + eth/ethconfig/config.go | 2 + miner/miner.go | 3 +- miner/worker.go | 17 +++-- 15 files changed, 244 insertions(+), 41 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 6ed003061c..23fe516b9b 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -171,6 +171,8 @@ var ( utils.RollupSuperchainUpgradesFlag, utils.ParallelTxFlag, utils.ParallelTxNumFlag, + utils.ParallelTxDAGFlag, + utils.ParallelTxDAGFileFlag, configFileFlag, utils.LogDebugFlag, utils.LogBacktraceAtFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 2974662beb..616ea4ea15 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1106,6 +1106,19 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Category: flags.VMCategory, } + ParallelTxDAGFlag = &cli.BoolFlag{ + Name: "parallel.txdag", + Usage: "Enable the experimental parallel TxDAG generation, only valid in full sync mode (default = false)", + Category: flags.VMCategory, + } + + ParallelTxDAGFileFlag = &cli.StringFlag{ + Name: "parallel.txdagfile", + Usage: "It indicates the TxDAG file path", + Value: "./parallel-txdag-output.csv", + Category: flags.VMCategory, + } + VMOpcodeOptimizeFlag = &cli.BoolFlag{ Name: "vm.opcode.optimize", Usage: "enable opcode optimization", @@ -2017,6 +2030,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.ParallelTxNum = parallelNum } + if ctx.IsSet(ParallelTxDAGFlag.Name) { + cfg.EnableParallelTxDAG = ctx.Bool(ParallelTxDAGFlag.Name) + } + + if ctx.IsSet(ParallelTxDAGFileFlag.Name) { + cfg.ParallelTxDAGFile = ctx.String(ParallelTxDAGFileFlag.Name) + } + if ctx.IsSet(VMOpcodeOptimizeFlag.Name) { cfg.EnableOpcodeOptimizing = ctx.Bool(VMOpcodeOptimizeFlag.Name) if cfg.EnableOpcodeOptimizing { diff --git a/core/blockchain.go b/core/blockchain.go index 31511af72d..f9af61b269 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -18,11 +18,16 @@ package core import ( + "bufio" + "bytes" + "encoding/hex" "errors" "fmt" "io" "math/big" + "os" "runtime" + "strconv" "strings" "sync" "sync/atomic" @@ -91,6 +96,9 @@ var ( triedbCommitExternalTimer = metrics.NewRegisteredTimer("chain/triedb/commit/external", nil) innerExecutionTimer = metrics.NewRegisteredTimer("chain/inner/execution", nil) + txDAGGenerateTimer = metrics.NewRegisteredTimer("chain/block/txdag/gen", nil) + txDAGDispatchTimer = metrics.NewRegisteredTimer("chain/block/txdag/dispatch", nil) + blockGasUsedGauge = metrics.NewRegisteredGauge("chain/block/gas/used", nil) mgaspsGauge = metrics.NewRegisteredGauge("chain/mgas/ps", nil) @@ -297,6 +305,9 @@ type BlockChain struct { forker *ForkChoice vmConfig vm.Config parallelExecution bool + enableTxDAG bool + txDAGWriteCh chan TxDAGOutputItem + txDAGMapping map[uint64]types.TxDAG } // NewBlockChain returns a fully initialised block chain using information @@ -1881,16 +1892,16 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) return it.index, err } - // TODO(galaio): use txDAG in some accelerate scenarios. - if len(block.TxDAG()) > 0 { - txDAG, err := types.DecodeTxDAG(block.TxDAG()) - if err != nil { - return it.index, err - } - log.Info("Insert chain", "block", block.NumberU64(), "txDAG", txDAG.Type()) - } + // TODO(galaio): use txDAG in some accelerate scenarios, like state pre-fetcher. + //if bc.enableTxDAG && len(block.TxDAG()) > 0 { + // txDAG, err := types.DecodeTxDAG(block.TxDAG()) + // if err != nil { + // return it.index, err + // } + // log.Info("Insert chain", "block", block.NumberU64(), "txDAG", txDAG) + //} // TODO(galaio): need hardfork - if bc.chainConfig.Optimism != nil && len(block.Header().Extra) > 0 { + if bc.enableTxDAG && bc.chainConfig.Optimism != nil && len(block.Header().Extra) > 0 { txDAG, err := types.DecodeTxDAG(block.Header().Extra) if err != nil { return it.index, err @@ -1952,8 +1963,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation) accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation) storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete(in validation) - blockExecutionTimer.Update(ptime) // The time spent on block execution - blockValidationTimer.Update(vtime) // The time spent on block validation + txDAGGenerateTimer.Update(statedb.TxDAGGenerate) + blockExecutionTimer.Update(ptime) // The time spent on block execution + blockValidationTimer.Update(vtime) // The time spent on block validation innerExecutionTimer.Update(DebugInnerExecutionDuration) @@ -2689,3 +2701,92 @@ func createDelFn(bc *BlockChain) func(db ethdb.KeyValueWriter, hash common.Hash, func (bc *BlockChain) HeaderChainForceSetHead(headNumber uint64) { bc.hc.SetHead(headNumber, nil, createDelFn(bc)) } + +func (bc *BlockChain) TxDAGEnabled() bool { + return bc.enableTxDAG +} + +func (bc *BlockChain) EnableTxDAGGeneration(output string) { + bc.enableTxDAG = true + if len(output) == 0 { + return + } + // read TxDAG file, and cache in mem + var err error + bc.txDAGMapping, err = readTxDAGMappingFromFile(output) + if err != nil { + log.Error("read TxDAG err", err) + } + + // write handler + bc.txDAGWriteCh = make(chan TxDAGOutputItem, 10000) + go func() { + writeHandle, err := os.OpenFile(output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) + if err != nil { + log.Error("OpenFile when open the txDAG output file", "file", output) + return + } + defer writeHandle.Close() + for { + select { + case <-bc.quit: + return + case item := <-bc.txDAGWriteCh: + if err := writeTxDAGToFile(writeHandle, item); err != nil { + log.Error("encode TxDAG err in OutputHandler", "err", err) + continue + } + } + } + }() +} + +type TxDAGOutputItem struct { + blockNumber uint64 + txDAG types.TxDAG +} + +func writeTxDAGToFile(writeHandle *os.File, item TxDAGOutputItem) error { + var buf bytes.Buffer + buf.WriteString(strconv.FormatUint(item.blockNumber, 10)) + buf.WriteByte(',') + enc, err := types.EncodeTxDAG(item.txDAG) + if err != nil { + return err + } + buf.WriteString(hex.EncodeToString(enc)) + buf.WriteByte('\n') + _, err = writeHandle.Write(buf.Bytes()) + return err +} + +func readTxDAGMappingFromFile(output string) (map[uint64]types.TxDAG, error) { + file, err := os.Open(output) + if err != nil { + return nil, err + } + defer file.Close() + + mapping := make(map[uint64]types.TxDAG) + scanner := bufio.NewScanner(file) + for scanner.Scan() { + tokens := strings.Split(scanner.Text(), ",") + if len(tokens) != 2 { + return nil, errors.New("txDAG output contain wrong size") + } + num, err := strconv.Atoi(tokens[0]) + if err != nil { + return nil, err + } + enc, err := hex.DecodeString(tokens[1]) + if err != nil { + return nil, err + } + txDAG, err := types.DecodeTxDAG(enc) + if err != nil { + return nil, err + } + mapping[uint64(num)] = txDAG + } + return mapping, nil +} diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index 82a480d0be..2667323c1e 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -60,7 +60,7 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn "blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000, "elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed), } - mgaspsGauge.Update(int64(st.usedGas)*1000/int64(elapsed)) + mgaspsGauge.Update(int64(st.usedGas) * 1000 / int64(elapsed)) if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 9f799181d9..b4d5a1381b 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -22,10 +22,13 @@ import ( "math/big" "math/rand" "os" + "path/filepath" "sync" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" @@ -4717,3 +4720,32 @@ func TestEIP3651(t *testing.T) { t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) } } + +func TestTxDAGFile_ReadWrite(t *testing.T) { + path := filepath.Join(os.TempDir(), "test.csv") + except := map[uint64]types.TxDAG{ + 0: types.NewEmptyTxDAG(), + 1: makeEmptyPlainTxDAG(1), + 2: makeEmptyPlainTxDAG(2), + } + writeFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) + require.NoError(t, err) + for num, dag := range except { + require.NoError(t, writeTxDAGToFile(writeFile, TxDAGOutputItem{blockNumber: num, txDAG: dag})) + } + writeFile.Close() + + actual, err := readTxDAGMappingFromFile(path) + require.NoError(t, err) + for num, dag := range except { + require.Equal(t, dag, actual[num]) + } +} + +func makeEmptyPlainTxDAG(cnt int) *types.PlainTxDAG { + dag := types.NewPlainTxDAG(cnt) + for i := range dag.TxDeps { + dag.TxDeps[i].TxIndexes = make([]uint64, 0) + } + return dag +} diff --git a/core/parallel_state_processor.go b/core/parallel_state_processor.go index 9fe363f151..7cbfe4cad9 100644 --- a/core/parallel_state_processor.go +++ b/core/parallel_state_processor.go @@ -3,6 +3,11 @@ package core import ( "errors" "fmt" + "runtime" + "sync" + "sync/atomic" + "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" @@ -11,10 +16,8 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" - "runtime" - "sync" - "sync/atomic" ) const ( @@ -189,6 +192,11 @@ func (p *ParallelStateProcessor) doStaticDispatchV2(txReqs []*ParallelTxRequest, return } + if metrics.EnabledExpensive { + defer func(start time.Time) { + txDAGDispatchTimer.Update(time.Since(start)) + }(time.Now()) + } // resolve isolate execution paths from TxDAG, it indicates the tx dispatch paths := types.MergeTxDAGExecutionPaths(txDAG) log.Info("doStaticDispatchV2 merge parallel execution paths", "slots", len(p.slotState), "paths", len(paths)) @@ -735,14 +743,20 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat txDAG types.TxDAG err error ) - if len(block.TxDAG()) != 0 { - txDAG, err = types.DecodeTxDAG(block.TxDAG()) - if err != nil { - return nil, nil, 0, err + if p.bc.enableTxDAG { + if len(block.TxDAG()) != 0 { + txDAG, err = types.DecodeTxDAG(block.TxDAG()) + if err != nil { + return nil, nil, 0, err + } + } + // load cache txDAG from file + if txDAG == nil && len(p.bc.txDAGMapping) > 0 { + txDAG = p.bc.txDAGMapping[block.NumberU64()] } } // TODO(galaio): need hardfork - if p.bc.chainConfig.Optimism != nil && len(block.Header().Extra) > 0 { + if p.bc.enableTxDAG && p.bc.chainConfig.Optimism != nil && len(block.Header().Extra) > 0 { txDAG, err = types.DecodeTxDAG(block.Header().Extra) if err != nil { return nil, nil, 0, err diff --git a/core/state/statedb.go b/core/state/statedb.go index 49d168175d..9f63253865 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -271,6 +271,7 @@ type StateDB struct { TrieDBCommits time.Duration TrieCommits time.Duration CodeCommits time.Duration + TxDAGGenerate time.Duration AccountUpdated int StorageUpdated int @@ -2419,6 +2420,11 @@ func (s *StateDB) FinaliseRWSet() error { if s.mvStates == nil || s.rwSet == nil { return nil } + if metrics.EnabledExpensive { + defer func(start time.Time) { + s.TxDAGGenerate += time.Since(start) + }(time.Now()) + } ver := types.StateVersion{ TxIndex: s.txIndex, } @@ -2486,6 +2492,11 @@ func (s *StateDB) MVStates2TxDAG() (types.TxDAG, map[int]*types.ExeStat) { if s.mvStates == nil { return types.NewEmptyTxDAG(), nil } + if metrics.EnabledExpensive { + defer func(start time.Time) { + s.TxDAGGenerate += time.Since(start) + }(time.Now()) + } return s.mvStates.ResolveTxDAG(), s.mvStates.Stats() } diff --git a/core/state_processor.go b/core/state_processor.go index 85441dbc6b..632e3df5ff 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -29,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" ) @@ -91,7 +90,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) } statedb.MarkFullProcessed() - statedb.ResetMVStates(len(block.Transactions())) + if p.bc.enableTxDAG { + statedb.ResetMVStates(len(block.Transactions())) + } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { statedb.BeginTxStat(i) @@ -121,13 +122,20 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals) - // TODO(galaio): append dag into block body, TxDAGPerformance will print metrics when profile is enabled - // compare input TxDAG when it enable in consensus - dag, exrStats := statedb.MVStates2TxDAG() - types.EvaluateTxDAGPerformance(dag, exrStats) - //fmt.Print(types.EvaluateTxDAGPerformance(dag, exrStats)) - log.Info("Process result", "block", block.NumberU64(), "txDAG", dag) - + if p.bc.enableTxDAG { + // TODO(galaio): append dag into block body, TxDAGPerformance will print metrics when profile is enabled + // compare input TxDAG when it enable in consensus + dag, exrStats := statedb.MVStates2TxDAG() + fmt.Print(types.EvaluateTxDAGPerformance(dag, exrStats)) + //log.Info("Process result", "block", block.NumberU64(), "txDAG", dag) + // try write txDAG into file + if p.bc.txDAGWriteCh != nil && dag != nil { + p.bc.txDAGWriteCh <- TxDAGOutputItem{ + blockNumber: block.NumberU64(), + txDAG: dag, + } + } + } return receipts, allLogs, *usedGas, nil } diff --git a/core/types/dag.go b/core/types/dag.go index b407c2bc77..dbd7cf9ea8 100644 --- a/core/types/dag.go +++ b/core/types/dag.go @@ -4,11 +4,12 @@ import ( "bytes" "errors" "fmt" + "strings" + "time" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" "golang.org/x/exp/slices" - "strings" - "time" ) // TxDAGType Used to extend TxDAG and customize a new DAG structure diff --git a/core/types/dag_test.go b/core/types/dag_test.go index bf12324246..bfda2de6e3 100644 --- a/core/types/dag_test.go +++ b/core/types/dag_test.go @@ -1,10 +1,11 @@ package types import ( - "github.com/cometbft/cometbft/libs/rand" "testing" "time" + "github.com/cometbft/cometbft/libs/rand" + "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/stretchr/testify/require" diff --git a/core/types/mvstates.go b/core/types/mvstates.go index 4db7586727..2584807467 100644 --- a/core/types/mvstates.go +++ b/core/types/mvstates.go @@ -4,12 +4,13 @@ import ( "encoding/hex" "errors" "fmt" + "strings" + "sync" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/holiman/uint256" "golang.org/x/exp/slices" - "strings" - "sync" ) const ( diff --git a/eth/backend.go b/eth/backend.go index a8ed4fe836..3fb51c4afb 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -272,6 +272,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, err } + if config.EnableParallelTxDAG { + eth.blockchain.EnableTxDAGGeneration(config.ParallelTxDAGFile) + } if chainConfig := eth.blockchain.Config(); chainConfig.Optimism != nil { // config.Genesis.Config.ChainID cannot be used because it's based on CLI flags only, thus default to mainnet L1 config.NetworkId = chainConfig.ChainID.Uint64() // optimism defaults eth network ID to chain ID eth.networkID = config.NetworkId diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 77080f5870..3f9624dc7c 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -221,6 +221,8 @@ type Config struct { ParallelTxMode bool // Whether to execute transaction in parallel mode when do full sync ParallelTxNum int // Number of slot for transaction execution EnableOpcodeOptimizing bool + EnableParallelTxDAG bool + ParallelTxDAGFile string } // CreateConsensusEngine creates a consensus engine for the given chain config. diff --git a/miner/miner.go b/miner/miner.go index b65b226238..8dbe58c45e 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -62,7 +62,8 @@ var ( snapshotAccountReadTimer = metrics.NewRegisteredTimer("miner/snapshot/account/reads", nil) snapshotStorageReadTimer = metrics.NewRegisteredTimer("miner/snapshot/storage/reads", nil) - waitPayloadTimer = metrics.NewRegisteredTimer("miner/wait/payload", nil) + waitPayloadTimer = metrics.NewRegisteredTimer("miner/wait/payload", nil) + txDAGGenerateTimer = metrics.NewRegisteredTimer("miner/txdag/gen", nil) isBuildBlockInterruptCounter = metrics.NewRegisteredCounter("miner/build/interrupt", nil) ) diff --git a/miner/worker.go b/miner/worker.go index d0a1a31b64..c375ae77b9 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1180,6 +1180,7 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err w.mu.RUnlock() start := time.Now() +<<<<<<< HEAD // Retrieve the pending transactions pre-filtered by the 1559/4844 dynamic fees filter := txpool.PendingFilter{ @@ -1197,6 +1198,10 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err filter.OnlyPlainTxs, filter.OnlyBlobTxs = false, true pendingBlobTxs := w.eth.TxPool().Pending(filter) + if w.chain.TxDAGEnabled() { + env.state.ResetMVStates(0) + } + packFromTxpoolTimer.UpdateSince(start) log.Debug("packFromTxpoolTimer", "duration", common.PrettyDuration(time.Since(start)), "hash", env.header.Hash(), "txs", len(pendingPlainTxs)) @@ -1204,8 +1209,6 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err localPlainTxs, remotePlainTxs := make(map[common.Address][]*txpool.LazyTransaction), pendingPlainTxs localBlobTxs, remoteBlobTxs := make(map[common.Address][]*txpool.LazyTransaction), pendingBlobTxs - env.state.ResetMVStates(0) - for _, account := range w.eth.TxPool().Locals() { if txs := remotePlainTxs[account]; len(txs) > 0 { delete(remotePlainTxs, account) @@ -1338,7 +1341,7 @@ func (w *worker) generateWork(genParams *generateParams) *newPayloadResult { } // Because the TxDAG appends after sidecar, so we only enable after cancun - if w.chainConfig.IsCancun(block.Number(), block.Time()) && w.chainConfig.Optimism == nil { + if w.chain.TxDAGEnabled() && w.chainConfig.IsCancun(block.Number(), block.Time()) && w.chainConfig.Optimism == nil { txDAG, _ := work.state.MVStates2TxDAG() rawTxDAG, err := types.EncodeTxDAG(txDAG) if err != nil { @@ -1348,7 +1351,7 @@ func (w *worker) generateWork(genParams *generateParams) *newPayloadResult { } // TODO(galaio): need hardfork - if w.chainConfig.Optimism != nil { + if w.chain.TxDAGEnabled() && w.chainConfig.Optimism != nil { txDAG, _ := work.state.MVStates2TxDAG() rawTxDAG, err := types.EncodeTxDAG(txDAG) if err != nil { @@ -1356,6 +1359,7 @@ func (w *worker) generateWork(genParams *generateParams) *newPayloadResult { } block.Header().Extra = rawTxDAG } + assembleBlockTimer.UpdateSince(start) log.Debug("assembleBlockTimer", "duration", common.PrettyDuration(time.Since(start)), "parentHash", genParams.parentHash) @@ -1367,6 +1371,7 @@ func (w *worker) generateWork(genParams *generateParams) *newPayloadResult { storageUpdateTimer.Update(work.state.StorageUpdates) // Storage updates are complete(in FinalizeAndAssemble) accountHashTimer.Update(work.state.AccountHashes) // Account hashes are complete(in FinalizeAndAssemble) storageHashTimer.Update(work.state.StorageHashes) // Storage hashes are complete(in FinalizeAndAssemble) + txDAGGenerateTimer.Update(work.state.TxDAGGenerate) innerExecutionTimer.Update(core.DebugInnerExecutionDuration) @@ -1463,7 +1468,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti } // Because the TxDAG appends after sidecar, so we only enable after cancun - if w.chainConfig.IsCancun(env.header.Number, env.header.Time) && w.chainConfig.Optimism == nil { + if w.chain.TxDAGEnabled() && w.chainConfig.IsCancun(env.header.Number, env.header.Time) && w.chainConfig.Optimism == nil { for i := len(env.txs); i < len(block.Transactions()); i++ { env.state.RecordSystemTxRWSet(i) } @@ -1476,7 +1481,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti } // TODO(galaio): need hardfork - if w.chainConfig.Optimism != nil { + if w.chain.TxDAGEnabled() && w.chainConfig.Optimism != nil { txDAG, _ := env.state.MVStates2TxDAG() rawTxDAG, err := types.EncodeTxDAG(txDAG) if err != nil {