mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
core: handle state updates
Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
parent
ee35dd98d9
commit
b1ef709ace
2 changed files with 102 additions and 1 deletions
|
|
@ -45,6 +45,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/syncx"
|
"github.com/ethereum/go-ethereum/internal/syncx"
|
||||||
|
|
@ -1583,15 +1584,18 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
log.Crit("Failed to write block into disk", "err", err)
|
log.Crit("Failed to write block into disk", "err", err)
|
||||||
}
|
}
|
||||||
// Commit all cached state changes into underlying memory database.
|
// Commit all cached state changes into underlying memory database.
|
||||||
root, err := statedb.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.chainConfig.IsCancun(block.Number(), block.Time()))
|
update, err := statedb.CommitWithUpdate(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.chainConfig.IsCancun(block.Number(), block.Time()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Tracing the state changes if the logger is enabled.
|
||||||
|
bc.handleStateUpdates(block, update)
|
||||||
// If node is running in path mode, skip explicit gc operation
|
// If node is running in path mode, skip explicit gc operation
|
||||||
// which is unnecessary in this mode.
|
// which is unnecessary in this mode.
|
||||||
if bc.triedb.Scheme() == rawdb.PathScheme {
|
if bc.triedb.Scheme() == rawdb.PathScheme {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
root := update.Root
|
||||||
// If we're running an archive node, always flush
|
// If we're running an archive node, always flush
|
||||||
if bc.cfg.ArchiveMode {
|
if bc.cfg.ArchiveMode {
|
||||||
return bc.triedb.Commit(root, false)
|
return bc.triedb.Commit(root, false)
|
||||||
|
|
@ -1647,6 +1651,98 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *BlockChain) handleStateUpdates(block *types.Block, update *state.StateUpdate) {
|
||||||
|
if bc.logger == nil || bc.logger.OnStateCommit != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
accountSize, storageSize, nodeSize, codeSize int
|
||||||
|
accounts, storages, nodes, codes int
|
||||||
|
)
|
||||||
|
|
||||||
|
for addr, oldValue := range update.AccountsOrigin {
|
||||||
|
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||||
|
newValue, exists := update.Accounts[addrHash]
|
||||||
|
if !exists {
|
||||||
|
log.Warn("State update missing account", "address", addr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(newValue) == 0 {
|
||||||
|
accounts -= 1
|
||||||
|
accountSize -= common.AddressLength
|
||||||
|
}
|
||||||
|
if len(oldValue) == 0 {
|
||||||
|
accounts += 1
|
||||||
|
accountSize += common.AddressLength
|
||||||
|
}
|
||||||
|
accountSize += len(newValue) - len(oldValue)
|
||||||
|
}
|
||||||
|
for addr, slots := range update.StoragesOrigin {
|
||||||
|
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||||
|
subset, exists := update.Storages[addrHash]
|
||||||
|
if !exists {
|
||||||
|
log.Warn("State update missing storage", "address", addr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for key, oldValue := range slots {
|
||||||
|
var (
|
||||||
|
exists bool
|
||||||
|
newValue []byte
|
||||||
|
)
|
||||||
|
if update.RawStorageKey {
|
||||||
|
newValue, exists = subset[crypto.Keccak256Hash(key.Bytes())]
|
||||||
|
} else {
|
||||||
|
newValue, exists = subset[key]
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
log.Warn("State update missing storage slot", "address", addr, "key", key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(newValue) == 0 {
|
||||||
|
storages -= 1
|
||||||
|
storageSize -= common.HashLength
|
||||||
|
}
|
||||||
|
if len(oldValue) == 0 {
|
||||||
|
storages += 1
|
||||||
|
storageSize += common.HashLength
|
||||||
|
}
|
||||||
|
storageSize += len(newValue) - len(oldValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, subset := range update.Nodes.Sets {
|
||||||
|
for path, n := range subset.Nodes {
|
||||||
|
if len(n.Blob) == 0 {
|
||||||
|
nodes -= 1
|
||||||
|
nodeSize -= len(path) + common.HashLength
|
||||||
|
}
|
||||||
|
if n.OriginLen() == 0 {
|
||||||
|
nodes += 1
|
||||||
|
nodeSize += len(path) + common.HashLength
|
||||||
|
}
|
||||||
|
nodeSize += len(n.Blob) - n.OriginLen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, code := range update.Codes {
|
||||||
|
codes += 1
|
||||||
|
codeSize += code.CodeLen() + common.HashLength // no deduplication
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.logger.OnStateCommit(&tracing.StateUpdate{
|
||||||
|
Number: block.NumberU64(),
|
||||||
|
Hash: block.Hash(),
|
||||||
|
Time: block.Time(),
|
||||||
|
Accounts: int64(accounts),
|
||||||
|
AccountSize: int64(accountSize),
|
||||||
|
Storages: int64(storages),
|
||||||
|
StorageSize: int64(storageSize),
|
||||||
|
Trienodes: int64(nodes),
|
||||||
|
TrienodeSize: int64(nodeSize),
|
||||||
|
Codes: int64(codes),
|
||||||
|
CodeSize: int64(codeSize),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
||||||
// This function expects the chain mutex to be held.
|
// This function expects the chain mutex to be held.
|
||||||
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ type contractCode struct {
|
||||||
blob []byte // blob is the binary representation of the contract code.
|
blob []byte // blob is the binary representation of the contract code.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CodeLen returns the length of the contract code blob.
|
||||||
|
func (c *contractCode) CodeLen() int {
|
||||||
|
return len(c.blob)
|
||||||
|
}
|
||||||
|
|
||||||
// accountDelete represents an operation for deleting an Ethereum account.
|
// accountDelete represents an operation for deleting an Ethereum account.
|
||||||
type accountDelete struct {
|
type accountDelete struct {
|
||||||
address common.Address // address is the unique account identifier
|
address common.Address // address is the unique account identifier
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue