mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
core: calculate changeset inside stateupdate
Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
parent
a6f31d86c2
commit
5ab49e9342
2 changed files with 116 additions and 94 deletions
|
|
@ -45,7 +45,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/internal/syncx"
|
||||
|
|
@ -1589,7 +1588,22 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
return err
|
||||
}
|
||||
// Tracing the state changes if the logger is enabled.
|
||||
bc.handleStateUpdates(block, update)
|
||||
if bc.logger != nil && bc.logger.OnStateCommit != nil {
|
||||
sc := update.IntoChangeset()
|
||||
bc.logger.OnStateCommit(&tracing.StateUpdate{
|
||||
Number: block.NumberU64(),
|
||||
Hash: block.Hash(),
|
||||
Time: block.Time(),
|
||||
Accounts: int64(sc.Accounts),
|
||||
AccountSize: int64(sc.AccountSize),
|
||||
Storages: int64(sc.Storages),
|
||||
StorageSize: int64(sc.StorageSize),
|
||||
Trienodes: int64(sc.Trienodes),
|
||||
TrienodeSize: int64(sc.TrienodeSize),
|
||||
Codes: int64(sc.Codes),
|
||||
CodeSize: int64(sc.CodeSize),
|
||||
})
|
||||
}
|
||||
// If node is running in path mode, skip explicit gc operation
|
||||
// which is unnecessary in this mode.
|
||||
if bc.triedb.Scheme() == rawdb.PathScheme {
|
||||
|
|
@ -1651,98 +1665,6 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
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.
|
||||
// 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) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import (
|
|||
"maps"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
)
|
||||
|
|
@ -192,3 +194,101 @@ func (sc *StateUpdate) stateSet() *triedb.StateSet {
|
|||
RawStorageKey: sc.RawStorageKey,
|
||||
}
|
||||
}
|
||||
|
||||
// StateChangeset represents a state mutations that occurred during the execution of a block.
|
||||
type StateChangeset struct {
|
||||
Accounts int // Total number of accounts present in the state at this block
|
||||
Storages int // Total number of storage entries across all accounts in the state at this block
|
||||
Trienodes int // Total number of trie nodes present in the state at this block
|
||||
Codes int // Total number of contract codes present in the state at this block, with 32 bytes hash as the identifier
|
||||
AccountSize int // Combined size of all accounts in the state, with 20 bytes address as the identifier
|
||||
StorageSize int // Combined size of all storage entries, with 32 bytes key as the identifier
|
||||
TrienodeSize int // Combined size of all trie nodes, with varying size node path as the identifier (up to 64 bytes)
|
||||
CodeSize int // Combined size of all contract codes in the state, with 20 bytes address as the identifier
|
||||
}
|
||||
|
||||
// IntoChangeset converts the current StateUpdate into a StateChangeset.
|
||||
func (sc *StateUpdate) IntoChangeset() *StateChangeset {
|
||||
var (
|
||||
accountSize, storageSize, nodeSize, codeSize int
|
||||
accounts, storages, nodes, codes int
|
||||
)
|
||||
|
||||
for addr, oldValue := range sc.AccountsOrigin {
|
||||
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||
newValue, exists := sc.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 sc.StoragesOrigin {
|
||||
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||
subset, exists := sc.Storages[addrHash]
|
||||
if !exists {
|
||||
log.Warn("State update missing storage", "address", addr)
|
||||
continue
|
||||
}
|
||||
for key, oldValue := range slots {
|
||||
var (
|
||||
exists bool
|
||||
newValue []byte
|
||||
)
|
||||
if sc.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 sc.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 sc.Codes {
|
||||
codes += 1
|
||||
codeSize += code.CodeLen() + common.HashLength // no deduplication
|
||||
}
|
||||
|
||||
return &StateChangeset{
|
||||
Accounts: accounts,
|
||||
AccountSize: accountSize,
|
||||
Storages: storages,
|
||||
StorageSize: storageSize,
|
||||
Trienodes: nodes,
|
||||
TrienodeSize: nodeSize,
|
||||
Codes: codes,
|
||||
CodeSize: codeSize,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue