mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 05:06:43 +00:00
add dedicated selfdestruct hook (TODO: this commit is bugged because a prefunded account which is the target of a create2 initcode can become empty without explicitly selfdestructing
This commit is contained in:
parent
cb632f0345
commit
12311ee59e
4 changed files with 39 additions and 18 deletions
|
|
@ -39,16 +39,17 @@ func NewBlockAccessListTracer(startIdx int) (*BlockAccessListTracer, *tracing.Ho
|
|||
accessListBuilder: bal.NewAccessListBuilder(),
|
||||
}
|
||||
hooks := &tracing.Hooks{
|
||||
OnTxEnd: balTracer.TxEndHook,
|
||||
OnTxStart: balTracer.TxStartHook,
|
||||
OnEnter: balTracer.OnEnter,
|
||||
OnExit: balTracer.OnExit,
|
||||
OnCodeChangeV2: balTracer.OnCodeChange,
|
||||
OnBalanceChange: balTracer.OnBalanceChange,
|
||||
OnNonceChangeV2: balTracer.OnNonceChange,
|
||||
OnStorageChange: balTracer.OnStorageChange,
|
||||
OnColdAccountRead: balTracer.OnColdAccountRead,
|
||||
OnColdStorageRead: balTracer.OnColdStorageRead,
|
||||
OnTxEnd: balTracer.TxEndHook,
|
||||
OnTxStart: balTracer.TxStartHook,
|
||||
OnEnter: balTracer.OnEnter,
|
||||
OnExit: balTracer.OnExit,
|
||||
OnCodeChangeV2: balTracer.OnCodeChange,
|
||||
OnBalanceChange: balTracer.OnBalanceChange,
|
||||
OnNonceChangeV2: balTracer.OnNonceChange,
|
||||
OnStorageChange: balTracer.OnStorageChange,
|
||||
OnColdAccountRead: balTracer.OnColdAccountRead,
|
||||
OnColdStorageRead: balTracer.OnColdStorageRead,
|
||||
OnSelfDestructChange: balTracer.OnSelfDestruct,
|
||||
}
|
||||
wrappedHooks, err := tracing.WrapWithJournal(hooks)
|
||||
if err != nil {
|
||||
|
|
@ -107,6 +108,10 @@ func (a *BlockAccessListTracer) OnCodeChange(addr common.Address, prevCodeHash c
|
|||
a.accessListBuilder.CodeChange(addr, prevCode, code)
|
||||
}
|
||||
|
||||
func (a *BlockAccessListTracer) OnSelfDestruct(addr common.Address) {
|
||||
a.accessListBuilder.SelfDestruct(addr)
|
||||
}
|
||||
|
||||
func (a *BlockAccessListTracer) OnBalanceChange(addr common.Address, prevBalance, newBalance *big.Int, _ tracing.BalanceChangeReason) {
|
||||
newU256 := new(uint256.Int).SetBytes(newBalance.Bytes())
|
||||
prevU256 := new(uint256.Int).SetBytes(prevBalance.Bytes())
|
||||
|
|
|
|||
|
|
@ -254,10 +254,13 @@ func (s *hookedStateDB) AddLog(log *types.Log) {
|
|||
|
||||
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) {
|
||||
defer s.inner.Finalise(deleteEmptyObjects)
|
||||
if s.hooks.OnBalanceChange != nil || s.hooks.OnNonceChangeV2 != nil || s.hooks.OnCodeChangeV2 != nil || s.hooks.OnCodeChange != nil {
|
||||
if s.hooks.OnSelfDestructChange != nil || s.hooks.OnBalanceChange != nil || s.hooks.OnNonceChangeV2 != nil || s.hooks.OnCodeChangeV2 != nil || s.hooks.OnCodeChange != nil {
|
||||
for addr := range s.inner.journal.dirties {
|
||||
obj := s.inner.stateObjects[addr]
|
||||
if obj != nil && obj.selfDestructed {
|
||||
if s.hooks.OnSelfDestructChange != nil {
|
||||
s.hooks.OnSelfDestructChange(obj.address)
|
||||
}
|
||||
// If ether was sent to account post-selfdestruct it is burnt.
|
||||
if s.hooks.OnBalanceChange != nil {
|
||||
if bal := obj.Balance(); bal.Sign() != 0 {
|
||||
|
|
|
|||
|
|
@ -189,6 +189,8 @@ type (
|
|||
// ColdAccountReadHook is called before an previously-unread account is read.
|
||||
ColdAccountReadHook = func(address common.Address)
|
||||
|
||||
SelfDestructHook = func(address common.Address)
|
||||
|
||||
// LogHook is called when a log is emitted.
|
||||
LogHook = func(log *types.Log)
|
||||
|
||||
|
|
@ -217,13 +219,14 @@ type Hooks struct {
|
|||
OnSystemCallEnd OnSystemCallEndHook
|
||||
|
||||
// State events
|
||||
OnBalanceChange BalanceChangeHook
|
||||
OnNonceChange NonceChangeHook
|
||||
OnNonceChangeV2 NonceChangeHookV2
|
||||
OnCodeChange CodeChangeHook
|
||||
OnCodeChangeV2 CodeChangeHookV2
|
||||
OnStorageChange StorageChangeHook
|
||||
OnLog LogHook
|
||||
OnBalanceChange BalanceChangeHook
|
||||
OnNonceChange NonceChangeHook
|
||||
OnNonceChangeV2 NonceChangeHookV2
|
||||
OnCodeChange CodeChangeHook
|
||||
OnCodeChangeV2 CodeChangeHookV2
|
||||
OnStorageChange StorageChangeHook
|
||||
OnLog LogHook
|
||||
OnSelfDestructChange SelfDestructHook
|
||||
//State read events
|
||||
OnColdStorageRead ColdStorageReadHook
|
||||
OnColdAccountRead ColdAccountReadHook
|
||||
|
|
|
|||
|
|
@ -133,6 +133,10 @@ func (c *AccessListBuilder) CodeChange(address common.Address, prev, cur []byte)
|
|||
acctAccesses.CodeChange(cur)
|
||||
}
|
||||
|
||||
func (c *AccessListBuilder) SelfDestruct(address common.Address) {
|
||||
delete(c.accessesStack[len(c.accessesStack)-1], address)
|
||||
}
|
||||
|
||||
func (c *AccessListBuilder) NonceChange(address common.Address, prev, cur uint64) {
|
||||
if _, ok := c.prestates[address]; !ok {
|
||||
c.prestates[address] = &AccountState{}
|
||||
|
|
@ -203,6 +207,12 @@ func (a *AccessListBuilder) FinaliseIdxChanges() (*StateDiff, StateAccesses) {
|
|||
}
|
||||
}
|
||||
|
||||
// two cases of account being removed:
|
||||
// * initcode runs at address, calls SENDALL (account could be prefunded, but not pre-existing as a contract)
|
||||
// - if the account makes storage mutations, we have no way to distinguish it from a regular contract that didn't selfdestruct
|
||||
//
|
||||
// * contract created in same tx calls SENDALL
|
||||
|
||||
// two scenarios where an account can become non-existent:
|
||||
// account was created/deleted in the same transaction
|
||||
// account only had balance set (prefunded), was target of create2 initcode which called SENDALL leaving the account empty
|
||||
|
|
|
|||
Loading…
Reference in a new issue