From 285cd967fb50f8809c810127b3ebd3864d3886d5 Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Thu, 6 May 2021 18:58:39 +0200 Subject: [PATCH 1/3] changes --- cmd/utils/cmd.go | 14 +++++ core/block_validator.go | 32 +++++----- core/blockchain.go | 4 ++ core/genesis.go | 3 +- core/state/database.go | 2 +- core/types/gen_account_rlp.go | 7 ++- core/types/gen_header_rlp.go | 113 ++++++++++++++++++++++++++++++++++ core/types/gen_log_rlp.go | 7 ++- 8 files changed, 162 insertions(+), 20 deletions(-) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index de25fd1a146d..b4aceeeb4c5f 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -26,6 +26,7 @@ import ( "os" "os/signal" "runtime" + "runtime/pprof" "strings" "syscall" "time" @@ -40,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/urfave/cli/v2" ) @@ -177,6 +179,18 @@ func ImportChain(chain *core.BlockChain, fn string) error { } } + cpuProfile, err := os.Create("cpu.out") + if err != nil { + return fmt.Errorf("Error creating CPU profile: %v", err) + } + defer cpuProfile.Close() + err = pprof.StartCPUProfile(cpuProfile) + if err != nil { + return fmt.Errorf("Error starting CPU profile: %v", err) + } + defer pprof.StopCPUProfile() + params.ClearVerkleWitnessCosts() + stream := rlp.NewStream(reader, 0) // Run actual the import. diff --git a/core/block_validator.go b/core/block_validator.go index b1ceab9d5c6c..bef0470362cf 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -98,13 +98,17 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { return errors.New("data blobs present in block body") } } - if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { - if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { - return consensus.ErrUnknownAncestor - } - fmt.Println("failure here") - return consensus.ErrPrunedAncestor - } + // XXX I had to deactivate this check for replay to work: the block state root + // hash is the one of the overlay tree, but in replay mode, it's the hash of + // the base tree that takes precedence, as the chain would not otherwise be + // recognized. + // if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { + // if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { + // return consensus.ErrUnknownAncestor + // } + // fmt.Println("failure here") + // return consensus.ErrPrunedAncestor + // } return nil } @@ -122,15 +126,15 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) } // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]])) - receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil)) - if receiptSha != header.ReceiptHash { - return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) - } + // receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil)) + // if receiptSha != header.ReceiptHash { + // return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) + // } // Validate the state root against the received state root and throw // an error if they don't match. - if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { - return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error()) - } + // if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { + // return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error()) + // } return nil } diff --git a/core/blockchain.go b/core/blockchain.go index a1b3b6b6cb68..ca198cd4d098 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1785,6 +1785,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) } ptime := time.Since(pstart) + if statedb.Database().InTransition() || statedb.Database().Transitioned() { + bc.AddRootTranslation(block.Root(), statedb.IntermediateRoot(false)) + } + vstart := time.Now() if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { bc.reportBlock(block, receipts, err) diff --git a/core/genesis.go b/core/genesis.go index 6b521369bcbe..dcdd8e238f2b 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -182,7 +182,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas } rawdb.WriteGenesisStateSpec(db, blockhash, blob) - return nil + return statedb.Cap(root) // XXX check this is still necessary } // CommitGenesisState loads the stored genesis state with the given block @@ -342,6 +342,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen // We have the genesis block in database(perhaps in ancient database) // but the corresponding state is missing. header := rawdb.ReadHeader(db, stored, 0) + if header.Root != types.EmptyRootHash && !rawdb.HasLegacyTrieNode(db, header.Root) { if genesis == nil { genesis = DefaultGenesisBlock() diff --git a/core/state/database.go b/core/state/database.go index 7ee8489d3f62..49330c520000 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -318,7 +318,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { ) // TODO separate both cases when I can be certain that it won't - // find a Verkle trie where is expects a Transitoion trie. + // find a Verkle trie where is expects a Transition trie. if db.started || db.ended { var r common.Hash if db.ended { diff --git a/core/types/gen_account_rlp.go b/core/types/gen_account_rlp.go index 5181d884112f..9d07200e33b3 100644 --- a/core/types/gen_account_rlp.go +++ b/core/types/gen_account_rlp.go @@ -5,8 +5,11 @@ package types -import "github.com/ethereum/go-ethereum/rlp" -import "io" +import ( + "io" + + "github.com/ethereum/go-ethereum/rlp" +) func (obj *StateAccount) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go index a5ed5cd15094..f322411bad9c 100644 --- a/core/types/gen_header_rlp.go +++ b/core/types/gen_header_rlp.go @@ -5,6 +5,7 @@ package types +import "github.com/ethereum/go-ethereum/common" import "github.com/ethereum/go-ethereum/rlp" import "io" @@ -78,3 +79,115 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.ListEnd(_tmp0) return w.Flush() } + +func (obj *Header) DecodeRLP(dec *rlp.Stream) error { + var _tmp0 Header + { + if _, err := dec.List(); err != nil { + return err + } + // ParentHash: + var _tmp1 common.Hash + if err := dec.ReadBytes(_tmp1[:]); err != nil { + return err + } + _tmp0.ParentHash = _tmp1 + // UncleHash: + var _tmp2 common.Hash + if err := dec.ReadBytes(_tmp2[:]); err != nil { + return err + } + _tmp0.UncleHash = _tmp2 + // Coinbase: + var _tmp3 common.Address + if err := dec.ReadBytes(_tmp3[:]); err != nil { + return err + } + _tmp0.Coinbase = _tmp3 + // Root: + var _tmp4 common.Hash + if err := dec.ReadBytes(_tmp4[:]); err != nil { + return err + } + _tmp0.Root = _tmp4 + // TxHash: + var _tmp5 common.Hash + if err := dec.ReadBytes(_tmp5[:]); err != nil { + return err + } + _tmp0.TxHash = _tmp5 + // ReceiptHash: + var _tmp6 common.Hash + if err := dec.ReadBytes(_tmp6[:]); err != nil { + return err + } + _tmp0.ReceiptHash = _tmp6 + // Bloom: + var _tmp7 Bloom + if err := dec.ReadBytes(_tmp7[:]); err != nil { + return err + } + _tmp0.Bloom = _tmp7 + // Difficulty: + _tmp8, err := dec.BigInt() + if err != nil { + return err + } + _tmp0.Difficulty = _tmp8 + // Number: + _tmp9, err := dec.BigInt() + if err != nil { + return err + } + _tmp0.Number = _tmp9 + // GasLimit: + _tmp10, err := dec.Uint64() + if err != nil { + return err + } + _tmp0.GasLimit = _tmp10 + // GasUsed: + _tmp11, err := dec.Uint64() + if err != nil { + return err + } + _tmp0.GasUsed = _tmp11 + // Time: + _tmp12, err := dec.Uint64() + if err != nil { + return err + } + _tmp0.Time = _tmp12 + // Extra: + _tmp13, err := dec.Bytes() + if err != nil { + return err + } + _tmp0.Extra = _tmp13 + // MixDigest: + var _tmp14 common.Hash + if err := dec.ReadBytes(_tmp14[:]); err != nil { + return err + } + _tmp0.MixDigest = _tmp14 + // Nonce: + var _tmp15 BlockNonce + if err := dec.ReadBytes(_tmp15[:]); err != nil { + return err + } + _tmp0.Nonce = _tmp15 + // BaseFee: + if dec.MoreDataInList() { + _tmp16, err := dec.BigInt() + if err != nil { + return err + } + _tmp0.BaseFee = _tmp16 + } + if err := dec.ListEnd(); err != nil { + return err + } + } + *obj = _tmp0 + return nil +} diff --git a/core/types/gen_log_rlp.go b/core/types/gen_log_rlp.go index 4a6c6b0094f8..78fa783cee1f 100644 --- a/core/types/gen_log_rlp.go +++ b/core/types/gen_log_rlp.go @@ -5,8 +5,11 @@ package types -import "github.com/ethereum/go-ethereum/rlp" -import "io" +import ( + "io" + + "github.com/ethereum/go-ethereum/rlp" +) func (obj *rlpLog) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) From a905b3d997a2fccd93ad77b50168a449852e0fd1 Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Fri, 11 Aug 2023 21:02:38 +0200 Subject: [PATCH 2/3] changes to activate replay --- core/genesis.go | 2 +- core/types/gen_account_rlp.go | 7 +-- core/types/gen_header_rlp.go | 113 ---------------------------------- core/types/gen_log_rlp.go | 7 +-- 4 files changed, 5 insertions(+), 124 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index dcdd8e238f2b..4cc3b014145a 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -182,7 +182,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas } rawdb.WriteGenesisStateSpec(db, blockhash, blob) - return statedb.Cap(root) // XXX check this is still necessary + return nil } // CommitGenesisState loads the stored genesis state with the given block diff --git a/core/types/gen_account_rlp.go b/core/types/gen_account_rlp.go index 9d07200e33b3..5181d884112f 100644 --- a/core/types/gen_account_rlp.go +++ b/core/types/gen_account_rlp.go @@ -5,11 +5,8 @@ package types -import ( - "io" - - "github.com/ethereum/go-ethereum/rlp" -) +import "github.com/ethereum/go-ethereum/rlp" +import "io" func (obj *StateAccount) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go index f322411bad9c..a5ed5cd15094 100644 --- a/core/types/gen_header_rlp.go +++ b/core/types/gen_header_rlp.go @@ -5,7 +5,6 @@ package types -import "github.com/ethereum/go-ethereum/common" import "github.com/ethereum/go-ethereum/rlp" import "io" @@ -79,115 +78,3 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.ListEnd(_tmp0) return w.Flush() } - -func (obj *Header) DecodeRLP(dec *rlp.Stream) error { - var _tmp0 Header - { - if _, err := dec.List(); err != nil { - return err - } - // ParentHash: - var _tmp1 common.Hash - if err := dec.ReadBytes(_tmp1[:]); err != nil { - return err - } - _tmp0.ParentHash = _tmp1 - // UncleHash: - var _tmp2 common.Hash - if err := dec.ReadBytes(_tmp2[:]); err != nil { - return err - } - _tmp0.UncleHash = _tmp2 - // Coinbase: - var _tmp3 common.Address - if err := dec.ReadBytes(_tmp3[:]); err != nil { - return err - } - _tmp0.Coinbase = _tmp3 - // Root: - var _tmp4 common.Hash - if err := dec.ReadBytes(_tmp4[:]); err != nil { - return err - } - _tmp0.Root = _tmp4 - // TxHash: - var _tmp5 common.Hash - if err := dec.ReadBytes(_tmp5[:]); err != nil { - return err - } - _tmp0.TxHash = _tmp5 - // ReceiptHash: - var _tmp6 common.Hash - if err := dec.ReadBytes(_tmp6[:]); err != nil { - return err - } - _tmp0.ReceiptHash = _tmp6 - // Bloom: - var _tmp7 Bloom - if err := dec.ReadBytes(_tmp7[:]); err != nil { - return err - } - _tmp0.Bloom = _tmp7 - // Difficulty: - _tmp8, err := dec.BigInt() - if err != nil { - return err - } - _tmp0.Difficulty = _tmp8 - // Number: - _tmp9, err := dec.BigInt() - if err != nil { - return err - } - _tmp0.Number = _tmp9 - // GasLimit: - _tmp10, err := dec.Uint64() - if err != nil { - return err - } - _tmp0.GasLimit = _tmp10 - // GasUsed: - _tmp11, err := dec.Uint64() - if err != nil { - return err - } - _tmp0.GasUsed = _tmp11 - // Time: - _tmp12, err := dec.Uint64() - if err != nil { - return err - } - _tmp0.Time = _tmp12 - // Extra: - _tmp13, err := dec.Bytes() - if err != nil { - return err - } - _tmp0.Extra = _tmp13 - // MixDigest: - var _tmp14 common.Hash - if err := dec.ReadBytes(_tmp14[:]); err != nil { - return err - } - _tmp0.MixDigest = _tmp14 - // Nonce: - var _tmp15 BlockNonce - if err := dec.ReadBytes(_tmp15[:]); err != nil { - return err - } - _tmp0.Nonce = _tmp15 - // BaseFee: - if dec.MoreDataInList() { - _tmp16, err := dec.BigInt() - if err != nil { - return err - } - _tmp0.BaseFee = _tmp16 - } - if err := dec.ListEnd(); err != nil { - return err - } - } - *obj = _tmp0 - return nil -} diff --git a/core/types/gen_log_rlp.go b/core/types/gen_log_rlp.go index 78fa783cee1f..4a6c6b0094f8 100644 --- a/core/types/gen_log_rlp.go +++ b/core/types/gen_log_rlp.go @@ -5,11 +5,8 @@ package types -import ( - "io" - - "github.com/ethereum/go-ethereum/rlp" -) +import "github.com/ethereum/go-ethereum/rlp" +import "io" func (obj *rlpLog) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) From 46267e0f4d916e4828f1940d33f948e42eec74b9 Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:04:36 +0200 Subject: [PATCH 3/3] returns a verkle trie after the transition --- core/state/database.go | 15 +-------------- trie/verkle.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/core/state/database.go b/core/state/database.go index 49330c520000..2ce4ea051d32 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -366,20 +366,7 @@ func (db *cachingDB) openStorageMPTrie(stateRoot common.Hash, address common.Add // OpenStorageTrie opens the storage trie of an account func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) { if db.ended { - mpt, err := db.openStorageMPTrie(common.Hash{}, address, common.Hash{}, self) - if err != nil { - return nil, err - } - // Return a "storage trie" that is an adapter between the storge MPT - // and the unique verkle tree. - switch self := self.(type) { - case *trie.VerkleTrie: - return trie.NewTransitionTree(mpt.(*trie.StateTrie), self, true), nil - case *trie.TransitionTrie: - return trie.NewTransitionTree(mpt.(*trie.StateTrie), self.Overlay(), true), nil - default: - panic("unexpected trie type") - } + return trie.NewStorageAdapterFromMainTree(self.(*trie.VerkleTrie)), nil } if db.started { mpt, err := db.openStorageMPTrie(db.LastMerkleRoot, address, root, nil) diff --git a/trie/verkle.go b/trie/verkle.go index fcf9e114cfc0..8c16dda7a404 100644 --- a/trie/verkle.go +++ b/trie/verkle.go @@ -39,6 +39,7 @@ type VerkleTrie struct { db *Database pointCache *utils.PointCache ended bool + storage bool } func (vt *VerkleTrie) ToDot() string { @@ -54,6 +55,18 @@ func NewVerkleTrie(root verkle.VerkleNode, db *Database, pointCache *utils.Point } } +// NewVerkleTrieFromMainTree creates a new VerkleTrie from the main trie, that +// is used as an adapter for the main trie to be used as a storage trie. +func NewStorageAdapterFromMainTree(self *VerkleTrie) *VerkleTrie { + return &VerkleTrie{ + root: self.root, + db: self.db, + pointCache: self.pointCache, + ended: self.ended, + storage: true, + } +} + func (trie *VerkleTrie) flatdbNodeResolver(path []byte) ([]byte, error) { return trie.db.diskdb.Get(append(FlatDBVerkleNodeKeyPrefix, path...)) } @@ -261,6 +274,13 @@ func nodeToDBKey(n verkle.VerkleNode) []byte { // Commit writes all nodes to the trie's memory database, tracking the internal // and external (for account tries) references. func (trie *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) { + if trie.storage { + // Do not commit anything if this is a "storage trie" adapter for + // the main trie. Verkle tries only commit the single trie once at + // the end of block processing. + return common.Hash{}, nil, nil + } + root, ok := trie.root.(*verkle.InternalNode) if !ok { return common.Hash{}, nil, errors.New("unexpected root node type")