@@ -32,6 +32,7 @@ import (
3232 "github.com/ethereum/go-ethereum/ethdb"
3333 "github.com/ethereum/go-ethereum/params"
3434 "github.com/ethereum/go-ethereum/triedb"
35+ "github.com/gballet/go-verkle"
3536 "github.com/holiman/uint256"
3637)
3738
@@ -418,6 +419,112 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int,
418419 return db , blocks , receipts
419420}
420421
422+ func GenerateVerkleChain (config * params.ChainConfig , parent * types.Block , engine consensus.Engine , db ethdb.Database , trdb * triedb.Database , n int , gen func (int , * BlockGen )) ([]* types.Block , []types.Receipts , []* verkle.VerkleProof , []verkle.StateDiff ) {
423+ if config == nil {
424+ config = params .TestChainConfig
425+ }
426+ proofs := make ([]* verkle.VerkleProof , 0 , n )
427+ keyvals := make ([]verkle.StateDiff , 0 , n )
428+ cm := newChainMaker (parent , config , engine )
429+
430+ genblock := func (i int , parent * types.Block , triedb * triedb.Database , statedb * state.StateDB ) (* types.Block , types.Receipts ) {
431+ b := & BlockGen {i : i , cm : cm , parent : parent , statedb : statedb , engine : engine }
432+ b .header = cm .makeHeader (parent , statedb , b .engine )
433+
434+ // TODO uncomment when proof generation is merged
435+ // Save pre state for proof generation
436+ // preState := statedb.Copy()
437+
438+ // TODO uncomment when the 2935 PR is merged
439+ // if config.IsPrague(b.header.Number, b.header.Time) {
440+ // if !config.IsPrague(b.parent.Number(), b.parent.Time()) {
441+ // Transition case: insert all 256 ancestors
442+ // InsertBlockHashHistoryAtEip2935Fork(statedb, b.header.Number.Uint64()-1, b.header.ParentHash, chainreader)
443+ // } else {
444+ // ProcessParentBlockHash(statedb, b.header.Number.Uint64()-1, b.header.ParentHash)
445+ // }
446+ // }
447+ // Execute any user modifications to the block
448+ if gen != nil {
449+ gen (i , b )
450+ }
451+ body := & types.Body {
452+ Transactions : b .txs ,
453+ Uncles : b .uncles ,
454+ Withdrawals : b .withdrawals ,
455+ }
456+ block , err := b .engine .FinalizeAndAssemble (cm , b .header , statedb , body , b .receipts )
457+ if err != nil {
458+ panic (err )
459+ }
460+
461+ // Write state changes to db
462+ root , err := statedb .Commit (b .header .Number .Uint64 (), config .IsEIP158 (b .header .Number ))
463+ if err != nil {
464+ panic (fmt .Sprintf ("state write error: %v" , err ))
465+ }
466+ if err = triedb .Commit (root , false ); err != nil {
467+ panic (fmt .Sprintf ("trie write error: %v" , err ))
468+ }
469+
470+ // TODO uncomment when proof generation is merged
471+ // proofs = append(proofs, block.ExecutionWitness().VerkleProof)
472+ // keyvals = append(keyvals, block.ExecutionWitness().StateDiff)
473+
474+ return block , b .receipts
475+ }
476+
477+ for i := 0 ; i < n ; i ++ {
478+ statedb , err := state .New (parent .Root (), state .NewDatabaseWithNodeDB (db , trdb ), nil )
479+ if err != nil {
480+ panic (err )
481+ }
482+ block , receipts := genblock (i , parent , trdb , statedb )
483+
484+ // Post-process the receipts.
485+ // Here we assign the final block hash and other info into the receipt.
486+ // In order for DeriveFields to work, the transaction and receipt lists need to be
487+ // of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be
488+ // extra ones, so we just trim the lists here.
489+ receiptsCount := len (receipts )
490+ txs := block .Transactions ()
491+ if len (receipts ) > len (txs ) {
492+ receipts = receipts [:len (txs )]
493+ } else if len (receipts ) < len (txs ) {
494+ txs = txs [:len (receipts )]
495+ }
496+ var blobGasPrice * big.Int
497+ if block .ExcessBlobGas () != nil {
498+ blobGasPrice = eip4844 .CalcBlobFee (* block .ExcessBlobGas ())
499+ }
500+ if err := receipts .DeriveFields (config , block .Hash (), block .NumberU64 (), block .Time (), block .BaseFee (), blobGasPrice , txs ); err != nil {
501+ panic (err )
502+ }
503+
504+ // Re-expand to ensure all receipts are returned.
505+ receipts = receipts [:receiptsCount ]
506+
507+ // Advance the chain.
508+ cm .add (block , receipts )
509+ parent = block
510+ }
511+ return cm .chain , cm .receipts , proofs , keyvals
512+ }
513+
514+ func GenerateVerkleChainWithGenesis (genesis * Genesis , engine consensus.Engine , n int , gen func (int , * BlockGen )) (ethdb.Database , []* types.Block , []types.Receipts , []* verkle.VerkleProof , []verkle.StateDiff ) {
515+ db := rawdb .NewMemoryDatabase ()
516+ cacheConfig := DefaultCacheConfigWithScheme (rawdb .PathScheme )
517+ cacheConfig .SnapshotLimit = 0
518+ triedb := triedb .NewDatabase (db , cacheConfig .triedbConfig (true ))
519+ defer triedb .Close ()
520+ genesisBlock , err := genesis .Commit (db , triedb )
521+ if err != nil {
522+ panic (err )
523+ }
524+ blocks , receipts , proofs , keyvals := GenerateVerkleChain (genesis .Config , genesisBlock , engine , db , triedb , n , gen )
525+ return db , blocks , receipts , proofs , keyvals
526+ }
527+
421528func (cm * chainMaker ) makeHeader (parent * types.Block , state * state.StateDB , engine consensus.Engine ) * types.Header {
422529 time := parent .Time () + 10 // block time is fixed at 10 seconds
423530 header := & types.Header {
0 commit comments