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

overlay-tree: allow resumable runs #233

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 5 additions & 3 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1688,7 +1688,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
}

if parent.Number.Uint64() == conversionBlock {
bc.StartVerkleTransition(parent.Root, emptyVerkleRoot)
if err := bc.StartVerkleTransition(parent.Root, emptyVerkleRoot); err != nil {
return it.index, fmt.Errorf("failed to start verkle transition: %s", err)
}
}
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
if err != nil {
Expand Down Expand Up @@ -2459,8 +2461,8 @@ func (bc *BlockChain) SetBlockValidatorAndProcessorForTesting(v Validator, p Pro
bc.processor = p
}

func (bc *BlockChain) StartVerkleTransition(originalRoot, translatedRoot common.Hash) {
bc.stateCache.(*state.ForkingDB).StartTransition(originalRoot, translatedRoot)
func (bc *BlockChain) StartVerkleTransition(originalRoot, translatedRoot common.Hash) error {
return bc.stateCache.(*state.ForkingDB).StartTransition(originalRoot, translatedRoot)
}

func (bc *BlockChain) AddRootTranslation(originalRoot, translatedRoot common.Hash) {
Expand Down
49 changes: 34 additions & 15 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/utils"
"github.com/gballet/go-verkle"
Expand All @@ -40,6 +41,12 @@ const (
codeCacheSize = 64 * 1024 * 1024
)

var (
dbKeyOverlayTransitionStarted = []byte("overlay-transition-started")
dbKeyOverlayTransitionEnded = []byte("overlay-transition-ended")
translatedRootPrefix = []byte("translated-")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the db key prefix for saving the root translation table.

)

// Database wraps access to tries and contract code.
type Database interface {
// OpenTrie opens the main account trie.
Expand Down Expand Up @@ -137,6 +144,14 @@ func NewDatabase(db ethdb.Database) Database {
// large memory cache.
func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
csc, _ := lru.New(codeSizeCacheSize)
transitionStarted, err := db.Has(dbKeyOverlayTransitionStarted)
if err != nil {
panic(err)
}
transitionEnded, err := db.Has(dbKeyOverlayTransitionEnded)
if err != nil {
panic(err)
}
return &ForkingDB{
cachingDB: &cachingDB{
db: trie.NewDatabaseWithConfig(db, config),
Expand All @@ -151,8 +166,8 @@ func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
codeCache: fastcache.New(codeCacheSize),
addrToPoint: utils.NewPointCache(),
},
started: (config != nil && config.UseVerkle),
ended: (config != nil && config.UseVerkle),
started: transitionStarted,
ended: transitionEnded,
}
}

Expand All @@ -164,9 +179,6 @@ type ForkingDB struct {

// TODO ensure that this info is in the DB
started, ended bool
translatedRoots [32]common.Hash // hash of the translated root, for opening
origRoots [32]common.Hash
translationIndex int
translatedRootsLock sync.RWMutex

baseRoot common.Hash // hash of the read-only base tree
Expand Down Expand Up @@ -283,7 +295,7 @@ func (fdg *ForkingDB) Transitionned() bool {
}

// Fork implements the fork
func (fdb *ForkingDB) StartTransition(originalRoot, translatedRoot common.Hash) {
func (fdb *ForkingDB) StartTransition(originalRoot, translatedRoot common.Hash) error {
fmt.Println(`
__________.__ .__ .__ __ .__ .__ ____
\__ ___| |__ ____ ____ | | ____ ______ | |__ _____ _____/ |_ | |__ _____ ______ __ _ _|__| ____ / ___\ ______
Expand All @@ -292,13 +304,18 @@ func (fdb *ForkingDB) StartTransition(originalRoot, translatedRoot common.Hash)
|____| |___| /\___ \___ |____/\___ | __/|___| (____ |___| |__| |___| (____ /_____/ \/\_/ |__|___| /_____//_____/
|__|`)
fdb.started = true
if err := fdb.VerkleDB.diskdb.Put(dbKeyOverlayTransitionStarted, []byte{1}); err != nil {
return fmt.Errorf("failed to start transition: %s", err)
}
fdb.AddTranslation(originalRoot, translatedRoot)
fdb.baseRoot = originalRoot
// initialize so that the first storage-less accounts are processed
fdb.StorageProcessed = true

return nil
}

func (fdb *ForkingDB) EndTransition() {
func (fdb *ForkingDB) EndTransition() error {
fmt.Println(`
__________.__ .__ .__ __ .__ .__ .___ .___
\__ ___| |__ ____ ____ | | ____ ______ | |__ _____ _____/ |_ | |__ _____ ______ | | _____ ____ __| _/____ __| _/
Expand All @@ -307,26 +324,28 @@ func (fdb *ForkingDB) EndTransition() {
|____| |___| /\___ \___ |____/\___ | __/|___| (____ |___| |__| |___| (____ /_____/ |____(____ |___| \____ |\___ \____ |
|__|`)
fdb.ended = true
if err := fdb.VerkleDB.diskdb.Put(dbKeyOverlayTransitionEnded, []byte{1}); err != nil {
return fmt.Errorf("failed to mark transition as ended: %s", err)
}
return nil
}

func (fdb *ForkingDB) AddTranslation(orig, trans common.Hash) {
// TODO make this persistent
fdb.translatedRootsLock.Lock()
defer fdb.translatedRootsLock.Unlock()
fdb.translatedRoots[fdb.translationIndex] = trans
fdb.origRoots[fdb.translationIndex] = orig
fdb.translationIndex = (fdb.translationIndex + 1) % len(fdb.translatedRoots)
fdb.diskdb.Put(append(translatedRootPrefix, orig.Bytes()...), trans.Bytes())
log.Info("Saved translation", "originRoot", orig.Bytes(), "translatedRoot", trans.Bytes())
Comment on lines -316 to +338
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of writing to the map, we save into the database.
I left an extra log-info since it can help a bit after when something doesn't work.

}

func (fdb *ForkingDB) getTranslation(orig common.Hash) common.Hash {
fdb.translatedRootsLock.RLock()
defer fdb.translatedRootsLock.RUnlock()
for i, o := range fdb.origRoots {
if o == orig {
return fdb.translatedRoots[i]
}
trans, err := fdb.diskdb.Get(append(translatedRootPrefix, orig.Bytes()...))
if err != nil {
return common.Hash{}
}
Comment on lines +345 to 347
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically speaking, this is equivalent to before. If Get returns err=leveldb.NotFound it returns common.Hash{} as before.

There's an extra border-case here if the err is related to a disk error. Very low chance for now to care about, but that needs bubbling some error in the chain. Not sure if this code will stay for long, but we can properly handle and clean up after.

return common.Hash{}
return common.BytesToHash(trans)
}

type cachingDB struct {
Expand Down