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

Integrate CaptureArbitrumStorageGet/Set into the prestate tracer #2602

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions arbos/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (s *Storage) Get(key common.Hash) (common.Hash, error) {
return common.Hash{}, err
}
if info := s.burner.TracingInfo(); info != nil {
info.RecordStorageGet(key)
info.RecordStorageGet(s.mapAddress(key))
}
return s.GetFree(key), nil
}
Expand Down Expand Up @@ -167,7 +167,7 @@ func (s *Storage) Set(key common.Hash, value common.Hash) error {
return err
}
if info := s.burner.TracingInfo(); info != nil {
info.RecordStorageSet(key, value)
info.RecordStorageSet(s.mapAddress(key), value)
}
s.db.SetState(s.account, s.mapAddress(key), value)
return nil
Expand Down
2 changes: 1 addition & 1 deletion go-ethereum
61 changes: 61 additions & 0 deletions system_tests/debugapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package arbtest
import (
"context"
"encoding/json"
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -13,9 +14,18 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/rpc"

"github.com/offchainlabs/nitro/arbos/arbosState"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/solgen/go/precompilesgen"
)

type account struct {
Balance *hexutil.Big `json:"balance,omitempty"`
Code []byte `json:"code,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
}

func TestDebugAPI(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down Expand Up @@ -57,3 +67,54 @@ func TestDebugAPI(t *testing.T) {
err = l2rpc.CallContext(ctx, &result, "debug_traceTransaction", tx.Hash(), &tracers.TraceConfig{Tracer: &flatCallTracer})
Require(t, err)
}

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

builder := NewNodeBuilder(ctx).DefaultConfig(t, false)
cleanup := builder.Build(t)
defer cleanup()

auth := builder.L2Info.GetDefaultTransactOpts("Owner", ctx)
arbOwner, err := precompilesgen.NewArbOwner(common.HexToAddress("0x70"), builder.L2.Client)
Require(t, err, "could not bind ArbOwner contract")

// Schedule a noop upgrade
tx, err := arbOwner.ScheduleArbOSUpgrade(&auth, 1, 1)
Require(t, err)
_, err = builder.L2.EnsureTxSucceeded(tx)
Require(t, err)

statedb, err := builder.L2.ExecNode.Backend.ArbInterface().BlockChain().State()
Require(t, err)
burner := burn.NewSystemBurner(nil, false)
arbosSt, err := arbosState.OpenArbosState(statedb, burner)
Require(t, err)

l2rpc := builder.L2.Stack.Attach()
var result map[common.Address]*account
prestateTracer := "prestateTracer"
err = l2rpc.CallContext(ctx, &result, "debug_traceTransaction", tx.Hash(), &tracers.TraceConfig{Tracer: &prestateTracer})
Require(t, err)

// ArbOSVersion and BrotliCompressionLevel storage slots should be accessed by arbos so we check if the current values of these appear in the prestateTrace
arbOSVersionHash := common.BigToHash(new(big.Int).SetUint64(arbosSt.ArbOSVersion()))
bcl, err := arbosSt.BrotliCompressionLevel()
Require(t, err)
bclHash := common.BigToHash(new(big.Int).SetUint64(bcl))

if _, ok := result[types.ArbosStateAddress]; !ok {
t.Fatal("ArbosStateAddress storage accesses not logged in the prestateTracer's trace")
}

found := 0
for _, val := range result[types.ArbosStateAddress].Storage {
if val == arbOSVersionHash || val == bclHash {
found++
}
}
if found != 2 {
t.Fatal("ArbosStateAddress storage accesses for ArbOSVersion and BrotliCompressionLevel not logged in the prestateTracer's trace")
}
}
12 changes: 12 additions & 0 deletions system_tests/precompile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package arbtest

import (
"context"
"encoding/json"
"fmt"
"math/big"
"sort"
Expand Down Expand Up @@ -539,6 +540,17 @@ func TestScheduleArbosUpgrade(t *testing.T) {
t.Errorf("expected completed scheduled upgrade to be ignored, got version %v timestamp %v", scheduled.ArbosVersion, scheduled.ScheduledForTimestamp)
}

l2rpc := builder.L2.Stack.Attach()
var result json.RawMessage
traceConfig := map[string]interface{}{
"tracer": "prestateTracer",
"tracerConfig": map[string]interface{}{
"diffMode": true,
},
}
err = l2rpc.CallContext(ctx, &result, "debug_traceTransaction", tx.Hash(), traceConfig)
Require(t, err)

// TODO: Once we have an ArbOS 30, test a real upgrade with it
// We can't test 11 -> 20 because 11 doesn't have the GetScheduledUpgrade method we want to test
var testVersion uint64 = 100
Expand Down
Loading