mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
Merge 574f9027ae into 7c9032dff6
This commit is contained in:
commit
679860866a
6 changed files with 53 additions and 55 deletions
|
|
@ -764,44 +764,6 @@ func (s *StateDB) GetRefund() uint64 {
|
||||||
return s.refund
|
return s.refund
|
||||||
}
|
}
|
||||||
|
|
||||||
type removedAccountWithBalance struct {
|
|
||||||
address common.Address
|
|
||||||
balance *uint256.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogsForBurnAccounts returns the eth burn logs for accounts scheduled for
|
|
||||||
// removal which still have positive balance. The purpose of this function is
|
|
||||||
// to handle a corner case of EIP-7708 where a self-destructed account might
|
|
||||||
// still receive funds between sending/burning its previous balance and actual
|
|
||||||
// removal. In this case the burning of these remaining balances still need to
|
|
||||||
// be logged.
|
|
||||||
// Specification EIP-7708: https://eips.ethereum.org/EIPS/eip-7708
|
|
||||||
//
|
|
||||||
// This function should only be invoked at the transaction boundary, specifically
|
|
||||||
// before the Finalise.
|
|
||||||
func (s *StateDB) LogsForBurnAccounts() []*types.Log {
|
|
||||||
var list []removedAccountWithBalance
|
|
||||||
for addr := range s.journal.mutations {
|
|
||||||
if obj, exist := s.stateObjects[addr]; exist && obj.selfDestructed && !obj.Balance().IsZero() {
|
|
||||||
list = append(list, removedAccountWithBalance{
|
|
||||||
address: obj.address,
|
|
||||||
balance: obj.Balance(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if list == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
sort.Slice(list, func(i, j int) bool {
|
|
||||||
return list[i].address.Cmp(list[j].address) < 0
|
|
||||||
})
|
|
||||||
logs := make([]*types.Log, len(list))
|
|
||||||
for i, acct := range list {
|
|
||||||
logs[i] = types.EthBurnLog(acct.address, acct.balance)
|
|
||||||
}
|
|
||||||
return logs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finalise finalises the state by removing the destructed objects and clears
|
// Finalise finalises the state by removing the destructed objects and clears
|
||||||
// the journal as well as the refunds. Finalise, however, will not push any updates
|
// the journal as well as the refunds. Finalise, however, will not push any updates
|
||||||
// into the tries just yet. Only IntermediateRoot or Commit will do that.
|
// into the tries just yet. Only IntermediateRoot or Commit will do that.
|
||||||
|
|
@ -821,7 +783,40 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) *bal.ConstructionBlockAccess
|
||||||
// finalise or delete, so ignore it here.
|
// finalise or delete, so ignore it here.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) {
|
// EIP-8246: clear code/storage/nonce, preserve balance.
|
||||||
|
if obj.selfDestructed && s.stateAccessList != nil {
|
||||||
|
clearSelfdestructAccount(obj)
|
||||||
|
|
||||||
|
if deleteEmptyObjects && obj.empty() {
|
||||||
|
// Cleanup left account empty; delete per EIP-161.
|
||||||
|
delete(s.stateObjects, obj.address)
|
||||||
|
s.markDelete(addr)
|
||||||
|
if _, ok := s.stateObjectsDestruct[obj.address]; !ok {
|
||||||
|
s.stateObjectsDestruct[obj.address] = obj
|
||||||
|
}
|
||||||
|
balance := uint256.NewInt(0)
|
||||||
|
if state.balanceSet && balance.Cmp(state.balance) != 0 {
|
||||||
|
s.stateAccessList.BalanceChange(s.blockAccessIndex, addr, balance)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Keep as balance-only account.
|
||||||
|
balance := obj.Balance()
|
||||||
|
if state.balanceSet && balance.Cmp(state.balance) != 0 {
|
||||||
|
s.stateAccessList.BalanceChange(s.blockAccessIndex, addr, balance)
|
||||||
|
}
|
||||||
|
nonce := obj.Nonce()
|
||||||
|
if state.nonceSet && nonce != state.nonce {
|
||||||
|
s.stateAccessList.NonceChange(addr, s.blockAccessIndex, nonce)
|
||||||
|
}
|
||||||
|
if state.codeSet {
|
||||||
|
if code := obj.Code(); !bytes.Equal(code, state.code) {
|
||||||
|
s.stateAccessList.CodeChange(addr, s.blockAccessIndex, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj.finalise()
|
||||||
|
s.markUpdate(addr)
|
||||||
|
}
|
||||||
|
} else if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) {
|
||||||
delete(s.stateObjects, obj.address)
|
delete(s.stateObjects, obj.address)
|
||||||
s.markDelete(addr)
|
s.markDelete(addr)
|
||||||
|
|
||||||
|
|
@ -887,6 +882,17 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) *bal.ConstructionBlockAccess
|
||||||
return s.stateAccessList
|
return s.stateAccessList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clearSelfdestructAccount clears code, storage, and nonce for an EIP-8246
|
||||||
|
// selfdestructed account while preserving the balance.
|
||||||
|
func clearSelfdestructAccount(obj *stateObject) {
|
||||||
|
obj.data.CodeHash = types.EmptyCodeHash.Bytes()
|
||||||
|
obj.dirtyCode = true
|
||||||
|
obj.dirtyStorage = make(Storage)
|
||||||
|
obj.pendingStorage = make(Storage)
|
||||||
|
obj.originStorage = make(Storage)
|
||||||
|
obj.data.Nonce = 0
|
||||||
|
}
|
||||||
|
|
||||||
// IntermediateRoot computes the current root hash of the state trie.
|
// IntermediateRoot computes the current root hash of the state trie.
|
||||||
// It is called in between transactions to get the root hash that
|
// It is called in between transactions to get the root hash that
|
||||||
// goes into transaction receipts.
|
// goes into transaction receipts.
|
||||||
|
|
|
||||||
|
|
@ -230,10 +230,6 @@ func (s *hookedStateDB) AddLog(log *types.Log) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *hookedStateDB) LogsForBurnAccounts() []*types.Log {
|
|
||||||
return s.inner.LogsForBurnAccounts()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) *bal.ConstructionBlockAccessList {
|
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) *bal.ConstructionBlockAccessList {
|
||||||
if s.hooks.OnBalanceChange == nil && s.hooks.OnNonceChangeV2 == nil && s.hooks.OnNonceChange == nil && s.hooks.OnCodeChangeV2 == nil && s.hooks.OnCodeChange == nil {
|
if s.hooks.OnBalanceChange == nil && s.hooks.OnNonceChangeV2 == nil && s.hooks.OnNonceChange == nil && s.hooks.OnCodeChangeV2 == nil && s.hooks.OnCodeChange == nil {
|
||||||
// Short circuit if no relevant hooks are set.
|
// Short circuit if no relevant hooks are set.
|
||||||
|
|
@ -261,7 +257,8 @@ func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) *bal.ConstructionBlock
|
||||||
// Bingo: state object was self-destructed, call relevant hooks.
|
// Bingo: state object was self-destructed, call relevant hooks.
|
||||||
|
|
||||||
// If ether was sent to account post-selfdestruct, record as burnt.
|
// If ether was sent to account post-selfdestruct, record as burnt.
|
||||||
if s.hooks.OnBalanceChange != nil {
|
// EIP-8246: balance is preserved, skip the burn trace.
|
||||||
|
if s.hooks.OnBalanceChange != nil && s.inner.stateAccessList == nil {
|
||||||
if bal := obj.Balance(); bal.Sign() != 0 {
|
if bal := obj.Balance(); bal.Sign() != 0 {
|
||||||
s.hooks.OnBalanceChange(addr, bal.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestructBurn)
|
s.hooks.OnBalanceChange(addr, bal.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestructBurn)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -744,12 +744,6 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP-7708: Emit the ETH-burn logs
|
|
||||||
if rules.IsAmsterdam {
|
|
||||||
for _, log := range st.evm.StateDB.LogsForBurnAccounts() {
|
|
||||||
st.evm.StateDB.AddLog(log)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ExecutionResult{
|
return &ExecutionResult{
|
||||||
UsedGas: gasUsed,
|
UsedGas: gasUsed,
|
||||||
MaxUsedGas: peakUsed,
|
MaxUsedGas: peakUsed,
|
||||||
|
|
|
||||||
|
|
@ -916,7 +916,11 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro
|
||||||
if this != beneficiary { // Skip no-op transfer when self-destructing to self.
|
if this != beneficiary { // Skip no-op transfer when self-destructing to self.
|
||||||
evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct)
|
evm.StateDB.AddBalance(beneficiary, balance, tracing.BalanceIncreaseSelfdestruct)
|
||||||
}
|
}
|
||||||
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
// EIP-8246: if the beneficiary is the executing account itself and the fork
|
||||||
|
// is active, the balance remains unchanged instead of being burned.
|
||||||
|
if !evm.chainRules.IsAmsterdam || this != beneficiary {
|
||||||
|
evm.StateDB.SubBalance(this, balance, tracing.BalanceDecreaseSelfdestruct)
|
||||||
|
}
|
||||||
evm.StateDB.SelfDestruct(this)
|
evm.StateDB.SelfDestruct(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -928,8 +932,6 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro
|
||||||
if evm.chainRules.IsAmsterdam && !balance.IsZero() {
|
if evm.chainRules.IsAmsterdam && !balance.IsZero() {
|
||||||
if this != beneficiary {
|
if this != beneficiary {
|
||||||
evm.StateDB.AddLog(types.EthTransferLog(this, beneficiary, balance))
|
evm.StateDB.AddLog(types.EthTransferLog(this, beneficiary, balance))
|
||||||
} else if newContract {
|
|
||||||
evm.StateDB.AddLog(types.EthBurnLog(this, balance))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,6 @@ type StateDB interface {
|
||||||
Snapshot() int
|
Snapshot() int
|
||||||
|
|
||||||
AddLog(*types.Log)
|
AddLog(*types.Log)
|
||||||
LogsForBurnAccounts() []*types.Log
|
|
||||||
AddPreimage(common.Hash, []byte)
|
AddPreimage(common.Hash, []byte)
|
||||||
|
|
||||||
Witness() *stateless.Witness
|
Witness() *stateless.Witness
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ func TestProtocolHandshakeErrors(t *testing.T) {
|
||||||
p1, p2 := MsgPipe()
|
p1, p2 := MsgPipe()
|
||||||
go Send(p1, test.code, test.msg)
|
go Send(p1, test.code, test.msg)
|
||||||
_, err := readProtocolHandshake(p2)
|
_, err := readProtocolHandshake(p2)
|
||||||
if !reflect.DeepEqual(err, test.err) {
|
if err.Error() != test.err.Error() {
|
||||||
t.Errorf("test %d: error mismatch: got %q, want %q", i, err, test.err)
|
t.Errorf("test %d: error mismatch: got %q, want %q", i, err, test.err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue