Skip to content

Commit

Permalink
Add a test for storage trie determinism
Browse files Browse the repository at this point in the history
This includes a new BigMap contract in the nitro-contracts repo in the mocks
package.

The test attempts to set a lot of storage slots to some value in one
transaction, and then to clear 75% of them and add 10% more values in a second
transaction.

Finally, validation is run to ensure that the validator is behaving correctly.

The idea is that this test will pass validation with the state db's
deterministic flag set, but fail without it set.

Related to: NIT-3068
  • Loading branch information
eljobe committed Jan 31, 2025
1 parent 1d9c68d commit 5356621
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
2 changes: 1 addition & 1 deletion contracts
Submodule contracts updated 270 files
13 changes: 13 additions & 0 deletions system_tests/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ func (tc *TestClient) SendWaitTestTransactions(t *testing.T, txs []*types.Transa
return SendWaitTestTransactions(t, tc.ctx, tc.Client, txs)
}

func (tc *TestClient) DeployBigMap(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.BigMap) {
return deployBigMap(t, tc.ctx, auth, tc.Client)
}

func (tc *TestClient) DeploySimple(t *testing.T, auth bind.TransactOpts) (common.Address, *mocksgen.Simple) {
return deploySimple(t, tc.ctx, auth, tc.Client)
}
Expand Down Expand Up @@ -1713,6 +1717,15 @@ func getDeadlineTimeout(t *testing.T, defaultTimeout time.Duration) time.Duratio
return timeout
}

func deployBigMap(t *testing.T, ctx context.Context, auth bind.TransactOpts, client *ethclient.Client,
) (common.Address, *mocksgen.BigMap) {
addr, tx, bigMap, err := mocksgen.DeployBigMap(&auth, client)
Require(t, err, "could not deploy BigMap.sol contract")
_, err = EnsureTxSucceeded(ctx, client, tx)
Require(t, err)
return addr, bigMap
}

func deploySimple(
t *testing.T, ctx context.Context, auth bind.TransactOpts, client *ethclient.Client,
) (common.Address, *mocksgen.Simple) {
Expand Down
74 changes: 74 additions & 0 deletions system_tests/storage_trie_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2025, Offchain Labs, Inc.
// For license information, see:
// https://github.com/OffchainLabs/nitro/blob/master/LICENSE.md

package arbtest

import (
"context"
"math/big"
"testing"
"time"

"github.com/ethereum/go-ethereum/core/rawdb"

"github.com/offchainlabs/nitro/util/arbmath"
"github.com/offchainlabs/nitro/validator/valnode"
)

var withL1 = true

func TestStorageTrie(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

builder := NewNodeBuilder(ctx).DefaultConfig(t, withL1)

// retryableSetup is being called by tests that validate blocks.
// For now validation only works with HashScheme set.
builder.execConfig.Caching.StateScheme = rawdb.HashScheme
builder.nodeConfig.BlockValidator.Enable = false
builder.nodeConfig.Staker.Enable = true
builder.nodeConfig.BatchPoster.Enable = true
builder.nodeConfig.ParentChainReader.Enable = true
builder.nodeConfig.ParentChainReader.OldHeaderTimeout = 10 * time.Minute

valConf := valnode.TestValidationConfig
valConf.UseJit = true
_, valStack := createTestValidationNode(t, ctx, &valConf)
configByValidationNode(builder.nodeConfig, valStack)

cleanup := builder.Build(t)
defer cleanup()

ownerTxOpts := builder.L2Info.GetDefaultTransactOpts("Owner", ctx)
_, bigMap := builder.L2.DeployBigMap(t, ownerTxOpts)

// Store enough values to use just over 32M gas
values := big.NewInt(1431)

userTxOpts := builder.L2Info.GetDefaultTransactOpts("Faucet", ctx)
tx, err := bigMap.StoreValues(&userTxOpts, values)
Require(t, err)

receipt, err := builder.L2.EnsureTxSucceeded(tx)
Require(t, err)

if receipt.GasUsed != 32_002_907 {
t.Errorf("Want GasUsed: 32002907: got: %d", receipt.GasUsed)
}

// Clear about 75% of them, and add another 10%
toClear := arbmath.BigDiv(arbmath.BigMul(values, big.NewInt(75)), big.NewInt(100))
toAdd := arbmath.BigDiv(arbmath.BigMul(values, big.NewInt(10)), big.NewInt(100))

tx, err = bigMap.ClearAndAddValues(&userTxOpts, toClear, toAdd)
Require(t, err)

receipt, err = builder.L2.EnsureTxSucceeded(tx)
Require(t, err)

// Ensures that the validator gets the same results as the executor
validateBlockRange(t, []uint64{receipt.BlockNumber.Uint64()}, true, builder)
}

0 comments on commit 5356621

Please sign in to comment.