Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upstream: merge geth date 1210 #2799

Merged
merged 45 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
66d8185
version: begin v1.14.13 release cycle
holiman Nov 19, 2024
aa63692
version: fix typo in v1.14.13 release cycle name
holiman Nov 19, 2024
6d3d252
core/vm/program: evm bytecode-building utility (#30725)
holiman Nov 20, 2024
e3d61e6
core, eth, internal, cmd: rework EVM constructor (#30745)
rjl493456442 Nov 20, 2024
a25be32
core, eth, internal, miner: remove unnecessary parameters (#30776)
rjl493456442 Nov 22, 2024
2cd25fd
internal/ethapi: remove double map-clone (#30788)
hyunsooda Nov 22, 2024
16f2f71
all: typos in comments (#30779)
wangjingcun Nov 22, 2024
6eeff3e
trie: replace custom logic with bytes.HasPrefix (#30771)
j2gg0s Nov 22, 2024
6485d5e
core, triedb: remove destruct flag in state snapshot (#30752)
rjl493456442 Nov 22, 2024
5e1a39d
internal/flags: fix "flag redefined" bug for alias on custom flags (#…
gzliudan Nov 24, 2024
ab4a1cc
eth/tracers/logger: fix json-logger output missing (#30804)
holiman Nov 25, 2024
02159d5
eth/tracers/logger: improve markdown logger (#30805)
holiman Nov 25, 2024
19fa71b
internal/ethapi: remove double map-clone (#30803)
hyunsooda Nov 25, 2024
3c754e2
accounts/abi: fix MakeTopics mutation of big.Int inputs (#30785)
jmank88 Nov 25, 2024
2380012
core/state/snapshot: simplify snapshot rebuild (#30772)
ARR4N Nov 25, 2024
b4d99e3
eth/ethconfig: improve error message if TTD missing (#30807)
fjl Nov 26, 2024
d7e7b54
core/tracing: add GetCodeHash to StateDB (#30784)
nebojsa94 Nov 26, 2024
a11b4be
Revert "core/state/snapshot: simplify snapshot rebuild (#30772)" (#30…
rjl493456442 Nov 26, 2024
915248c
cmd/evm: don't reuse state between iterations, show errors (#30780)
jwasinger Nov 26, 2024
e0deac7
core: better document reason for dropping error on return (#30811)
wangjingcun Nov 27, 2024
8c1a36d
core/state/snapshot: handle legacy journal (#30802)
rjl493456442 Nov 28, 2024
2406305
trie: combine validation loops in VerifyRangeProof (#30823)
weiihann Nov 28, 2024
db8eed8
all: exclude empty outputs in requests commitment (#30670)
fjl Nov 28, 2024
53f66c1
cmd/bootnode: remove bootnode utility (#30813)
MariusVanDerWijden Nov 28, 2024
c7a8bce
core/types: add length check in CalcRequestsHash (#30829)
fjl Nov 28, 2024
05148d9
triedb/pathdb: track flat state changes in pathdb (snapshot integrati…
rjl493456442 Nov 29, 2024
03c37cd
core/state: introduce code reader interface (#30816)
rjl493456442 Nov 29, 2024
a793bc7
core: switch EVM tx context in ApplyMessage (#30809)
rjl493456442 Nov 29, 2024
ce8cec0
eth/tracers: fix state hooks in API (#30830)
s1na Nov 29, 2024
5347280
cmd/evm: improve block/state test runner (#30633)
lightclient Dec 2, 2024
9848e9b
fuzzing: fix oss-fuzz fuzzer (#30845)
holiman Dec 2, 2024
ae5a16f
internal/debug: rename --trace to --go-execution-trace (#30846)
fjl Dec 2, 2024
4afab7e
eth/downloader: move SyncMode to package eth/ethconfig (#30847)
fjl Dec 3, 2024
84cabb5
CODEOWNERS: add some more entries for auto assignment (#30851)
fjl Dec 3, 2024
f0e7382
cmd/evm, eth/tracers: refactor structlogger and make it streaming (#3…
holiman Dec 4, 2024
67a3b08
core/tracing: extends tracing.Hooks with OnSystemCallStartV2 (#30786)
nebojsa94 Dec 4, 2024
08e6bdb
trie/utils: ensure master can generate a correct genesis for kaustine…
gballet Dec 6, 2024
a722adb
core/txpool: remove unused parameter `local` (#30871)
stevemilk Dec 9, 2024
a91dcf3
core/state: enable partial-functional reader (snapshot integration pt…
rjl493456442 Dec 10, 2024
75f8473
cmd/evm: consolidate evm output switches (#30849)
holiman Dec 10, 2024
4ecf085
core/vm: remove unnecessary comment (#30887)
hzysvilla Dec 10, 2024
9045b79
metrics, cmd/geth: change init-process of metrics (#30814)
holiman Dec 10, 2024
4ed36ea
build: update to Go 1.23.4 (#30872)
hteevoli Dec 10, 2024
330190e
accounts/abi: support unpacking solidity errors (#30738)
darrenvechain Dec 10, 2024
2a1dcaf
Merge branch 'geth-master-date-1210' into bsc-develop
buddh0 Dec 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
triedb/pathdb: track flat state changes in pathdb (snapshot integrati…
…on pt 2) (#30643)

This pull request ports some changes from the main state snapshot
integration one, specifically introducing the flat state tracking in
pathdb.

Note, the tracked flat state changes are only held in memory and won't
be persisted in the disk. Meanwhile, the correspoding state retrieval in
persistent state is also not supported yet. The states management in
disk is more complicated and will be implemented in a separate pull
request.

Part 1: ethereum/go-ethereum#30752
  • Loading branch information
rjl493456442 authored Nov 29, 2024
commit 05148d972c1b0546c0183e7d302c334f5effbb06
11 changes: 11 additions & 0 deletions triedb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ type backend interface {
// An error will be returned if the specified state is not available.
NodeReader(root common.Hash) (database.NodeReader, error)

// StateReader returns a reader for accessing flat states within the specified
// state. An error will be returned if the specified state is not available.
StateReader(root common.Hash) (database.StateReader, error)

// Initialized returns an indicator if the state data is already initialized
// according to the state scheme.
Initialized(genesisRoot common.Hash) bool
Expand Down Expand Up @@ -122,6 +126,13 @@ func (db *Database) NodeReader(blockRoot common.Hash) (database.NodeReader, erro
return db.backend.NodeReader(blockRoot)
}

// StateReader returns a reader that allows access to the state data associated
// with the specified state. An error will be returned if the specified state is
// not available.
func (db *Database) StateReader(blockRoot common.Hash) (database.StateReader, error) {
return db.backend.StateReader(blockRoot)
}

// Update performs a state transition by committing dirty nodes contained in the
// given set in order to update state from the specified parent to the specified
// root. The held pre-images accumulated up to this point will be flushed in case
Expand Down
6 changes: 6 additions & 0 deletions triedb/hashdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,3 +635,9 @@ func (reader *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]
blob, _ := reader.db.node(hash)
return blob, nil
}

// StateReader returns a reader that allows access to the state data associated
// with the specified state.
func (db *Database) StateReader(root common.Hash) (database.StateReader, error) {
return nil, errors.New("not implemented")
}
36 changes: 27 additions & 9 deletions triedb/pathdb/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,40 +33,56 @@ import (
// must be checked before diving into disk (since it basically is not yet written
// data).
type buffer struct {
layers uint64 // The number of diff layers aggregated inside
limit uint64 // The maximum memory allowance in bytes
nodes *nodeSet // Aggregated trie node set
layers uint64 // The number of diff layers aggregated inside
limit uint64 // The maximum memory allowance in bytes
nodes *nodeSet // Aggregated trie node set
states *stateSet // Aggregated state set
}

// newBuffer initializes the buffer with the provided states and trie nodes.
func newBuffer(limit int, nodes *nodeSet, layers uint64) *buffer {
func newBuffer(limit int, nodes *nodeSet, states *stateSet, layers uint64) *buffer {
// Don't panic for lazy users if any provided set is nil
if nodes == nil {
nodes = newNodeSet(nil)
}
if states == nil {
states = newStates(nil, nil)
}
return &buffer{
layers: layers,
limit: uint64(limit),
nodes: nodes,
states: states,
}
}

// account retrieves the account blob with account address hash.
func (b *buffer) account(hash common.Hash) ([]byte, bool) {
return b.states.account(hash)
}

// storage retrieves the storage slot with account address hash and slot key.
func (b *buffer) storage(addrHash common.Hash, storageHash common.Hash) ([]byte, bool) {
return b.states.storage(addrHash, storageHash)
}

// node retrieves the trie node with node path and its trie identifier.
func (b *buffer) node(owner common.Hash, path []byte) (*trienode.Node, bool) {
return b.nodes.node(owner, path)
}

// commit merges the provided states and trie nodes into the buffer.
func (b *buffer) commit(nodes *nodeSet) *buffer {
func (b *buffer) commit(nodes *nodeSet, states *stateSet) *buffer {
b.layers++
b.nodes.merge(nodes)
b.states.merge(states)
return b
}

// revert is the reverse operation of commit. It also merges the provided states
// revertTo is the reverse operation of commit. It also merges the provided states
// and trie nodes into the buffer. The key difference is that the provided state
// set should reverse the changes made by the most recent state transition.
func (b *buffer) revert(db ethdb.KeyValueReader, nodes map[common.Hash]map[string]*trienode.Node) error {
func (b *buffer) revertTo(db ethdb.KeyValueReader, nodes map[common.Hash]map[string]*trienode.Node, accounts map[common.Hash][]byte, storages map[common.Hash]map[common.Hash][]byte) error {
// Short circuit if no embedded state transition to revert
if b.layers == 0 {
return errStateUnrecoverable
Expand All @@ -78,14 +94,16 @@ func (b *buffer) revert(db ethdb.KeyValueReader, nodes map[common.Hash]map[strin
b.reset()
return nil
}
b.nodes.revert(db, nodes)
b.nodes.revertTo(db, nodes)
b.states.revertTo(accounts, storages)
return nil
}

// reset cleans up the disk cache.
func (b *buffer) reset() {
b.layers = 0
b.nodes.reset()
b.states.reset()
}

// empty returns an indicator if buffer is empty.
Expand All @@ -101,7 +119,7 @@ func (b *buffer) full() bool {

// size returns the approximate memory size of the held content.
func (b *buffer) size() uint64 {
return b.nodes.size
return b.states.size + b.nodes.size
}

// flush persists the in-memory dirty trie node into the disk if the configured
Expand Down
39 changes: 29 additions & 10 deletions triedb/pathdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ type layer interface {
// - no error will be returned if the requested node is not found in database.
node(owner common.Hash, path []byte, depth int) ([]byte, common.Hash, *nodeLoc, error)

// account directly retrieves the account RLP associated with a particular
// hash in the slim data format. An error will be returned if the read
// operation exits abnormally. Specifically, if the layer is already stale.
//
// Note:
// - the returned account is not a copy, please don't modify it.
// - no error will be returned if the requested account is not found in database.
account(hash common.Hash, depth int) ([]byte, error)

// storage directly retrieves the storage data associated with a particular hash,
// within a particular account. An error will be returned if the read operation
// exits abnormally. Specifically, if the layer is already stale.
//
// Note:
// - the returned storage data is not a copy, please don't modify it.
// - no error will be returned if the requested slot is not found in database.
storage(accountHash, storageHash common.Hash, depth int) ([]byte, error)

// rootHash returns the root hash for which this layer was made.
rootHash() common.Hash

Expand Down Expand Up @@ -130,17 +148,18 @@ var Defaults = &Config{
// ReadOnly is the config in order to open database in read only mode.
var ReadOnly = &Config{ReadOnly: true}

// Database is a multiple-layered structure for maintaining in-memory trie nodes.
// It consists of one persistent base layer backed by a key-value store, on top
// of which arbitrarily many in-memory diff layers are stacked. The memory diffs
// can form a tree with branching, but the disk layer is singleton and common to
// all. If a reorg goes deeper than the disk layer, a batch of reverse diffs can
// be applied to rollback. The deepest reorg that can be handled depends on the
// amount of state histories tracked in the disk.
// Database is a multiple-layered structure for maintaining in-memory states
// along with its dirty trie nodes. It consists of one persistent base layer
// backed by a key-value store, on top of which arbitrarily many in-memory diff
// layers are stacked. The memory diffs can form a tree with branching, but the
// disk layer is singleton and common to all. If a reorg goes deeper than the
// disk layer, a batch of reverse diffs can be applied to rollback. The deepest
// reorg that can be handled depends on the amount of state histories tracked
// in the disk.
//
// At most one readable and writable database can be opened at the same time in
// the whole system which ensures that only one database writer can operate disk
// state. Unexpected open operations can cause the system to panic.
// the whole system which ensures that only one database writer can operate the
// persistent state. Unexpected open operations can cause the system to panic.
type Database struct {
// readOnly is the flag whether the mutation is allowed to be applied.
// It will be set automatically when the database is journaled during
Expand Down Expand Up @@ -358,7 +377,7 @@ func (db *Database) Enable(root common.Hash) error {
}
// Re-construct a new disk layer backed by persistent state
// with **empty clean cache and node buffer**.
db.tree.reset(newDiskLayer(root, 0, db, nil, newBuffer(db.config.WriteBufferSize, nil, 0)))
db.tree.reset(newDiskLayer(root, 0, db, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0)))

// Re-enable the database as the final step.
db.waitSync = false
Expand Down
2 changes: 1 addition & 1 deletion triedb/pathdb/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode
delete(t.storages, addrHash)
}
}
return root, ctx.nodes, NewStateSetWithOrigin(ctx.accountOrigin, ctx.storageOrigin)
return root, ctx.nodes, NewStateSetWithOrigin(ctx.accounts, ctx.storages, ctx.accountOrigin, ctx.storageOrigin)
}

// lastHash returns the latest root hash, or empty if nothing is cached.
Expand Down
53 changes: 53 additions & 0 deletions triedb/pathdb/difflayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes
states: states,
}
dirtyNodeWriteMeter.Mark(int64(nodes.size))
dirtyStateWriteMeter.Mark(int64(states.size))
log.Debug("Created new diff layer", "id", id, "block", block, "nodesize", common.StorageSize(nodes.size), "statesize", common.StorageSize(states.size))
return dl
}
Expand Down Expand Up @@ -96,6 +97,58 @@ func (dl *diffLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co
return dl.parent.node(owner, path, depth+1)
}

// account directly retrieves the account RLP associated with a particular
// hash in the slim data format.
//
// Note the returned account is not a copy, please don't modify it.
func (dl *diffLayer) account(hash common.Hash, depth int) ([]byte, error) {
// Hold the lock, ensure the parent won't be changed during the
// state accessing.
dl.lock.RLock()
defer dl.lock.RUnlock()

if blob, found := dl.states.account(hash); found {
dirtyStateHitMeter.Mark(1)
dirtyStateHitDepthHist.Update(int64(depth))
dirtyStateReadMeter.Mark(int64(len(blob)))

if len(blob) == 0 {
stateAccountInexMeter.Mark(1)
} else {
stateAccountExistMeter.Mark(1)
}
return blob, nil
}
// Account is unknown to this layer, resolve from parent
return dl.parent.account(hash, depth+1)
}

// storage directly retrieves the storage data associated with a particular hash,
// within a particular account.
//
// Note the returned storage slot is not a copy, please don't modify it.
func (dl *diffLayer) storage(accountHash, storageHash common.Hash, depth int) ([]byte, error) {
// Hold the lock, ensure the parent won't be changed during the
// state accessing.
dl.lock.RLock()
defer dl.lock.RUnlock()

if blob, found := dl.states.storage(accountHash, storageHash); found {
dirtyStateHitMeter.Mark(1)
dirtyStateHitDepthHist.Update(int64(depth))
dirtyStateReadMeter.Mark(int64(len(blob)))

if len(blob) == 0 {
stateStorageInexMeter.Mark(1)
} else {
stateStorageExistMeter.Mark(1)
}
return blob, nil
}
// storage slot is unknown to this layer, resolve from parent
return dl.parent.storage(accountHash, storageHash, depth+1)
}

// update implements the layer interface, creating a new layer on top of the
// existing layer tree with the specified data items.
func (dl *diffLayer) update(root common.Hash, id uint64, block uint64, nodes *nodeSet, states *StateSetWithOrigin) *diffLayer {
Expand Down
8 changes: 4 additions & 4 deletions triedb/pathdb/difflayer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
func emptyLayer() *diskLayer {
return &diskLayer{
db: New(rawdb.NewMemoryDatabase(), nil, false),
buffer: newBuffer(defaultBufferSize, nil, 0),
buffer: newBuffer(defaultBufferSize, nil, nil, 0),
}
}

Expand Down Expand Up @@ -76,7 +76,7 @@ func benchmarkSearch(b *testing.B, depth int, total int) {
nblob = common.CopyBytes(blob)
}
}
return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil))
return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil, nil, nil))
}
var layer layer
layer = emptyLayer()
Expand Down Expand Up @@ -118,7 +118,7 @@ func BenchmarkPersist(b *testing.B) {
)
nodes[common.Hash{}][string(path)] = node
}
return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil))
return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil, nil, nil))
}
for i := 0; i < b.N; i++ {
b.StopTimer()
Expand Down Expand Up @@ -156,7 +156,7 @@ func BenchmarkJournal(b *testing.B) {
)
nodes[common.Hash{}][string(path)] = node
}
return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), new(StateSetWithOrigin))
return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil, nil, nil))
}
var layer layer
layer = emptyLayer()
Expand Down
Loading