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

[wip] snapshot block hash changes #691

Draft
wants to merge 36 commits into
base: libevm
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
314fe42
format: as subnet-evm
darioush Sep 25, 2024
72a4b00
take changes up to d72ff25 from subnet-evm
darioush Oct 2, 2024
b3647e3
complete use core/vm
darioush Sep 26, 2024
20754f7
format: as coreth
darioush Oct 2, 2024
6ff7f77
ci fixes
darioush Sep 26, 2024
512ae03
use race free version
darioush Sep 26, 2024
0baae1a
update version
darioush Sep 26, 2024
4fe802b
rebase new libevm
darioush Sep 27, 2024
df98c4e
remove WithExtras hack
darioush Oct 1, 2024
8e223b9
cleanup
darioush Oct 2, 2024
43dde81
fix genesis EthUpgrades
darioush Oct 3, 2024
0976d50
update libevm
darioush Oct 7, 2024
473a6ab
snapshot: initial refactoring for use with upstream statedb
darioush Oct 7, 2024
95c4c16
refactor: inline CommitWithSnap
darioush Oct 7, 2024
b82d5fa
remove unused args
darioush Oct 7, 2024
ac1e437
reduce diff
darioush Oct 7, 2024
2ebad51
handle snapshot update with root same as parent
darioush Oct 7, 2024
6b6fb64
reference root refactor (use triedb)
darioush Oct 8, 2024
b985d91
to fix on master
darioush Oct 8, 2024
87f64eb
nit: reduce diff w/ upstream
darioush Oct 8, 2024
e379625
no mc funds were used in genesis (mainnet/fuji)
darioush Oct 8, 2024
2d0ea28
minor improvement
darioush Oct 8, 2024
a963103
use libevm rebased for arr4n/state-db-extra-payload-handling
darioush Oct 8, 2024
dac5b3e
remove trie/ package
darioush Oct 8, 2024
27f02f1
use libevm for triedb
darioush Oct 9, 2024
4704b1c
update version e2e
darioush Oct 9, 2024
18d20f1
update geth packages
darioush Oct 9, 2024
1aa620e
remove triedb package
darioush Oct 9, 2024
83a4e52
format: rename to libevm
darioush Nov 12, 2024
373adba
Merge branch 'libevm' of github.com:ava-labs/coreth into use-libevm-s…
darioush Nov 12, 2024
716d584
oops
darioush Nov 12, 2024
03f7086
use DBOverride to specify backends
darioush Nov 13, 2024
f9f6852
libevm version changes
darioush Nov 21, 2024
4f1e58e
snapshot block hash changes
darioush Nov 21, 2024
13dd0d2
replace in e2e
darioush Nov 21, 2024
f8f597d
fix
darioush Nov 21, 2024
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
5 changes: 5 additions & 0 deletions accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2179,6 +2179,11 @@ func golangBindings(t *testing.T, overload bool) {
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}
replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/ava-labs/[email protected]", "-replace", "github.com/ava-labs/libevm=github.com/ava-labs/[email protected]")
replacer.Dir = pkg
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}
tidier := exec.Command(gocmd, "mod", "tidy", "-compat=1.22")
tidier.Dir = pkg
if out, err := tidier.CombinedOutput(); err != nil {
Expand Down
9 changes: 7 additions & 2 deletions accounts/abi/bind/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,15 @@ func TestWaitDeployedCornerCases(t *testing.T) {
// Create a transaction to an account.
code := "6060604052600a8060106000396000f360606040526008565b00"
tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
tx, _ = types.SignTx(tx, types.LatestSigner(params.TestChainConfig), testKey)
tx, err := types.SignTx(tx, types.LatestSignerForChainID(big.NewInt(1337)), testKey)
if err != nil {
t.Fatalf("Failed to sign transaction: %s", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
backend.Client().SendTransaction(ctx, tx)
if err := backend.Client().SendTransaction(ctx, tx); err != nil {
t.Fatalf("Failed to send transaction: %s", err)
}
backend.Commit(true)
notContractCreation := errors.New("tx is not contract creation")
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != notContractCreation.Error() {
Expand Down
2 changes: 1 addition & 1 deletion consensus/dummy/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"github.com/ava-labs/coreth/core/state"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/trie"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/trie"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
"github.com/ava-labs/coreth/core/state"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/trie"
"github.com/ava-labs/libevm/trie"
)

// BlockValidator is responsible for validating block headers, uncles and
Expand Down
90 changes: 56 additions & 34 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ import (
"github.com/ava-labs/coreth/consensus/misc/eip4844"
"github.com/ava-labs/coreth/core/rawdb"
"github.com/ava-labs/coreth/core/state"
"github.com/ava-labs/coreth/core/state/snapshot"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/internal/version"
"github.com/ava-labs/coreth/metrics"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/trie"
"github.com/ava-labs/coreth/triedb"
"github.com/ava-labs/coreth/triedb/hashdb"
"github.com/ava-labs/coreth/triedb/pathdb"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/common/lru"
ethsnapshot "github.com/ava-labs/libevm/core/state/snapshot"
"github.com/ava-labs/libevm/core/vm"
"github.com/ava-labs/libevm/ethdb"
"github.com/ava-labs/libevm/event"
"github.com/ava-labs/libevm/log"
"github.com/ava-labs/libevm/trie"
"github.com/ava-labs/libevm/triedb"
)

var (
Expand Down Expand Up @@ -177,18 +177,19 @@ type CacheConfig struct {
// triedbConfig derives the configures for trie database.
func (c *CacheConfig) triedbConfig() *triedb.Config {
config := &triedb.Config{Preimages: c.Preimages}
if c.StateScheme == rawdb.HashScheme {
config.HashDB = &hashdb.Config{
if c.StateScheme == rawdb.HashScheme || c.StateScheme == "" {
config.DBOverride = hashdb.Config{
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
StatsPrefix: trieCleanCacheStatsNamespace,
}
ReferenceRoot: true, // Automatically reference root nodes when an update is made
}.BackendConstructor
}
if c.StateScheme == rawdb.PathScheme {
config.PathDB = &pathdb.Config{
config.DBOverride = pathdb.Config{
StateHistory: c.StateHistory,
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
}
}.BackendConstructor
}
return config
}
Expand Down Expand Up @@ -241,11 +242,11 @@ type BlockChain struct {
chainConfig *params.ChainConfig // Chain & network configuration
cacheConfig *CacheConfig // Cache configuration for pruning

db ethdb.Database // Low level persistent database to store final content in
snaps *snapshot.Tree // Snapshot tree for fast trie leaf access
triedb *triedb.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
db ethdb.Database // Low level persistent database to store final content in
snaps *ethsnapshot.Tree // Snapshot tree for fast trie leaf access
triedb *triedb.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
stateManager TrieWriter

hc *HeaderChain
Expand Down Expand Up @@ -939,6 +940,14 @@ func (bc *BlockChain) Stop() {

// Ensure that the entirety of the state snapshot is journaled to disk.
if bc.snaps != nil {
_, err := bc.db.Has(nil)
dbOpen := err == nil
if dbOpen {
//if _, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil {
// log.Error("Failed to journal state snapshot", "err", err)
//}
}
bc.snaps.AbortGeneration()
bc.snaps.Release()
}
if bc.triedb.Scheme() == rawdb.PathScheme {
Expand Down Expand Up @@ -1125,8 +1134,8 @@ func (bc *BlockChain) newTip(block *types.Block) bool {
// canonical chain.
// writeBlockAndSetHead expects to be the last verification step during InsertBlock
// since it creates a reference that will only be cleaned up by Accept/Reject.
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB) error {
if err := bc.writeBlockWithState(block, receipts, state); err != nil {
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, parentRoot common.Hash, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB) error {
if err := bc.writeBlockWithState(block, parentRoot, receipts, state); err != nil {
return err
}

Expand All @@ -1143,7 +1152,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types

// writeBlockWithState writes the block and all associated state to the database,
// but it expects the chain mutex to be held.
func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error {
func (bc *BlockChain) writeBlockWithState(block *types.Block, parentRoot common.Hash, receipts []*types.Receipt, state *state.StateDB) error {
// Irrelevant of the canonical status, write the block itself to the database.
//
// Note all the components of block(hash->number map, header, body, receipts)
Expand All @@ -1157,14 +1166,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
}

// Commit all cached state changes into underlying memory database.
// If snapshots are enabled, call CommitWithSnaps to explicitly create a snapshot
// diff layer for the block.
var err error
if bc.snaps == nil {
_, err = state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), true)
} else {
_, err = state.CommitWithSnap(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.snaps, block.Hash(), block.ParentHash(), true)
}
_, err = bc.commitWithSnap(block, parentRoot, state)
if err != nil {
return err
}
Expand Down Expand Up @@ -1367,7 +1370,7 @@ func (bc *BlockChain) insertBlock(block *types.Block, writes bool) error {
// will be cleaned up in Accept/Reject so we need to ensure an error cannot occur
// later in verification, since that would cause the referenced root to never be dereferenced.
wstart := time.Now()
if err := bc.writeBlockAndSetHead(block, receipts, logs, statedb); err != nil {
if err := bc.writeBlockAndSetHead(block, parent.Root, receipts, logs, statedb); err != nil {
return err
}
// Update the metrics touched during block commit
Expand Down Expand Up @@ -1667,7 +1670,7 @@ func (bc *BlockChain) reprocessBlock(parent *types.Block, current *types.Block)
if snap == nil {
return common.Hash{}, fmt.Errorf("failed to get snapshot for parent root: %s", parentRoot)
}
statedb, err = state.NewWithSnapshot(parentRoot, bc.stateCache, snap)
statedb, err = state.New(parentRoot, bc.stateCache, bc.snaps)
}
if err != nil {
return common.Hash{}, fmt.Errorf("could not fetch state for (%s: %d): %v", parent.Hash().Hex(), parent.NumberU64(), err)
Expand All @@ -1692,12 +1695,33 @@ func (bc *BlockChain) reprocessBlock(parent *types.Block, current *types.Block)
log.Debug("Processed block", "block", current.Hash(), "number", current.NumberU64())

// Commit all cached state changes into underlying memory database.
// If snapshots are enabled, call CommitWithSnaps to explicitly create a snapshot
// diff layer for the block.
if bc.snaps == nil {
return statedb.Commit(current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()), false)
return bc.commitWithSnap(current, parentRoot, statedb)
}

func (bc *BlockChain) commitWithSnap(
current *types.Block, parentRoot common.Hash, statedb *state.StateDB,
) (common.Hash, error) {
// If snapshots are enabled, WithBlockHashes must be called as snapshot layers
// are stored by block hash.
root, err := statedb.Commit(
current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()),
ethsnapshot.WithBlockHashes(current.Hash(), current.ParentHash()),
)
if err != nil {
return common.Hash{}, err
}
// Upstream does not perform a snapshot update if the root is the same as the
// parent root, however here the snapshots are based on the block hash, so
// this update is necessary.
if bc.snaps != nil && root == parentRoot {
if err := bc.snaps.Update(
root, parentRoot, nil, nil, nil,
ethsnapshot.WithBlockHashes(current.Hash(), current.ParentHash()),
); err != nil {
return common.Hash{}, err
}
}
return statedb.CommitWithSnap(current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()), bc.snaps, current.Hash(), current.ParentHash(), false)
return root, nil
}

// initSnapshot instantiates a Snapshot instance and adds it to [bc]
Expand All @@ -1715,14 +1739,13 @@ func (bc *BlockChain) initSnapshot(b *types.Header) {
asyncBuild := !bc.cacheConfig.SnapshotWait && b.Number.Uint64() > 0
noBuild := bc.cacheConfig.SnapshotNoBuild && b.Number.Uint64() > 0
log.Info("Initializing snapshots", "async", asyncBuild, "rebuild", !noBuild, "headHash", b.Hash(), "headRoot", b.Root)
snapconfig := snapshot.Config{
snapconfig := ethsnapshot.Config{
CacheSize: bc.cacheConfig.SnapshotLimit,
NoBuild: noBuild,
AsyncBuild: asyncBuild,
SkipVerify: !bc.cacheConfig.SnapshotVerify,
}
var err error
bc.snaps, err = snapshot.New(snapconfig, bc.db, bc.triedb, b.Hash(), b.Root)
bc.snaps, err = ethsnapshot.New(snapconfig, bc.db, bc.triedb, b.Root)
if err != nil {
log.Error("failed to initialize snapshots", "headHash", b.Hash(), "headRoot", b.Root, "err", err, "async", asyncBuild)
}
Expand Down Expand Up @@ -1838,7 +1861,6 @@ func (bc *BlockChain) reprocessState(current *types.Block, reexec uint64) error
// Flatten snapshot if initialized, holding a reference to the state root until the next block
// is processed.
if err := bc.flattenSnapshot(func() error {
triedb.Reference(root, common.Hash{})
if previousRoot != (common.Hash{}) {
triedb.Dereference(previousRoot)
}
Expand Down
8 changes: 6 additions & 2 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ import (
"github.com/ava-labs/coreth/core/state/snapshot"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/triedb"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/vm"
"github.com/ava-labs/libevm/event"
"github.com/ava-labs/libevm/triedb"
)

// CurrentHeader retrieves the current head header of the canonical chain. The
Expand Down Expand Up @@ -264,10 +264,14 @@ func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }
func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }

// Snapshots returns the blockchain snapshot tree.
func (bc *BlockChain) Snapshots() *snapshot.Tree {
func (bc *BlockChain) Snapshots() snapshot.DiskIterable {
return bc.snaps
}

func (bc *BlockChain) VerifySnapshot(root common.Hash) error {
return bc.snaps.Verify(root)
}

// Validator returns the current validator.
func (bc *BlockChain) Validator() Validator {
return bc.validator
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_repair_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ import (
"github.com/ava-labs/coreth/core/rawdb"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/triedb"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/vm"
"github.com/ava-labs/libevm/crypto"
"github.com/ava-labs/libevm/triedb"
"github.com/stretchr/testify/require"
)

Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [
t.Errorf("The corresponding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom)
} else if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) {
t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot())
} else if len(chain.snaps.Snapshots(block.Hash(), -1, false)) != 1 {
} else if len(chain.snaps.Snapshots(block.Root(), -1, false)) != 1 {
t.Errorf("The corresponding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom)
}

Expand Down
4 changes: 2 additions & 2 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ import (
"github.com/ava-labs/coreth/core/state"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/triedb"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/vm"
"github.com/ava-labs/libevm/ethdb"
"github.com/ava-labs/libevm/triedb"
"github.com/holiman/uint256"
)

Expand Down Expand Up @@ -298,7 +298,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}

// Write state changes to db
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number), false)
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
}
Expand Down
2 changes: 1 addition & 1 deletion core/chain_makers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import (
"github.com/ava-labs/coreth/core/rawdb"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/triedb"
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/core/vm"
"github.com/ava-labs/libevm/crypto"
"github.com/ava-labs/libevm/triedb"
)

func ExampleGenerateChain() {
Expand Down
13 changes: 12 additions & 1 deletion core/extstate/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import (

type VmStateDB interface {
vm.StateDB
Logs() []*types.Log

GetTxHash() common.Hash
GetLogData() (topics [][]common.Hash, data [][]byte)
GetBalanceMultiCoin(common.Address, common.Hash) *big.Int
AddBalanceMultiCoin(common.Address, common.Hash, *big.Int)
SubBalanceMultiCoin(common.Address, common.Hash, *big.Int)
Expand All @@ -36,6 +37,16 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d
s.VmStateDB.Prepare(rules, sender, coinbase, dst, precompiles, list)
}

// GetLogData returns the underlying topics and data from each log included in the StateDB
// Test helper function.
func (s *StateDB) GetLogData() (topics [][]common.Hash, data [][]byte) {
for _, log := range s.Logs() {
topics = append(topics, log.Topics)
data = append(data, common.CopyBytes(log.Data))
}
return topics, data
}

// GetPredicateStorageSlots returns the storage slots associated with the address, index pair.
// A list of access tuples can be included within transaction types post EIP-2930. The address
// is declared directly on the access tuple and the index is the i'th occurrence of an access
Expand Down
Loading
Loading