Skip to content
Merged
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
2 changes: 1 addition & 1 deletion cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down
4 changes: 2 additions & 2 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
},
Expand Down
30 changes: 22 additions & 8 deletions core/state/statedb_hooked.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb_hooked_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
18 changes: 9 additions & 9 deletions core/state/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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),
},
Expand Down Expand Up @@ -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)
}
},
},
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions core/state/trie_prefetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
29 changes: 29 additions & 0 deletions core/tracing/gen_code_change_reason_stringer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions core/tracing/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -211,6 +214,7 @@ type Hooks struct {
OnNonceChange NonceChangeHook
OnNonceChangeV2 NonceChangeHookV2
OnCodeChange CodeChangeHook
OnCodeChangeV2 CodeChangeHookV2
OnStorageChange StorageChangeHook
OnLog LogHook
// Block hash read
Expand Down Expand Up @@ -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
)
25 changes: 23 additions & 2 deletions core/tracing/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
}
Expand Down
Loading