mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +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
|
|
@ -49,6 +49,7 @@ func NewBlockAccessListTracer(startIdx int) (*BlockAccessListTracer, *tracing.Ho
|
||||||
OnStorageChange: balTracer.OnStorageChange,
|
OnStorageChange: balTracer.OnStorageChange,
|
||||||
OnColdAccountRead: balTracer.OnColdAccountRead,
|
OnColdAccountRead: balTracer.OnColdAccountRead,
|
||||||
OnColdStorageRead: balTracer.OnColdStorageRead,
|
OnColdStorageRead: balTracer.OnColdStorageRead,
|
||||||
|
OnSelfDestructChange: balTracer.OnSelfDestruct,
|
||||||
}
|
}
|
||||||
wrappedHooks, err := tracing.WrapWithJournal(hooks)
|
wrappedHooks, err := tracing.WrapWithJournal(hooks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -107,6 +108,10 @@ func (a *BlockAccessListTracer) OnCodeChange(addr common.Address, prevCodeHash c
|
||||||
a.accessListBuilder.CodeChange(addr, prevCode, code)
|
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) {
|
func (a *BlockAccessListTracer) OnBalanceChange(addr common.Address, prevBalance, newBalance *big.Int, _ tracing.BalanceChangeReason) {
|
||||||
newU256 := new(uint256.Int).SetBytes(newBalance.Bytes())
|
newU256 := new(uint256.Int).SetBytes(newBalance.Bytes())
|
||||||
prevU256 := new(uint256.Int).SetBytes(prevBalance.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) {
|
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
defer s.inner.Finalise(deleteEmptyObjects)
|
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 {
|
for addr := range s.inner.journal.dirties {
|
||||||
obj := s.inner.stateObjects[addr]
|
obj := s.inner.stateObjects[addr]
|
||||||
if obj != nil && obj.selfDestructed {
|
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 ether was sent to account post-selfdestruct it is burnt.
|
||||||
if s.hooks.OnBalanceChange != nil {
|
if s.hooks.OnBalanceChange != nil {
|
||||||
if bal := obj.Balance(); bal.Sign() != 0 {
|
if bal := obj.Balance(); bal.Sign() != 0 {
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,8 @@ type (
|
||||||
// ColdAccountReadHook is called before an previously-unread account is read.
|
// ColdAccountReadHook is called before an previously-unread account is read.
|
||||||
ColdAccountReadHook = func(address common.Address)
|
ColdAccountReadHook = func(address common.Address)
|
||||||
|
|
||||||
|
SelfDestructHook = func(address common.Address)
|
||||||
|
|
||||||
// LogHook is called when a log is emitted.
|
// LogHook is called when a log is emitted.
|
||||||
LogHook = func(log *types.Log)
|
LogHook = func(log *types.Log)
|
||||||
|
|
||||||
|
|
@ -224,6 +226,7 @@ type Hooks struct {
|
||||||
OnCodeChangeV2 CodeChangeHookV2
|
OnCodeChangeV2 CodeChangeHookV2
|
||||||
OnStorageChange StorageChangeHook
|
OnStorageChange StorageChangeHook
|
||||||
OnLog LogHook
|
OnLog LogHook
|
||||||
|
OnSelfDestructChange SelfDestructHook
|
||||||
//State read events
|
//State read events
|
||||||
OnColdStorageRead ColdStorageReadHook
|
OnColdStorageRead ColdStorageReadHook
|
||||||
OnColdAccountRead ColdAccountReadHook
|
OnColdAccountRead ColdAccountReadHook
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,10 @@ func (c *AccessListBuilder) CodeChange(address common.Address, prev, cur []byte)
|
||||||
acctAccesses.CodeChange(cur)
|
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) {
|
func (c *AccessListBuilder) NonceChange(address common.Address, prev, cur uint64) {
|
||||||
if _, ok := c.prestates[address]; !ok {
|
if _, ok := c.prestates[address]; !ok {
|
||||||
c.prestates[address] = &AccountState{}
|
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:
|
// two scenarios where an account can become non-existent:
|
||||||
// account was created/deleted in the same transaction
|
// 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
|
// account only had balance set (prefunded), was target of create2 initcode which called SENDALL leaving the account empty
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue