From 9968d4c9a7c620ac156516e2fd3ae0aed1738cbd Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 1 Oct 2024 16:50:55 +0530 Subject: [PATCH 1/6] [config change] Improve BlocksReExecutor implementation --- blocks_reexecutor/blocks_reexecutor.go | 153 ++++++++++++++++++------- cmd/nitro/nitro.go | 6 +- system_tests/blocks_reexecutor_test.go | 8 +- 3 files changed, 120 insertions(+), 47 deletions(-) diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go index b43999a7db..e5d2fdb2b2 100644 --- a/blocks_reexecutor/blocks_reexecutor.go +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -9,22 +9,27 @@ import ( "strings" "github.com/ethereum/go-ethereum/arbitrum" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-ethereum/triedb/hashdb" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/stopwaiter" flag "github.com/spf13/pflag" ) type Config struct { - Enable bool `koanf:"enable"` - Mode string `koanf:"mode"` - StartBlock uint64 `koanf:"start-block"` - EndBlock uint64 `koanf:"end-block"` - Room int `koanf:"room"` - BlocksPerThread uint64 `koanf:"blocks-per-thread"` + Enable bool `koanf:"enable"` + Mode string `koanf:"mode"` + StartBlock uint64 `koanf:"start-block"` + EndBlock uint64 `koanf:"end-block"` + Room int `koanf:"room"` + MinBlocksPerThread uint64 `koanf:"min-blocks-per-thread"` } func (c *Config) Validate() error { @@ -48,10 +53,10 @@ var DefaultConfig = Config{ } var TestConfig = Config{ - Enable: true, - Mode: "full", - Room: runtime.NumCPU(), - BlocksPerThread: 10, + Enable: true, + Mode: "full", + Room: runtime.NumCPU(), + MinBlocksPerThread: 10, } func ConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -60,22 +65,26 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".start-block", DefaultConfig.StartBlock, "first block number of the block range for re-execution") f.Uint64(prefix+".end-block", DefaultConfig.EndBlock, "last block number of the block range for re-execution") f.Int(prefix+".room", DefaultConfig.Room, "number of threads to parallelize blocks re-execution") - f.Uint64(prefix+".blocks-per-thread", DefaultConfig.BlocksPerThread, "minimum number of blocks to execute per thread. When mode is random this acts as the size of random block range sample") + f.Uint64(prefix+".min-blocks-per-thread", DefaultConfig.MinBlocksPerThread, "minimum number of blocks to execute per thread. When mode is random this acts as the size of random block range sample") } type BlocksReExecutor struct { stopwaiter.StopWaiter - config *Config - blockchain *core.BlockChain - stateFor arbitrum.StateForHeaderFunction - done chan struct{} - fatalErrChan chan error - startBlock uint64 - currentBlock uint64 - blocksPerThread uint64 + config *Config + db state.Database + blockchain *core.BlockChain + stateFor arbitrum.StateForHeaderFunction + done chan struct{} + fatalErrChan chan error + startBlock uint64 + currentBlock uint64 + minBlocksPerThread uint64 } -func New(c *Config, blockchain *core.BlockChain, fatalErrChan chan error) *BlocksReExecutor { +func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrChan chan error) (*BlocksReExecutor, error) { + if blockchain.TrieDB().Scheme() == rawdb.PathScheme { + return nil, errors.New("blocksReExecutor not supported on pathdb") + } start := c.StartBlock end := c.EndBlock chainStart := blockchain.Config().ArbitrumChainParams.GenesisBlockNum @@ -92,13 +101,13 @@ func New(c *Config, blockchain *core.BlockChain, fatalErrChan chan error) *Block log.Warn("invalid state reexecutor's end block number, resetting to latest", "end", end, "latest", chainEnd) end = chainEnd } - blocksPerThread := uint64(10000) - if c.BlocksPerThread != 0 { - blocksPerThread = c.BlocksPerThread + minBlocksPerThread := uint64(10000) + if c.MinBlocksPerThread != 0 { + minBlocksPerThread = c.MinBlocksPerThread } if c.Mode == "random" && end != start { - // Reexecute a range of 10000 or (non-zero) c.BlocksPerThread number of blocks between start to end picked randomly - rng := blocksPerThread + // Reexecute a range of 10000 or (non-zero) c.MinBlocksPerThread number of blocks between start to end picked randomly + rng := minBlocksPerThread if rng > end-start { rng = end - start } @@ -111,32 +120,41 @@ func New(c *Config, blockchain *core.BlockChain, fatalErrChan chan error) *Block if start > 0 && start != chainStart { start-- } - // Divide work equally among available threads when BlocksPerThread is zero - if c.BlocksPerThread == 0 { + // Divide work equally among available threads when MinBlocksPerThread is zero + if c.MinBlocksPerThread == 0 { // #nosec G115 work := (end - start) / uint64(c.Room) if work > 0 { - blocksPerThread = work + minBlocksPerThread = work } } - return &BlocksReExecutor{ - config: c, - blockchain: blockchain, - currentBlock: end, - startBlock: start, - blocksPerThread: blocksPerThread, - done: make(chan struct{}, c.Room), - fatalErrChan: fatalErrChan, - stateFor: func(header *types.Header) (*state.StateDB, arbitrum.StateReleaseFunc, error) { - state, err := blockchain.StateAt(header.Root) - return state, arbitrum.NoopStateRelease, err - }, + trieConfig := triedb.Config{ + Preimages: false, + HashDB: hashdb.Defaults, + } + blocksReExecutor := &BlocksReExecutor{ + config: c, + db: state.NewDatabaseWithConfig(ethDb, &trieConfig), + blockchain: blockchain, + currentBlock: end, + startBlock: start, + minBlocksPerThread: minBlocksPerThread, + done: make(chan struct{}, c.Room), + fatalErrChan: fatalErrChan, } + blocksReExecutor.stateFor = func(header *types.Header) (*state.StateDB, arbitrum.StateReleaseFunc, error) { + sdb, err := state.NewDeterministic(header.Root, blocksReExecutor.db) + if err == nil { + _ = blocksReExecutor.db.TrieDB().Reference(header.Root, common.Hash{}) // Will be dereferenced later in advanceStateUpToBlock + } + return sdb, arbitrum.NoopStateRelease, err + } + return blocksReExecutor, nil } -// LaunchBlocksReExecution launches the thread to apply blocks of range [currentBlock-s.config.BlocksPerThread, currentBlock] to the last available valid state +// LaunchBlocksReExecution launches the thread to apply blocks of range [currentBlock-s.config.MinBlocksPerThread, currentBlock] to the last available valid state func (s *BlocksReExecutor) LaunchBlocksReExecution(ctx context.Context, currentBlock uint64) uint64 { - start := arbmath.SaturatingUSub(currentBlock, s.blocksPerThread) + start := arbmath.SaturatingUSub(currentBlock, s.minBlocksPerThread) if start < s.startBlock { start = s.startBlock } @@ -149,8 +167,8 @@ func (s *BlocksReExecutor) LaunchBlocksReExecution(ctx context.Context, currentB defer release() start = startHeader.Number.Uint64() s.LaunchThread(func(ctx context.Context) { - _, err := arbitrum.AdvanceStateUpToBlock(ctx, s.blockchain, startState, s.blockchain.GetHeaderByNumber(currentBlock), startHeader, nil) - if err != nil { + log.Info("Starting reexecution of blocks against historic state", "stateAt", start, "startBlock", start+1, "endBlock", currentBlock) + if err := s.advanceStateUpToBlock(ctx, startState, s.blockchain.GetHeaderByNumber(currentBlock), startHeader); err != nil { s.fatalErrChan <- fmt.Errorf("blocksReExecutor errored advancing state from block %d to block %d, err: %w", start, currentBlock, err) } else { log.Info("Successfully reexecuted blocks against historic state", "stateAt", start, "startBlock", start+1, "endBlock", currentBlock) @@ -199,3 +217,50 @@ func (s *BlocksReExecutor) Start(ctx context.Context, done chan struct{}) { func (s *BlocksReExecutor) StopAndWait() { s.StopWaiter.StopAndWait() } + +func (s *BlocksReExecutor) commitStateAndVerify(statedb *state.StateDB, expected common.Hash, blockNumber uint64) (*state.StateDB, error) { + result, err := statedb.Commit(blockNumber, true) + if err != nil { + return nil, err + } + if result != expected { + return nil, fmt.Errorf("bad root hash expected: %v got: %v", expected, result) + } + _ = s.db.TrieDB().Reference(result, common.Hash{}) + return state.New(result, statedb.Database(), nil) +} + +func (s *BlocksReExecutor) advanceStateUpToBlock(ctx context.Context, state *state.StateDB, targetHeader *types.Header, lastAvailableHeader *types.Header) error { + targetBlockNumber := targetHeader.Number.Uint64() + blockToRecreate := lastAvailableHeader.Number.Uint64() + 1 + prevHash := lastAvailableHeader.Hash() + lastRoot := lastAvailableHeader.Root + defer func() { + if (lastRoot != common.Hash{}) { + _ = s.db.TrieDB().Dereference(lastRoot) + } + }() + var block *types.Block + var err error + for ctx.Err() == nil { + state, block, err = arbitrum.AdvanceStateByBlock(ctx, s.blockchain, state, targetHeader, blockToRecreate, prevHash, nil) + if err != nil { + return err + } + prevHash = block.Hash() + state, err = s.commitStateAndVerify(state, block.Root(), block.NumberU64()) + if err != nil { + return fmt.Errorf("failed committing state for block %d : %w", blockToRecreate, err) + } + _ = s.db.TrieDB().Dereference(lastRoot) + lastRoot = block.Root() + if blockToRecreate >= targetBlockNumber { + if block.Hash() != targetHeader.Hash() { + return fmt.Errorf("blockHash doesn't match when recreating number: %d expected: %v got: %v", blockToRecreate, targetHeader.Hash(), block.Hash()) + } + return nil + } + blockToRecreate++ + } + return ctx.Err() +} diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index bc2155a475..4fa49d4187 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -470,7 +470,11 @@ func mainImpl() int { var blocksReExecutor *blocksreexecutor.BlocksReExecutor if nodeConfig.BlocksReExecutor.Enable && l2BlockChain != nil { - blocksReExecutor = blocksreexecutor.New(&nodeConfig.BlocksReExecutor, l2BlockChain, fatalErrChan) + blocksReExecutor, err = blocksreexecutor.New(&nodeConfig.BlocksReExecutor, l2BlockChain, chainDb, fatalErrChan) + if err != nil { + log.Error("error initializing blocksReExecutor", "err", err) + return 1 + } if nodeConfig.Init.ThenQuit { if err := gethexec.PopulateStylusTargetCache(&nodeConfig.Execution.StylusTarget); err != nil { log.Error("error populating stylus target cache", "err", err) diff --git a/system_tests/blocks_reexecutor_test.go b/system_tests/blocks_reexecutor_test.go index c6a7181c46..1a97919e66 100644 --- a/system_tests/blocks_reexecutor_test.go +++ b/system_tests/blocks_reexecutor_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" blocksreexecutor "github.com/offchainlabs/nitro/blocks_reexecutor" ) @@ -13,6 +14,7 @@ func TestBlocksReExecutorModes(t *testing.T) { defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, false) + builder.execConfig.Caching.StateScheme = rawdb.HashScheme cleanup := builder.Build(t) defer cleanup() @@ -37,7 +39,8 @@ func TestBlocksReExecutorModes(t *testing.T) { // Reexecute blocks at mode full success := make(chan struct{}) - executorFull := blocksreexecutor.New(&blocksreexecutor.TestConfig, blockchain, feedErrChan) + executorFull, err := blocksreexecutor.New(&blocksreexecutor.TestConfig, blockchain, builder.L2.ExecNode.ChainDB, feedErrChan) + Require(t, err) executorFull.Start(ctx, success) select { case err := <-feedErrChan: @@ -49,7 +52,8 @@ func TestBlocksReExecutorModes(t *testing.T) { success = make(chan struct{}) c := &blocksreexecutor.TestConfig c.Mode = "random" - executorRandom := blocksreexecutor.New(c, blockchain, feedErrChan) + executorRandom, err := blocksreexecutor.New(c, blockchain, builder.L2.ExecNode.ChainDB, feedErrChan) + Require(t, err) executorRandom.Start(ctx, success) select { case err := <-feedErrChan: From b550510b7a93406f954b30dd8e6d9596ba53ec08 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 2 Oct 2024 11:33:38 +0530 Subject: [PATCH 2/6] address PR comments --- blocks_reexecutor/blocks_reexecutor.go | 46 ++++++++++++++++---------- go-ethereum | 2 +- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go index e5d2fdb2b2..c71c5b194e 100644 --- a/blocks_reexecutor/blocks_reexecutor.go +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -30,6 +30,7 @@ type Config struct { EndBlock uint64 `koanf:"end-block"` Room int `koanf:"room"` MinBlocksPerThread uint64 `koanf:"min-blocks-per-thread"` + TrieCleanLimit int `koanf:"trie-clean-limit"` } func (c *Config) Validate() error { @@ -57,6 +58,7 @@ var TestConfig = Config{ Mode: "full", Room: runtime.NumCPU(), MinBlocksPerThread: 10, + TrieCleanLimit: 600, } func ConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -66,6 +68,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".end-block", DefaultConfig.EndBlock, "last block number of the block range for re-execution") f.Int(prefix+".room", DefaultConfig.Room, "number of threads to parallelize blocks re-execution") f.Uint64(prefix+".min-blocks-per-thread", DefaultConfig.MinBlocksPerThread, "minimum number of blocks to execute per thread. When mode is random this acts as the size of random block range sample") + f.Int(prefix+".trie-clean-limit", DefaultConfig.TrieCleanLimit, "memory allowance (MB) to use for caching trie nodes in memory") } type BlocksReExecutor struct { @@ -128,9 +131,11 @@ func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrC minBlocksPerThread = work } } + hashConfig := *hashdb.Defaults + hashConfig.CleanCacheSize = c.TrieCleanLimit * 1024 * 1024 trieConfig := triedb.Config{ Preimages: false, - HashDB: hashdb.Defaults, + HashDB: &hashConfig, } blocksReExecutor := &BlocksReExecutor{ config: c, @@ -146,6 +151,10 @@ func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrC sdb, err := state.NewDeterministic(header.Root, blocksReExecutor.db) if err == nil { _ = blocksReExecutor.db.TrieDB().Reference(header.Root, common.Hash{}) // Will be dereferenced later in advanceStateUpToBlock + stateReleaseFunc := func() { + _ = blocksReExecutor.db.TrieDB().Dereference(header.Root) + } + return sdb, stateReleaseFunc, err } return sdb, arbitrum.NoopStateRelease, err } @@ -163,12 +172,10 @@ func (s *BlocksReExecutor) LaunchBlocksReExecution(ctx context.Context, currentB s.fatalErrChan <- fmt.Errorf("blocksReExecutor failed to get last available state while searching for state at %d, err: %w", start, err) return s.startBlock } - // NoOp - defer release() start = startHeader.Number.Uint64() s.LaunchThread(func(ctx context.Context) { log.Info("Starting reexecution of blocks against historic state", "stateAt", start, "startBlock", start+1, "endBlock", currentBlock) - if err := s.advanceStateUpToBlock(ctx, startState, s.blockchain.GetHeaderByNumber(currentBlock), startHeader); err != nil { + if err := s.advanceStateUpToBlock(ctx, startState, s.blockchain.GetHeaderByNumber(currentBlock), startHeader, release); err != nil { s.fatalErrChan <- fmt.Errorf("blocksReExecutor errored advancing state from block %d to block %d, err: %w", start, currentBlock, err) } else { log.Info("Successfully reexecuted blocks against historic state", "stateAt", start, "startBlock", start+1, "endBlock", currentBlock) @@ -218,27 +225,32 @@ func (s *BlocksReExecutor) StopAndWait() { s.StopWaiter.StopAndWait() } -func (s *BlocksReExecutor) commitStateAndVerify(statedb *state.StateDB, expected common.Hash, blockNumber uint64) (*state.StateDB, error) { +func (s *BlocksReExecutor) commitStateAndVerify(statedb *state.StateDB, expected common.Hash, blockNumber uint64) (*state.StateDB, arbitrum.StateReleaseFunc, error) { result, err := statedb.Commit(blockNumber, true) if err != nil { - return nil, err + return nil, arbitrum.NoopStateRelease, err } if result != expected { - return nil, fmt.Errorf("bad root hash expected: %v got: %v", expected, result) + return nil, arbitrum.NoopStateRelease, fmt.Errorf("bad root hash expected: %v got: %v", expected, result) + } + sdb, err := state.New(result, statedb.Database(), nil) + if err == nil { + _ = s.db.TrieDB().Reference(result, common.Hash{}) + stateReleaseFunc := func() { + _ = s.db.TrieDB().Dereference(result) + } + return sdb, stateReleaseFunc, nil } - _ = s.db.TrieDB().Reference(result, common.Hash{}) - return state.New(result, statedb.Database(), nil) + return sdb, arbitrum.NoopStateRelease, err } -func (s *BlocksReExecutor) advanceStateUpToBlock(ctx context.Context, state *state.StateDB, targetHeader *types.Header, lastAvailableHeader *types.Header) error { +func (s *BlocksReExecutor) advanceStateUpToBlock(ctx context.Context, state *state.StateDB, targetHeader *types.Header, lastAvailableHeader *types.Header, lastRelease arbitrum.StateReleaseFunc) error { targetBlockNumber := targetHeader.Number.Uint64() blockToRecreate := lastAvailableHeader.Number.Uint64() + 1 prevHash := lastAvailableHeader.Hash() - lastRoot := lastAvailableHeader.Root + var stateRelease arbitrum.StateReleaseFunc defer func() { - if (lastRoot != common.Hash{}) { - _ = s.db.TrieDB().Dereference(lastRoot) - } + lastRelease() }() var block *types.Block var err error @@ -248,12 +260,12 @@ func (s *BlocksReExecutor) advanceStateUpToBlock(ctx context.Context, state *sta return err } prevHash = block.Hash() - state, err = s.commitStateAndVerify(state, block.Root(), block.NumberU64()) + state, stateRelease, err = s.commitStateAndVerify(state, block.Root(), block.NumberU64()) if err != nil { return fmt.Errorf("failed committing state for block %d : %w", blockToRecreate, err) } - _ = s.db.TrieDB().Dereference(lastRoot) - lastRoot = block.Root() + lastRelease() + lastRelease = stateRelease if blockToRecreate >= targetBlockNumber { if block.Hash() != targetHeader.Hash() { return fmt.Errorf("blockHash doesn't match when recreating number: %d expected: %v got: %v", blockToRecreate, targetHeader.Hash(), block.Hash()) diff --git a/go-ethereum b/go-ethereum index b068464bf5..fece13e75a 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b068464bf59ab5414f72c2d4aba855b8af5edc17 +Subproject commit fece13e75a3448d5ef53e72a7d46ebb6118575ad From 5c4967db0712146f143f2e800562f26db633931f Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Wed, 2 Oct 2024 14:07:27 +0530 Subject: [PATCH 3/6] fix lint error --- blocks_reexecutor/blocks_reexecutor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go index c71c5b194e..c6083a9ad5 100644 --- a/blocks_reexecutor/blocks_reexecutor.go +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -154,7 +154,7 @@ func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrC stateReleaseFunc := func() { _ = blocksReExecutor.db.TrieDB().Dereference(header.Root) } - return sdb, stateReleaseFunc, err + return sdb, stateReleaseFunc, nil } return sdb, arbitrum.NoopStateRelease, err } From d4e2ecdc7c05a6f6618f39752aec38109e875163 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 29 Oct 2024 11:19:36 +0530 Subject: [PATCH 4/6] handle race condition and address minor comments --- blocks_reexecutor/blocks_reexecutor.go | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go index c6083a9ad5..6347975534 100644 --- a/blocks_reexecutor/blocks_reexecutor.go +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -7,6 +7,7 @@ import ( "math/rand" "runtime" "strings" + "sync" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" @@ -82,6 +83,7 @@ type BlocksReExecutor struct { startBlock uint64 currentBlock uint64 minBlocksPerThread uint64 + mutex sync.Mutex } func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrChan chan error) (*BlocksReExecutor, error) { @@ -126,7 +128,7 @@ func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrC // Divide work equally among available threads when MinBlocksPerThread is zero if c.MinBlocksPerThread == 0 { // #nosec G115 - work := (end - start) / uint64(c.Room) + work := (end - start) / uint64(c.Room*2) if work > 0 { minBlocksPerThread = work } @@ -148,13 +150,12 @@ func New(c *Config, blockchain *core.BlockChain, ethDb ethdb.Database, fatalErrC fatalErrChan: fatalErrChan, } blocksReExecutor.stateFor = func(header *types.Header) (*state.StateDB, arbitrum.StateReleaseFunc, error) { - sdb, err := state.NewDeterministic(header.Root, blocksReExecutor.db) + blocksReExecutor.mutex.Lock() + defer blocksReExecutor.mutex.Unlock() + sdb, err := state.New(header.Root, blocksReExecutor.db, nil) if err == nil { _ = blocksReExecutor.db.TrieDB().Reference(header.Root, common.Hash{}) // Will be dereferenced later in advanceStateUpToBlock - stateReleaseFunc := func() { - _ = blocksReExecutor.db.TrieDB().Dereference(header.Root) - } - return sdb, stateReleaseFunc, nil + return sdb, func() { blocksReExecutor.dereferenceRoot(header.Root) }, nil } return sdb, arbitrum.NoopStateRelease, err } @@ -225,7 +226,15 @@ func (s *BlocksReExecutor) StopAndWait() { s.StopWaiter.StopAndWait() } +func (s *BlocksReExecutor) dereferenceRoot(root common.Hash) { + s.mutex.Lock() + defer s.mutex.Unlock() + _ = s.db.TrieDB().Dereference(root) +} + func (s *BlocksReExecutor) commitStateAndVerify(statedb *state.StateDB, expected common.Hash, blockNumber uint64) (*state.StateDB, arbitrum.StateReleaseFunc, error) { + s.mutex.Lock() + defer s.mutex.Unlock() result, err := statedb.Commit(blockNumber, true) if err != nil { return nil, arbitrum.NoopStateRelease, err @@ -233,13 +242,10 @@ func (s *BlocksReExecutor) commitStateAndVerify(statedb *state.StateDB, expected if result != expected { return nil, arbitrum.NoopStateRelease, fmt.Errorf("bad root hash expected: %v got: %v", expected, result) } - sdb, err := state.New(result, statedb.Database(), nil) + sdb, err := state.New(result, s.db, nil) if err == nil { _ = s.db.TrieDB().Reference(result, common.Hash{}) - stateReleaseFunc := func() { - _ = s.db.TrieDB().Dereference(result) - } - return sdb, stateReleaseFunc, nil + return sdb, func() { s.dereferenceRoot(result) }, nil } return sdb, arbitrum.NoopStateRelease, err } From 8d8cfbead170540ea0dc5a25e98aa755a51ff405 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 29 Oct 2024 11:45:19 +0530 Subject: [PATCH 5/6] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index fece13e75a..2f247a3182 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit fece13e75a3448d5ef53e72a7d46ebb6118575ad +Subproject commit 2f247a31822ecd06e39d89f7d5332fa16fd2f6b6 From c2ccab55821d47110c76cbe434c1b7c5330a792d Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 29 Oct 2024 12:03:53 +0530 Subject: [PATCH 6/6] StateBuildingLogFunction shouldn't take targetHeader as an arg --- blocks_reexecutor/blocks_reexecutor.go | 2 +- execution/gethexec/block_recorder.go | 32 ++++++++++++++------------ go-ethereum | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go index 6347975534..5a883e5d42 100644 --- a/blocks_reexecutor/blocks_reexecutor.go +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -261,7 +261,7 @@ func (s *BlocksReExecutor) advanceStateUpToBlock(ctx context.Context, state *sta var block *types.Block var err error for ctx.Err() == nil { - state, block, err = arbitrum.AdvanceStateByBlock(ctx, s.blockchain, state, targetHeader, blockToRecreate, prevHash, nil) + state, block, err = arbitrum.AdvanceStateByBlock(ctx, s.blockchain, state, blockToRecreate, prevHash, nil) if err != nil { return err } diff --git a/execution/gethexec/block_recorder.go b/execution/gethexec/block_recorder.go index a3af7876a8..6f30e16e5c 100644 --- a/execution/gethexec/block_recorder.go +++ b/execution/gethexec/block_recorder.go @@ -75,19 +75,21 @@ func NewBlockRecorder(config *BlockRecorderConfig, execEngine *ExecutionEngine, return recorder } -func stateLogFunc(targetHeader, header *types.Header, hasState bool) { - if targetHeader == nil || header == nil { - return - } - gap := targetHeader.Number.Int64() - header.Number.Int64() - step := int64(500) - stage := "computing state" - if !hasState { - step = 3000 - stage = "looking for full block" - } - if (gap >= step) && (gap%step == 0) { - log.Info("Setting up validation", "stage", stage, "current", header.Number, "target", targetHeader.Number) +func stateLogFunc(targetHeader *types.Header) arbitrum.StateBuildingLogFunction { + return func(header *types.Header, hasState bool) { + if targetHeader == nil || header == nil { + return + } + gap := targetHeader.Number.Int64() - header.Number.Int64() + step := int64(500) + stage := "computing state" + if !hasState { + step = 3000 + stage = "looking for full block" + } + if (gap >= step) && (gap%step == 0) { + log.Info("Setting up validation", "stage", stage, "current", header.Number, "target", targetHeader.Number) + } } } @@ -109,7 +111,7 @@ func (r *BlockRecorder) RecordBlockCreation( } } - recordingdb, chaincontext, recordingKV, err := r.recordingDatabase.PrepareRecording(ctx, prevHeader, stateLogFunc) + recordingdb, chaincontext, recordingKV, err := r.recordingDatabase.PrepareRecording(ctx, prevHeader, stateLogFunc(prevHeader)) if err != nil { return nil, err } @@ -321,7 +323,7 @@ func (r *BlockRecorder) PrepareForRecord(ctx context.Context, start, end arbutil log.Warn("prepareblocks asked for non-found block", "hdrNum", hdrNum) break } - _, err := r.recordingDatabase.GetOrRecreateState(ctx, header, stateLogFunc) + _, err := r.recordingDatabase.GetOrRecreateState(ctx, header, stateLogFunc(header)) if err != nil { log.Warn("prepareblocks failed to get state for block", "hdrNum", hdrNum, "err", err) break diff --git a/go-ethereum b/go-ethereum index 2f247a3182..f9b447d74c 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 2f247a31822ecd06e39d89f7d5332fa16fd2f6b6 +Subproject commit f9b447d74c00e554752ae60eb2200966d68a4f7a