Skip to content

Commit

Permalink
overlay transition
Browse files Browse the repository at this point in the history
Fix some bugs identified in the code review

Co-authored-by: Ignacio Hagopian <[email protected]>

Include base -> overlay key-values migration logic (#199)

* mod: add go-verkle version with key-value migration new apis

Signed-off-by: Ignacio Hagopian <[email protected]>

* core/stateprocessor: use constant for max number of migrated key-values

Signed-off-by: Ignacio Hagopian <[email protected]>

* core: add base->overlay key-values migration logic

Signed-off-by: Ignacio Hagopian <[email protected]>

* core: fix some compiler errors

Signed-off-by: Ignacio Hagopian <[email protected]>

* trie: consider removing transition trie api in the future

Signed-off-by: Ignacio Hagopian <[email protected]>

* mod: use latest go-verkle

Signed-off-by: Ignacio Hagopian <[email protected]>

---------

Signed-off-by: Ignacio Hagopian <[email protected]>

fix some unit tests errors

get convresion block from file

fix compilation issues

fix initialization issue in migrator

fix: changes needed to run the first 28 blocks

important sutff: fix the banner

fix: use nonce instead of balance in nonce leaf (#202)

fixes for performing the overlay transition (#203)

* fixes for performing the overlay transition

* fixes for the full replay

* fix: deletion-and-recreation of EoA

* fixes to replay 2M+ blocks

* upgrade to go-verkle@master

* fix: proper number of chunk evals

* rewrite conversion loop to fix known issues

changes to make replay work with the overlay method (#216)

* fixes for performing the overlay transition

fixes for the full replay

fix: deletion-and-recreation of EoA

fixes to replay 2M+ blocks

upgrade to go-verkle@master

fix: proper number of chunk evals

rewrite conversion loop to fix known issues

changes to make replay work with the overlay method

fixes to replay 2M+ blocks

update to latest go-verkle@master

* use a PBSS-like scheme for internal nodes (#221)

* use a PBSS-like scheme for internal nodes

* a couple of fixes coming from debugging replay

* fix: use an error to notify the transition tree that a deleted account was found in the overlay tree (#222)

* fixes for pbss replay (#227)

* fixes for pbss replay

* trie/verkle: use capped batch size (#229)

* trie/verkle: use capped batch size

Signed-off-by: Ignacio Hagopian <[email protected]>

* trie/verkle: avoid path variable allocation per db.Put

Signed-off-by: Ignacio Hagopian <[email protected]>

* don't keep more than 32 state root conversions in RAM (#230)

---------

Signed-off-by: Ignacio Hagopian <[email protected]>
Co-authored-by: Guillaume Ballet <[email protected]>

* cleanup some code

* mod: update go-verkle

Signed-off-by: Ignacio Hagopian <[email protected]>

* re-enable snapshot (#231)

* re-enable cancun block / snapshot (#226)

* clear storage conversion key upon translating account (#234)

* clear storage conversion key upon translating account

* mod: use latest go-verkle

Signed-off-by: Ignacio Hagopian <[email protected]>

---------

Signed-off-by: Ignacio Hagopian <[email protected]>
Co-authored-by: Ignacio Hagopian <[email protected]>

* fix: self-deadlock with translated root map mutex (#236)

* return compressed commitment as root commitment (#237)

---------

Signed-off-by: Ignacio Hagopian <[email protected]>
Co-authored-by: Ignacio Hagopian <[email protected]>

---------

Signed-off-by: Ignacio Hagopian <[email protected]>
Co-authored-by: Ignacio Hagopian <[email protected]>

---------

Signed-off-by: Ignacio Hagopian <[email protected]>
Co-authored-by: Ignacio Hagopian <[email protected]>

fix first panic in *TransitionTrie.Copy()

upgrade go-verkle to latest master

mod: update go-verkle (#239)

Signed-off-by: Ignacio Hagopian <[email protected]>

core: print state root every 100 blocks (#240)

Signed-off-by: Ignacio Hagopian <[email protected]>

fix: only Commit the account trie (#242)

fixes to get TestProcessVerkle to work with the overlay branch (#238)

* fixes to get TestProcessVerkle to work with the overlay branch

* fix all panics in verkle state processor test

* fix proof verification

move transition management to cachingDB
  • Loading branch information
gballet committed Jul 27, 2023
1 parent 0a7efe1 commit 60aa2c4
Show file tree
Hide file tree
Showing 18 changed files with 940 additions and 91 deletions.
13 changes: 6 additions & 7 deletions cmd/geth/verkle.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,13 @@ func convertToVerkle(ctx *cli.Context) error {
vRoot = verkle.New().(*verkle.InternalNode)
)

saveverkle := func(node verkle.VerkleNode) {
comm := node.Commit()
saveverkle := func(path []byte, node verkle.VerkleNode) {
node.Commit()
s, err := node.Serialize()
if err != nil {
panic(err)
}
commB := comm.Bytes()
if err := chaindb.Put(commB[:], s); err != nil {
if err := chaindb.Put(path, s); err != nil {
panic(err)
}
}
Expand Down Expand Up @@ -330,7 +329,7 @@ func checkChildren(root verkle.VerkleNode, resolver verkle.NodeResolverFn) error
return fmt.Errorf("could not find child %x in db: %w", childC, err)
}
// depth is set to 0, the tree isn't rebuilt so it's not a problem
childN, err := verkle.ParseNode(childS, 0, childC[:])
childN, err := verkle.ParseNode(childS, 0)
if err != nil {
return fmt.Errorf("decode error child %x in db: %w", child.Commitment().Bytes(), err)
}
Expand Down Expand Up @@ -390,7 +389,7 @@ func verifyVerkle(ctx *cli.Context) error {
if err != nil {
return err
}
root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
root, err := verkle.ParseNode(serializedRoot, 0)
if err != nil {
return err
}
Expand Down Expand Up @@ -439,7 +438,7 @@ func expandVerkle(ctx *cli.Context) error {
if err != nil {
return err
}
root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
root, err := verkle.ParseNode(serializedRoot, 0)
if err != nil {
return err
}
Expand Down
12 changes: 12 additions & 0 deletions cmd/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"os"
"os/signal"
"runtime"
"runtime/pprof"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -173,6 +174,17 @@ func ImportChain(chain *core.BlockChain, fn string) error {
return err
}
}
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()

stream := rlp.NewStream(reader, 0)

// Run actual the import.
Expand Down
31 changes: 18 additions & 13 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,17 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
}
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
return consensus.ErrUnknownAncestor
}
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
}

Expand All @@ -90,15 +95,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)", header.Root, root)
}
// if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
// return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
// }
return nil
}

Expand Down
36 changes: 36 additions & 0 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
package core

import (
"bufio"
"errors"
"fmt"
"io"
"math/big"
"os"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -1486,6 +1489,21 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
return 0, nil
}

f, err := os.Open("conversion.txt")
if err != nil {
log.Error("Failed to open conversion.txt", "err", err)
return 0, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Scan()
conversionBlock, err := strconv.ParseUint(scanner.Text(), 10, 64)
if err != nil {
log.Error("Failed to parse conversionBlock", "err", err)
return 0, err
}
log.Info("Found conversion block info", "conversionBlock", conversionBlock)

// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)

Expand Down Expand Up @@ -1670,6 +1688,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
if parent == nil {
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
}

if parent.Number.Uint64() == conversionBlock {
bc.StartVerkleTransition(parent.Root, emptyVerkleRoot, bc.Config(), parent.Number)
}
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
if err != nil {
return it.index, err
Expand Down Expand Up @@ -1706,6 +1728,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
return it.index, err
}

if statedb.Database().InTransition() || statedb.Database().Transitionned() {
bc.AddRootTranslation(block.Root(), statedb.IntermediateRoot(false))
}

// Update the metrics touched during block processing
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete, we can mark them
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete, we can mark them
Expand Down Expand Up @@ -2287,6 +2313,8 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
return false
}

var emptyVerkleRoot common.Hash

// indexBlocks reindexes or unindexes transactions depending on user configuration
func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
defer func() { close(done) }()
Expand Down Expand Up @@ -2431,3 +2459,11 @@ func (bc *BlockChain) SetBlockValidatorAndProcessorForTesting(v Validator, p Pro
bc.validator = v
bc.processor = p
}

func (bc *BlockChain) StartVerkleTransition(originalRoot, translatedRoot common.Hash, chainConfig *params.ChainConfig, cancunBlock *big.Int) {
bc.stateCache.StartVerkleTransition(originalRoot, translatedRoot, chainConfig, cancunBlock)
}

func (bc *BlockChain) AddRootTranslation(originalRoot, translatedRoot common.Hash) {
bc.stateCache.AddRootTranslation(originalRoot, translatedRoot)
}
18 changes: 17 additions & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
keyvals := make([]verkle.StateDiff, 0, n)
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
chainreader := &fakeChainReader{config: config}
var preStateTrie *trie.VerkleTrie
genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
b.header = makeHeader(chainreader, parent, statedb, b.engine)
Expand Down Expand Up @@ -372,13 +373,28 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
kvs[string(key)] = v
}

// Initialize the preStateTrie if it is nil, this should
// correspond to the genesis block. This is a workaround
// needed until the main verkle PR is rebased on top of
// PBSS.
if preStateTrie == nil {
preStateTrie = vtr
}

vtr.Hash()
p, k, err := vtr.ProveAndSerialize(statedb.Witness().Keys(), kvs)
p, k, err := preStateTrie.ProveAndSerialize(statedb.Witness().Keys(), kvs)
if err != nil {
panic(err)
}
proofs = append(proofs, p)
keyvals = append(keyvals, k)

// save the current state of the trie for producing the proof for the next block,
// since reading it from disk is broken with the intermediate PBSS-like system we
// have: it will read the post-state as this is the only state present on disk.
// This is a workaround needed until the main verkle PR is rebased on top of PBSS.
preStateTrie = statedb.GetTrie().(*trie.VerkleTrie)

return block, b.receipts
}
return nil, nil
Expand Down
Loading

0 comments on commit 60aa2c4

Please sign in to comment.