diff --git a/arbos/arbosState/initialize.go b/arbos/arbosState/initialize.go index c44febf386..56fa579c15 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -6,10 +6,12 @@ package arbosState import ( "errors" "math/big" + "regexp" "sort" "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" @@ -64,6 +66,8 @@ func InitializeArbosInDatabase(db ethdb.Database, cacheConfig *core.CacheConfig, log.Crit("failed to init empty statedb", "error", err) } + noStateTrieChangesToCommitError := regexp.MustCompile("^triedb layer .+ is disk layer$") + // commit avoids keeping the entire state in memory while importing the state. // At some time it was also used to avoid reprocessing the whole import in case of a crash. commit := func() (common.Hash, error) { @@ -73,7 +77,11 @@ func InitializeArbosInDatabase(db ethdb.Database, cacheConfig *core.CacheConfig, } err = stateDatabase.TrieDB().Commit(root, true) if err != nil { - return common.Hash{}, err + // pathdb returns an error when there are no state trie changes to commit and we try to commit. + // This checks if the error is the expected one and ignores it. + if (cacheConfig.StateScheme != rawdb.PathScheme) || !noStateTrieChangesToCommitError.MatchString(err.Error()) { + return common.Hash{}, err + } } statedb, err = state.New(root, stateDatabase, nil) if err != nil { diff --git a/cmd/nitro/init_test.go b/cmd/nitro/init_test.go index 6171f631cc..7375a8ab49 100644 --- a/cmd/nitro/init_test.go +++ b/cmd/nitro/init_test.go @@ -29,6 +29,7 @@ import ( "github.com/offchainlabs/nitro/cmd/conf" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" + "github.com/offchainlabs/nitro/util/testhelpers/env" ) const ( @@ -506,3 +507,38 @@ func TestPurgeVersion0WasmStoreEntries(t *testing.T) { checkKeys(t, db, collidedKeys, true) checkKeys(t, db, otherKeys, true) } + +func TestOpenInitializeChainDbEmptyInit(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + stackConfig := testhelpers.CreateStackConfigForTest(t.TempDir()) + stack, err := node.New(stackConfig) + defer stack.Close() + Require(t, err) + + nodeConfig := NodeConfigDefault + nodeConfig.Execution.Caching.StateScheme = env.GetTestStateScheme() + nodeConfig.Chain.ID = 42161 + nodeConfig.Node = *arbnode.ConfigDefaultL2Test() + nodeConfig.Init.Empty = true + + l1Client := ethclient.NewClient(stack.Attach()) + + chainDb, blockchain, err := openInitializeChainDb( + ctx, + stack, + &nodeConfig, + new(big.Int).SetUint64(nodeConfig.Chain.ID), + gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), + &nodeConfig.Persistent, + l1Client, + chaininfo.RollupAddresses{}, + ) + Require(t, err) + blockchain.Stop() + err = chainDb.Close() + Require(t, err) +}