diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index da1fb3701f..7ea6e578cc 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -423,7 +423,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB sdb := state.NewDatabase(tdb, nil) statedb, _ := state.New(types.EmptyRootHash, sdb) for addr, a := range accounts { - statedb.SetCode(addr, a.Code) + statedb.SetCode(addr, a.Code, tracing.CodeChangeUnspecified) statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis) statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance) for k, v := range a.Storage { diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index b2cf28353b..ebb3e04461 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -322,7 +322,7 @@ func runCmd(ctx *cli.Context) error { } } else { if len(code) > 0 { - prestate.SetCode(receiver, code) + prestate.SetCode(receiver, code, tracing.CodeChangeUnspecified) } execFunc = func() ([]byte, uint64, error) { // don't mutate the state! diff --git a/core/genesis.go b/core/genesis.go index f1a620da57..2673334e9e 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -153,7 +153,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) { if account.Balance != nil { statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance) } - statedb.SetCode(addr, account.Code) + statedb.SetCode(addr, account.Code, tracing.CodeChangeGenesis) statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis) for key, value := range account.Storage { statedb.SetState(addr, key, value) @@ -179,7 +179,7 @@ func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, e // already captures the allocations. statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance) } - statedb.SetCode(addr, account.Code) + statedb.SetCode(addr, account.Code, tracing.CodeChangeGenesis) statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis) for key, value := range account.Storage { statedb.SetState(addr, key, value) diff --git a/core/state/statedb.go b/core/state/statedb.go index 6474d3a2fa..cdfd638221 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -458,7 +458,7 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.Non } } -func (s *StateDB) SetCode(addr common.Address, code []byte) (prev []byte) { +func (s *StateDB) SetCode(addr common.Address, code []byte, reason tracing.CodeChangeReason) (prev []byte) { stateObject := s.getOrNewStateObject(addr) if stateObject != nil { return stateObject.SetCode(crypto.Keccak256Hash(code), code) diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go index 7dada63d45..f4761bd10c 100644 --- a/core/state/statedb_fuzz_test.go +++ b/core/state/statedb_fuzz_test.go @@ -89,7 +89,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction code := make([]byte, 16) binary.BigEndian.PutUint64(code, uint64(a.args[0])) binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) - s.SetCode(addr, code) + s.SetCode(addr, code, tracing.CodeChangeUnspecified) }, args: make([]int64, 2), }, diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index 556a3e6c49..d2595bcefe 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -189,14 +189,20 @@ func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tr } } -func (s *hookedStateDB) SetCode(address common.Address, code []byte) []byte { - prev := s.inner.SetCode(address, code) - if s.hooks.OnCodeChange != nil { +func (s *hookedStateDB) SetCode(address common.Address, code []byte, reason tracing.CodeChangeReason) []byte { + prev := s.inner.SetCode(address, code, reason) + if s.hooks.OnCodeChangeV2 != nil || s.hooks.OnCodeChange != nil { prevHash := types.EmptyCodeHash if len(prev) != 0 { prevHash = crypto.Keccak256Hash(prev) } - s.hooks.OnCodeChange(address, prevHash, prev, crypto.Keccak256Hash(code), code) + codeHash := crypto.Keccak256Hash(code) + + if s.hooks.OnCodeChangeV2 != nil { + s.hooks.OnCodeChangeV2(address, prevHash, prev, codeHash, code, reason) + } else if s.hooks.OnCodeChange != nil { + s.hooks.OnCodeChange(address, prevHash, prev, codeHash, code) + } } return prev } @@ -224,8 +230,12 @@ func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int { s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) } - if s.hooks.OnCodeChange != nil && len(prevCode) > 0 { - s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil) + if len(prevCode) > 0 { + if s.hooks.OnCodeChangeV2 != nil { + s.hooks.OnCodeChangeV2(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil, tracing.CodeChangeSelfDestruct) + } else if s.hooks.OnCodeChange != nil { + s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil) + } } return prev @@ -246,8 +256,12 @@ func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, b s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct) } - if s.hooks.OnCodeChange != nil && changed && len(prevCode) > 0 { - s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil) + if changed && len(prevCode) > 0 { + if s.hooks.OnCodeChangeV2 != nil { + s.hooks.OnCodeChangeV2(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil, tracing.CodeChangeSelfDestruct) + } else if s.hooks.OnCodeChange != nil { + s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil) + } } return prev, changed diff --git a/core/state/statedb_hooked_test.go b/core/state/statedb_hooked_test.go index f319b0e63c..bacb7baee1 100644 --- a/core/state/statedb_hooked_test.go +++ b/core/state/statedb_hooked_test.go @@ -114,7 +114,7 @@ func TestHooks(t *testing.T) { sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified) sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer) sdb.SetNonce(common.Address{0xaa}, 1337, tracing.NonceChangeGenesis) - sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37}) + sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37}, tracing.CodeChangeUnspecified) sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11")) sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22")) sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x01")) diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 67e27cc832..147546a3c7 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -65,7 +65,7 @@ func TestUpdateLeaks(t *testing.T) { state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) } if i%3 == 0 { - state.SetCode(addr, []byte{i, i, i, i, i}) + state.SetCode(addr, []byte{i, i, i, i, i}, tracing.CodeChangeUnspecified) } } @@ -101,7 +101,7 @@ func TestIntermediateLeaks(t *testing.T) { state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) } if i%3 == 0 { - state.SetCode(addr, []byte{i, i, i, i, i, tweak}) + state.SetCode(addr, []byte{i, i, i, i, i, tweak}, tracing.CodeChangeUnspecified) } } @@ -374,7 +374,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction { code := make([]byte, 16) binary.BigEndian.PutUint64(code, uint64(a.args[0])) binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) - s.SetCode(addr, code) + s.SetCode(addr, code, tracing.CodeChangeUnspecified) }, args: make([]int64, 2), }, @@ -403,7 +403,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction { // which would cause a difference in state when unrolling // the journal. (CreateContact assumes created was false prior to // invocation, and the journal rollback sets it to false). - s.SetCode(addr, []byte{1}) + s.SetCode(addr, []byte{1}, tracing.CodeChangeUnspecified) } }, }, @@ -731,7 +731,7 @@ func TestCopyCommitCopy(t *testing.T) { sval := common.HexToHash("bbb") state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata + state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata state.SetState(addr, skey, sval) // Change the storage trie if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { @@ -804,7 +804,7 @@ func TestCopyCopyCommitCopy(t *testing.T) { sval := common.HexToHash("bbb") state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata + state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata state.SetState(addr, skey, sval) // Change the storage trie if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { @@ -874,7 +874,7 @@ func TestCommitCopy(t *testing.T) { sval1, sval2 := common.HexToHash("b1"), common.HexToHash("b2") state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata + state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata state.SetState(addr, skey1, sval1) // Change the storage trie if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { @@ -987,10 +987,10 @@ func testMissingTrieNodes(t *testing.T, scheme string) { addr := common.BytesToAddress([]byte("so")) { state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified) - state.SetCode(addr, []byte{1, 2, 3}) + state.SetCode(addr, []byte{1, 2, 3}, tracing.CodeChangeUnspecified) a2 := common.BytesToAddress([]byte("another")) state.SetBalance(a2, uint256.NewInt(100), tracing.BalanceChangeUnspecified) - state.SetCode(a2, []byte{1, 2, 4}) + state.SetCode(a2, []byte{1, 2, 4}, tracing.CodeChangeUnspecified) root, _ = state.Commit(0, false, false) t.Logf("root: %x", root) // force-flush diff --git a/core/state/trie_prefetcher_test.go b/core/state/trie_prefetcher_test.go index 4d1b627c4d..41349c0c0e 100644 --- a/core/state/trie_prefetcher_test.go +++ b/core/state/trie_prefetcher_test.go @@ -39,7 +39,7 @@ func filledStateDB() *StateDB { sval := common.HexToHash("bbb") state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata + state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata state.SetState(addr, skey, sval) // Change the storage trie for i := 0; i < 100; i++ { sk := common.BigToHash(big.NewInt(int64(i))) @@ -81,7 +81,7 @@ func TestVerklePrefetcher(t *testing.T) { sval := testrand.Hash() state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata + state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata state.SetState(addr, skey, sval) // Change the storage trie root, _ := state.Commit(0, true, false) diff --git a/core/state_transition.go b/core/state_transition.go index 681c300696..2cafe4865f 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -617,12 +617,12 @@ func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization) st.state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization) if auth.Address == (common.Address{}) { // Delegation to zero address means clear. - st.state.SetCode(authority, nil) + st.state.SetCode(authority, nil, tracing.CodeChangeAuthorizationClear) return nil } // Otherwise install delegation to auth.Address. - st.state.SetCode(authority, types.AddressToDelegation(auth.Address)) + st.state.SetCode(authority, types.AddressToDelegation(auth.Address), tracing.CodeChangeAuthorization) return nil } diff --git a/core/tracing/gen_code_change_reason_stringer.go b/core/tracing/gen_code_change_reason_stringer.go new file mode 100644 index 0000000000..9372954063 --- /dev/null +++ b/core/tracing/gen_code_change_reason_stringer.go @@ -0,0 +1,29 @@ +// Code generated by "stringer -type=CodeChangeReason -trimprefix=CodeChange -output gen_code_change_reason_stringer.go"; DO NOT EDIT. + +package tracing + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[CodeChangeUnspecified-0] + _ = x[CodeChangeContractCreation-1] + _ = x[CodeChangeGenesis-2] + _ = x[CodeChangeAuthorization-3] + _ = x[CodeChangeAuthorizationClear-4] + _ = x[CodeChangeSelfDestruct-5] + _ = x[CodeChangeRevert-6] +} + +const _CodeChangeReason_name = "UnspecifiedContractCreationGenesisAuthorizationAuthorizationClearSelfDestructRevert" + +var _CodeChangeReason_index = [...]uint8{0, 11, 27, 34, 47, 65, 77, 83} + +func (i CodeChangeReason) String() string { + if i >= CodeChangeReason(len(_CodeChangeReason_index)-1) { + return "CodeChangeReason(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _CodeChangeReason_name[_CodeChangeReason_index[i]:_CodeChangeReason_index[i+1]] +} diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index 0485f7a3eb..8e50dc3d8f 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -177,6 +177,9 @@ type ( // CodeChangeHook is called when the code of an account changes. CodeChangeHook = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) + // CodeChangeHookV2 is called when the code of an account changes. + CodeChangeHookV2 = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason) + // StorageChangeHook is called when the storage of an account changes. StorageChangeHook = func(addr common.Address, slot common.Hash, prev, new common.Hash) @@ -211,6 +214,7 @@ type Hooks struct { OnNonceChange NonceChangeHook OnNonceChangeV2 NonceChangeHookV2 OnCodeChange CodeChangeHook + OnCodeChangeV2 CodeChangeHookV2 OnStorageChange StorageChangeHook OnLog LogHook // Block hash read @@ -372,3 +376,31 @@ const ( // It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal). NonceChangeRevert NonceChangeReason = 6 ) + +// CodeChangeReason is used to indicate the reason for a code change. +type CodeChangeReason byte + +//go:generate go run golang.org/x/tools/cmd/stringer -type=CodeChangeReason -trimprefix=CodeChange -output gen_code_change_reason_stringer.go + +const ( + CodeChangeUnspecified CodeChangeReason = 0 + + // CodeChangeContractCreation is when a new contract is deployed via CREATE/CREATE2 operations. + CodeChangeContractCreation CodeChangeReason = 1 + + // CodeChangeGenesis is when contract code is set during blockchain genesis or initial setup. + CodeChangeGenesis CodeChangeReason = 2 + + // CodeChangeAuthorization is when code is set via EIP-7702 Set Code Authorization. + CodeChangeAuthorization CodeChangeReason = 3 + + // CodeChangeAuthorizationClear is when EIP-7702 delegation is cleared by setting to zero address. + CodeChangeAuthorizationClear CodeChangeReason = 4 + + // CodeChangeSelfDestruct is when contract code is cleared due to self-destruct. + CodeChangeSelfDestruct CodeChangeReason = 5 + + // CodeChangeRevert is emitted when the code is reverted back to a previous value due to call failure. + // It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal). + CodeChangeRevert CodeChangeReason = 6 +) diff --git a/core/tracing/journal.go b/core/tracing/journal.go index a402f1ac09..62a70d6c27 100644 --- a/core/tracing/journal.go +++ b/core/tracing/journal.go @@ -42,12 +42,15 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) { return nil, errors.New("wrapping nil tracer") } // No state change to journal, return the wrapped hooks as is - if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil { + if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnCodeChangeV2 == nil && hooks.OnStorageChange == nil { return hooks, nil } if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil { return nil, errors.New("cannot have both OnNonceChange and OnNonceChangeV2") } + if hooks.OnCodeChange != nil && hooks.OnCodeChangeV2 != nil { + return nil, errors.New("cannot have both OnCodeChange and OnCodeChangeV2") + } // Create a new Hooks instance and copy all hooks wrapped := *hooks @@ -72,6 +75,9 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) { if hooks.OnCodeChange != nil { wrapped.OnCodeChange = j.OnCodeChange } + if hooks.OnCodeChangeV2 != nil { + wrapped.OnCodeChangeV2 = j.OnCodeChangeV2 + } if hooks.OnStorageChange != nil { wrapped.OnStorageChange = j.OnStorageChange } @@ -174,6 +180,19 @@ func (j *journal) OnCodeChange(addr common.Address, prevCodeHash common.Hash, pr } } +func (j *journal) OnCodeChangeV2(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason) { + j.entries = append(j.entries, codeChange{ + addr: addr, + prevCodeHash: prevCodeHash, + prevCode: prevCode, + newCodeHash: codeHash, + newCode: code, + }) + if j.hooks.OnCodeChangeV2 != nil { + j.hooks.OnCodeChangeV2(addr, prevCodeHash, prevCode, codeHash, code, reason) + } +} + func (j *journal) OnStorageChange(addr common.Address, slot common.Hash, prev, new common.Hash) { j.entries = append(j.entries, storageChange{addr: addr, slot: slot, prev: prev, new: new}) if j.hooks.OnStorageChange != nil { @@ -225,7 +244,9 @@ func (n nonceChange) revert(hooks *Hooks) { } func (c codeChange) revert(hooks *Hooks) { - if hooks.OnCodeChange != nil { + if hooks.OnCodeChangeV2 != nil { + hooks.OnCodeChangeV2(c.addr, c.newCodeHash, c.newCode, c.prevCodeHash, c.prevCode, CodeChangeRevert) + } else if hooks.OnCodeChange != nil { hooks.OnCodeChange(c.addr, c.newCodeHash, c.newCode, c.prevCodeHash, c.prevCode) } } diff --git a/core/tracing/journal_test.go b/core/tracing/journal_test.go index 99447e1e1d..cf74d83483 100644 --- a/core/tracing/journal_test.go +++ b/core/tracing/journal_test.go @@ -23,6 +23,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) type testTracer struct { @@ -56,6 +57,11 @@ func (t *testTracer) OnCodeChange(addr common.Address, prevCodeHash common.Hash, t.code = code } +func (t *testTracer) OnCodeChangeV2(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason) { + t.t.Logf("OnCodeChangeV2(%v, %v -> %v, %v)", addr, prevCodeHash, codeHash, reason) + t.code = code +} + func (t *testTracer) OnStorageChange(addr common.Address, slot common.Hash, prev common.Hash, new common.Hash) { t.t.Logf("OnStorageCodeChange(%v, %v, %v -> %v)", addr, slot, prev, new) if t.storage == nil { @@ -232,6 +238,27 @@ func TestOnNonceChangeV2(t *testing.T) { } } +func TestOnCodeChangeV2(t *testing.T) { + tr := &testTracer{t: t} + wr, err := WrapWithJournal(&Hooks{OnCodeChangeV2: tr.OnCodeChangeV2}) + if err != nil { + t.Fatalf("failed to wrap test tracer: %v", err) + } + + addr := common.HexToAddress("0x1234") + code := []byte{1, 2, 3} + { + wr.OnEnter(2, 0, addr, addr, nil, 1000, big.NewInt(0)) + wr.OnCodeChangeV2(addr, common.Hash{}, nil, crypto.Keccak256Hash(code), code, CodeChangeContractCreation) + wr.OnExit(2, nil, 100, nil, true) + } + + // After revert, code should be nil + if tr.code != nil { + t.Fatalf("unexpected code after revert: %v", tr.code) + } +} + func TestAllHooksCalled(t *testing.T) { tracer := newTracerAllHooks() hooks := tracer.hooks() @@ -298,6 +325,7 @@ func newTracerAllHooks() *tracerAllHooks { t.hooksCalled[hooksType.Field(i).Name] = false } delete(t.hooksCalled, "OnNonceChange") + delete(t.hooksCalled, "OnCodeChange") return t } @@ -322,7 +350,7 @@ func (t *tracerAllHooks) hooks() *Hooks { hooksValue := reflect.ValueOf(h).Elem() for i := 0; i < hooksValue.NumField(); i++ { field := hooksValue.Type().Field(i) - if field.Name == "OnNonceChange" { + if field.Name == "OnNonceChange" || field.Name == "OnCodeChange" { continue } hookMethod := reflect.MakeFunc(field.Type, func(args []reflect.Value) []reflect.Value { diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 1ba080b749..0c8642659d 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -2292,8 +2292,8 @@ func TestSetCodeTransactions(t *testing.T) { pending: 1, run: func(name string) { aa := common.Address{0xaa, 0xaa} - statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...)) - statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}) + statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...), tracing.CodeChangeUnspecified) + statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}, tracing.CodeChangeUnspecified) // Send gapped transaction, it should be rejected. if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrOutOfOrderTxFromDelegated) { @@ -2317,7 +2317,7 @@ func TestSetCodeTransactions(t *testing.T) { } // Reset the delegation, avoid leaking state into the other tests - statedb.SetCode(addrA, nil) + statedb.SetCode(addrA, nil, tracing.CodeChangeUnspecified) }, }, { @@ -2583,7 +2583,7 @@ func TestSetCodeTransactionsReorg(t *testing.T) { } // Simulate the chain moving blockchain.statedb.SetNonce(addrA, 1, tracing.NonceChangeAuthorization) - blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address)) + blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address), tracing.CodeChangeUnspecified) <-pool.requestReset(nil, nil) // Set an authorization for 0x00 auth, _ = types.SignSetCode(keyA, types.SetCodeAuthorization{ @@ -2601,7 +2601,7 @@ func TestSetCodeTransactionsReorg(t *testing.T) { } // Simulate the chain moving blockchain.statedb.SetNonce(addrA, 2, tracing.NonceChangeAuthorization) - blockchain.statedb.SetCode(addrA, nil) + blockchain.statedb.SetCode(addrA, nil, tracing.CodeChangeUnspecified) <-pool.requestReset(nil, nil) // Now send two transactions from addrA if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); err != nil { diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go index ed85d1555f..ca0c928c3c 100644 --- a/core/verkle_witness_test.go +++ b/core/verkle_witness_test.go @@ -232,7 +232,7 @@ func TestProcessParentBlockHash(t *testing.T) { // etc checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) { statedb.SetNonce(params.HistoryStorageAddress, 1, tracing.NonceChangeUnspecified) - statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode) + statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode, tracing.CodeChangeUnspecified) // Process n blocks, from 1 .. num var num = 2 for i := 1; i <= num; i++ { diff --git a/core/vm/evm.go b/core/vm/evm.go index e360187f7b..88ef1cf121 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -601,7 +601,7 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b } } - evm.StateDB.SetCode(address, ret) + evm.StateDB.SetCode(address, ret, tracing.CodeChangeContractCreation) return ret, nil } diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index cb6143c0b5..7fe76b0a63 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -87,7 +88,7 @@ func TestEIP2200(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) statedb.CreateAccount(address) - statedb.SetCode(address, hexutil.MustDecode(tt.input)) + statedb.SetCode(address, hexutil.MustDecode(tt.input), tracing.CodeChangeUnspecified) statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original})) statedb.Finalise(true) // Push the state into the "original" slot @@ -139,7 +140,7 @@ func TestCreateGas(t *testing.T) { address := common.BytesToAddress([]byte("contract")) statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) statedb.CreateAccount(address) - statedb.SetCode(address, hexutil.MustDecode(tt.code)) + statedb.SetCode(address, hexutil.MustDecode(tt.code), tracing.CodeChangeUnspecified) statedb.Finalise(true) vmctx := BlockContext{ CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true }, diff --git a/core/vm/interface.go b/core/vm/interface.go index 42a72db482..d7f4c10e1f 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -43,7 +43,7 @@ type StateDB interface { GetCode(common.Address) []byte // SetCode sets the new code for the address, and returns the previous code, if any. - SetCode(common.Address, []byte) []byte + SetCode(common.Address, []byte, tracing.CodeChangeReason) []byte GetCodeSize(common.Address) int AddRefund(uint64) diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 8ed512316b..90eeda34e6 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -45,7 +46,7 @@ func TestLoopInterrupt(t *testing.T) { for i, tt := range loopInterruptTests { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) statedb.CreateAccount(address) - statedb.SetCode(address, common.Hex2Bytes(tt)) + statedb.SetCode(address, common.Hex2Bytes(tt), tracing.CodeChangeUnspecified) statedb.Finalise(true) evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{}) diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 9d984291f2..b40e99d047 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -139,7 +140,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) cfg.State.CreateAccount(address) // set the receiver's (the executing contract) code for execution. - cfg.State.SetCode(address, code) + cfg.State.SetCode(address, code, tracing.CodeChangeUnspecified) // Call the code with the given configuration. ret, leftOverGas, err := vmenv.Call( cfg.Origin, diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index d75a5b0459..cabc57d1fb 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -114,7 +114,7 @@ func TestCall(t *testing.T) { byte(vm.PUSH1), 32, byte(vm.PUSH1), 0, byte(vm.RETURN), - }) + }, tracing.CodeChangeUnspecified) ret, _, err := Call(address, nil, &Config{State: state}) if err != nil { @@ -167,7 +167,7 @@ func benchmarkEVM_Create(bench *testing.B, code string) { ) statedb.CreateAccount(sender) - statedb.SetCode(receiver, common.FromHex(code)) + statedb.SetCode(receiver, common.FromHex(code), tracing.CodeChangeUnspecified) runtimeConfig := Config{ Origin: sender, State: statedb, @@ -232,7 +232,7 @@ func BenchmarkEVM_SWAP1(b *testing.B) { b.Run("10k", func(b *testing.B) { contractCode := swapContract(10_000) - state.SetCode(contractAddr, contractCode) + state.SetCode(contractAddr, contractCode, tracing.CodeChangeUnspecified) for i := 0; i < b.N; i++ { _, _, err := Call(contractAddr, []byte{}, &Config{State: state}) @@ -263,7 +263,7 @@ func BenchmarkEVM_RETURN(b *testing.B) { b.ReportAllocs() contractCode := returnContract(n) - state.SetCode(contractAddr, contractCode) + state.SetCode(contractAddr, contractCode, tracing.CodeChangeUnspecified) for i := 0; i < b.N; i++ { ret, _, err := Call(contractAddr, []byte{}, &Config{State: state}) @@ -422,12 +422,12 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.REVERT), - }) + }, tracing.CodeChangeUnspecified) } //cfg.State.CreateAccount(cfg.Origin) // set the receiver's (the executing contract) code for execution. - cfg.State.SetCode(destination, code) + cfg.State.SetCode(destination, code, tracing.CodeChangeUnspecified) Call(destination, nil, cfg) b.Run(name, func(b *testing.B) { @@ -772,12 +772,12 @@ func TestRuntimeJSTracer(t *testing.T) { for i, jsTracer := range jsTracers { for j, tc := range tests { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) - statedb.SetCode(main, tc.code) - statedb.SetCode(common.HexToAddress("0xbb"), calleeCode) - statedb.SetCode(common.HexToAddress("0xcc"), calleeCode) - statedb.SetCode(common.HexToAddress("0xdd"), calleeCode) - statedb.SetCode(common.HexToAddress("0xee"), calleeCode) - statedb.SetCode(common.HexToAddress("0xff"), suicideCode) + statedb.SetCode(main, tc.code, tracing.CodeChangeUnspecified) + statedb.SetCode(common.HexToAddress("0xbb"), calleeCode, tracing.CodeChangeUnspecified) + statedb.SetCode(common.HexToAddress("0xcc"), calleeCode, tracing.CodeChangeUnspecified) + statedb.SetCode(common.HexToAddress("0xdd"), calleeCode, tracing.CodeChangeUnspecified) + statedb.SetCode(common.HexToAddress("0xee"), calleeCode, tracing.CodeChangeUnspecified) + statedb.SetCode(common.HexToAddress("0xff"), suicideCode, tracing.CodeChangeUnspecified) tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil, params.MergedTestChainConfig) if err != nil { @@ -862,8 +862,8 @@ func BenchmarkTracerStepVsCallFrame(b *testing.B) { // delegation designator incurs the correct amount of gas based on the tracer. func TestDelegatedAccountAccessCost(t *testing.T) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) - statedb.SetCode(common.HexToAddress("0xff"), types.AddressToDelegation(common.HexToAddress("0xaa"))) - statedb.SetCode(common.HexToAddress("0xaa"), program.New().Return(0, 0).Bytes()) + statedb.SetCode(common.HexToAddress("0xff"), types.AddressToDelegation(common.HexToAddress("0xaa")), tracing.CodeChangeUnspecified) + statedb.SetCode(common.HexToAddress("0xaa"), program.New().Return(0, 0).Bytes(), tracing.CodeChangeUnspecified) for i, tc := range []struct { code []byte diff --git a/internal/ethapi/override/override.go b/internal/ethapi/override/override.go index 0bcf3c444d..9d57a78651 100644 --- a/internal/ethapi/override/override.go +++ b/internal/ethapi/override/override.go @@ -91,7 +91,7 @@ func (diff *StateOverride) Apply(statedb *state.StateDB, precompiles vm.Precompi } // Override account(contract) code. if account.Code != nil { - statedb.SetCode(addr, *account.Code) + statedb.SetCode(addr, *account.Code, tracing.CodeChangeUnspecified) } // Override account balance. if account.Balance != nil { diff --git a/tests/state_test_util.go b/tests/state_test_util.go index a22e470ad8..ec7eec1f39 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -511,7 +511,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo sdb := state.NewDatabase(triedb, nil) statedb, _ := state.New(types.EmptyRootHash, sdb) for addr, a := range accounts { - statedb.SetCode(addr, a.Code) + statedb.SetCode(addr, a.Code, tracing.CodeChangeUnspecified) statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeUnspecified) statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceChangeUnspecified) for k, v := range a.Storage {