Skip to content

Commit 09ce003

Browse files
core/state: correct account selfdestruct EIP-6780 (part of 7702) (#53)
* pick up ethereum/go-ethereum#29520 * core/state: update test cases * core/state: fix SetStorage override behavior (#30185) This pull request fixes the broken feature where the entire storage set is overridden. Originally, the storage set override was achieved by marking the associated account as deleted, preventing access to the storage slot on disk. However, since #29520, this flag is also checked when accessing the account, rendering the account unreachable. A fix has been applied in this pull request, which re-creates a new state object with all account metadata inherited. * fixup! pick up ethereum/go-ethereum#29520 * fixup! core/state: fix SetStorage override behavior (#30185) --------- Co-authored-by: rjl493456442 <[email protected]>
1 parent ed539c9 commit 09ce003

File tree

10 files changed

+570
-396
lines changed

10 files changed

+570
-396
lines changed

core/state/journal.go

Lines changed: 120 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package state
1818

1919
import (
20+
"maps"
2021
"math/big"
2122

2223
"github.com/ethereum/go-ethereum/common"
@@ -30,6 +31,9 @@ type journalEntry interface {
3031

3132
// dirtied returns the Ethereum address modified by this journal entry.
3233
dirtied() *common.Address
34+
35+
// copy returns a deep-copied journal entry.
36+
copy() journalEntry
3337
}
3438

3539
// journal contains the list of state modifications applied since the last state
@@ -84,25 +88,30 @@ func (j *journal) length() int {
8488
return len(j.entries)
8589
}
8690

91+
// copy returns a deep-copied journal.
92+
func (j *journal) copy() *journal {
93+
entries := make([]journalEntry, 0, j.length())
94+
for i := 0; i < j.length(); i++ {
95+
entries = append(entries, j.entries[i].copy())
96+
}
97+
return &journal{
98+
entries: entries,
99+
dirties: maps.Clone(j.dirties),
100+
}
101+
}
102+
87103
type (
88104
// Changes to the account trie.
89105
createObjectChange struct {
90106
account *common.Address
91107
}
92-
resetObjectChange struct {
93-
account *common.Address
94-
prev *stateObject
95-
prevdestruct bool
96-
97-
// tracking previous states of accounts and storages in snapshot, before each transaction
98-
prevAccount []byte
99-
prevStorage map[common.Hash][]byte
100-
101-
// tracking previous states of accounts and storages in trie, before each commit
102-
prevAccountOriginExist bool
103-
prevAccountOrigin []byte
104-
prevStorageOrigin map[common.Hash][]byte
108+
// createContractChange represents an account becoming a contract-account.
109+
// This event happens prior to executing initcode. The journal-event simply
110+
// manages the created-flag, in order to allow same-tx destruction.
111+
createContractChange struct {
112+
account common.Address
105113
}
114+
106115
selfDestructChange struct {
107116
account *common.Address
108117
prev bool // whether account had already self-destructed
@@ -157,34 +166,30 @@ type (
157166

158167
func (ch createObjectChange) revert(s *StateDB) {
159168
delete(s.stateObjects, *ch.account)
160-
delete(s.stateObjectsDirty, *ch.account)
161169
}
162170

163171
func (ch createObjectChange) dirtied() *common.Address {
164172
return ch.account
165173
}
166174

167-
func (ch resetObjectChange) revert(s *StateDB) {
168-
s.setStateObject(ch.prev)
169-
if !ch.prevdestruct && s.snap != nil {
170-
delete(s.stateObjectsDestruct, ch.prev.address)
171-
}
172-
if ch.prevAccountOriginExist {
173-
s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin
174-
}
175-
if ch.prevStorageOrigin != nil {
176-
s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin
177-
}
178-
if ch.prevAccount != nil {
179-
s.accounts[ch.prev.addrHash] = ch.prevAccount
180-
}
181-
if ch.prevStorage != nil {
182-
s.storages[ch.prev.addrHash] = ch.prevStorage
175+
func (ch createObjectChange) copy() journalEntry {
176+
return createObjectChange{
177+
account: ch.account,
183178
}
184179
}
185180

186-
func (ch resetObjectChange) dirtied() *common.Address {
187-
return ch.account
181+
func (ch createContractChange) revert(s *StateDB) {
182+
s.getStateObject(ch.account).newContract = false
183+
}
184+
185+
func (ch createContractChange) dirtied() *common.Address {
186+
return nil
187+
}
188+
189+
func (ch createContractChange) copy() journalEntry {
190+
return createContractChange{
191+
account: ch.account,
192+
}
188193
}
189194

190195
func (ch selfDestructChange) revert(s *StateDB) {
@@ -199,6 +204,14 @@ func (ch selfDestructChange) dirtied() *common.Address {
199204
return ch.account
200205
}
201206

207+
func (ch selfDestructChange) copy() journalEntry {
208+
return selfDestructChange{
209+
account: ch.account,
210+
prev: ch.prev,
211+
prevbalance: new(big.Int).Set(ch.prevbalance),
212+
}
213+
}
214+
202215
var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
203216

204217
func (ch touchChange) revert(s *StateDB) {
@@ -208,6 +221,12 @@ func (ch touchChange) dirtied() *common.Address {
208221
return ch.account
209222
}
210223

224+
func (ch touchChange) copy() journalEntry {
225+
return touchChange{
226+
account: ch.account,
227+
}
228+
}
229+
211230
func (ch balanceChange) revert(s *StateDB) {
212231
s.getStateObject(*ch.account).setBalance(ch.prev)
213232
}
@@ -216,6 +235,13 @@ func (ch balanceChange) dirtied() *common.Address {
216235
return ch.account
217236
}
218237

238+
func (ch balanceChange) copy() journalEntry {
239+
return balanceChange{
240+
account: ch.account,
241+
prev: new(big.Int).Set(ch.prev),
242+
}
243+
}
244+
219245
func (ch nonceChange) revert(s *StateDB) {
220246
s.getStateObject(*ch.account).setNonce(ch.prev)
221247
}
@@ -224,6 +250,13 @@ func (ch nonceChange) dirtied() *common.Address {
224250
return ch.account
225251
}
226252

253+
func (ch nonceChange) copy() journalEntry {
254+
return nonceChange{
255+
account: ch.account,
256+
prev: ch.prev,
257+
}
258+
}
259+
227260
func (ch codeChange) revert(s *StateDB) {
228261
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
229262
}
@@ -232,6 +265,14 @@ func (ch codeChange) dirtied() *common.Address {
232265
return ch.account
233266
}
234267

268+
func (ch codeChange) copy() journalEntry {
269+
return codeChange{
270+
account: ch.account,
271+
prevhash: common.CopyBytes(ch.prevhash),
272+
prevcode: common.CopyBytes(ch.prevcode),
273+
}
274+
}
275+
235276
func (ch storageChange) revert(s *StateDB) {
236277
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
237278
}
@@ -240,6 +281,14 @@ func (ch storageChange) dirtied() *common.Address {
240281
return ch.account
241282
}
242283

284+
func (ch storageChange) copy() journalEntry {
285+
return storageChange{
286+
account: ch.account,
287+
key: ch.key,
288+
prevalue: ch.prevalue,
289+
}
290+
}
291+
243292
func (ch transientStorageChange) revert(s *StateDB) {
244293
s.setTransientState(*ch.account, ch.key, ch.prevalue)
245294
}
@@ -248,6 +297,14 @@ func (ch transientStorageChange) dirtied() *common.Address {
248297
return nil
249298
}
250299

300+
func (ch transientStorageChange) copy() journalEntry {
301+
return transientStorageChange{
302+
account: ch.account,
303+
key: ch.key,
304+
prevalue: ch.prevalue,
305+
}
306+
}
307+
251308
func (ch refundChange) revert(s *StateDB) {
252309
s.refund = ch.prev
253310
}
@@ -256,6 +313,12 @@ func (ch refundChange) dirtied() *common.Address {
256313
return nil
257314
}
258315

316+
func (ch refundChange) copy() journalEntry {
317+
return refundChange{
318+
prev: ch.prev,
319+
}
320+
}
321+
259322
func (ch addLogChange) revert(s *StateDB) {
260323
logs := s.logs[ch.txhash]
261324
if len(logs) == 1 {
@@ -270,6 +333,12 @@ func (ch addLogChange) dirtied() *common.Address {
270333
return nil
271334
}
272335

336+
func (ch addLogChange) copy() journalEntry {
337+
return addLogChange{
338+
txhash: ch.txhash,
339+
}
340+
}
341+
273342
func (ch addPreimageChange) revert(s *StateDB) {
274343
delete(s.preimages, ch.hash)
275344
}
@@ -278,6 +347,12 @@ func (ch addPreimageChange) dirtied() *common.Address {
278347
return nil
279348
}
280349

350+
func (ch addPreimageChange) copy() journalEntry {
351+
return addPreimageChange{
352+
hash: ch.hash,
353+
}
354+
}
355+
281356
func (ch accessListAddAccountChange) revert(s *StateDB) {
282357
/*
283358
One important invariant here, is that whenever a (addr, slot) is added, if the
@@ -299,6 +374,19 @@ func (ch accessListAddSlotChange) revert(s *StateDB) {
299374
s.accessList.DeleteSlot(*ch.address, *ch.slot)
300375
}
301376

377+
func (ch accessListAddAccountChange) copy() journalEntry {
378+
return accessListAddAccountChange{
379+
address: ch.address,
380+
}
381+
}
382+
302383
func (ch accessListAddSlotChange) dirtied() *common.Address {
303384
return nil
304385
}
386+
387+
func (ch accessListAddSlotChange) copy() journalEntry {
388+
return accessListAddSlotChange{
389+
address: ch.address,
390+
slot: ch.slot,
391+
}
392+
}

0 commit comments

Comments
 (0)