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

attach ref. counting to triedb instead of statedb #574

Draft
wants to merge 1 commit into
base: coreth-001-minimal
Choose a base branch
from
Draft
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
10 changes: 5 additions & 5 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ func NewBlockChain(
}
// Open trie database with provided config
triedb := trie.NewDatabase(db, cacheConfig.triedbConfig())
triedb.EnableRefCounting()
Copy link
Collaborator Author

@darioush darioush Jun 7, 2024

Choose a reason for hiding this comment

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

can move this to the config or NewDatabaseWithRefCounting, sort of same IMO

Copy link
Collaborator

@ceyonur ceyonur Jun 10, 2024

Choose a reason for hiding this comment

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

agreed, IMO config sounds better.


// Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the
Expand Down Expand Up @@ -1239,9 +1240,9 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// diff layer for the block.
var err error
if bc.snaps == nil {
_, err = state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), true)
_, err = state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()))
} else {
_, err = state.CommitWithSnap(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.snaps, block.Hash(), block.ParentHash(), true)
_, err = state.CommitWithSnap(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.snaps, block.Hash(), block.ParentHash())
}
if err != nil {
return err
Expand Down Expand Up @@ -1793,9 +1794,9 @@ func (bc *BlockChain) reprocessBlock(parent *types.Block, current *types.Block)
// 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 statedb.Commit(current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()))
}
return statedb.CommitWithSnap(current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()), bc.snaps, current.Hash(), current.ParentHash(), false)
return statedb.CommitWithSnap(current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()), bc.snaps, current.Hash(), current.ParentHash())
}

// initSnapshot instantiates a Snapshot instance and adds it to [bc]
Expand Down Expand Up @@ -1936,7 +1937,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
2 changes: 1 addition & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,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/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func (g *Genesis) toBlock(db ethdb.Database, triedb *trie.Database) *types.Block
}
}

statedb.Commit(0, false, false)
statedb.Commit(0, false)
// Commit newly generated states into disk if it's not empty.
if root != types.EmptyRootHash {
if err := triedb.Commit(root, true); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion core/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestIterativeDump(t *testing.T) {
// write some of them to the trie
s.state.updateStateObject(obj1)
s.state.updateStateObject(obj2)
root, _ := s.state.Commit(0, false, false)
root, _ := s.state.Commit(0, false)
s.state, _ = New(root, tdb, nil)

b := &bytes.Buffer{}
Expand Down
20 changes: 7 additions & 13 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -1262,14 +1262,14 @@ func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.A
}

// Commit writes the state to the underlying in-memory trie database.
func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool, referenceRoot bool) (common.Hash, error) {
return s.commit(block, deleteEmptyObjects, nil, common.Hash{}, common.Hash{}, referenceRoot)
func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) {
return s.commit(block, deleteEmptyObjects, nil, common.Hash{}, common.Hash{})
}

// CommitWithSnap writes the state to the underlying in-memory trie database and
// generates a snapshot layer for the newly committed state.
func (s *StateDB) CommitWithSnap(block uint64, deleteEmptyObjects bool, snaps *snapshot.Tree, blockHash, parentHash common.Hash, referenceRoot bool) (common.Hash, error) {
return s.commit(block, deleteEmptyObjects, snaps, blockHash, parentHash, referenceRoot)
func (s *StateDB) CommitWithSnap(block uint64, deleteEmptyObjects bool, snaps *snapshot.Tree, blockHash, parentHash common.Hash) (common.Hash, error) {
return s.commit(block, deleteEmptyObjects, snaps, blockHash, parentHash)
}

// Once the state is committed, tries cached in stateDB (including account
Expand All @@ -1279,7 +1279,7 @@ func (s *StateDB) CommitWithSnap(block uint64, deleteEmptyObjects bool, snaps *s
//
// The associated block number of the state transition is also provided
// for more chain context.
func (s *StateDB) commit(block uint64, deleteEmptyObjects bool, snaps *snapshot.Tree, blockHash, parentHash common.Hash, referenceRoot bool) (common.Hash, error) {
func (s *StateDB) commit(block uint64, deleteEmptyObjects bool, snaps *snapshot.Tree, blockHash, parentHash common.Hash) (common.Hash, error) {
// Short circuit in case any database failure occurred earlier.
if s.dbErr != nil {
return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
Expand Down Expand Up @@ -1388,14 +1388,8 @@ func (s *StateDB) commit(block uint64, deleteEmptyObjects bool, snaps *snapshot.
if root != origin {
start := time.Now()
set := triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete)
if referenceRoot {
if err := s.db.TrieDB().UpdateAndReferenceRoot(root, origin, block, nodes, set); err != nil {
return common.Hash{}, err
}
} else {
if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil {
return common.Hash{}, err
}
if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil {
return common.Hash{}, err
}
s.originalRoot = root
if metrics.EnabledExpensive {
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func (test *stateTest) run() bool {
} else {
state.IntermediateRoot(true) // call intermediateRoot at the transaction boundary
}
nroot, err := state.Commit(0, true, false) // call commit at the block boundary
nroot, err := state.Commit(0, true) // call commit at the block boundary
if err != nil {
panic(err)
}
Expand Down
36 changes: 18 additions & 18 deletions core/state/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ func TestIntermediateLeaks(t *testing.T) {
}

// Commit and cross check the databases.
transRoot, err := transState.Commit(0, false, false)
transRoot, err := transState.Commit(0, false)
if err != nil {
t.Fatalf("failed to commit transition state: %v", err)
}
if err = transNdb.Commit(transRoot, false); err != nil {
t.Errorf("can not commit trie %v to persistent database", transRoot.Hex())
}

finalRoot, err := finalState.Commit(0, false, false)
finalRoot, err := finalState.Commit(0, false)
if err != nil {
t.Fatalf("failed to commit final state: %v", err)
}
Expand Down Expand Up @@ -542,7 +542,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
func TestTouchDelete(t *testing.T) {
s := newStateEnv()
s.state.GetOrNewStateObject(common.Address{})
root, _ := s.state.Commit(0, false, false)
root, _ := s.state.Commit(0, false)
s.state, _ = NewWithSnapshot(root, s.state.db, s.state.snap)

snapshot := s.state.Snapshot()
Expand Down Expand Up @@ -630,7 +630,7 @@ func TestCopyCommitCopy(t *testing.T) {
t.Fatalf("second copy committed storage slot mismatch: have %x, want %x", val, sval)
}
// Commit state, ensure states can be loaded from disk
root, _ := state.Commit(0, false, false)
root, _ := state.Commit(0, false)
state, _ = New(root, tdb, nil)
if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42)
Expand Down Expand Up @@ -744,7 +744,7 @@ func TestCommitCopy(t *testing.T) {
t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
}
// Copy the committed state database, the copied one is not functional.
state.Commit(0, true, false)
state.Commit(0, true)
copied := state.Copy()
if balance := copied.GetBalance(addr); balance.Cmp(big.NewInt(0)) != 0 {
t.Fatalf("unexpected balance: have %v", balance)
Expand Down Expand Up @@ -778,7 +778,7 @@ func TestDeleteCreateRevert(t *testing.T) {
addr := common.BytesToAddress([]byte("so"))
state.SetBalance(addr, big.NewInt(1))

root, _ := state.Commit(0, false, false)
root, _ := state.Commit(0, false)
state, _ = NewWithSnapshot(root, state.db, state.snap)

// Simulate self-destructing in one transaction, then create-reverting in another
Expand All @@ -790,7 +790,7 @@ func TestDeleteCreateRevert(t *testing.T) {
state.RevertToSnapshot(id)

// Commit the entire state and make sure we don't crash and have the correct state
root, _ = state.Commit(0, true, false)
root, _ = state.Commit(0, true)
state, _ = NewWithSnapshot(root, state.db, state.snap)

if state.getStateObject(addr) != nil {
Expand Down Expand Up @@ -833,7 +833,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
a2 := common.BytesToAddress([]byte("another"))
state.SetBalance(a2, big.NewInt(100))
state.SetCode(a2, []byte{1, 2, 4})
root, _ = state.Commit(0, false, false)
root, _ = state.Commit(0, false)
t.Logf("root: %x", root)
// force-flush
triedb.Commit(root, false)
Expand All @@ -857,7 +857,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
}
// Modify the state
state.SetBalance(addr, big.NewInt(2))
root, err := state.Commit(0, false, false)
root, err := state.Commit(0, false)
if err == nil {
t.Fatalf("expected error, got root :%x", root)
}
Expand Down Expand Up @@ -1043,7 +1043,7 @@ func TestMultiCoinOperations(t *testing.T) {
assetID := common.Hash{2}

s.state.GetOrNewStateObject(addr)
root, _ := s.state.Commit(0, false, false)
root, _ := s.state.Commit(0, false)
s.state, _ = NewWithSnapshot(root, s.state.db, s.state.snap)

s.state.AddBalance(addr, new(big.Int))
Expand Down Expand Up @@ -1100,22 +1100,22 @@ func TestMultiCoinSnapshot(t *testing.T) {
assertBalances(10, 0, 0)

// Commit and get the new root
root, _ = stateDB.Commit(0, false, false)
root, _ = stateDB.Commit(0, false)
assertBalances(10, 0, 0)

// Create a new state from the latest root, add a multicoin balance, and
// commit it to the tree.
stateDB, _ = New(root, sdb, snapTree)
stateDB.AddBalanceMultiCoin(addr, assetID1, big.NewInt(10))
root, _ = stateDB.Commit(0, false, false)
root, _ = stateDB.Commit(0, false)
assertBalances(10, 10, 0)

// Add more layers than the cap and ensure the balances and layers are correct
for i := 0; i < 256; i++ {
stateDB, _ = New(root, sdb, snapTree)
stateDB.AddBalanceMultiCoin(addr, assetID1, big.NewInt(1))
stateDB.AddBalanceMultiCoin(addr, assetID2, big.NewInt(2))
root, _ = stateDB.Commit(0, false, false)
root, _ = stateDB.Commit(0, false)
}
assertBalances(10, 266, 512)

Expand All @@ -1124,7 +1124,7 @@ func TestMultiCoinSnapshot(t *testing.T) {
stateDB, _ = New(root, sdb, snapTree)
stateDB.AddBalance(addr, big.NewInt(1))
stateDB.AddBalanceMultiCoin(addr, assetID1, big.NewInt(1))
root, _ = stateDB.Commit(0, false, false)
root, _ = stateDB.Commit(0, false)
stateDB, _ = New(root, sdb, snapTree)
assertBalances(11, 267, 512)
}
Expand All @@ -1146,7 +1146,7 @@ func TestGenerateMultiCoinAccounts(t *testing.T) {
t.Fatal(err)
}
stateDB.SetBalanceMultiCoin(addr, assetID, assetBalance)
root, err := stateDB.Commit(0, false, false)
root, err := stateDB.Commit(0, false)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1206,7 +1206,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
state.SetState(common.Address{a}, common.Hash{a, s}, common.Hash{a, s})
}
}
root, err := state.Commit(0, false, false)
root, err := state.Commit(0, false)
if err != nil {
t.Fatalf("failed to commit state trie: %v", err)
}
Expand Down Expand Up @@ -1285,7 +1285,7 @@ func TestResetObject(t *testing.T) {
state.CreateAccount(addr)
state.SetBalance(addr, big.NewInt(2))
state.SetState(addr, slotB, common.BytesToHash([]byte{0x2}))
root, _ := state.CommitWithSnap(0, true, snaps, common.Hash{}, common.Hash{}, false)
root, _ := state.CommitWithSnap(0, true, snaps, common.Hash{}, common.Hash{})

// Ensure the original account is wiped properly
snap := snaps.Snapshot(root)
Expand Down Expand Up @@ -1316,7 +1316,7 @@ func TestDeleteStorage(t *testing.T) {
value := common.Hash(uint256.NewInt(uint64(10 * i)).Bytes32())
state.SetState(addr, slot, value)
}
root, _ := state.CommitWithSnap(0, true, snaps, common.Hash{}, common.Hash{}, false)
root, _ := state.CommitWithSnap(0, true, snaps, common.Hash{}, common.Hash{})
// Init phase done, create two states, one with snap and one without
fastState, _ := New(root, db, snaps)
slowState, _ := New(root, db, nil)
Expand Down
2 changes: 1 addition & 1 deletion core/state/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
}
accounts = append(accounts, acc)
}
root, _ := state.Commit(0, false, false)
root, _ := state.Commit(0, false)

// Return the generated state
return db, sdb, nodeDb, root, accounts
Expand Down
10 changes: 5 additions & 5 deletions core/txpool/blobpool/blobpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ func TestOpenDrops(t *testing.T) {
statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), big.NewInt(1000000))
statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), big.NewInt(1000000))
statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), big.NewInt(10000000))
statedb.Commit(0, true, false)
statedb.Commit(0, true)

chain := &testBlockChain{
config: testChainConfig,
Expand Down Expand Up @@ -664,7 +664,7 @@ func TestOpenIndex(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr, big.NewInt(1_000_000_000))
statedb.Commit(0, true, false)
statedb.Commit(0, true)

chain := &testBlockChain{
config: testChainConfig,
Expand Down Expand Up @@ -767,7 +767,7 @@ func TestOpenHeap(t *testing.T) {
statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
statedb.Commit(0, true, false)
statedb.Commit(0, true)

chain := &testBlockChain{
config: testChainConfig,
Expand Down Expand Up @@ -848,7 +848,7 @@ func TestOpenCap(t *testing.T) {
statedb.AddBalance(addr1, big.NewInt(params.Ether))
statedb.AddBalance(addr2, big.NewInt(params.Ether))
statedb.AddBalance(addr3, big.NewInt(params.Ether))
statedb.Commit(0, true, false)
statedb.Commit(0, true)

chain := &testBlockChain{
config: testChainConfig,
Expand Down Expand Up @@ -1248,7 +1248,7 @@ func TestAdd(t *testing.T) {
store.Put(blob)
}
}
statedb.Commit(0, true, false)
statedb.Commit(0, true)
store.Close()

// Create a blob pool out of the pre-seeded dats
Expand Down
6 changes: 3 additions & 3 deletions eth/api_debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func TestAccountRange(t *testing.T) {
m[addr] = true
}
}
root, _ := sdb.Commit(0, true, false)
root, _ := sdb.Commit(0, true)
sdb, _ = state.New(root, statedb, nil)

trie, err := statedb.OpenTrie(root)
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestEmptyAccountRange(t *testing.T) {
st, _ = state.New(types.EmptyRootHash, statedb, nil)
)
// Commit(although nothing to flush) and re-init the statedb
st.Commit(0, true, false)
st.Commit(0, true)
st, _ = state.New(types.EmptyRootHash, statedb, nil)

results := st.RawDump(&state.DumpConfig{
Expand Down Expand Up @@ -197,7 +197,7 @@ func TestStorageRangeAt(t *testing.T) {
for _, entry := range storage {
sdb.SetState(addr, *entry.Key, entry.Value)
}
root, _ := sdb.Commit(0, false, false)
root, _ := sdb.Commit(0, false)
sdb, _ = state.New(root, db, nil)

// Check a few combinations of limit and start/end.
Expand Down
3 changes: 2 additions & 1 deletion eth/state_accessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
logged time.Time
parent common.Hash
)
triedb.EnableRefCounting()
for current.NumberU64() < origin {
if err := ctx.Err(); err != nil {
return nil, nil, err
Expand All @@ -162,7 +163,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err)
}
// Finalize the state so any modifications are written to the trie
root, err := statedb.Commit(current.NumberU64(), eth.blockchain.Config().IsEIP158(current.Number()), true)
root, err := statedb.Commit(current.NumberU64(), eth.blockchain.Config().IsEIP158(current.Number()))
if err != nil {
return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w",
current.NumberU64(), current.Root().Hex(), err)
Expand Down
2 changes: 1 addition & 1 deletion tests/state_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
}
}
// Commit and re-open to start with a clean state.
root, _ := statedb.Commit(0, false, false)
root, _ := statedb.Commit(0, false)

var snaps *snapshot.Tree
if snapshotter {
Expand Down
Loading
Loading