Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pull in geth changes for state recreation #2005

Merged
merged 49 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8eebd46
update geth and adjust tests
magicxyyz Dec 7, 2023
6fb2ba5
update geth
magicxyyz Dec 7, 2023
f865d1e
Merge branch 'master' into state-release
magicxyyz Dec 7, 2023
a40f8f1
Merge branch 'master' into state-release
magicxyyz Dec 8, 2023
d21fdd8
update geth
magicxyyz Dec 11, 2023
a1ac5d0
Merge branch 'master' into state-release
magicxyyz Dec 11, 2023
4ff776d
Revert "update geth and adjust tests"
magicxyyz Dec 18, 2023
32df394
update expected error in TestRecreateStateForRPCBlockNotFoundWhileRec…
magicxyyz Dec 18, 2023
a9a0772
update geth
magicxyyz Dec 18, 2023
1234559
Merge branch 'master' into state-release
amsanghi Dec 19, 2023
ea05f0a
add test for getting state for rpc
magicxyyz Dec 19, 2023
dc936ea
Merge branch 'state-release-test' into state-release
magicxyyz Dec 19, 2023
7659d68
add missing error check in recreate state test
magicxyyz Dec 19, 2023
c1bdefd
update geth
magicxyyz Dec 19, 2023
923bc4c
add test for getting state for rpc on hybrid archive node
magicxyyz Dec 19, 2023
ac9d63b
add missing error check in recreate state test
magicxyyz Dec 19, 2023
42b6c83
add missing error check
magicxyyz Dec 19, 2023
bb5c908
Merge branch 'state-release-test' into state-release
magicxyyz Dec 19, 2023
b776a68
Merge branch 'master' into state-release
amsanghi Dec 20, 2023
8e2ede8
update geth
magicxyyz Jan 12, 2024
d1f244f
update geth
magicxyyz Jan 26, 2024
25bd9eb
Merge branch 'master' into state-release
magicxyyz Jan 26, 2024
f69b53e
update go.mod
magicxyyz Jan 26, 2024
fdc42ba
update recreate state tests to account for states saved on shutdown
magicxyyz Feb 5, 2024
e12dd8a
update geth
magicxyyz Feb 5, 2024
811d4fa
Merge branch 'master' into state-release
magicxyyz Feb 5, 2024
2e3d313
update geth
magicxyyz Feb 6, 2024
e415501
Merge branch 'master' into state-release
magicxyyz Feb 6, 2024
a781faf
fix recreation after restart test
magicxyyz Feb 6, 2024
72d678d
update geth
magicxyyz Feb 6, 2024
9bff2b2
remove commited by mistake files
magicxyyz Feb 8, 2024
60e4ff4
update geth
magicxyyz Feb 9, 2024
c341182
system_tests: fix initialization of default value of MaxRecreateState…
magicxyyz Feb 16, 2024
5559118
update geth
magicxyyz Feb 22, 2024
ab310ac
Merge branch 'master' into state-release
magicxyyz Feb 22, 2024
251abe0
update blocks reexecutor
magicxyyz Feb 23, 2024
41ebf43
update geth
magicxyyz Feb 23, 2024
22fa881
uncomment testing defaults in recreate state tests
magicxyyz Feb 23, 2024
49ec18c
Merge branch 'master' into state-release
magicxyyz Feb 27, 2024
6890439
update geth
magicxyyz Mar 6, 2024
48d0b9d
update geth
magicxyyz Mar 6, 2024
7296df7
Merge branch 'master' into state-release
magicxyyz Mar 6, 2024
2a53d99
Merge branch 'master' into state-release
magicxyyz Mar 7, 2024
2d449ae
add StateAndHeader test
magicxyyz Mar 12, 2024
8f4bf75
Merge branch 'master' into state-release
magicxyyz Mar 12, 2024
8c24484
update StateAndHeader test
magicxyyz Mar 12, 2024
b64198a
update error check in StateAndHeader test
magicxyyz Mar 12, 2024
7718918
update geth
magicxyyz Mar 12, 2024
25624db
update geth
magicxyyz Mar 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 160 additions & 63 deletions system_tests/recreatestate_rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package arbtest
import (
"context"
"errors"
"fmt"
"math/big"
"strings"
"testing"
Expand All @@ -12,21 +13,16 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
"github.com/offchainlabs/nitro/arbnode"
"github.com/offchainlabs/nitro/execution/gethexec"
"github.com/offchainlabs/nitro/util"
)

func prepareNodeWithHistory(t *testing.T, ctx context.Context, execConfig *gethexec.Config, txCount uint64) (node *arbnode.Node, executionNode *gethexec.ExecutionNode, l2client *ethclient.Client, cancel func()) {
t.Helper()
builder := NewNodeBuilder(ctx).DefaultConfig(t, true)
builder.execConfig = execConfig
cleanup := builder.Build(t)
builder.L2Info.GenerateAccount("User2")
func makeSomeTransfers(t *testing.T, ctx context.Context, builder *NodeBuilder, txCount uint64) {
var txs []*types.Transaction
for i := uint64(0); i < txCount; i++ {
tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, common.Big1, nil)
Expand All @@ -38,8 +34,16 @@ func prepareNodeWithHistory(t *testing.T, ctx context.Context, execConfig *gethe
_, err := builder.L2.EnsureTxSucceeded(tx)
Require(t, err)
}
}

return builder.L2.ConsensusNode, builder.L2.ExecNode, builder.L2.Client, cleanup
func prepareNodeWithHistory(t *testing.T, ctx context.Context, execConfig *gethexec.Config, txCount uint64) (*NodeBuilder, func()) {
t.Helper()
builder := NewNodeBuilder(ctx).DefaultConfig(t, true)
builder.execConfig = execConfig
cleanup := builder.Build(t)
builder.L2Info.GenerateAccount("User2")
makeSomeTransfers(t, ctx, builder, txCount)
return builder, cleanup
}

func fillHeaderCache(t *testing.T, bc *core.BlockChain, from, to uint64) {
Expand Down Expand Up @@ -89,17 +93,18 @@ func removeStatesFromDb(t *testing.T, bc *core.BlockChain, db ethdb.Database, fr
func TestRecreateStateForRPCNoDepthLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
nodeConfig := gethexec.ConfigDefaultTest()
nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
nodeConfig.Sequencer.MaxBlockSpeed = 0
nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
nodeConfig.Caching.Archive = true
execConfig := gethexec.ConfigDefaultTest()
execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
execConfig.Caching.Archive = true
// disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there
nodeConfig.Caching.TrieCleanCache = 0
nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
_, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32)
execConfig.Caching.TrieCleanCache = 0
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, 32)
defer cancelNode()
execNode, l2client := builder.L2.ExecNode, builder.L2.Client
bc := execNode.Backend.ArbInterface().BlockChain()
db := execNode.Backend.ChainDb()

Expand All @@ -123,17 +128,18 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
depthGasLimit := int64(256 * util.NormalizeL2GasForL1GasInitial(800_000, params.GWei))
nodeConfig := gethexec.ConfigDefaultTest()
nodeConfig.RPC.MaxRecreateStateDepth = depthGasLimit
nodeConfig.Sequencer.MaxBlockSpeed = 0
nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
nodeConfig.Caching.Archive = true
execConfig := gethexec.ConfigDefaultTest()
execConfig.RPC.MaxRecreateStateDepth = depthGasLimit
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
execConfig.Caching.Archive = true
// disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there
nodeConfig.Caching.TrieCleanCache = 0
nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
_, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32)
execConfig.Caching.TrieCleanCache = 0
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, 32)
defer cancelNode()
execNode, l2client := builder.L2.ExecNode, builder.L2.Client
bc := execNode.Backend.ArbInterface().BlockChain()
db := execNode.Backend.ChainDb()

Expand All @@ -157,17 +163,18 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) {
func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
nodeConfig := gethexec.ConfigDefaultTest()
nodeConfig.RPC.MaxRecreateStateDepth = int64(200)
nodeConfig.Sequencer.MaxBlockSpeed = 0
nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
nodeConfig.Caching.Archive = true
execConfig := gethexec.ConfigDefaultTest()
execConfig.RPC.MaxRecreateStateDepth = int64(200)
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
execConfig.Caching.Archive = true
// disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there
nodeConfig.Caching.TrieCleanCache = 0
nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
_, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32)
execConfig.Caching.TrieCleanCache = 0
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, 32)
defer cancelNode()
execNode, l2client := builder.L2.ExecNode, builder.L2.Client
bc := execNode.Backend.ArbInterface().BlockChain()
db := execNode.Backend.ChainDb()

Expand All @@ -191,17 +198,18 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) {
var headerCacheLimit uint64 = 512
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
nodeConfig := gethexec.ConfigDefaultTest()
nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
nodeConfig.Sequencer.MaxBlockSpeed = 0
nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
nodeConfig.Caching.Archive = true
execConfig := gethexec.ConfigDefaultTest()
execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
execConfig.Caching.Archive = true
// disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there
nodeConfig.Caching.TrieCleanCache = 0
nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
_, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, headerCacheLimit+5)
execConfig.Caching.TrieCleanCache = 0
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, headerCacheLimit+5)
defer cancelNode()
execNode, l2client := builder.L2.ExecNode, builder.L2.Client
bc := execNode.Backend.ArbInterface().BlockChain()
db := execNode.Backend.ChainDb()

Expand Down Expand Up @@ -236,16 +244,17 @@ func TestRecreateStateForRPCBeyondGenesis(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

nodeConfig := gethexec.ConfigDefaultTest()
nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
nodeConfig.Sequencer.MaxBlockSpeed = 0
nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
nodeConfig.Caching.Archive = true
execConfig := gethexec.ConfigDefaultTest()
execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
execConfig.Caching.Archive = true
// disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there
nodeConfig.Caching.TrieCleanCache = 0
nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
_, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, 32)
execConfig.Caching.TrieCleanCache = 0
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, 32)
execNode, l2client := builder.L2.ExecNode, builder.L2.Client
defer cancelNode()
bc := execNode.Backend.ArbInterface().BlockChain()
db := execNode.Backend.ChainDb()
Expand All @@ -271,17 +280,18 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) {
var blockCacheLimit uint64 = 256
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
nodeConfig := gethexec.ConfigDefaultTest()
nodeConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
nodeConfig.Sequencer.MaxBlockSpeed = 0
nodeConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
nodeConfig.Caching.Archive = true
execConfig := gethexec.ConfigDefaultTest()
execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
execConfig.Caching.Archive = true
// disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there
nodeConfig.Caching.TrieCleanCache = 0
execConfig.Caching.TrieCleanCache = 0

nodeConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
nodeConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
_, execNode, l2client, cancelNode := prepareNodeWithHistory(t, ctx, nodeConfig, blockCacheLimit+4)
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0
execConfig.Caching.MaxAmountOfGasToSkipStateSaving = 0
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, blockCacheLimit+4)
execNode, l2client := builder.L2.ExecNode, builder.L2.Client
defer cancelNode()
bc := execNode.Backend.ArbInterface().BlockChain()
db := execNode.Backend.ChainDb()
Expand All @@ -306,7 +316,7 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) {
hash := rawdb.ReadCanonicalHash(db, lastBlock)
Fatal(t, "Didn't fail to get balance at block:", lastBlock, " with hash:", hash, ", lastBlock:", lastBlock)
}
if !strings.Contains(err.Error(), "block not found while recreating") {
if !strings.Contains(err.Error(), fmt.Sprintf("block #%d not found", blockBodyToRemove)) {
Fatal(t, "Failed with unexpected error: \"", err, "\", at block:", lastBlock, "lastBlock:", lastBlock)
}
}
Expand Down Expand Up @@ -458,3 +468,90 @@ func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) {
}
}
}

func TestGettingStateForRPCFullNode(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
execConfig := gethexec.ConfigDefaultTest()
execConfig.Caching.SnapshotCache = 0 // disable snapshots
execConfig.Caching.BlockAge = 0 // use only Caching.BlockCount to keep only last N blocks in dirties cache, no matter how new they are
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, 16)
execNode, _ := builder.L2.ExecNode, builder.L2.Client
defer cancelNode()
bc := execNode.Backend.ArbInterface().BlockChain()
api := execNode.Backend.APIBackend()

header := bc.CurrentBlock()
if header == nil {
Fatal(t, "failed to get current block header")
}
state, _, err := api.StateAndHeaderByNumber(ctx, rpc.BlockNumber(header.Number.Uint64()))
Require(t, err)
addr := builder.L2Info.GetAddress("User2")
exists := state.Exist(addr)
err = state.Error()
Require(t, err)
if !exists {
Fatal(t, "User2 address does not exist in the state")
}
// Get the state again to avoid caching
state, _, err = api.StateAndHeaderByNumber(ctx, rpc.BlockNumber(header.Number.Uint64()))
Require(t, err)

blockCountRequiredToFlushDirties := builder.execConfig.Caching.BlockCount
makeSomeTransfers(t, ctx, builder, blockCountRequiredToFlushDirties)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add here a check that StateAndHeaderByNumber will now fail?
Or maybe force state to drop after the end of current test - and check that StateAndHeaderByNumber fails then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in #2442

exists = state.Exist(addr)
err = state.Error()
Require(t, err)
if !exists {
Fatal(t, "User2 address does not exist in the state")
}
}

func TestGettingStateForRPCHybridArchiveNode(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the logic here different from above other than config? can we merge the functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in #2442

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
execConfig := gethexec.ConfigDefaultTest()
execConfig.Caching.Archive = true
execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 128
execConfig.Caching.BlockCount = 128
execConfig.Caching.SnapshotCache = 0 // disable snapshots
execConfig.Caching.BlockAge = 0 // use only Caching.BlockCount to keep only last N blocks in dirties cache, no matter how new they are
execConfig.Sequencer.MaxBlockSpeed = 0
execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110
builder, cancelNode := prepareNodeWithHistory(t, ctx, execConfig, 16)
execNode, _ := builder.L2.ExecNode, builder.L2.Client
defer cancelNode()
bc := execNode.Backend.ArbInterface().BlockChain()
api := execNode.Backend.APIBackend()

header := bc.CurrentBlock()
if header == nil {
Fatal(t, "failed to get current block header")
}
state, _, err := api.StateAndHeaderByNumber(ctx, rpc.BlockNumber(header.Number.Uint64()))
Require(t, err)
addr := builder.L2Info.GetAddress("User2")
exists := state.Exist(addr)
err = state.Error()
Require(t, err)
if !exists {
Fatal(t, "User2 address does not exist in the state")
}
// Get the state again to avoid caching
state, _, err = api.StateAndHeaderByNumber(ctx, rpc.BlockNumber(header.Number.Uint64()))
Require(t, err)

blockCountRequiredToFlushDirties := builder.execConfig.Caching.BlockCount
makeSomeTransfers(t, ctx, builder, blockCountRequiredToFlushDirties)

exists = state.Exist(addr)
err = state.Error()
Require(t, err)
if !exists {
Fatal(t, "User2 address does not exist in the state")
}
}