Skip to content

Commit 4a9ce10

Browse files
holimanrjl493456442
authored andcommitted
core/state: move state log mechanism to a separate layer (ethereum#30569)
This PR moves the logging/tracing-facilities out of `*state.StateDB`, in to a wrapping struct which implements `vm.StateDB` instead. In most places, it is a pretty straight-forward change: - First, hoisting the invocations from state objects up to the statedb. - Then making the mutation-methods simply return the previous value, so that the external logging layer could log everything. Some internal code uses the direct object-accessors to mutate the state, particularly in testing and in setting up state overrides, which means that these changes are unobservable for the hooked layer. Thus, configuring the overrides are not necessarily part of the API we want to publish. The trickiest part about the layering is that when the selfdestructs are finally deleted during `Finalise`, there's the possibility that someone sent some ether to it, which is burnt at that point, and thus needs to be logged. The hooked layer reaches into the inner layer to figure out these events. In package `vm`, the conversion from `state.StateDB + hooks` into a hooked `vm.StateDB` is performed where needed. --------- Co-authored-by: Gary Rong <garyrong0905@gmail.com>
1 parent b103828 commit 4a9ce10

25 files changed

+519
-138
lines changed

consensus/beacon/consensus.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/ethereum/go-ethereum/core/state"
2929
"github.com/ethereum/go-ethereum/core/tracing"
3030
"github.com/ethereum/go-ethereum/core/types"
31+
"github.com/ethereum/go-ethereum/core/vm"
3132
"github.com/ethereum/go-ethereum/params"
3233
"github.com/ethereum/go-ethereum/rpc"
3334
"github.com/ethereum/go-ethereum/trie"
@@ -349,7 +350,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
349350
}
350351

351352
// Finalize implements consensus.Engine and processes withdrawals on top.
352-
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
353+
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
353354
if !beacon.IsPoSHeader(header) {
354355
beacon.ethone.Finalize(chain, header, state, body)
355356
return

consensus/clique/clique.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
3636
"github.com/ethereum/go-ethereum/core/state"
3737
"github.com/ethereum/go-ethereum/core/types"
38+
"github.com/ethereum/go-ethereum/core/vm"
3839
"github.com/ethereum/go-ethereum/crypto"
3940
"github.com/ethereum/go-ethereum/ethdb"
4041
"github.com/ethereum/go-ethereum/log"
@@ -573,7 +574,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
573574

574575
// Finalize implements consensus.Engine. There is no post-transaction
575576
// consensus rules in clique, do nothing here.
576-
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
577+
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
577578
// No block rewards in PoA, so the state remains as is
578579
}
579580

consensus/consensus.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/ethereum/go-ethereum/common"
2424
"github.com/ethereum/go-ethereum/core/state"
2525
"github.com/ethereum/go-ethereum/core/types"
26+
"github.com/ethereum/go-ethereum/core/vm"
2627
"github.com/ethereum/go-ethereum/params"
2728
"github.com/ethereum/go-ethereum/rpc"
2829
)
@@ -88,7 +89,7 @@ type Engine interface {
8889
//
8990
// Note: The state database might be updated to reflect any consensus rules
9091
// that happen at finalization (e.g. block rewards).
91-
Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body)
92+
Finalize(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body)
9293

9394
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
9495
// rewards or process withdrawals) and assembles the final block.

consensus/ethash/consensus.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/ethereum/go-ethereum/core/state"
3131
"github.com/ethereum/go-ethereum/core/tracing"
3232
"github.com/ethereum/go-ethereum/core/types"
33+
"github.com/ethereum/go-ethereum/core/vm"
3334
"github.com/ethereum/go-ethereum/params"
3435
"github.com/ethereum/go-ethereum/rlp"
3536
"github.com/ethereum/go-ethereum/trie"
@@ -503,7 +504,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H
503504
}
504505

505506
// Finalize implements consensus.Engine, accumulating the block and uncle rewards.
506-
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
507+
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
507508
// Accumulate any block and uncle rewards
508509
accumulateRewards(chain.Config(), state, header, body.Uncles)
509510
}
@@ -566,7 +567,7 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
566567
// accumulateRewards credits the coinbase of the given block with the mining
567568
// reward. The total reward consists of the static block reward and rewards for
568569
// included uncles. The coinbase of each uncle block is also rewarded.
569-
func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, header *types.Header, uncles []*types.Header) {
570+
func accumulateRewards(config *params.ChainConfig, stateDB vm.StateDB, header *types.Header, uncles []*types.Header) {
570571
// Select the correct block reward based on chain progression
571572
blockReward := FrontierBlockReward
572573
if config.IsByzantium(header.Number) {

consensus/misc/dao.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ import (
2121
"errors"
2222
"math/big"
2323

24-
"github.com/ethereum/go-ethereum/core/state"
2524
"github.com/ethereum/go-ethereum/core/tracing"
2625
"github.com/ethereum/go-ethereum/core/types"
26+
"github.com/ethereum/go-ethereum/core/vm"
2727
"github.com/ethereum/go-ethereum/params"
28-
"github.com/holiman/uint256"
2928
)
3029

3130
var (
@@ -74,15 +73,16 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header)
7473
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
7574
// rules, transferring all balances of a set of DAO accounts to a single refund
7675
// contract.
77-
func ApplyDAOHardFork(statedb *state.StateDB) {
76+
func ApplyDAOHardFork(statedb vm.StateDB) {
7877
// Retrieve the contract to refund balances into
7978
if !statedb.Exist(params.DAORefundContract) {
8079
statedb.CreateAccount(params.DAORefundContract)
8180
}
8281

8382
// Move every DAO account and extra-balance account funds into the refund contract
8483
for _, addr := range params.DAODrainList() {
85-
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract)
86-
statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount)
84+
balance := statedb.GetBalance(addr)
85+
statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract)
86+
statedb.SubBalance(addr, balance, tracing.BalanceDecreaseDaoAccount)
8787
}
8888
}

core/blockchain.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1774,7 +1774,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
17741774
if err != nil {
17751775
return nil, it.index, err
17761776
}
1777-
statedb.SetLogger(bc.logger)
17781777

17791778
// If we are past Byzantium, enable prefetching to pull in trie node paths
17801779
// while processing transactions. Before Byzantium the prefetcher is mostly

core/state/state_object.go

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"time"
2424

2525
"github.com/ethereum/go-ethereum/common"
26-
"github.com/ethereum/go-ethereum/core/tracing"
2726
"github.com/ethereum/go-ethereum/core/types"
2827
"github.com/ethereum/go-ethereum/crypto"
2928
"github.com/ethereum/go-ethereum/log"
@@ -208,19 +207,18 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
208207
}
209208

210209
// SetState updates a value in account storage.
211-
func (s *stateObject) SetState(key, value common.Hash) {
210+
// It returns the previous value
211+
func (s *stateObject) SetState(key, value common.Hash) common.Hash {
212212
// If the new value is the same as old, don't set. Otherwise, track only the
213213
// dirty changes, supporting reverting all of it back to no change.
214214
prev, origin := s.getState(key)
215215
if prev == value {
216-
return
216+
return prev
217217
}
218218
// New value is different, update and journal the change
219219
s.db.journal.storageChange(s.address, key, prev, origin)
220220
s.setState(key, value, origin)
221-
if s.db.logger != nil && s.db.logger.OnStorageChange != nil {
222-
s.db.logger.OnStorageChange(s.address, key, prev, value)
223-
}
221+
return prev
224222
}
225223

226224
// setState updates a value in account dirty storage. The dirtiness will be
@@ -448,33 +446,25 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
448446

449447
// AddBalance adds amount to s's balance.
450448
// It is used to add funds to the destination account of a transfer.
451-
func (s *stateObject) AddBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) {
449+
// returns the previous balance
450+
func (s *stateObject) AddBalance(amount *uint256.Int) uint256.Int {
452451
// EIP161: We must check emptiness for the objects such that the account
453452
// clearing (0,0,0 objects) can take effect.
454453
if amount.IsZero() {
455454
if s.empty() {
456455
s.touch()
457456
}
458-
return
457+
return *(s.Balance())
459458
}
460-
s.SetBalance(new(uint256.Int).Add(s.Balance(), amount), reason)
459+
return s.SetBalance(new(uint256.Int).Add(s.Balance(), amount))
461460
}
462461

463-
// SubBalance removes amount from s's balance.
464-
// It is used to remove funds from the origin account of a transfer.
465-
func (s *stateObject) SubBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) {
466-
if amount.IsZero() {
467-
return
468-
}
469-
s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount), reason)
470-
}
471-
472-
func (s *stateObject) SetBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) {
462+
// SetBalance sets the balance for the object, and returns the previous balance.
463+
func (s *stateObject) SetBalance(amount *uint256.Int) uint256.Int {
464+
prev := *s.data.Balance
473465
s.db.journal.balanceChange(s.address, s.data.Balance)
474-
if s.db.logger != nil && s.db.logger.OnBalanceChange != nil {
475-
s.db.logger.OnBalanceChange(s.address, s.Balance().ToBig(), amount.ToBig(), reason)
476-
}
477466
s.setBalance(amount)
467+
return prev
478468
}
479469

480470
func (s *stateObject) setBalance(amount *uint256.Int) {
@@ -547,10 +537,6 @@ func (s *stateObject) CodeSize() int {
547537

548538
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
549539
s.db.journal.setCode(s.address)
550-
if s.db.logger != nil && s.db.logger.OnCodeChange != nil {
551-
// TODO remove prevcode from this callback
552-
s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), nil, codeHash, code)
553-
}
554540
s.setCode(codeHash, code)
555541
}
556542

@@ -562,9 +548,6 @@ func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
562548

563549
func (s *stateObject) SetNonce(nonce uint64) {
564550
s.db.journal.nonceChange(s.address, s.data.Nonce)
565-
if s.db.logger != nil && s.db.logger.OnNonceChange != nil {
566-
s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce)
567-
}
568551
s.setNonce(nonce)
569552
}
570553

core/state/state_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323

2424
"github.com/ethereum/go-ethereum/common"
2525
"github.com/ethereum/go-ethereum/core/rawdb"
26-
"github.com/ethereum/go-ethereum/core/tracing"
2726
"github.com/ethereum/go-ethereum/core/types"
2827
"github.com/ethereum/go-ethereum/crypto"
2928
"github.com/ethereum/go-ethereum/triedb"
@@ -48,11 +47,11 @@ func TestDump(t *testing.T) {
4847

4948
// generate a few entries
5049
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
51-
obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified)
50+
obj1.AddBalance(uint256.NewInt(22))
5251
obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
5352
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
5453
obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
55-
obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified)
54+
obj3.SetBalance(uint256.NewInt(44))
5655

5756
// write some of them to the trie
5857
s.state.updateStateObject(obj1)
@@ -106,13 +105,13 @@ func TestIterativeDump(t *testing.T) {
106105

107106
// generate a few entries
108107
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
109-
obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified)
108+
obj1.AddBalance(uint256.NewInt(22))
110109
obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
111110
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
112111
obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
113-
obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified)
112+
obj3.SetBalance(uint256.NewInt(44))
114113
obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00}))
115-
obj4.AddBalance(uint256.NewInt(1337), tracing.BalanceChangeUnspecified)
114+
obj4.AddBalance(uint256.NewInt(1337))
116115

117116
// write some of them to the trie
118117
s.state.updateStateObject(obj1)
@@ -200,7 +199,7 @@ func TestCreateObjectRevert(t *testing.T) {
200199

201200
state.CreateAccount(addr)
202201
so0 := state.getStateObject(addr)
203-
so0.SetBalance(uint256.NewInt(42), tracing.BalanceChangeUnspecified)
202+
so0.SetBalance(uint256.NewInt(42))
204203
so0.SetNonce(43)
205204
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
206205
state.setStateObject(so0)

0 commit comments

Comments
 (0)