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

Add hook to force committing state to disk #280

Draft
wants to merge 15 commits into
base: snap_sync
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 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
2 changes: 1 addition & 1 deletion accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.Genesis
GasLimit: gasLimit,
Alloc: alloc,
}
blockchain, _ := core.NewBlockChain(database, nil, nil, &genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
blockchain, _ := core.NewBlockChain(database, nil, nil, &genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)

backend := &SimulatedBackend{
database: database,
Expand Down
6 changes: 3 additions & 3 deletions arbitrum/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func TestSimpleSync(t *testing.T) {
testUser2Address: {Balance: new(big.Int).Lsh(big.NewInt(1), 250)},
},
}
sourceChain, _ := core.NewBlockChain(sourceDb, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
sourceChain, _ := core.NewBlockChain(sourceDb, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
signer := types.MakeSigner(sourceChain.Config(), big.NewInt(1), 0)

firstAddress := common.Address{}
Expand Down Expand Up @@ -302,7 +302,7 @@ func TestSimpleSync(t *testing.T) {
if err != nil {
t.Fatal(err)
}
badChain, _ := core.NewBlockChain(badDb, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
badChain, _ := core.NewBlockChain(badDb, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
if _, err := badChain.InsertChain(badBlocks[:pivotBlockNum]); err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -344,7 +344,7 @@ func TestSimpleSync(t *testing.T) {
if err != nil {
t.Fatal(err)
}
destChain, _ := core.NewBlockChain(destDb, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
destChain, _ := core.NewBlockChain(destDb, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
destHandler := NewProtocolHandler(destDb, destChain, &dummySyncHelper{syncBlock.Header(), nil}, true)
destStack.RegisterProtocols(destHandler.MakeProtocols(iter))

Expand Down
2 changes: 1 addition & 1 deletion cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2136,7 +2136,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}

// Disable transaction indexing/unindexing by default.
chain, err := core.NewBlockChain(chainDb, cache, nil, gspec, nil, engine, vmcfg, nil, nil)
chain, err := core.NewBlockChain(chainDb, cache, nil, gspec, nil, engine, vmcfg, nil, nil, nil)
if err != nil {
Fatalf("Can't create BlockChain: %v", err)
}
Expand Down
6 changes: 3 additions & 3 deletions consensus/clique/clique_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestReimportMirroredState(t *testing.T) {
copy(genspec.ExtraData[extraVanity:], addr[:])

// Generate a batch of blocks, each properly signed
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, genspec, nil, engine, vm.Config{}, nil, nil)
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil)
defer chain.Stop()

_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
Expand Down Expand Up @@ -87,7 +87,7 @@ func TestReimportMirroredState(t *testing.T) {
}
// Insert the first two blocks and make sure the chain is valid
db = rawdb.NewMemoryDatabase()
chain, _ = core.NewBlockChain(db, nil, nil, genspec, nil, engine, vm.Config{}, nil, nil)
chain, _ = core.NewBlockChain(db, nil, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil)
defer chain.Stop()

if _, err := chain.InsertChain(blocks[:2]); err != nil {
Expand All @@ -100,7 +100,7 @@ func TestReimportMirroredState(t *testing.T) {
// Simulate a crash by creating a new chain on top of the database, without
// flushing the dirty states out. Insert the last block, triggering a sidechain
// reimport.
chain, _ = core.NewBlockChain(db, nil, nil, genspec, nil, engine, vm.Config{}, nil, nil)
chain, _ = core.NewBlockChain(db, nil, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil)
defer chain.Stop()

if _, err := chain.InsertChain(blocks[2:]); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion consensus/clique/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ func (tt *cliqueTest) run(t *testing.T) {
batches[len(batches)-1] = append(batches[len(batches)-1], block)
}
// Pass all the headers through clique and ensure tallying succeeds
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, genesis, nil, engine, vm.Config{}, nil, nil)
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, genesis, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("failed to create test chain: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions core/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {

// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
chainman, _ := NewBlockChain(db, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
chainman, _ := NewBlockChain(db, nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
Expand Down Expand Up @@ -307,7 +307,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
chain, err := NewBlockChain(db, &cacheConfig, nil, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, &cacheConfig, nil, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
if err != nil {
b.Fatalf("error creating chain: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions core/block_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header()
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
defer chain.Stop()

for i := 0; i < len(blocks); i++ {
Expand Down Expand Up @@ -158,7 +158,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
t.Logf("Post-merge header: %d", block.NumberU64())
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
defer chain.Stop()

// Verify the blocks before the merging
Expand Down
12 changes: 11 additions & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,11 @@ type BlockChain struct {

numberOfBlocksToSkipStateSaving uint32
amountOfGasInBlocksToSkipStateSaving uint64
forceTriedbCommitHook ForceTriedbCommitHook
}

type ForceTriedbCommitHook func(*types.Block) bool

type trieGcEntry struct {
Root common.Hash
Timestamp uint64
Expand All @@ -255,7 +258,7 @@ type trieGcEntry struct {
// NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator
// and Processor.
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) {
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64, forceTriedbCommitHook ForceTriedbCommitHook) (*BlockChain, error) {
magicxyyz marked this conversation as resolved.
Show resolved Hide resolved
if cacheConfig == nil {
cacheConfig = defaultCacheConfig
}
Expand Down Expand Up @@ -469,6 +472,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
bc.wg.Add(1)
go bc.maintainTxIndex()
}
bc.forceTriedbCommitHook = forceTriedbCommitHook
return bc, nil
}

Expand Down Expand Up @@ -1430,6 +1434,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
if err != nil {
return err
}

if bc.forceTriedbCommitHook != nil && bc.forceTriedbCommitHook(block) {
bc.numberOfBlocksToSkipStateSaving = bc.cacheConfig.MaxNumberOfBlocksToSkipStateSaving
bc.amountOfGasInBlocksToSkipStateSaving = bc.cacheConfig.MaxAmountOfGasToSkipStateSaving
return bc.triedb.Commit(root, false)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I want the storing-from-force to happen together with storing here:

 if bc.gcproc > flushInterval && prevEntry != nil && !archiveNode

So the hook should check gcproc, and if it returns yes gcproc should also be updated.
Hook should probably also get archiveNode (or it can get that info directly)
need to make sure we don't skip over the block in partial-archive and in the for !bc.triegc.Empty() { loop

Copy link
Collaborator

Choose a reason for hiding this comment

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

not sure it's the best solution, but my current thought is that if the hook is null we use a function that replicates the current behavior for hook (tests bc.gcproc > flushInterval)

// If we're running an archive node, flush
// If MaxNumberOfBlocksToSkipStateSaving or MaxAmountOfGasToSkipStateSaving is not zero, then flushing of some blocks will be skipped:
// * at most MaxNumberOfBlocksToSkipStateSaving block state commits will be skipped
Expand Down
8 changes: 4 additions & 4 deletions core/blockchain_repair_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256
config.SnapshotWait = true
}
chain, err := NewBlockChain(db, config, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, config, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
Expand Down Expand Up @@ -1846,7 +1846,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
}
defer db.Close()

newChain, err := NewBlockChain(db, nil, nil, gspec, nil, engine, vm.Config{}, nil, nil)
newChain, err := NewBlockChain(db, nil, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down Expand Up @@ -1924,7 +1924,7 @@ func TestIssue23496(t *testing.T) {
TrieRetention: 30 * time.Minute,
}
)
chain, err := NewBlockChain(db, config, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, config, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
Expand Down Expand Up @@ -1972,7 +1972,7 @@ func TestIssue23496(t *testing.T) {
}
defer db.Close()

chain, err = NewBlockChain(db, nil, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err = NewBlockChain(db, nil, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_sethead_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1987,7 +1987,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256
config.SnapshotWait = true
}
chain, err := NewBlockChain(db, config, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, config, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
Expand Down
20 changes: 10 additions & 10 deletions core/blockchain_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
// will happen during the block insertion.
cacheConfig = defaultCacheConfig
)
chain, err := NewBlockChain(db, cacheConfig, nil, gspec, nil, engine, vm.Config{}, nil, nil)
chain, err := NewBlockChain(db, cacheConfig, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to create chain: %v", err)
}
Expand Down Expand Up @@ -226,7 +226,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {

// Restart the chain normally
chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down Expand Up @@ -267,13 +267,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
// the crash, we do restart twice here: one after the crash and one
// after the normal stop. It's used to ensure the broken snapshot
// can be detected all the time.
newchain, err := NewBlockChain(newdb, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(newdb, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
newchain.Stop()

newchain, err = NewBlockChain(newdb, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err = NewBlockChain(newdb, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down Expand Up @@ -314,15 +314,15 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
}
newchain, err := NewBlockChain(snaptest.db, cacheConfig, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(snaptest.db, cacheConfig, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
newchain.InsertChain(gappedBlocks)
newchain.Stop()

// Restart the chain with enabling the snapshot
newchain, err = NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err = NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down Expand Up @@ -350,7 +350,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
chain.SetHead(snaptest.setHead)
chain.Stop()

newchain, err := NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down Expand Up @@ -390,7 +390,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0,
}
newchain, err := NewBlockChain(snaptest.db, config, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err := NewBlockChain(snaptest.db, config, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand All @@ -411,15 +411,15 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
SnapshotLimit: 256,
SnapshotWait: false, // Don't wait rebuild
}
tmp, err := NewBlockChain(snaptest.db, config, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
tmp, err := NewBlockChain(snaptest.db, config, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}

// Simulate the blockchain crash.
tmp.stopWithoutSaving()

newchain, err = NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
newchain, err = NewBlockChain(snaptest.db, nil, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatalf("Failed to recreate chain: %v", err)
}
Expand Down
Loading
Loading