Skip to content

Commit f2a7287

Browse files
committed
1 parent ed539c9 commit f2a7287

File tree

3 files changed

+342
-243
lines changed

3 files changed

+342
-243
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+
}

core/state/state_object.go

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,8 @@ import (
3434

3535
var emptyCodeHash = crypto.Keccak256(nil)
3636

37-
type Code []byte
38-
39-
func (c Code) String() string {
40-
return string(c) //strings.Join(Disassemble(c), " ")
41-
}
42-
4337
type Storage map[common.Hash]common.Hash
4438

45-
func (s Storage) String() (str string) {
46-
for key, value := range s {
47-
str += fmt.Sprintf("%X : %X\n", key, value)
48-
}
49-
50-
return
51-
}
52-
5339
func (s Storage) Copy() Storage {
5440
cpy := make(Storage)
5541
for key, value := range s {
@@ -80,8 +66,8 @@ type stateObject struct {
8066
dbErr error
8167

8268
// Write caches.
83-
trie Trie // storage trie, which becomes non-nil on first access
84-
code Code // contract bytecode, which gets set when code is loaded
69+
trie Trie // storage trie, which becomes non-nil on first access
70+
code []byte // contract bytecode, which gets set when code is loaded
8571

8672
originStorage Storage // Storage cache of original entries to dedup rewrites
8773
pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block
@@ -91,17 +77,16 @@ type stateObject struct {
9177
// Cache flags.
9278
dirtyCode bool // true if the code was updated
9379

94-
// Flag whether the account was marked as selfDestructed. The selfDestructed account
95-
// is still accessible in the scope of same transaction.
80+
// Flag whether the account was marked as self-destructed. The self-destructed
81+
// account is still accessible in the scope of same transaction.
9682
selfDestructed bool
9783

98-
// Flag whether the account was marked as deleted. The selfDestructed account
99-
// or the account is considered as empty will be marked as deleted at
100-
// the end of transaction and no longer accessible anymore.
101-
deleted bool
102-
103-
// Flag whether the object was created in the current transaction
104-
created bool
84+
// This is an EIP-6780 flag indicating whether the object is eligible for
85+
// self-destruct according to EIP-6780. The flag could be set either when
86+
// the contract is just created within the current transaction, or when the
87+
// object was previously existent and is being deployed as a contract within
88+
// the current transaction.
89+
newContract bool
10590
}
10691

10792
// empty returns whether the account is considered empty.
@@ -332,6 +317,10 @@ func (s *stateObject) finalise(prefetch bool) {
332317
if len(s.dirtyStorage) > 0 {
333318
s.dirtyStorage = make(Storage)
334319
}
320+
// Revoke the flag at the end of the transaction. It finalizes the status
321+
// of the newly-created object as it's no longer eligible for self-destruct
322+
// by EIP-6780. For non-newly-created objects, it's a no-op.
323+
s.newContract = false
335324
}
336325

337326
// updateTrie writes cached storage modifications into the object's storage trie.
@@ -518,12 +507,12 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject {
518507
stateObject.trie = db.db.CopyTrie(s.trie)
519508
}
520509
stateObject.code = s.code
521-
stateObject.dirtyStorage = s.dirtyStorage.Copy()
522510
stateObject.originStorage = s.originStorage.Copy()
523511
stateObject.pendingStorage = s.pendingStorage.Copy()
524-
stateObject.selfDestructed = s.selfDestructed
512+
stateObject.dirtyStorage = s.dirtyStorage.Copy()
525513
stateObject.dirtyCode = s.dirtyCode
526-
stateObject.deleted = s.deleted
514+
stateObject.selfDestructed = s.selfDestructed
515+
stateObject.newContract = s.newContract
527516
return stateObject
528517
}
529518

@@ -538,7 +527,7 @@ func (s *stateObject) Address() common.Address {
538527

539528
// Code returns the contract code associated with this object, if any.
540529
func (s *stateObject) Code() []byte {
541-
if s.code != nil {
530+
if len(s.code) != 0 {
542531
return s.code
543532
}
544533
if bytes.Equal(s.CodeHash(), emptyCodeHash) {
@@ -556,7 +545,7 @@ func (s *stateObject) Code() []byte {
556545
// or zero if none. This method is an almost mirror of Code, but uses a cache
557546
// inside the database to avoid loading codes seen recently.
558547
func (s *stateObject) CodeSize(db Database) int {
559-
if s.code != nil {
548+
if len(s.code) != 0 {
560549
return len(s.code)
561550
}
562551
if bytes.Equal(s.CodeHash(), emptyCodeHash) {

0 commit comments

Comments
 (0)