Skip to content

Commit 95ab716

Browse files
gballetjsign
andauthored
cmd/{geth, utils}: add a command to clear verkle costs (ethereum#326)
* cmd/{geth, utils}: add a command to clear verkle costs fix: boolean issue fix: load finalization state in FinalizeAndAssemble (ethereum#340) * Conversion and TransitionTrie fixes (ethereum#346) * fixes Signed-off-by: Ignacio Hagopian <[email protected]> * remove old comment Signed-off-by: Ignacio Hagopian <[email protected]> --------- Signed-off-by: Ignacio Hagopian <[email protected]> * trace cleanup --------- Signed-off-by: Ignacio Hagopian <[email protected]> Co-authored-by: Ignacio Hagopian <[email protected]>
1 parent 3c84e23 commit 95ab716

File tree

10 files changed

+107
-65
lines changed

10 files changed

+107
-65
lines changed

cmd/geth/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
183183
v := ctx.Uint64(utils.OverrideOverlayStride.Name)
184184
cfg.Eth.OverrideOverlayStride = &v
185185
}
186+
if ctx.IsSet(utils.ClearVerkleCosts.Name) {
187+
params.ClearVerkleWitnessCosts()
188+
}
186189
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
187190

188191
// Configure log filter RPC API.

cmd/geth/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ var (
7171
utils.OverrideCancun,
7272
utils.OverridePrague,
7373
utils.OverrideProofInBlock,
74+
utils.ClearVerkleCosts,
7475
utils.EnablePersonal,
7576
utils.TxPoolLocalsFlag,
7677
utils.TxPoolNoLocalsFlag,

cmd/utils/flags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ var (
284284
Usage: "Manually specify the proof-in-block setting",
285285
Category: flags.EthCategory,
286286
}
287+
ClearVerkleCosts = &cli.BoolFlag{
288+
Name: "clear.verkle.costs",
289+
Usage: "Clear verkle costs (for shadow forks)",
290+
Category: flags.EthCategory,
291+
}
287292
// Light server and client settings
288293
LightServeFlag = &cli.IntFlag{
289294
Name: "light.serve",

consensus/beacon/consensus.go

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/ethereum/go-ethereum/core/overlay"
2929
"github.com/ethereum/go-ethereum/core/state"
3030
"github.com/ethereum/go-ethereum/core/types"
31+
"github.com/ethereum/go-ethereum/log"
3132
"github.com/ethereum/go-ethereum/params"
3233
"github.com/ethereum/go-ethereum/rpc"
3334
"github.com/ethereum/go-ethereum/trie"
@@ -373,7 +374,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
373374
if chain.Config().IsPrague(header.Number, header.Time) {
374375
fmt.Println("at block", header.Number, "performing transition?", state.Database().InTransition())
375376
parent := chain.GetHeaderByHash(header.ParentHash)
376-
overlay.OverlayVerkleTransition(state, parent.Root, chain.Config().OverlayStride)
377+
if err := overlay.OverlayVerkleTransition(state, parent.Root, chain.Config().OverlayStride); err != nil {
378+
log.Error("error performing the transition", "err", err)
379+
}
377380
}
378381
}
379382

@@ -406,58 +409,61 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
406409
k verkle.StateDiff
407410
keys = state.Witness().Keys()
408411
)
409-
if chain.Config().IsPrague(header.Number, header.Time) && chain.Config().ProofInBlocks {
412+
if chain.Config().IsPrague(header.Number, header.Time) {
410413
// Open the pre-tree to prove the pre-state against
411414
parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
412415
if parent == nil {
413416
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
414417
}
415418

416419
state.Database().LoadTransitionState(parent.Root)
417-
preTrie, err := state.Database().OpenTrie(parent.Root)
418-
if err != nil {
419-
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
420-
}
421420

422-
var okpre, okpost bool
423-
var vtrpre, vtrpost *trie.VerkleTrie
424-
switch pre := preTrie.(type) {
425-
case *trie.VerkleTrie:
426-
vtrpre, okpre = preTrie.(*trie.VerkleTrie)
427-
switch tr := state.GetTrie().(type) {
421+
if chain.Config().ProofInBlocks {
422+
preTrie, err := state.Database().OpenTrie(parent.Root)
423+
if err != nil {
424+
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
425+
}
426+
427+
var okpre, okpost bool
428+
var vtrpre, vtrpost *trie.VerkleTrie
429+
switch pre := preTrie.(type) {
428430
case *trie.VerkleTrie:
429-
vtrpost = tr
430-
okpost = true
431-
// This is to handle a situation right at the start of the conversion:
432-
// the post trie is a transition tree when the pre tree is an empty
433-
// verkle tree.
431+
vtrpre, okpre = preTrie.(*trie.VerkleTrie)
432+
switch tr := state.GetTrie().(type) {
433+
case *trie.VerkleTrie:
434+
vtrpost = tr
435+
okpost = true
436+
// This is to handle a situation right at the start of the conversion:
437+
// the post trie is a transition tree when the pre tree is an empty
438+
// verkle tree.
439+
case *trie.TransitionTrie:
440+
vtrpost = tr.Overlay()
441+
okpost = true
442+
default:
443+
okpost = false
444+
}
434445
case *trie.TransitionTrie:
435-
vtrpost = tr.Overlay()
446+
vtrpre = pre.Overlay()
447+
okpre = true
448+
post, _ := state.GetTrie().(*trie.TransitionTrie)
449+
vtrpost = post.Overlay()
436450
okpost = true
437451
default:
438-
okpost = false
452+
// This should only happen for the first block,
453+
// so the previous tree is a merkle tree. Logically,
454+
// the "previous" verkle tree is an empty tree.
455+
okpre = true
456+
vtrpre = trie.NewVerkleTrie(verkle.New(), state.Database().TrieDB(), utils.NewPointCache(), false)
457+
post := state.GetTrie().(*trie.TransitionTrie)
458+
vtrpost = post.Overlay()
459+
okpost = true
439460
}
440-
case *trie.TransitionTrie:
441-
vtrpre = pre.Overlay()
442-
okpre = true
443-
post, _ := state.GetTrie().(*trie.TransitionTrie)
444-
vtrpost = post.Overlay()
445-
okpost = true
446-
default:
447-
// This should only happen for the first block,
448-
// so the previous tree is a merkle tree. Logically,
449-
// the "previous" verkle tree is an empty tree.
450-
okpre = true
451-
vtrpre = trie.NewVerkleTrie(verkle.New(), state.Database().TrieDB(), utils.NewPointCache(), false)
452-
post := state.GetTrie().(*trie.TransitionTrie)
453-
vtrpost = post.Overlay()
454-
okpost = true
455-
}
456-
if okpre && okpost {
457-
if len(keys) > 0 {
458-
p, k, err = trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver)
459-
if err != nil {
460-
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
461+
if okpre && okpost {
462+
if len(keys) > 0 {
463+
p, k, err = trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver)
464+
if err != nil {
465+
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
466+
}
461467
}
462468
}
463469
}

core/blockchain.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const (
103103
txLookupCacheLimit = 1024
104104
maxFutureBlocks = 256
105105
maxTimeFutureBlocks = 30
106-
TriesInMemory = 128
106+
TriesInMemory = 8192
107107

108108
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
109109
//
@@ -2009,7 +2009,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
20092009
parent = bc.GetHeader(parent.ParentHash, parent.Number.Uint64()-1)
20102010
}
20112011
if parent == nil {
2012-
return it.index, errors.New("missing parent")
2012+
return it.index, fmt.Errorf("missing parent: hash=%x, number=%d", current.Hash(), current.Number)
20132013
}
20142014
// Import all the pruned blocks to make the state available
20152015
var (
@@ -2070,7 +2070,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
20702070
}
20712071
}
20722072
if parent == nil {
2073-
return common.Hash{}, errors.New("missing parent")
2073+
return common.Hash{}, fmt.Errorf("missing parent during ancestor recovery: hash=%x, number=%d", block.ParentHash(), block.Number())
20742074
}
20752075
// Import all the pruned blocks to make the state available
20762076
for i := len(hashes) - 1; i >= 0; i-- {
@@ -2308,6 +2308,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
23082308
defer bc.chainmu.Unlock()
23092309

23102310
// Re-execute the reorged chain in case the head state is missing.
2311+
log.Trace("looking for state", "root", head.Root(), "has state", bc.HasState(head.Root()))
23112312
if !bc.HasState(head.Root()) {
23122313
if latestValidHash, err := bc.recoverAncestors(head); err != nil {
23132314
return latestValidHash, err

core/overlay/conversion.go

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ var zeroTreeIndex uint256.Int
4747
// collect the key-values in a way that is efficient.
4848
type keyValueMigrator struct {
4949
// leafData contains the values for the future leaf for a particular VKT branch.
50-
leafData []migratedKeyValue
50+
leafData map[branchKey]*migratedKeyValue
5151

5252
// When prepare() is called, it will start a background routine that will process the leafData
5353
// saving the result in newLeaves to be used by migrateCollectedKeyValues(). The background
@@ -66,7 +66,7 @@ func newKeyValueMigrator() *keyValueMigrator {
6666
_ = verkle.GetConfig()
6767
return &keyValueMigrator{
6868
processingReady: make(chan struct{}),
69-
leafData: make([]migratedKeyValue, 0, 10_000),
69+
leafData: make(map[branchKey]*migratedKeyValue, 10_000),
7070
}
7171
}
7272

@@ -138,19 +138,17 @@ func (kvm *keyValueMigrator) addAccountCode(addr []byte, codeSize uint64, chunks
138138
}
139139

140140
func (kvm *keyValueMigrator) getOrInitLeafNodeData(bk branchKey) *verkle.BatchNewLeafNodeData {
141-
// Remember that keyValueMigration receives actions ordered by (address, subtreeIndex).
142-
// This means that we can assume that the last element of leafData is the one that we
143-
// are looking for, or that we need to create a new one.
144-
if len(kvm.leafData) == 0 || kvm.leafData[len(kvm.leafData)-1].branchKey != bk {
145-
kvm.leafData = append(kvm.leafData, migratedKeyValue{
146-
branchKey: bk,
147-
leafNodeData: verkle.BatchNewLeafNodeData{
148-
Stem: nil, // It will be calculated in the prepare() phase, since it's CPU heavy.
149-
Values: make(map[byte][]byte),
150-
},
151-
})
141+
if ld, ok := kvm.leafData[bk]; ok {
142+
return &ld.leafNodeData
152143
}
153-
return &kvm.leafData[len(kvm.leafData)-1].leafNodeData
144+
kvm.leafData[bk] = &migratedKeyValue{
145+
branchKey: bk,
146+
leafNodeData: verkle.BatchNewLeafNodeData{
147+
Stem: nil, // It will be calculated in the prepare() phase, since it's CPU heavy.
148+
Values: make(map[byte][]byte, 256),
149+
},
150+
}
151+
return &kvm.leafData[bk].leafNodeData
154152
}
155153

156154
func (kvm *keyValueMigrator) prepare() {
@@ -159,6 +157,10 @@ func (kvm *keyValueMigrator) prepare() {
159157
go func() {
160158
// Step 1: We split kvm.leafData in numBatches batches, and we process each batch in a separate goroutine.
161159
// This fills each leafNodeData.Stem with the correct value.
160+
leafData := make([]migratedKeyValue, 0, len(kvm.leafData))
161+
for _, v := range kvm.leafData {
162+
leafData = append(leafData, *v)
163+
}
162164
var wg sync.WaitGroup
163165
batchNum := runtime.NumCPU()
164166
batchSize := (len(kvm.leafData) + batchNum - 1) / batchNum
@@ -170,7 +172,7 @@ func (kvm *keyValueMigrator) prepare() {
170172
}
171173
wg.Add(1)
172174

173-
batch := kvm.leafData[start:end]
175+
batch := leafData[start:end]
174176
go func() {
175177
defer wg.Done()
176178
var currAddr common.Address
@@ -190,8 +192,8 @@ func (kvm *keyValueMigrator) prepare() {
190192

191193
// Step 2: Now that we have all stems (i.e: tree keys) calculated, we can create the new leaves.
192194
nodeValues := make([]verkle.BatchNewLeafNodeData, len(kvm.leafData))
193-
for i := range kvm.leafData {
194-
nodeValues[i] = kvm.leafData[i].leafNodeData
195+
for i := range leafData {
196+
nodeValues[i] = leafData[i].leafNodeData
195197
}
196198

197199
// Create all leaves in batch mode so we can optimize cryptography operations.
@@ -306,7 +308,12 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC
306308
if err != nil {
307309
return err
308310
}
309-
stIt.Next()
311+
processed := stIt.Next()
312+
if processed {
313+
log.Debug("account has storage and a next item")
314+
} else {
315+
log.Debug("account has storage and NO next item")
316+
}
310317

311318
// fdb.StorageProcessed will be initialized to `true` if the
312319
// entire storage for an account was not entirely processed
@@ -315,6 +322,7 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC
315322
// If the entire storage was processed, then the iterator was
316323
// created in vain, but it's ok as this will not happen often.
317324
for ; !migrdb.GetStorageProcessed() && count < maxMovedCount; count++ {
325+
log.Trace("Processing storage", "count", count, "slot", stIt.Slot(), "storage processed", migrdb.GetStorageProcessed(), "current account", migrdb.GetCurrentAccountAddress(), "current account hash", migrdb.GetCurrentAccountHash())
318326
var (
319327
value []byte // slot value after RLP decoding
320328
safeValue [32]byte // 32-byte aligned value
@@ -337,6 +345,7 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC
337345
return fmt.Errorf("slotnr len is zero is not 32: %d", len(slotnr))
338346
}
339347
}
348+
log.Trace("found slot number", "number", slotnr)
340349
if crypto.Keccak256Hash(slotnr[:]) != stIt.Hash() {
341350
return fmt.Errorf("preimage file does not match storage hash: %s!=%s", crypto.Keccak256Hash(slotnr), stIt.Hash())
342351
}
@@ -378,6 +387,7 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC
378387
// Move to the next account, if available - or end
379388
// the transition otherwise.
380389
if accIt.Next() {
390+
log.Trace("Found another account to convert", "hash", accIt.Hash())
381391
var addr common.Address
382392
if hasPreimagesBin {
383393
if _, err := io.ReadFull(fpreimages, addr[:]); err != nil {
@@ -393,6 +403,7 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC
393403
if crypto.Keccak256Hash(addr[:]) != accIt.Hash() {
394404
return fmt.Errorf("preimage file does not match account hash: %s != %s", crypto.Keccak256Hash(addr[:]), accIt.Hash())
395405
}
406+
log.Trace("Converting account address", "hash", accIt.Hash(), "addr", addr)
396407
preimageSeek += int64(len(addr))
397408
migrdb.SetCurrentAccountAddress(addr)
398409
} else {

core/state/database.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,26 +340,30 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
340340
mpt Trie
341341
err error
342342
)
343+
fmt.Printf("opening trie with root %x, %v %v\n", root, db.InTransition(), db.Transitioned())
343344

344345
// TODO separate both cases when I can be certain that it won't
345346
// find a Verkle trie where is expects a Transitoion trie.
346347
if db.InTransition() || db.Transitioned() {
347348
// NOTE this is a kaustinen-only change, it will break replay
348349
vkt, err := db.openVKTrie(root)
349350
if err != nil {
351+
log.Error("failed to open the vkt", "err", err)
350352
return nil, err
351353
}
352354

353355
// If the verkle conversion has ended, return a single
354356
// verkle trie.
355357
if db.CurrentTransitionState.ended {
358+
log.Debug("transition ended, returning a simple verkle tree")
356359
return vkt, nil
357360
}
358361

359362
// Otherwise, return a transition trie, with a base MPT
360363
// trie and an overlay, verkle trie.
361364
mpt, err = db.openMPTTrie(db.baseRoot)
362365
if err != nil {
366+
log.Error("failed to open the mpt", "err", err, "root", db.baseRoot)
363367
return nil, err
364368
}
365369

@@ -547,6 +551,8 @@ func (db *cachingDB) SaveTransitionState(root common.Hash) {
547551
// Copy so that the address pointer isn't updated after
548552
// it has been saved.
549553
db.TransitionStatePerRoot[root] = db.CurrentTransitionState.Copy()
554+
555+
log.Debug("saving transition state", "storage processed", db.CurrentTransitionState.StorageProcessed, "addr", db.CurrentTransitionState.CurrentAccountAddress, "slot hash", db.CurrentTransitionState.CurrentSlotHash, "root", root, "ended", db.CurrentTransitionState.ended, "started", db.CurrentTransitionState.started)
550556
}
551557
}
552558

@@ -555,6 +561,9 @@ func (db *cachingDB) LoadTransitionState(root common.Hash) {
555561
db.TransitionStatePerRoot = make(map[common.Hash]*TransitionState)
556562
}
557563

564+
// Initialize the first transition state, with the "ended"
565+
// field set to true if the database was created
566+
// as a verkle database.
558567
ts, ok := db.TransitionStatePerRoot[root]
559568
if !ok || ts == nil {
560569
// Start with a fresh state
@@ -565,5 +574,5 @@ func (db *cachingDB) LoadTransitionState(root common.Hash) {
565574
// doesn't get overwritten.
566575
db.CurrentTransitionState = ts.Copy()
567576

568-
fmt.Println("loaded transition state", db.CurrentTransitionState.StorageProcessed)
577+
log.Debug("loaded transition state", "storage processed", db.CurrentTransitionState.StorageProcessed, "addr", db.CurrentTransitionState.CurrentAccountAddress, "slot hash", db.CurrentTransitionState.CurrentSlotHash, "root", root, "ended", db.CurrentTransitionState.ended, "started", db.CurrentTransitionState.started)
569578
}

core/state/statedb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
13101310
// - head layer is paired with HEAD state
13111311
// - head-1 layer is paired with HEAD-1 state
13121312
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
1313-
if err := s.snaps.Cap(root, 128); err != nil {
1313+
if err := s.snaps.Cap(root, 8192); err != nil {
13141314
log.Warn("Failed to cap snapshot tree", "root", root, "layers", 128, "err", err)
13151315
}
13161316
}

miner/worker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
852852
if genParams.parentHash != (common.Hash{}) {
853853
block := w.chain.GetBlockByHash(genParams.parentHash)
854854
if block == nil {
855-
return nil, fmt.Errorf("missing parent")
855+
return nil, fmt.Errorf("missing parent: %x", genParams.parentHash)
856856
}
857857
parent = block.Header()
858858
}

0 commit comments

Comments
 (0)