diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 0c79cb6480f..cdef0dfa93f 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -142,7 +142,8 @@ func (b *SimulatedBackend) Rollback() { } func (b *SimulatedBackend) emptyPendingBlock() { - blocks, _ := core.GenerateChain(b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(int, *core.BlockGen) {}) + ctx := b.blockchain.WithContext(context.Background(), big.NewInt(b.prependBlock.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(int, *core.BlockGen) {}) b.pendingBlock = blocks[0] b.pendingHeader = b.pendingBlock.Header() b.gasPool = new(core.GasPool).AddGas(b.pendingHeader.GasLimit) @@ -378,7 +379,8 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa return err } //fmt.Printf("==== Start producing block %d\n", (b.prependBlock.NumberU64() + 1)) - blocks, _ := core.GenerateChain(b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(number int, block *core.BlockGen) { + ctx = b.blockchain.WithContext(ctx, big.NewInt(b.prependBlock.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(number int, block *core.BlockGen) { for _, tx := range b.pendingBlock.Transactions() { block.AddTxWithChain(b.blockchain, tx) } @@ -462,7 +464,8 @@ func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethere func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { b.mu.Lock() defer b.mu.Unlock() - blocks, _ := core.GenerateChain(b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(number int, block *core.BlockGen) { + ctx := b.blockchain.WithContext(context.Background(), big.NewInt(b.prependBlock.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(number int, block *core.BlockGen) { for _, tx := range b.pendingBlock.Transactions() { block.AddTxWithChain(b.blockchain, tx) } diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 82f468ab121..cef40219031 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -101,6 +101,8 @@ var ( utils.CacheTrieFlag, utils.CacheGCFlag, utils.TrieCacheGenFlag, + utils.NoHistory, + utils.ArchiveSyncInterval, utils.ListenPortFlag, utils.MaxPeersFlag, utils.MaxPendingPeersFlag, diff --git a/cmd/geth/misccmd.go b/cmd/geth/misccmd.go index f7eba22e171..6225da8f7f2 100644 --- a/cmd/geth/misccmd.go +++ b/cmd/geth/misccmd.go @@ -114,7 +114,7 @@ func version(ctx *cli.Context) error { } fmt.Println("Architecture:", runtime.GOARCH) fmt.Println("Protocol Versions:", eth.ProtocolVersions) - fmt.Println("Network Id:", eth.DefaultConfig.NetworkId) + fmt.Println("Network Id:", eth.DefaultConfig.NetworkID) fmt.Println("Go Version:", runtime.Version()) fmt.Println("Operating System:", runtime.GOOS) fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH")) diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 2632af96756..fe7b93d2676 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -84,6 +84,8 @@ var AppHelpFlagGroups = []flagGroup{ utils.LightPeersFlag, utils.LightKDFFlag, utils.WhitelistFlag, + utils.NoHistory, + utils.ArchiveSyncInterval, }, }, { diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go index a0dc127df48..4354dee5902 100644 --- a/cmd/hack/hack.go +++ b/cmd/hack/hack.go @@ -17,9 +17,6 @@ import ( "time" "github.com/ledgerwatch/bolt" - "github.com/wcharczuk/go-chart" - "github.com/wcharczuk/go-chart/util" - "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/consensus/ethash" "github.com/ledgerwatch/turbo-geth/core" @@ -32,6 +29,8 @@ import ( "github.com/ledgerwatch/turbo-geth/params" "github.com/ledgerwatch/turbo-geth/rlp" "github.com/ledgerwatch/turbo-geth/trie" + "github.com/wcharczuk/go-chart" + "github.com/wcharczuk/go-chart/util" ) var emptyCodeHash = crypto.Keccak256(nil) diff --git a/cmd/state/state_snapshot.go b/cmd/state/state_snapshot.go index 0f63bec0e57..7c56cae64c8 100644 --- a/cmd/state/state_snapshot.go +++ b/cmd/state/state_snapshot.go @@ -8,11 +8,8 @@ import ( "time" "github.com/ledgerwatch/bolt" - "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/consensus/ethash" - - //"github.com/ledgerwatch/turbo-geth/consensus/misc" "github.com/ledgerwatch/turbo-geth/core" "github.com/ledgerwatch/turbo-geth/core/types/accounts" "github.com/ledgerwatch/turbo-geth/core/vm" diff --git a/cmd/state/tokens.go b/cmd/state/tokens.go index 37fbc1a3eaf..9b19e83b9c6 100644 --- a/cmd/state/tokens.go +++ b/cmd/state/tokens.go @@ -15,7 +15,6 @@ import ( "time" "github.com/ledgerwatch/bolt" - "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/consensus/ethash" "github.com/ledgerwatch/turbo-geth/core" diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a1267bd27c2..24dfa5d01b1 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -129,7 +129,7 @@ var ( NetworkIdFlag = cli.Uint64Flag{ Name: "networkid", Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)", - Value: eth.DefaultConfig.NetworkId, + Value: eth.DefaultConfig.NetworkID, } TestnetFlag = cli.BoolFlag{ Name: "testnet", @@ -343,6 +343,15 @@ var ( Usage: "Number of trie node generations to keep in memory", Value: int(state.MaxTrieCacheGen), } + NoHistory = cli.BoolTFlag{ + Name: "no-history", + Usage: "write the whole state history", + } + ArchiveSyncInterval = cli.IntFlag{ + Name: "archive-sync-interval", + Usage: "when to switch from full to archive sync", + Value: 1024, + } // Miner settings MiningEnabledFlag = cli.BoolFlag{ Name: "mine", @@ -1282,7 +1291,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { cfg.OnlyAnnounce = ctx.GlobalBool(OnlyAnnounceModeFlag.Name) } if ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) + cfg.NetworkID = ctx.GlobalUint64(NetworkIdFlag.Name) } if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 @@ -1294,6 +1303,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { } cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" + cfg.NoHistory = ctx.GlobalBoolT(NoHistory.Name) + cfg.ArchiveSyncInterval = ctx.GlobalInt(ArchiveSyncInterval.Name) + if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 } @@ -1350,22 +1362,22 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { switch { case ctx.GlobalBool(TestnetFlag.Name): if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 3 + cfg.NetworkID = 3 } cfg.Genesis = core.DefaultTestnetGenesisBlock() case ctx.GlobalBool(RinkebyFlag.Name): if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 4 + cfg.NetworkID = 4 } cfg.Genesis = core.DefaultRinkebyGenesisBlock() case ctx.GlobalBool(GoerliFlag.Name): if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 5 + cfg.NetworkID = 5 } cfg.Genesis = core.DefaultGoerliGenesisBlock() case ctx.GlobalBool(DeveloperFlag.Name): if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 1337 + cfg.NetworkID = 1337 } // Create new developer account or reuse existing one var ( diff --git a/common/debug/callers.go b/common/debug/callers.go new file mode 100644 index 00000000000..8c9dbdcce08 --- /dev/null +++ b/common/debug/callers.go @@ -0,0 +1,25 @@ +package debug + +import ( + "runtime" +) + +// Callers returns given number of callers with packages +func Callers(show int) []string { + fpcs := make([]uintptr, show) + n := runtime.Callers(2, fpcs) + if n == 0 { + return nil + } + + callers := make([]string, 0, len(fpcs)) + for _, p := range fpcs { + caller := runtime.FuncForPC(p - 1) + if caller == nil { + continue + } + callers = append(callers, caller.Name()) + } + + return callers +} diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index 3492c6b0579..c002749d4c2 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -18,7 +18,9 @@ package clique import ( "bytes" + "context" "crypto/ecdsa" + "math/big" "sort" "testing" @@ -413,8 +415,15 @@ func TestClique(t *testing.T) { engine := New(config.Clique, db) engine.fakeDiff = true + chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil) + if err != nil { + t.Errorf("test %d: failed to create test chain: %v", i, err) + continue + } + genesisBlock, _, _, _ := genesis.ToBlock(db) - blocks, _ := core.GenerateChain(&config, genesisBlock, engine, db, len(tt.votes), func(j int, gen *core.BlockGen) { + ctx := chain.WithContext(context.Background(), big.NewInt(genesisBlock.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, &config, genesisBlock, engine, db, len(tt.votes), func(j int, gen *core.BlockGen) { // Cast the vote contained in this block gen.SetCoinbase(accounts.address(tt.votes[j].voted)) if tt.votes[j].auth { @@ -450,11 +459,6 @@ func TestClique(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(db, nil, &config, engine, vm.Config{}, nil) - if err != nil { - t.Errorf("test %d: failed to create test chain: %v", i, err) - continue - } failed := false for j := 0; j < len(batches)-1; j++ { if k, err := chain.InsertChain(batches[j]); err != nil { diff --git a/core/bench_test.go b/core/bench_test.go index d076d0e0b48..e08ad55b691 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -17,6 +17,7 @@ package core import ( + "context" "crypto/ecdsa" "io/ioutil" "math/big" @@ -171,12 +172,14 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { Alloc: GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}}, } genesis := gspec.MustCommit(db) - chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, b.N, gen) - // Time the insertion of the new chain. - // State and blocks are stored in the same DB. chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + ctx := chainman.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) defer chainman.Stop() + chain, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), db, b.N, gen) + + // Time the insertion of the new chain. + // State and blocks are stored in the same DB. b.ReportAllocs() b.ResetTimer() if i, err := chainman.InsertChain(chain); err != nil { diff --git a/core/block_validator.go b/core/block_validator.go index 3926a521f7b..3b1f9c2aaeb 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -17,6 +17,7 @@ package core import ( + "context" "errors" "fmt" "io/ioutil" @@ -83,13 +84,14 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin // ValidateBody validates the given block's uncles and verifies the block // header's transaction and uncle roots. The headers are assumed to be already // validated at this point. -func (v *BlockValidator) ValidateBody(block *types.Block) error { +func (v *BlockValidator) ValidateBody(ctx context.Context, block *types.Block) error { // Check whether the block's known, and if not, that it's linkable //if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) { // return ErrKnownBlock //} // Check whether the block is linkable - if !v.bc.noHistory && v.bc.GetBlockByHash(block.ParentHash()) == nil { + _, noHistory := params.GetNoHistoryByBlock(ctx, block.Number()) + if !noHistory && v.bc.GetBlockByHash(block.ParentHash()) == nil { return consensus.ErrUnknownAncestor } // Header validity is known at this point, check the uncles and transactions @@ -103,7 +105,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { if hash := types.DeriveSha(block.Transactions()); hash != header.TxHash { return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash) } - if v.bc.noHistory { + if noHistory { return nil } if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { diff --git a/core/block_validator_test.go b/core/block_validator_test.go index af14893687a..cf794586b2f 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -17,6 +17,8 @@ package core import ( + "context" + "math/big" "runtime" "testing" "time" @@ -35,16 +37,18 @@ func TestHeaderVerification(t *testing.T) { testdb = ethdb.NewMemDatabase() gspec = &Genesis{Config: params.TestChainConfig} genesis = gspec.MustCommit(testdb) - blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb.MemCopy(), 8, nil) ) + chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil) + ctx := chain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + defer chain.Stop() + + blocks, _ := GenerateChain(ctx, params.TestChainConfig, genesis, ethash.NewFaker(), testdb.MemCopy(), 8, nil) + headers := make([]*types.Header, len(blocks)) for i, block := range blocks { headers[i] = block.Header() } // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil) - defer chain.Stop() - for i := 0; i < len(blocks); i++ { for j, valid := range []bool{true, false} { var results <-chan error @@ -89,7 +93,7 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) { testdb = ethdb.NewMemDatabase() gspec = &Genesis{Config: params.TestChainConfig} genesis = gspec.MustCommit(testdb) - blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil) + blocks, _ = GenerateChain(context.Background(), params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil) ) headers := make([]*types.Header, len(blocks)) seals := make([]bool, len(blocks)) @@ -161,7 +165,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) { testdb = ethdb.NewMemDatabase() gspec = &Genesis{Config: params.TestChainConfig} genesis = gspec.MustCommit(testdb) - blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil) + blocks, _ = GenerateChain(context.Background(), params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil) ) headers := make([]*types.Header, len(blocks)) seals := make([]bool, len(blocks)) diff --git a/core/blockchain.go b/core/blockchain.go index 0fe3095754f..e83cde4da2a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -79,6 +79,9 @@ type CacheConfig struct { TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk + + ArchiveSyncInterval uint64 + NoHistory bool } // BlockChain represents the canonical chain given a database with a genesis @@ -137,11 +140,11 @@ type BlockChain struct { validator Validator // block and state validator interface vmConfig vm.Config - badBlocks *lru.Cache // Bad block cache - shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block. - noHistory bool - enableReceipts bool // Whether receipts need to be written to the database - resolveReads bool + badBlocks *lru.Cache // Bad block cache + highestKnownBlock uint64 + highestKnownBlockMu sync.Mutex + enableReceipts bool // Whether receipts need to be written to the database + resolveReads bool } // NewBlockChain returns a fully initialised block chain using information @@ -153,8 +156,13 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, + NoHistory: true, } } + if cacheConfig.ArchiveSyncInterval == 0 { + cacheConfig.ArchiveSyncInterval = 1024 + } + bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) receiptsCache, _ := lru.New(receiptsCacheLimit) @@ -212,10 +220,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par return bc, nil } -func (bc *BlockChain) SetNoHistory(nh bool) { - bc.noHistory = nh -} - func (bc *BlockChain) SetResolveReads(rr bool) { bc.resolveReads = rr } @@ -233,7 +237,6 @@ func (bc *BlockChain) GetTrieDbState() (*state.TrieDbState, error) { if err != nil { return nil, err } - bc.trieDbState.SetNoHistory(bc.noHistory) bc.trieDbState.SetResolveReads(bc.resolveReads) if err := bc.trieDbState.Rebuild(); err != nil { return nil, err @@ -982,26 +985,24 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // Make sure no inconsistent state is leaked during insertion currentBlock := bc.CurrentBlock() - if !bc.noHistory { - // Calculate the total difficulty of the block - ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) - if ptd == nil { - return NonStatTy, consensus.ErrUnknownAncestor - } - //localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) - externTd := new(big.Int).Add(block.Difficulty(), ptd) - // Irrelevant of the canonical status, write the block itself to the database - if err := bc.hc.WriteTd(bc.db, block.Hash(), block.NumberU64(), externTd); err != nil { - return NonStatTy, err - } - rawdb.WriteBlock(bc.db, block) - } else { - rawdb.WriteHeader(bc.db, block.Header()) + // Calculate the total difficulty of the block + ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) + if ptd == nil { + return NonStatTy, consensus.ErrUnknownAncestor + } + //localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) + externTd := new(big.Int).Add(block.Difficulty(), ptd) + + // Irrelevant of the canonical status, write the block itself to the database + if err := bc.hc.WriteTd(bc.db, block.Hash(), block.NumberU64(), externTd); err != nil { + return NonStatTy, err } + rawdb.WriteBlock(bc.db, block) tds.SetBlockNr(block.NumberU64()) - ctx := bc.chainConfig.WithEIPsFlags(context.Background(), block.Number()) + + ctx := bc.WithContext(context.Background(), block.Number()) if err := state.CommitBlock(ctx, tds.DbStateWriter()); err != nil { return NonStatTy, err } @@ -1089,8 +1090,9 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { // Only insert if the difficulty of the inserted chain is bigger than existing chain // Pre-checks passed, start the full block imports bc.wg.Add(1) + ctx := bc.WithContext(context.Background(), chain[0].Number()) bc.chainmu.Lock() - n, events, logs, err := bc.insertChain(chain, true) + n, events, logs, err := bc.insertChain(ctx, chain, true) bc.chainmu.Unlock() bc.wg.Done() @@ -1106,7 +1108,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { // racey behaviour. If a sidechain import is in progress, and the historic state // is imported, but then new canon-head is added before the actual sidechain // completes, then the historic state could be pruned again -func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []interface{}, []*types.Log, error) { +func (bc *BlockChain) insertChain(ctx context.Context, chain types.Blocks, verifySeals bool) (int, []interface{}, []*types.Log, error) { // If the chain is terminating, don't even bother starting u if atomic.LoadInt32(&bc.procInterrupt) == 1 { return 0, nil, nil, nil @@ -1135,71 +1137,69 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] lastCanon *types.Block coalescedLogs []*types.Log ) - var verifyFrom int = len(chain) - if !bc.noHistory { - externTd := big.NewInt(0) - if len(chain) > 0 && chain[0].NumberU64() > 0 { - d := bc.GetTd(chain[0].ParentHash(), chain[0].NumberU64()-1) - if d != nil { - externTd = externTd.Set(d) - } + externTd := big.NewInt(0) + if len(chain) > 0 && chain[0].NumberU64() > 0 { + d := bc.GetTd(chain[0].ParentHash(), chain[0].NumberU64()-1) + if d != nil { + externTd = externTd.Set(d) } - localTd := bc.GetTd(bc.CurrentBlock().Hash(), bc.CurrentBlock().NumberU64()) - for verifyFrom = 0; verifyFrom < len(chain) && localTd.Cmp(externTd) >= 0; verifyFrom++ { - header := chain[verifyFrom].Header() - err := <-results - if err != nil { - bc.reportBlock(chain[verifyFrom], nil, err) - return 0, events, coalescedLogs, err - } - externTd = externTd.Add(externTd, header.Difficulty) - } - if localTd.Cmp(externTd) >= 0 { - log.Warn("Ignoring the chain segment because of insufficient difficulty", "external", externTd, "local", localTd) - // But we still write the blocks to the database because others might build on top of them - td := bc.GetTd(chain[0].ParentHash(), chain[0].NumberU64()-1) - for _, block := range chain { - log.Warn("Saving", "block", block.NumberU64(), "hash", block.Hash()) - td = new(big.Int).Add(block.Difficulty(), td) - rawdb.WriteBlock(bc.db, block) - rawdb.WriteTd(bc.db, block.Hash(), block.NumberU64(), td) - } - return 0, events, coalescedLogs, nil + } + + localTd := bc.GetTd(bc.CurrentBlock().Hash(), bc.CurrentBlock().NumberU64()) + var verifyFrom int + for verifyFrom = 0; verifyFrom < len(chain) && localTd.Cmp(externTd) >= 0; verifyFrom++ { + header := chain[verifyFrom].Header() + err := <-results + if err != nil { + bc.reportBlock(chain[verifyFrom], nil, err) + return 0, events, coalescedLogs, err + } + externTd = externTd.Add(externTd, header.Difficulty) + } + if localTd.Cmp(externTd) >= 0 { + log.Warn("Ignoring the chain segment because of insufficient difficulty", "external", externTd, "local", localTd) + // But we still write the blocks to the database because others might build on top of them + td := bc.GetTd(chain[0].ParentHash(), chain[0].NumberU64()-1) + for _, block := range chain { + log.Warn("Saving", "block", block.NumberU64(), "hash", block.Hash()) + td = new(big.Int).Add(block.Difficulty(), td) + rawdb.WriteBlock(bc.db, block) + rawdb.WriteTd(bc.db, block.Hash(), block.NumberU64(), td) } + return 0, events, coalescedLogs, nil } var offset int var parent *types.Block var parentNumber = chain[0].NumberU64() - 1 // Find correct insertion point for this chain - if !bc.noHistory { - preBlocks := []*types.Block{} - parentHash := chain[0].ParentHash() + + preBlocks := []*types.Block{} + parentHash := chain[0].ParentHash() + parent = bc.GetBlock(parentHash, parentNumber) + if parent == nil { + log.Error("chain segment could not be inserted, missing parent", "hash", parentHash) + return 0, events, coalescedLogs, fmt.Errorf("chain segment could not be inserted, missing parent %x", parentHash) + } + canonicalHash := rawdb.ReadCanonicalHash(bc.db, parentNumber) + for canonicalHash != parentHash { + log.Warn("Chain segment's parent not on canonical hash, adding to pre-blocks", "block", parentNumber, "hash", parentHash) + preBlocks = append(preBlocks, parent) + parentNumber-- + parentHash = parent.ParentHash() parent = bc.GetBlock(parentHash, parentNumber) if parent == nil { - log.Error("Chain segment could not be inserted, missing parent", "hash", parentHash) - return 0, events, coalescedLogs, fmt.Errorf("Chain segment could not be inserted, missing parent %x", parentHash) - } - canonicalHash := rawdb.ReadCanonicalHash(bc.db, parentNumber) - for canonicalHash != parentHash { - log.Warn("Chain segment's parent not on canonical hash, adding to pre-blocks", "block", parentNumber, "hash", parentHash) - preBlocks = append(preBlocks, parent) - parentNumber-- - parentHash = parent.ParentHash() - parent = bc.GetBlock(parentHash, parentNumber) - if parent == nil { - log.Error("Chain segment could not be inserted, missing parent", "hash", parentHash) - return 0, events, coalescedLogs, fmt.Errorf("Chain segment could not be inserter, missing parent %x", parentHash) - } - canonicalHash = rawdb.ReadCanonicalHash(bc.db, parentNumber) - } - for left, right := 0, len(preBlocks)-1; left < right; left, right = left+1, right-1 { - preBlocks[left], preBlocks[right] = preBlocks[right], preBlocks[left] - } - offset = len(preBlocks) - if offset > 0 { - chain = append(preBlocks, chain...) + log.Error("chain segment could not be inserted, missing parent", "hash", parentHash) + return 0, events, coalescedLogs, fmt.Errorf("chain segment could not be inserted, missing parent %x", parentHash) } + canonicalHash = rawdb.ReadCanonicalHash(bc.db, parentNumber) + } + for left, right := 0, len(preBlocks)-1; left < right; left, right = left+1, right-1 { + preBlocks[left], preBlocks[right] = preBlocks[right], preBlocks[left] + } + offset = len(preBlocks) + if offset > 0 { + chain = append(preBlocks, chain...) } // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss) senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain) @@ -1227,7 +1227,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] err = <-results } if err == nil { - err = bc.Validator().ValidateBody(block) + ctx, _ = params.GetNoHistoryByBlock(ctx, block.Number()) + err = bc.Validator().ValidateBody(ctx, block) } switch { case err == ErrKnownBlock: @@ -1768,3 +1769,52 @@ func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscript func (bc *BlockChain) ChainDb() ethdb.Database { return bc.db } + +func (bc *BlockChain) NoHistory() bool { + return bc.cacheConfig.NoHistory +} + +func (bc *BlockChain) IsNoHistory(currentBlock *big.Int) bool { + if currentBlock == nil { + return bc.cacheConfig.NoHistory + } + + if !bc.cacheConfig.NoHistory { + return false + } + + if bc.cacheConfig.ArchiveSyncInterval != 0 { + return false + } + + var isArchiveInterval bool + currentBlockNumber := bc.CurrentBlock().Number().Uint64() + highestKnownBlock := bc.getHeightKnownBlock() + if highestKnownBlock > currentBlockNumber { + isArchiveInterval = (currentBlock.Uint64() - highestKnownBlock) <= bc.cacheConfig.ArchiveSyncInterval + } else { + isArchiveInterval = (currentBlock.Uint64() - currentBlockNumber) <= bc.cacheConfig.ArchiveSyncInterval + } + + return bc.cacheConfig.NoHistory || isArchiveInterval +} + +func (bc *BlockChain) NotifyHeightKnownBlock(h uint64) { + bc.highestKnownBlockMu.Lock() + if bc.highestKnownBlock < h { + bc.highestKnownBlock = h + } + bc.highestKnownBlockMu.Unlock() +} + +func (bc *BlockChain) getHeightKnownBlock() uint64 { + bc.highestKnownBlockMu.Lock() + defer bc.highestKnownBlockMu.Unlock() + return bc.highestKnownBlock +} + +func (bc *BlockChain) WithContext(ctx context.Context, blockNum *big.Int) context.Context { + ctx = bc.Config().WithEIPsFlags(ctx, blockNum) + ctx = params.WithNoHistory(ctx, bc.NoHistory(), bc.IsNoHistory) + return ctx +} diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index ade0ab58b59..aaf6da8e474 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -17,12 +17,10 @@ package core import ( - //"time" + "context" - //"github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/mclock" "github.com/ledgerwatch/turbo-geth/core/types" - //"github.com/ledgerwatch/turbo-geth/log" ) // insertStats tracks and reports on block insertion. @@ -101,7 +99,7 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid // next returns the next block in the iterator, along with any potential validation // error for that block. When the end is reached, it will return (nil, nil). -func (it *insertIterator) next() (*types.Block, error) { +func (it *insertIterator) next(ctx context.Context) (*types.Block, error) { if it.index+1 >= len(it.chain) { it.index = len(it.chain) return nil, nil @@ -110,7 +108,7 @@ func (it *insertIterator) next() (*types.Block, error) { if err := <-it.results; err != nil { return it.chain[it.index], err } - return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index]) + return it.chain[it.index], it.validator.ValidateBody(ctx, it.chain[it.index]) } // previous returns the previous block was being processed, or nil diff --git a/core/blockchain_test.go b/core/blockchain_test.go index c347282203a..8fb6d82a7c9 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -17,6 +17,7 @@ package core import ( + "context" "fmt" "math/big" "math/rand" @@ -24,8 +25,6 @@ import ( "testing" "time" - "context" - "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/consensus" "github.com/ledgerwatch/turbo-geth/consensus/ethash" @@ -47,34 +46,43 @@ var ( // newCanonical creates a chain database, and injects a deterministic canonical // chain. Depending on the full flag, if creates either a full block chain or a // header only chain. -func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { +func newCanonical(engine consensus.Engine, n int, full bool) (context.Context, ethdb.Database, *BlockChain, error) { var ( db = ethdb.NewMemDatabase() genesis = (&Genesis{Config: params.AllEthashProtocolChanges}).MustCommit(db) ) // Initialize a fresh chain with only a genesis block - blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil) + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + blockchain, _ := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + // Create and inject the requested chain if n == 0 { - return db, blockchain, nil + return ctx, db, blockchain, nil } + if full { // Full block-chain requested - blocks := makeBlockChain(genesis, n, engine, db.MemCopy(), canonicalSeed) + blocks := makeBlockChain(ctx, genesis, n, engine, db.MemCopy(), canonicalSeed) _, err := blockchain.InsertChain(blocks) - return db, blockchain, err + return ctx, db, blockchain, err } // Header-only chain requested - headers := makeHeaderChain(genesis.Header(), n, engine, db.MemCopy(), canonicalSeed) + headers := makeHeaderChain(ctx, genesis.Header(), n, engine, db.MemCopy(), canonicalSeed) _, err := blockchain.InsertHeaderChain(headers, 1) - return db, blockchain, err + return ctx, db, blockchain, err } // Test fork of length N starting from block i func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { // Copy old chain up to #i into a new db - db, blockchain2, err := newCanonical(ethash.NewFaker(), i, true) + ctx, db, blockchain2, err := newCanonical(ethash.NewFaker(), i, true) if err != nil { t.Fatal("could not make new canonical in testFork", err) } @@ -99,14 +107,14 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara ) var tdPre, tdPost *big.Int if full { - blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db.MemCopy(), forkSeed) + blockChainB = makeBlockChain(ctx, blockchain2.CurrentBlock(), n, ethash.NewFaker(), db.MemCopy(), forkSeed) tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) if _, err := blockchain.InsertChain(blockChainB); err != nil { t.Fatalf("failed to insert forking chain: %v", err) } tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) } else { - headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db.MemCopy(), forkSeed) + headerChainB = makeHeaderChain(ctx, blockchain2.CurrentHeader(), n, ethash.NewFaker(), db.MemCopy(), forkSeed) tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) if _, err := blockchain.InsertHeaderChain(headerChainB, 1); err != nil { t.Fatalf("failed to insert forking chain: %v", err) @@ -138,10 +146,12 @@ func printChain(bc *BlockChain) { // the database if successful. func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { for _, block := range chain { + ctx := blockchain.WithContext(context.Background(), block.Number()) + // Try and process the block err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) if err == nil { - err = blockchain.validator.ValidateBody(block) + err = blockchain.validator.ValidateBody(ctx, block) } if err != nil { if err == ErrKnownBlock { @@ -171,7 +181,6 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { return err } blockchain.chainmu.Lock() - ctx := blockchain.chainConfig.WithEIPsFlags(context.Background(), block.Number()) tds.SetBlockNr(block.NumberU64()) if err := statedb.CommitBlock(ctx, tds.DbStateWriter()); err != nil { return err @@ -213,14 +222,14 @@ func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t * } func TestLastBlock(t *testing.T) { - db, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } defer blockchain.Stop() dbCopy := db.MemCopy() - blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), dbCopy, 0) + blocks := makeBlockChain(ctx, blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), dbCopy, 0) if _, err := blockchain.InsertChain(blocks); err != nil { t.Fatalf("Failed to insert block: %v", err) } @@ -238,7 +247,7 @@ func testExtendCanonical(t *testing.T, full bool) { length := 5 // Make first chain starting from genesis - _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -266,7 +275,7 @@ func testShorterFork(t *testing.T, full bool) { length := 10 // Make first chain starting from genesis - _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -296,7 +305,7 @@ func testLongerFork(t *testing.T, full bool) { length := 10 // Make first chain starting from genesis - _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -326,7 +335,7 @@ func testEqualFork(t *testing.T, full bool) { length := 10 // Make first chain starting from genesis - _, processor, err := newCanonical(ethash.NewFaker(), length, full) + _, _, processor, err := newCanonical(ethash.NewFaker(), length, full) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -353,7 +362,7 @@ func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } func testBrokenChain(t *testing.T, full bool) { // Make chain starting from genesis - db, blockchain, err := newCanonical(ethash.NewFaker(), 10, true) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 10, true) if err != nil { t.Fatalf("failed to make new canonical chain: %v", err) } @@ -361,12 +370,12 @@ func testBrokenChain(t *testing.T, full bool) { // Create a forked chain, and try to insert with a missing link if full { - chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] + chain := makeBlockChain(ctx, blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] if err := testBlockChainImport(chain, blockchain); err == nil { t.Errorf("broken block chain not reported") } } else { - chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] + chain := makeHeaderChain(ctx, blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] if err := testHeaderChainImport(chain, blockchain); err == nil { t.Errorf("broken header chain not reported") } @@ -404,17 +413,17 @@ func testReorgShort(t *testing.T, full bool) { func testReorg(t *testing.T, first, second []int64, td int64, full bool) { // Create a pristine chain and database - db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } defer blockchain.Stop() // Insert an easy and a difficult chain afterwards - easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db.MemCopy(), len(first), func(i int, b *BlockGen) { + easyBlocks, _ := GenerateChain(ctx, params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db.MemCopy(), len(first), func(i int, b *BlockGen) { b.OffsetTime(first[i]) }) - diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db.MemCopy(), len(second), func(i int, b *BlockGen) { + diffBlocks, _ := GenerateChain(ctx, params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db.MemCopy(), len(second), func(i int, b *BlockGen) { b.OffsetTime(second[i]) }) if full { @@ -475,7 +484,7 @@ func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } func testBadHashes(t *testing.T, full bool) { // Create a pristine chain and database - db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -483,14 +492,14 @@ func testBadHashes(t *testing.T, full bool) { // Create a chain, ban a hash and try to import if full { - blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db.MemCopy(), 10) + blocks := makeBlockChain(ctx, blockchain.CurrentBlock(), 3, ethash.NewFaker(), db.MemCopy(), 10) BadHashes[blocks[2].Header().Hash()] = true defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() _, err = blockchain.InsertChain(blocks) } else { - headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db.MemCopy(), 10) + headers := makeHeaderChain(ctx, blockchain.CurrentHeader(), 3, ethash.NewFaker(), db.MemCopy(), 10) BadHashes[headers[2].Hash()] = true defer func() { delete(BadHashes, headers[2].Hash()) }() @@ -509,13 +518,13 @@ func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } func testReorgBadHashes(t *testing.T, full bool) { // Create a pristine chain and database - db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } // Create a chain, import and ban afterwards - headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db.MemCopy(), 10) - blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db.MemCopy(), 10) + headers := makeHeaderChain(ctx, blockchain.CurrentHeader(), 4, ethash.NewFaker(), db.MemCopy(), 10) + blocks := makeBlockChain(ctx, blockchain.CurrentBlock(), 4, ethash.NewFaker(), db.MemCopy(), 10) if full { if _, err = blockchain.InsertChain(blocks); err != nil { @@ -539,7 +548,13 @@ func testReorgBadHashes(t *testing.T, full bool) { blockchain.Stop() // Create a new BlockChain and check that it rolled back the state. - ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil) + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + ncm, err := NewBlockChain(blockchain.db, cacheConfig, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil) if err != nil { t.Fatalf("failed to create new chain manager: %v", err) } @@ -565,7 +580,7 @@ func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } func testInsertNonceError(t *testing.T, full bool) { for i := 1; i < 25 && !t.Failed(); i++ { // Create a pristine chain and database - db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } @@ -578,7 +593,7 @@ func testInsertNonceError(t *testing.T, full bool) { failNum uint64 ) if full { - blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db.MemCopy(), 0) + blocks := makeBlockChain(ctx, blockchain.CurrentBlock(), i, ethash.NewFaker(), db.MemCopy(), 0) failAt = rand.Int() % len(blocks) failNum = blocks[failAt].NumberU64() @@ -586,7 +601,7 @@ func testInsertNonceError(t *testing.T, full bool) { blockchain.engine = ethash.NewFakeFailer(failNum) failRes, err = blockchain.InsertChain(blocks) } else { - headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db.MemCopy(), 0) + headers := makeHeaderChain(ctx, blockchain.CurrentHeader(), i, ethash.NewFaker(), db.MemCopy(), 0) failAt = rand.Int() % len(headers) failNum = headers[failAt].Number.Uint64() @@ -632,7 +647,7 @@ func TestFastVsFullChains(t *testing.T) { genesis = gspec.MustCommit(gendb) signer = types.NewEIP155Signer(gspec.Config.ChainID) ) - blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { + blocks, receipts := GenerateChain(context.TODO(), gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { block.SetCoinbase(common.Address{0x00}) // If the block number is multiple of 3, send a few bonus transactions to the miner @@ -653,7 +668,13 @@ func TestFastVsFullChains(t *testing.T) { // Import the chain as an archive node for the comparison baseline archiveDb := ethdb.NewMemDatabase() gspec.MustCommit(archiveDb) - archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + archive, _ := NewBlockChain(archiveDb, cacheConfig, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) defer archive.Stop() if n, err := archive.InsertChain(blocks); err != nil { @@ -718,7 +739,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { genesis = gspec.MustCommit(gendb) ) height := uint64(1024) - blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) + blocks, receipts := GenerateChain(context.TODO(), gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) // Configure a subchain to roll back remove := []common.Hash{} @@ -741,7 +762,13 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { archiveDb := ethdb.NewMemDatabase() gspec.MustCommit(archiveDb) - archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + archive, _ := NewBlockChain(archiveDb, cacheConfig, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) if n, err := archive.InsertChain(blocks); err != nil { t.Fatalf("failed to process block %d: %v", n, err) } @@ -828,7 +855,18 @@ func TestChainTxReorgs(t *testing.T) { // - futureAdd: transaction added after the reorg has already finished var pastAdd, freshAdd, futureAdd *types.Transaction - chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 3, func(i int, gen *BlockGen) { + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + blockchain, _ := NewBlockChain(db, cacheConfig, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + blockchain.EnableReceipts(true) + + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + + chain, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 3, func(i int, gen *BlockGen) { switch i { case 0: pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) @@ -846,15 +884,13 @@ func TestChainTxReorgs(t *testing.T) { } }) // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) - blockchain.EnableReceipts(true) if i, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert original chain[%d]: %v", i, err) } defer blockchain.Stop() // overwrite the old chain - chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 5, func(i int, gen *BlockGen) { + chain, _ = GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 5, func(i int, gen *BlockGen) { switch i { case 0: pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) @@ -919,13 +955,20 @@ func TestLogReorgs(t *testing.T) { signer = types.NewEIP155Signer(gspec.Config.ChainID) ) - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + blockchain, _ := NewBlockChain(db, cacheConfig, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) blockchain.EnableReceipts(true) defer blockchain.Stop() rmLogsCh := make(chan RemovedLogsEvent) blockchain.SubscribeRemovedLogsEvent(rmLogsCh) - chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 2, func(i int, gen *BlockGen) { + chain, _ := GenerateChain(ctx, params.TestChainConfig, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 2, func(i int, gen *BlockGen) { if i == 1 { tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) if err != nil { @@ -938,7 +981,7 @@ func TestLogReorgs(t *testing.T) { t.Fatalf("failed to insert chain: %v", err) } - chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 3, func(i int, gen *BlockGen) {}) + chain, _ = GenerateChain(ctx, params.TestChainConfig, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 3, func(i int, gen *BlockGen) {}) if _, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert forked chain: %v", err) } @@ -970,14 +1013,15 @@ func TestReorgSideEvent(t *testing.T) { ) blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) defer blockchain.Stop() - chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 3, func(i int, gen *BlockGen) {}) + chain, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 3, func(i int, gen *BlockGen) {}) if _, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert chain: %v", err) } - replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 4, func(i int, gen *BlockGen) { + replacementBlocks, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), genesisDb.MemCopy(), 4, func(i int, gen *BlockGen) { tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) if i == 2 { gen.OffsetTime(-9) @@ -1041,13 +1085,13 @@ done: // Tests if the canonical block can be fetched from the database during chain insertion. func TestCanonicalBlockRetrieval(t *testing.T) { - db, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) + ctx, db, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) if err != nil { t.Fatalf("failed to create pristine chain: %v", err) } defer blockchain.Stop() - chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), db.MemCopy(), 10, func(i int, gen *BlockGen) {}) + chain, _ := GenerateChain(ctx, blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), db.MemCopy(), 10, func(i int, gen *BlockGen) {}) var pend sync.WaitGroup pend.Add(len(chain)) @@ -1099,9 +1143,10 @@ func TestEIP155Transition(t *testing.T) { ) blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) defer blockchain.Stop() - blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db.MemCopy(), 4, func(i int, block *BlockGen) { + blocks, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), db.MemCopy(), 4, func(i int, block *BlockGen) { var ( tx *types.Transaction err error @@ -1164,7 +1209,8 @@ func TestEIP155Transition(t *testing.T) { // generate an invalid chain id transaction config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} - blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db.MemCopy(), 4, func(i int, block *BlockGen) { + ctx = blockchain.WithContext(context.Background(), big.NewInt(blocks[len(blocks)-1].Number().Int64()+1)) + blocks, _ = GenerateChain(ctx, config, blocks[len(blocks)-1], ethash.NewFaker(), db.MemCopy(), 4, func(i int, block *BlockGen) { var ( tx *types.Transaction err error @@ -1207,9 +1253,10 @@ func TestEIP161AccountRemoval(t *testing.T) { genesisDb = db.MemCopy() ) blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) defer blockchain.Stop() - blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genesisDb, 3, func(i int, block *BlockGen) { + blocks, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), genesisDb, 3, func(i int, block *BlockGen) { var ( tx *types.Transaction err error @@ -1264,8 +1311,23 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { db := ethdb.NewMemDatabase() genesis := (&Genesis{Config: params.TestChainConfig}).MustCommit(db) - //genesisDb := db.MemCopy() - blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db.MemCopy(), 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) + + diskdb := ethdb.NewMemDatabase() + (&Genesis{Config: params.TestChainConfig}).MustCommit(diskdb) + + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + chain, err := NewBlockChain(diskdb, cacheConfig, params.TestChainConfig, engine, vm.Config{}, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + ctx := chain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + + blocks, _ := GenerateChain(ctx, params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) // Generate a bunch of fork blocks, each side forking from the canonical chain forks := make([]*types.Block, len(blocks)) @@ -1274,23 +1336,17 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { if i > 0 { parent = blocks[i-1] } - fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db.MemCopy(), 1, func(i int, b *BlockGen) { + ctx = chain.WithContext(ctx, big.NewInt(parent.Number().Int64()+1)) + fork, _ := GenerateChain(ctx, params.TestChainConfig, parent, engine, db.MemCopy(), 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) b.OffsetTime(-2) // By reducing time, we increase difficulty of the fork, so that it can overwrite the canonical chain }) forks[i] = fork[0] // Move db forward by 1 block - GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) + GenerateChain(ctx, params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) } // Import the canonical and fork chain side by side, verifying the current block // and current header consistency - diskdb := ethdb.NewMemDatabase() - (&Genesis{Config: params.TestChainConfig}).MustCommit(diskdb) - - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } for i := 0; i < len(blocks); i++ { //fmt.Printf("inserting chain %d to %d\n", blocks[0].NumberU64(), blocks[i].NumberU64()) if _, err := chain.InsertChain(blocks[0 : i+1]); err != nil { @@ -1315,24 +1371,31 @@ func TestLargeReorgTrieGC(t *testing.T) { // Generate the original common chain segment and the two competing forks engine := ethash.NewFaker() + diskdb := ethdb.NewMemDatabase() + (&Genesis{Config: params.TestChainConfig}).MustCommit(diskdb) + cacheConfig := &CacheConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + NoHistory: false, + } + chain, err := NewBlockChain(diskdb, cacheConfig, params.TestChainConfig, engine, vm.Config{}, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + ctx := chain.WithContext(context.Background(), big.NewInt(1)) + db := ethdb.NewMemDatabase() genesis := (&Genesis{Config: params.TestChainConfig}).MustCommit(db) - shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db.MemCopy(), 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) - competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db.MemCopy(), 2*triesInMemory+1, func(i int, b *BlockGen) { + shared, _ := GenerateChain(ctx, params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) + original, _ := GenerateChain(ctx, params.TestChainConfig, shared[len(shared)-1], engine, db.MemCopy(), 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) + competitor, _ := GenerateChain(ctx, params.TestChainConfig, shared[len(shared)-1], engine, db.MemCopy(), 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) b.OffsetTime(-2) }) // Import the shared chain and the original canonical one - diskdb := ethdb.NewMemDatabase() - (&Genesis{Config: params.TestChainConfig}).MustCommit(diskdb) - - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } if _, err := chain.InsertChain(shared); err != nil { t.Fatalf("failed to insert shared chain: %v", err) } @@ -1389,7 +1452,15 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in } } - shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) + diskdb := ethdb.NewMemDatabase() + gspec.MustCommit(diskdb) + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + if err != nil { + b.Fatalf("failed to create tester chain: %v", err) + } + ctx := chain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + + shared, _ := GenerateChain(ctx, params.TestChainConfig, genesis, engine, db.MemCopy(), numBlocks, blockGenerator) b.StopTimer() b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/core/chain_makers.go b/core/chain_makers.go index 89792d9a455..5db82ae97ad 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -175,7 +175,7 @@ func (b *BlockGen) OffsetTime(seconds int64) { // Blocks created by GenerateChain do not contain valid proof of work // values. Inserting them into BlockChain requires use of FakePow or // a similar non-validating proof of work implementation. -func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { +func GenerateChain(ctx context.Context, config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { if config == nil { config = params.TestChainConfig } @@ -206,7 +206,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if _, err := b.engine.Finalize(config, b.header, statedb, b.txs, b.uncles, b.receipts); err != nil { panic(fmt.Sprintf("could not finalize block: %v", err)) } - ctx := config.WithEIPsFlags(context.Background(), b.header.Number) + ctx, _ = params.GetNoHistoryByBlock(ctx, b.header.Number) if err := statedb.FinalizeTx(ctx, tds.TrieStateWriter()); err != nil { panic(err) } @@ -224,7 +224,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse block := types.NewBlock(b.header, b.txs, b.uncles, b.receipts) tds.SetBlockNr(block.NumberU64()) // Write state changes to db - if err := statedb.CommitBlock(config.WithEIPsFlags(context.Background(), b.header.Number), tds.DbStateWriter()); err != nil { + if err := statedb.CommitBlock(ctx, tds.DbStateWriter()); err != nil { panic(fmt.Sprintf("state write error: %v", err)) } return block, b.receipts @@ -278,8 +278,8 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, engine consens } // makeHeaderChain creates a deterministic chain of headers rooted at parent. -func makeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header { - blocks := makeBlockChain(types.NewBlockWithHeader(parent), n, engine, db, seed) +func makeHeaderChain(ctx context.Context, parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header { + blocks := makeBlockChain(ctx, types.NewBlockWithHeader(parent), n, engine, db, seed) headers := make([]*types.Header, len(blocks)) for i, block := range blocks { headers[i] = block.Header() @@ -288,8 +288,8 @@ func makeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db et } // makeBlockChain creates a deterministic chain of blocks rooted at parent. -func makeBlockChain(parent *types.Block, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Block { - blocks, _ := GenerateChain(params.TestChainConfig, parent, engine, db, n, func(i int, b *BlockGen) { +func makeBlockChain(ctx context.Context, parent *types.Block, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Block { + blocks, _ := GenerateChain(ctx, params.TestChainConfig, parent, engine, db, n, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) }) return blocks diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index c106458401b..c59840fcba0 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -17,6 +17,7 @@ package core import ( + "context" "fmt" "math/big" @@ -53,11 +54,15 @@ func ExampleGenerateChain() { } genesis := gspec.MustCommit(db) + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + defer blockchain.Stop() + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + // This call generates a chain of 5 blocks. The function runs for // each block and adds different features to gen based on the // block index. signer := types.HomesteadSigner{} - chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db.MemCopy(), 5, func(i int, gen *BlockGen) { + chain, _ := GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), db.MemCopy(), 5, func(i int, gen *BlockGen) { switch i { case 0: // In block 1, addr1 sends addr2 some ether. @@ -86,9 +91,6 @@ func ExampleGenerateChain() { }) // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) - defer blockchain.Stop() - if i, err := blockchain.InsertChain(chain); err != nil { fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err) return diff --git a/core/dao_test.go b/core/dao_test.go index 7f0fde33443..98b5e0acc0d 100644 --- a/core/dao_test.go +++ b/core/dao_test.go @@ -17,6 +17,7 @@ package core import ( + "context" "math/big" "testing" @@ -35,18 +36,19 @@ func TestDAOForkRangeExtradata(t *testing.T) { db := ethdb.NewMemDatabase() gspec := &Genesis{Config: params.TestChainConfig} genesis := gspec.MustCommit(db) - prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) - // Create the concurrent, conflicting two nodes proDb := ethdb.NewMemDatabase() gspec.MustCommit(proDb) + // Create the concurrent, conflicting two nodes proConf := *params.TestChainConfig proConf.DAOForkBlock = forkBlock proConf.DAOForkSupport = true - proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) defer proBc.Stop() + ctx := proBc.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + + prefix, _ := GenerateChain(ctx, params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) conDb := ethdb.NewMemDatabase() gspec.MustCommit(conDb) @@ -71,6 +73,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { gspec.MustCommit(db) bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) defer bc.Stop() + ctx = bc.WithContext(context.Background(), big.NewInt(conBc.CurrentBlock().Number().Int64()+1)) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) for j := 0; j < len(blocks)/2; j++ { @@ -79,12 +82,12 @@ func TestDAOForkRangeExtradata(t *testing.T) { if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import contra-fork chain for expansion: %v", err) } - blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), conDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(ctx, &proConf, conBc.CurrentBlock(), ethash.NewFaker(), conDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) if _, err := conBc.InsertChain(blocks); err == nil { t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0]) } // Create a proper no-fork block for the contra-forker - blocks, _ = GenerateChain(&conConf, conBc.CurrentBlock(), ethash.NewFaker(), conDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(ctx, &conConf, conBc.CurrentBlock(), ethash.NewFaker(), conDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) if _, err := conBc.InsertChain(blocks); err != nil { t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err) } @@ -93,6 +96,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { gspec.MustCommit(db) bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) defer bc.Stop() + ctx = bc.WithContext(context.Background(), big.NewInt(proBc.CurrentBlock().Number().Int64()+1)) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) for j := 0; j < len(blocks)/2; j++ { @@ -101,12 +105,12 @@ func TestDAOForkRangeExtradata(t *testing.T) { if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import pro-fork chain for expansion: %v", err) } - blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), proDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(ctx, &conConf, proBc.CurrentBlock(), ethash.NewFaker(), proDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) if _, err := proBc.InsertChain(blocks); err == nil { t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0]) } // Create a proper pro-fork block for the pro-forker - blocks, _ = GenerateChain(&proConf, proBc.CurrentBlock(), ethash.NewFaker(), proDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(ctx, &proConf, proBc.CurrentBlock(), ethash.NewFaker(), proDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) if _, err := proBc.InsertChain(blocks); err != nil { t.Fatalf("pro-fork chain didn't accepted pro-fork block: %v", err) } @@ -116,6 +120,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { gspec.MustCommit(db) bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) defer bc.Stop() + ctx = bc.WithContext(context.Background(), big.NewInt(conBc.CurrentBlock().Number().Int64()+1)) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) for j := 0; j < len(blocks)/2; j++ { @@ -124,7 +129,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import contra-fork chain for expansion: %v", err) } - blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), conDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(ctx, &proConf, conBc.CurrentBlock(), ethash.NewFaker(), conDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) if _, err := conBc.InsertChain(blocks); err != nil { t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) } @@ -133,6 +138,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { gspec.MustCommit(db) bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) defer bc.Stop() + ctx = bc.WithContext(context.Background(), big.NewInt(proBc.CurrentBlock().Number().Int64()+1)) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) for j := 0; j < len(blocks)/2; j++ { @@ -141,7 +147,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { if _, err := bc.InsertChain(blocks); err != nil { t.Fatalf("failed to import pro-fork chain for expansion: %v", err) } - blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), proDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) + blocks, _ = GenerateChain(ctx, &conConf, proBc.CurrentBlock(), ethash.NewFaker(), proDb.MemCopy(), 1, func(i int, gen *BlockGen) {}) if _, err := proBc.InsertChain(blocks); err != nil { t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err) } diff --git a/core/genesis_test.go b/core/genesis_test.go index 890b61cb10e..8d050df5a35 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -17,6 +17,7 @@ package core import ( + "context" "math/big" "reflect" "testing" @@ -123,8 +124,9 @@ func TestSetupGenesis(t *testing.T) { bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil) defer bc.Stop() + ctx := bc.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) - blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db.MemCopy(), 4, nil) + blocks, _ := GenerateChain(ctx, oldcustomg.Config, genesis, ethash.NewFaker(), db.MemCopy(), 4, nil) bc.InsertChain(blocks) bc.CurrentBlock() // This should return a compatibility error. diff --git a/core/pruner/pruner_test.go b/core/pruner/pruner_test.go index c530da14ead..8a82214ea9b 100644 --- a/core/pruner/pruner_test.go +++ b/core/pruner/pruner_test.go @@ -1,6 +1,7 @@ package pruner import ( + "context" "fmt" "github.com/ledgerwatch/bolt" "github.com/ledgerwatch/turbo-geth/consensus/ethash" @@ -51,7 +52,8 @@ func TestOne(t *testing.T) { t.Fatal(err) } - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 3, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(int64(genesis.NumberU64())+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 3, func(i int, block *core.BlockGen) { var ( tx *types.Transaction genErr error diff --git a/core/state/database.go b/core/state/database.go index 9d8ce20cf37..7eb2fe8d09e 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -22,6 +22,7 @@ import ( "encoding/binary" "fmt" "github.com/ledgerwatch/turbo-geth/common/dbutils" + "github.com/ledgerwatch/turbo-geth/params" "io" "math/big" "runtime" @@ -52,7 +53,7 @@ type StateWriter interface { UpdateAccountData(ctx context.Context, address common.Address, original, account *accounts.Account) error UpdateAccountCode(codeHash common.Hash, code []byte) error DeleteAccount(ctx context.Context, address common.Address, original *accounts.Account) error - WriteAccountStorage(address common.Address, incarnation uint64, key, original, value *common.Hash) error + WriteAccountStorage(ctx context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error RemoveStorage(address common.Address, incarnation uint64) error } @@ -75,7 +76,7 @@ func (nw *NoopWriter) UpdateAccountCode(codeHash common.Hash, code []byte) error return nil } -func (nw *NoopWriter) WriteAccountStorage(address common.Address, incarnation uint64, key, original, value *common.Hash) error { +func (nw *NoopWriter) WriteAccountStorage(_ context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error { return nil } @@ -923,6 +924,10 @@ func (tds *TrieDbState) ReadAccountCodeSize(codeHash common.Hash) (codeSize int, var prevMemStats runtime.MemStats +type TrieStateWriter struct { + tds *TrieDbState +} + func (tds *TrieDbState) PruneTries(print bool) { if print { prunableNodes := tds.t.CountPrunableNodes() @@ -943,10 +948,6 @@ func (tds *TrieDbState) PruneTries(print bool) { } } -type TrieStateWriter struct { - tds *TrieDbState -} - type DbStateWriter struct { tds *TrieDbState } @@ -987,7 +988,7 @@ func accountsEqual(a1, a2 *accounts.Account) bool { return true } -func (tsw *TrieStateWriter) UpdateAccountData(ctx context.Context, address common.Address, original, account *accounts.Account) error { +func (tsw *TrieStateWriter) UpdateAccountData(_ context.Context, address common.Address, original, account *accounts.Account) error { addrHash, err := tsw.tds.HashAddress(address, false /*save*/) if err != nil { return err @@ -1015,7 +1016,8 @@ func (dsw *DbStateWriter) UpdateAccountData(ctx context.Context, address common. if err = dsw.tds.db.Put(dbutils.AccountsBucket, addrHash[:], data); err != nil { return err } - if dsw.tds.noHistory { + _, noHistory := params.GetNoHistory(ctx) + if dsw.tds.noHistory || noHistory { return nil } // Don't write historical record if the account did not change @@ -1051,7 +1053,8 @@ func (dsw *DbStateWriter) DeleteAccount(ctx context.Context, address common.Addr if err := dsw.tds.db.Delete(dbutils.AccountsBucket, addrHash[:]); err != nil { return err } - if dsw.tds.noHistory { + _, noHistory := params.GetNoHistory(ctx) + if dsw.tds.noHistory || noHistory { return nil } var originalData []byte @@ -1080,7 +1083,7 @@ func (dsw *DbStateWriter) UpdateAccountCode(codeHash common.Hash, code []byte) e return dsw.tds.db.Put(dbutils.CodeBucket, codeHash[:], code) } -func (tsw *TrieStateWriter) WriteAccountStorage(address common.Address, incarnation uint64, key, original, value *common.Hash) error { +func (tsw *TrieStateWriter) WriteAccountStorage(_ context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error { addrHash, err := tsw.tds.HashAddress(address, false /*save*/) if err != nil { return err @@ -1106,7 +1109,7 @@ func (tsw *TrieStateWriter) WriteAccountStorage(address common.Address, incarnat return nil } -func (dsw *DbStateWriter) WriteAccountStorage(address common.Address, incarnation uint64, key, original, value *common.Hash) error { +func (dsw *DbStateWriter) WriteAccountStorage(ctx context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error { if *original == *value { return nil } @@ -1133,7 +1136,8 @@ func (dsw *DbStateWriter) WriteAccountStorage(address common.Address, incarnatio if err != nil { return err } - if dsw.tds.noHistory { + _, noHistory := params.GetNoHistory(ctx) + if dsw.tds.noHistory || noHistory { return nil } o := bytes.TrimLeft(original[:], "\x00") diff --git a/core/state/dump.go b/core/state/dump.go index e35093377d4..88045f6b264 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -20,9 +20,9 @@ import ( "encoding/binary" "encoding/json" "fmt" - "github.com/ledgerwatch/turbo-geth/common/dbutils" "github.com/ledgerwatch/turbo-geth/common" + "github.com/ledgerwatch/turbo-geth/common/dbutils" "github.com/ledgerwatch/turbo-geth/core/types/accounts" ) diff --git a/core/state/intra_block_state.go b/core/state/intra_block_state.go index 1610cdd9054..91c0ea63ab4 100644 --- a/core/state/intra_block_state.go +++ b/core/state/intra_block_state.go @@ -777,7 +777,7 @@ func (sdb *IntraBlockState) FinalizeTx(ctx context.Context, stateWriter StateWri } stateObject.deleted = true } else { - if err := stateObject.updateTrie(stateWriter); err != nil { + if err := stateObject.updateTrie(ctx, stateWriter); err != nil { return err } @@ -815,7 +815,7 @@ func (sdb *IntraBlockState) CommitBlock(ctx context.Context, stateWriter StateWr } } - if err := stateObject.updateTrie(stateWriter); err != nil { + if err := stateObject.updateTrie(ctx, stateWriter); err != nil { return err } diff --git a/core/state/readonly.go b/core/state/readonly.go index a079674a027..df2c4c9cefc 100644 --- a/core/state/readonly.go +++ b/core/state/readonly.go @@ -19,11 +19,10 @@ package state import ( "bytes" "context" - "github.com/ledgerwatch/turbo-geth/common/dbutils" - - "github.com/ledgerwatch/turbo-geth/core/types/accounts" "github.com/ledgerwatch/turbo-geth/common" + "github.com/ledgerwatch/turbo-geth/common/dbutils" + "github.com/ledgerwatch/turbo-geth/core/types/accounts" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/log" "github.com/petar/GoLLRB/llrb" @@ -193,7 +192,7 @@ func (dbs *DbState) UpdateAccountCode(codeHash common.Hash, code []byte) error { return nil } -func (dbs *DbState) WriteAccountStorage(address common.Address, incarnation uint64, key, original, value *common.Hash) error { +func (dbs *DbState) WriteAccountStorage(_ context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error { t, ok := dbs.storage[address] if !ok { t = llrb.New() diff --git a/core/state/repair.go b/core/state/repair.go index 1086f2b968a..1a1214dadb8 100644 --- a/core/state/repair.go +++ b/core/state/repair.go @@ -18,17 +18,15 @@ package state import ( "bytes" + "context" "encoding/binary" "fmt" "github.com/ledgerwatch/turbo-geth/common/dbutils" "runtime" "sort" - "github.com/ledgerwatch/turbo-geth/core/types/accounts" - - "context" - "github.com/ledgerwatch/turbo-geth/common" + "github.com/ledgerwatch/turbo-geth/core/types/accounts" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/trie" ) @@ -245,7 +243,7 @@ func (rds *RepairDbState) getStorageTrie(address common.Address, create bool) (* return t, nil } -func (rds *RepairDbState) UpdateAccountData(ctx context.Context, address common.Address, original, account *accounts.Account) error { +func (rds *RepairDbState) UpdateAccountData(_ context.Context, address common.Address, original, account *accounts.Account) error { // Perform resolutions first var resolver *trie.TrieResolver var storageTrie *trie.Trie @@ -334,7 +332,7 @@ func (rds *RepairDbState) UpdateAccountData(ctx context.Context, address common. return nil } -func (rds *RepairDbState) DeleteAccount(ctx context.Context, address common.Address, original *accounts.Account) error { +func (rds *RepairDbState) DeleteAccount(_ context.Context, address common.Address, original *accounts.Account) error { addrHash, err := common.HashData(address[:]) if err != nil { return err diff --git a/core/state/state_object.go b/core/state/state_object.go index ee825c7ef3d..eaf7a8301d4 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -18,6 +18,7 @@ package state import ( "bytes" + "context" "fmt" "math/big" @@ -204,7 +205,7 @@ func (so *stateObject) setState(key, value common.Hash) { } // updateTrie writes cached storage modifications into the object's storage trie. -func (so *stateObject) updateTrie(stateWriter StateWriter) error { +func (so *stateObject) updateTrie(ctx context.Context, stateWriter StateWriter) error { if so.removeStorageTrie { so.originStorage = make(Storage) so.data.Root = trie.EmptyRoot @@ -219,7 +220,7 @@ func (so *stateObject) updateTrie(stateWriter StateWriter) error { original := so.blockOriginStorage[key] so.originStorage[key] = value - if err := stateWriter.WriteAccountStorage(so.address, so.data.GetIncarnation(), &key, &original, &value); err != nil { + if err := stateWriter.WriteAccountStorage(ctx, so.address, so.data.GetIncarnation(), &key, &original, &value); err != nil { return err } } diff --git a/core/state/stateless.go b/core/state/stateless.go index 3bec4719c53..9212cb6e2b7 100644 --- a/core/state/stateless.go +++ b/core/state/stateless.go @@ -586,7 +586,7 @@ func (s *Stateless) DeleteAccount(_ context.Context, address common.Address, ori return nil } -func (s *Stateless) WriteAccountStorage(address common.Address, incarnation uint64, key, original, value *common.Hash) error { +func (s *Stateless) WriteAccountStorage(_ context.Context, address common.Address, incarnation uint64, key, original, value *common.Hash) error { m, ok := s.storageUpdates[address] if !ok { m = make(map[common.Hash][]byte) diff --git a/core/state/trace.go b/core/state/trace.go index 362de1afebb..239a5da22ee 100644 --- a/core/state/trace.go +++ b/core/state/trace.go @@ -18,13 +18,11 @@ package state import ( "bytes" - "github.com/ledgerwatch/turbo-geth/common/dbutils" - - "github.com/ledgerwatch/turbo-geth/core/types/accounts" - "context" "github.com/ledgerwatch/turbo-geth/common" + "github.com/ledgerwatch/turbo-geth/common/dbutils" + "github.com/ledgerwatch/turbo-geth/core/types/accounts" "github.com/ledgerwatch/turbo-geth/ethdb" ) diff --git a/core/types.go b/core/types.go index 2fcf6e3dc99..69b7f85e2ca 100644 --- a/core/types.go +++ b/core/types.go @@ -17,6 +17,7 @@ package core import ( + "context" "github.com/ledgerwatch/turbo-geth/core/state" "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/vm" @@ -28,7 +29,7 @@ import ( // type Validator interface { // ValidateBody validates the given block's content. - ValidateBody(block *types.Block) error + ValidateBody(ctx context.Context, block *types.Block) error // ValidateState validates the given statedb and optionally the receipts and // gas used. diff --git a/eth/backend.go b/eth/backend.go index 572af53da36..cd00b61ba35 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -132,14 +132,14 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { accountManager: ctx.AccountManager, engine: CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.MinerNotify, config.MinerNoverify, chainDb), shutdownChan: make(chan bool), - networkID: config.NetworkId, + networkID: config.NetworkID, gasPrice: config.MinerGasPrice, etherbase: config.Etherbase, bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), } - log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId) + log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkID) if !config.SkipBcVersionCheck { bcVersion := rawdb.ReadDatabaseVersion(chainDb) @@ -156,7 +156,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { EWASMInterpreter: config.EWASMInterpreter, EVMInterpreter: config.EVMInterpreter, } - cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieCleanLimit: config.TrieCleanCache, TrieDirtyLimit: config.TrieDirtyCache, TrieTimeLimit: config.TrieTimeout} + cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieCleanLimit: config.TrieCleanCache, TrieDirtyLimit: config.TrieDirtyCache, TrieTimeLimit: config.TrieTimeout, NoHistory: config.NoHistory, ArchiveSyncInterval: uint64(config.ArchiveSyncInterval)} ) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.shouldPreserve) if err != nil { @@ -175,7 +175,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) - if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, config.Whitelist); err != nil { + if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkID, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, config.Whitelist); err != nil { return nil, err } diff --git a/eth/config.go b/eth/config.go index 43c17e72287..e25276f275d 100644 --- a/eth/config.go +++ b/eth/config.go @@ -43,7 +43,7 @@ var DefaultConfig = Config{ DatasetsInMem: 1, DatasetsOnDisk: 2, }, - NetworkId: 1, + NetworkID: 1, LightPeers: 100, DatabaseCache: 512, TrieCleanCache: 256, @@ -83,9 +83,11 @@ type Config struct { Genesis *core.Genesis `toml:",omitempty"` // Protocol options - NetworkId uint64 // Network ID to use for selecting peers to connect to - SyncMode downloader.SyncMode - NoPruning bool + NetworkID uint64 // Network ID to use for selecting peers to connect to + SyncMode downloader.SyncMode + NoPruning bool + NoHistory bool + ArchiveSyncInterval int // Whitelist of required block number -> hash values to accept Whitelist map[uint64]common.Hash `toml:"-"` diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 73e1223f00c..95499062dbb 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -195,6 +195,8 @@ type BlockChain interface { // InsertReceiptChain inserts a batch of receipts into the local chain. InsertReceiptChain(types.Blocks, []types.Receipts) (int, error) + + NotifyHeightKnownBlock(h uint64) } // New creates a new downloader to fetch hashes and blocks from remote peers. @@ -423,12 +425,14 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I if err != nil { return err } + + syncStatsChainHeight := d.GetSyncStatsChainHeight() d.syncStatsLock.Lock() - if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin { + if syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin { d.syncStatsChainOrigin = origin } - d.syncStatsChainHeight = height d.syncStatsLock.Unlock() + d.SetSyncStatsChainHeight(height) // Ensure our origin point is below any fast sync pivot point pivot := uint64(0) @@ -1415,11 +1419,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er origin += uint64(limit) } // Update the highest block number we know if a higher one is found. - d.syncStatsLock.Lock() - if d.syncStatsChainHeight < origin { - d.syncStatsChainHeight = origin - 1 - } - d.syncStatsLock.Unlock() + d.setGreaterSyncStatsChainHeight(origin-1, origin) // Signal the content downloaders of the availablility of new tasks for _, ch := range []chan bool{d.bodyWakeCh, d.receiptWakeCh} { @@ -1597,3 +1597,26 @@ func (d *Downloader) requestTTL() time.Duration { } return ttl } + +func (d *Downloader) SetSyncStatsChainHeight(h uint64) { + d.syncStatsLock.Lock() + d.syncStatsChainHeight = h + d.blockchain.NotifyHeightKnownBlock(h) + d.syncStatsLock.Unlock() +} + +func (d *Downloader) setGreaterSyncStatsChainHeight(h, old uint64) { + d.syncStatsLock.Lock() + if d.syncStatsChainHeight < old { + d.syncStatsChainHeight = h + d.blockchain.NotifyHeightKnownBlock(h) + } + d.syncStatsLock.Unlock() +} + +func (d *Downloader) GetSyncStatsChainHeight() uint64 { + d.syncStatsLock.RLock() + h := d.syncStatsChainHeight + d.syncStatsLock.RUnlock() + return h +} diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 024370cc96d..41fd54799af 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -279,6 +279,8 @@ func (dl *downloadTester) Rollback(hashes []common.Hash) { } } +func (dl *downloadTester) NotifyHeightKnownBlock(_ uint64) {} + // newPeer registers a new block download source into the downloader. func (dl *downloadTester) newPeer(id string, version int, chain *testChain) error { dl.lock.Lock() @@ -1227,7 +1229,7 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) { pending.Wait() // Simulate a successful sync above the fork - tester.downloader.syncStatsChainOrigin = tester.downloader.syncStatsChainHeight + tester.downloader.syncStatsChainOrigin = tester.downloader.GetSyncStatsChainHeight() // Synchronise with the second fork and check progress resets tester.newPeer("fork B", protocol, chainB) diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go index 2eba86758c5..17353d9e83e 100644 --- a/eth/downloader/testchain_test.go +++ b/eth/downloader/testchain_test.go @@ -17,6 +17,7 @@ package downloader import ( + "context" "fmt" "math/big" "sync" @@ -128,7 +129,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) tc.cpyLock.Lock() defer tc.cpyLock.Unlock() - blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), tc.db, n, func(i int, block *core.BlockGen) { + blocks, receipts := core.GenerateChain(context.Background(), params.TestChainConfig, parent, ethash.NewFaker(), tc.db, n, func(i int, block *core.BlockGen) { block.SetCoinbase(common.Address{seed}) // If a heavy chain is requested, delay blocks to raise difficulty if heavy { diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go index 11d12da8546..ae7886606d9 100644 --- a/eth/fetcher/fetcher_test.go +++ b/eth/fetcher/fetcher_test.go @@ -17,6 +17,7 @@ package fetcher import ( + "context" "errors" "math/big" "sync" @@ -48,7 +49,7 @@ var ( func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) { db := ethdb.NewMemDatabase() core.GenesisBlockForTesting(db, testAddress, big.NewInt(1000000000)) - blocks, _ := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), db, n, func(i int, block *core.BlockGen) { + blocks, _ := core.GenerateChain(context.Background(), params.TestChainConfig, parent, ethash.NewFaker(), db, n, func(i int, block *core.BlockGen) { block.SetCoinbase(common.Address{seed}) // If the block number is multiple of 3, send a bonus transaction to the miner diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index f8a898bd388..e0d77fc53fe 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -169,7 +169,7 @@ func TestBlockSubscription(t *testing.T) { backend = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed} api = NewPublicFilterAPI(backend, false) genesis = (&core.Genesis{Config: params.TestChainConfig}).MustCommit(db) - chain, _ = core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {}) + chain, _ = core.GenerateChain(context.Background(), params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {}) chainEvents = []core.ChainEvent{} ) diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 059f37b3b43..40422528536 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -67,7 +67,7 @@ func BenchmarkFilters(b *testing.B) { defer db.Close() genesis := core.GenesisBlockForTesting(db, addr1, big.NewInt(1000000)) - chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 100010, func(i int, gen *core.BlockGen) { + chain, receipts := core.GenerateChain(context.Background(), params.TestChainConfig, genesis, ethash.NewFaker(), db, 100010, func(i int, gen *core.BlockGen) { switch i { case 2403: receipt := makeReceipt(addr1) @@ -122,7 +122,7 @@ func TestFilters(t *testing.T) { defer db.Close() genesis := core.GenesisBlockForTesting(db, addr, big.NewInt(1000000)) - chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { + chain, receipts := core.GenerateChain(context.Background(), params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { switch i { case 1: receipt := types.NewReceipt(false, 0) diff --git a/eth/gen_config.go b/eth/gen_config.go index 53e72bcd6df..349a27d30a2 100644 --- a/eth/gen_config.go +++ b/eth/gen_config.go @@ -23,6 +23,8 @@ func (c Config) MarshalTOML() (interface{}, error) { NetworkId uint64 SyncMode downloader.SyncMode NoPruning bool + NoHistory bool + ArchiveSyncInterval int LightServ int `toml:",omitempty"` LightPeers int `toml:",omitempty"` OnlyAnnounce bool @@ -51,9 +53,11 @@ func (c Config) MarshalTOML() (interface{}, error) { } var enc Config enc.Genesis = c.Genesis - enc.NetworkId = c.NetworkId + enc.NetworkId = c.NetworkID enc.SyncMode = c.SyncMode enc.NoPruning = c.NoPruning + enc.NoHistory = c.NoHistory + enc.ArchiveSyncInterval = c.ArchiveSyncInterval enc.LightServ = c.LightServ enc.LightPeers = c.LightPeers enc.OnlyAnnounce = c.OnlyAnnounce @@ -90,6 +94,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { NetworkId *uint64 SyncMode *downloader.SyncMode NoPruning *bool + NoHistory *bool + ArchiveSyncInterval *int LightServ *int `toml:",omitempty"` LightPeers *int `toml:",omitempty"` OnlyAnnounce *bool @@ -124,7 +130,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { c.Genesis = dec.Genesis } if dec.NetworkId != nil { - c.NetworkId = *dec.NetworkId + c.NetworkID = *dec.NetworkId } if dec.SyncMode != nil { c.SyncMode = *dec.SyncMode @@ -132,6 +138,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.NoPruning != nil { c.NoPruning = *dec.NoPruning } + if dec.NoHistory != nil { + c.NoHistory = *dec.NoHistory + } + if dec.ArchiveSyncInterval != nil { + c.ArchiveSyncInterval = *dec.ArchiveSyncInterval + } if dec.LightServ != nil { c.LightServ = *dec.LightServ } diff --git a/eth/handler_test.go b/eth/handler_test.go index 635c2cadda0..ba771fbba90 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -17,6 +17,7 @@ package eth import ( + "context" "fmt" "io/ioutil" "math" @@ -391,7 +392,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool if err != nil { t.Fatalf("failed to create new blockchain: %v", err) } - pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db, nil) + pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkID, evmux, new(testTxPool), pow, blockchain, db, nil) if err != nil { t.Fatalf("failed to start test protocol manager: %v", err) } @@ -413,7 +414,8 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool } // Create a block to reply to the challenge if no timeout is simulated if !timeout { - blocks, _ := core.GenerateChain(¶ms.ChainConfig{}, genesis, ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, ¶ms.ChainConfig{}, genesis, ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) { if remoteForked { block.SetExtra(params.DAOForkBlockExtra) } @@ -472,7 +474,7 @@ func testBroadcastBlock(t *testing.T, totalPeers, broadcastExpected int) { if err != nil { t.Fatalf("failed to create new blockchain: %v", err) } - pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db, nil) + pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkID, evmux, new(testTxPool), pow, blockchain, db, nil) if err != nil { t.Fatalf("failed to start test protocol manager: %v", err) } @@ -484,7 +486,8 @@ func testBroadcastBlock(t *testing.T, totalPeers, broadcastExpected int) { defer peer.close() peers = append(peers, peer) } - chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {}) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + chain, _ := core.GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {}) pm.BroadcastBlock(chain[0], true /*propagate*/) errCh := make(chan error, totalPeers) diff --git a/eth/helper_test.go b/eth/helper_test.go index 9cd1f519977..2cbec87d488 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -20,6 +20,7 @@ package eth import ( + "context" "crypto/ecdsa" "crypto/rand" "log" @@ -58,13 +59,11 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func Config: params.TestChainConfig, Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}}, } + dbGen = ethdb.NewMemDatabase() // This database is only used to generate the chain, then discarded + genesis = gspec.MustCommit(dbGen) ) var chain []*types.Block - { - db_gen := ethdb.NewMemDatabase() // This database is only used to generate the chain, then discarded - genesis := gspec.MustCommit(db_gen) - chain, _ = core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db_gen, blocks, generator) - } + // Fresh database db := ethdb.NewMemDatabase() // Regenerate genesis block in the fresh database @@ -74,11 +73,15 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func return nil, nil, err } blockchain.EnableReceipts(true) + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + + chain, _ = core.GenerateChain(ctx, gspec.Config, genesis, ethash.NewFaker(), dbGen, blocks, generator) + if _, err := blockchain.InsertChain(chain); err != nil { return nil, nil, err } - pm, err := NewProtocolManager(gspec.Config, mode, DefaultConfig.NetworkId, evmux, &testTxPool{added: newtx}, engine, blockchain, db, nil) + pm, err := NewProtocolManager(gspec.Config, mode, DefaultConfig.NetworkID, evmux, &testTxPool{added: newtx}, engine, blockchain, db, nil) if err != nil { return nil, nil, err } @@ -227,7 +230,7 @@ func newFirehoseTestPeer(name string, pm *ProtocolManager) (*testFirehosePeer, < func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, genesis common.Hash) { msg := &statusData{ ProtocolVersion: uint32(p.version), - NetworkId: DefaultConfig.NetworkId, + NetworkId: DefaultConfig.NetworkID, TD: td, CurrentBlock: head, GenesisBlock: genesis, diff --git a/eth/protocol.go b/eth/protocol.go index 49635cab587..312b603dd74 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -90,7 +90,7 @@ var errorToString = map[int]string{ ErrDecode: "Invalid message", ErrInvalidMsgCode: "Invalid message code", ErrProtocolVersionMismatch: "Protocol version mismatch", - ErrNetworkIdMismatch: "NetworkId mismatch", + ErrNetworkIdMismatch: "NetworkID mismatch", ErrGenesisBlockMismatch: "Genesis block mismatch", ErrNoStatusMsg: "No status message", ErrExtraStatusMsg: "Extra status message", diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 539856bc3f6..d2718c358c0 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -59,7 +59,7 @@ func testStatusMsgErrors(t *testing.T, protocol int) { wantError: errResp(ErrNoStatusMsg, "first msg has code 2 (!= 0)"), }, { - code: StatusMsg, data: statusData{10, DefaultConfig.NetworkId, td, head.Hash(), genesis.Hash()}, + code: StatusMsg, data: statusData{10, DefaultConfig.NetworkID, td, head.Hash(), genesis.Hash()}, wantError: errResp(ErrProtocolVersionMismatch, "10 (!= %d)", protocol), }, { @@ -67,7 +67,7 @@ func testStatusMsgErrors(t *testing.T, protocol int) { wantError: errResp(ErrNetworkIdMismatch, "999 (!= 1)"), }, { - code: StatusMsg, data: statusData{uint32(protocol), DefaultConfig.NetworkId, td, head.Hash(), common.Hash{3}}, + code: StatusMsg, data: statusData{uint32(protocol), DefaultConfig.NetworkID, td, head.Hash(), common.Hash{3}}, wantError: errResp(ErrGenesisBlockMismatch, "0300000000000000 (!= %x)", genesis.Hash().Bytes()[:8]), }, } diff --git a/ethdb/database.go b/ethdb/database.go index 59697aad224..c2c7172d052 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -85,14 +85,6 @@ func (db *BoltDatabase) Put(bucket, key []byte, value []byte) error { return err } -func compositeKeySuffix(key []byte, timestamp uint64) (composite, suffix []byte) { - suffix = encodeTimestamp(timestamp) - composite = make([]byte, len(key)+len(suffix)) - copy(composite, key) - copy(composite[len(key):], suffix) - return composite, suffix -} - func historyBucket(bucket []byte) []byte { hb := make([]byte, len(bucket)+1) hb[0] = byte('h') @@ -124,6 +116,14 @@ func (db *BoltDatabase) PutS(hBucket, key, value []byte, timestamp uint64) error return err } +func compositeKeySuffix(key []byte, timestamp uint64) (composite, suffix []byte) { + suffix = encodeTimestamp(timestamp) + composite = make([]byte, len(key)+len(suffix)) + copy(composite, key) + copy(composite[len(key):], suffix) + return composite, suffix +} + func (db *BoltDatabase) MultiPut(tuples ...[]byte) (uint64, error) { var savedTx *bolt.Tx err := db.db.Update(func(tx *bolt.Tx) error { @@ -232,6 +232,7 @@ func (db *BoltDatabase) GetAsOf(bucket, hBucket, key []byte, timestamp uint64) ( return nil } } + return ErrKeyNotFound }) return dat, err diff --git a/ethdb/encoding.go b/ethdb/encoding.go index 78a5503abb7..ca4a3eb53b9 100644 --- a/ethdb/encoding.go +++ b/ethdb/encoding.go @@ -1,11 +1,5 @@ package ethdb -import () - -func encodingLen8to7(b []byte) int { - return (len(b)*8 + 6) / 7 -} - // Transforms b into encoding where only // 7 bits of each byte are used to encode the bits of b // The most significant bit is left empty, for other purposes diff --git a/ethdb/walk.go b/ethdb/walk.go index 701537b73f4..2b2b56000c4 100644 --- a/ethdb/walk.go +++ b/ethdb/walk.go @@ -20,15 +20,13 @@ import ( "bytes" "encoding/binary" "fmt" - "github.com/ledgerwatch/turbo-geth/common/dbutils" - - //"sort" "github.com/ledgerwatch/turbo-geth/common" + "github.com/ledgerwatch/turbo-geth/common/dbutils" "github.com/petar/GoLLRB/llrb" ) -var EndSuffix []byte = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} +var EndSuffix = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} // Generates rewind data for all buckets between the timestamp // timestapSrc is the current timestamp, and timestamp Dst is where we rewind diff --git a/miner/stress_clique.go b/miner/stress_clique.go index 54fc262acaa..c81d3302085 100644 --- a/miner/stress_clique.go +++ b/miner/stress_clique.go @@ -193,7 +193,7 @@ func makeSealer(genesis *core.Genesis) (*node.Node, error) { if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ð.Config{ Genesis: genesis, - NetworkId: genesis.Config.ChainID.Uint64(), + NetworkID: genesis.Config.ChainID.Uint64(), SyncMode: downloader.FullSync, DatabaseCache: 256, DatabaseHandles: 256, diff --git a/miner/stress_ethash.go b/miner/stress_ethash.go index 5bf6c79032e..856918ca77a 100644 --- a/miner/stress_ethash.go +++ b/miner/stress_ethash.go @@ -172,7 +172,7 @@ func makeMiner(genesis *core.Genesis) (*node.Node, error) { if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ð.Config{ Genesis: genesis, - NetworkId: genesis.Config.ChainID.Uint64(), + NetworkID: genesis.Config.ChainID.Uint64(), SyncMode: downloader.FullSync, DatabaseCache: 256, DatabaseHandles: 256, diff --git a/miner/worker_test.go b/miner/worker_test.go index c59c6a7ed11..ff00e2f3c39 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -17,6 +17,7 @@ package miner import ( + "context" "math/big" "testing" "time" @@ -101,7 +102,8 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine // Generate a small n-block chain and an uncle block for it if n > 0 { - blocks, _ := core.GenerateChain(chainConfig, genesis, engine, db, n, func(i int, gen *core.BlockGen) { + ctx := chain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, chainConfig, genesis, engine, db, n, func(i int, gen *core.BlockGen) { gen.SetCoinbase(testBankAddress) }) if _, err := chain.InsertChain(blocks); err != nil { @@ -112,7 +114,8 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine if n > 0 { parent = chain.GetBlockByHash(chain.CurrentBlock().ParentHash()) } - blocks, _ := core.GenerateChain(chainConfig, parent, engine, db, 1, func(i int, gen *core.BlockGen) { + ctx := chain.WithContext(context.Background(), big.NewInt(parent.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, chainConfig, parent, engine, db, 1, func(i int, gen *core.BlockGen) { gen.SetCoinbase(testUserAddress) }) diff --git a/params/eip_ctx.go b/params/eip_ctx.go index 78ff08ac512..21aaf6387c6 100644 --- a/params/eip_ctx.go +++ b/params/eip_ctx.go @@ -18,6 +18,8 @@ const ( IsPetersburgEnabled IsEWASM BlockNumber + NoHistory + WithHistoryHighest ) func (c *ChainConfig) WithEIPsFlags(ctx context.Context, blockNum *big.Int) context.Context { @@ -34,6 +36,10 @@ func (c *ChainConfig) WithEIPsFlags(ctx context.Context, blockNum *big.Int) cont return ctx } +func WithNoHistory(ctx context.Context, defaultValue bool, f noHistFunc) context.Context { + return context.WithValue(ctx, NoHistory, getIsNoHistory(defaultValue, f)) +} + func GetForkFlag(ctx context.Context, name configKey) bool { b := ctx.Value(name) if b == nil { @@ -44,3 +50,116 @@ func GetForkFlag(ctx context.Context, name configKey) bool { } return false } + +func GetBlockNumber(ctx context.Context) *big.Int { + b := ctx.Value(BlockNumber) + if b == nil { + return nil + } + if valB, ok := b.(*big.Int); ok { + return valB + } + return nil +} + +func GetNoHistoryByBlock(ctx context.Context, currentBlock *big.Int) (context.Context, bool) { + if currentBlock == nil { + return ctx, false + } + + key := getNoHistoryByBlock(currentBlock) + v, ok := getNoHistoryByKey(ctx, key) + if ok { + if !v { + ctx = updateHighestWithHistory(ctx, currentBlock) + } + return ctx, v + } + + return withNoHistory(ctx, currentBlock, key) +} + +func withNoHistory(ctx context.Context, currentBlock *big.Int, key configKey) (context.Context, bool) { + v := getNoHistory(ctx, currentBlock) + ctx = context.WithValue(ctx, key, v) + if !v { + ctx = updateHighestWithHistory(ctx, currentBlock) + } + + return ctx, v +} + +func updateHighestWithHistory(ctx context.Context, currentBlock *big.Int) context.Context { + highestWithHistory := getWithHistoryHighest(ctx) + var currentIsLower bool + if highestWithHistory != nil { + currentIsLower = currentBlock.Cmp(highestWithHistory) < 0 + } + if !currentIsLower { + ctx = setWithHistoryHighestByBlock(ctx, currentBlock) + } + return ctx +} + +func getNoHistory(ctx context.Context, currentBlock *big.Int) bool { + v := ctx.Value(NoHistory) + if v == nil { + return false + } + if val, ok := v.(noHistFunc); ok { + return val(currentBlock) + } + return false +} + +func getWithHistoryHighest(ctx context.Context) *big.Int { + v := ctx.Value(WithHistoryHighest) + if v == nil { + return nil + } + if val, ok := v.(*big.Int); ok { + return val + } + return nil +} + +func setWithHistoryHighestByBlock(ctx context.Context, block *big.Int) context.Context { + return context.WithValue(ctx, WithHistoryHighest, block) +} + +func getNoHistoryByKey(ctx context.Context, key configKey) (bool, bool) { + if key < 0 { + return false, false + } + v := ctx.Value(key) + if v == nil { + return false, false + } + if val, ok := v.(bool); ok { + return val, true + } + return false, false +} + +func getNoHistoryByBlock(block *big.Int) configKey { + if block == nil { + return configKey(-1) + } + return configKey(block.Uint64() + 1000) +} + +func GetNoHistory(ctx context.Context) (context.Context, bool) { + return GetNoHistoryByBlock(ctx, GetBlockNumber(ctx)) +} + +type noHistFunc func(currentBlock *big.Int) bool + +func getIsNoHistory(defaultValue bool, f noHistFunc) noHistFunc { + return func(currentBlock *big.Int) bool { + if f == nil { + return defaultValue + } + + return f(currentBlock) + } +} diff --git a/tests/statedb_chain_test.go b/tests/statedb_chain_test.go index 6262969c0ff..43efc903238 100644 --- a/tests/statedb_chain_test.go +++ b/tests/statedb_chain_test.go @@ -73,7 +73,6 @@ func TestEIP2027AccountStorageSize(t *testing.T) { if err != nil { t.Fatal(err) } - blockchain.EnableReceipts(true) contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) @@ -84,13 +83,14 @@ func TestEIP2027AccountStorageSize(t *testing.T) { var contractAddress common.Address var eipContract *contracts.Eip2027 - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 7, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 7, func(i int, block *core.BlockGen) { var ( tx *types.Transaction err error ) - ctx := gspec.Config.WithEIPsFlags(context.Background(), block.Number()) + ctx = gspec.Config.WithEIPsFlags(ctx, block.Number()) switch i { case 0: @@ -282,13 +282,14 @@ func TestEIP2027AccountStorageSizeOnDeploy(t *testing.T) { var contractAddress common.Address var eipContract *contracts.Eip2027 - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 3, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 3, func(i int, block *core.BlockGen) { var ( tx *types.Transaction err error ) - ctx := gspec.Config.WithEIPsFlags(context.Background(), block.Number()) + ctx = gspec.Config.WithEIPsFlags(ctx, block.Number()) switch i { case 0: @@ -416,13 +417,14 @@ func TestEIP2027AccountStorageSizeWithoutEIP(t *testing.T) { var contractAddress common.Address var eipContract *contracts.Eip2027 - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 7, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 7, func(i int, block *core.BlockGen) { var ( tx *types.Transaction err error ) - ctx := gspec.Config.WithEIPsFlags(context.Background(), block.Number()) + ctx = gspec.Config.WithEIPsFlags(ctx, block.Number()) switch i { case 0: @@ -603,13 +605,14 @@ func TestEIP2027AccountStorageSizeRevertRemove(t *testing.T) { var contractAddress common.Address var eipContract *contracts.Eip2027 - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 7, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 7, func(i int, block *core.BlockGen) { var ( tx *types.Transaction err error ) - ctx := gspec.Config.WithEIPsFlags(context.Background(), block.Number()) + ctx = gspec.Config.WithEIPsFlags(ctx, block.Number()) switch i { case 0: @@ -807,13 +810,14 @@ func TestEIP2027AccountStorageSizeRevertUpdate(t *testing.T) { var contractAddress common.Address var eipContract *contracts.Eip2027 - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 6, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 6, func(i int, block *core.BlockGen) { var ( tx *types.Transaction err error ) - ctx := gspec.Config.WithEIPsFlags(context.Background(), block.Number()) + ctx = gspec.Config.WithEIPsFlags(ctx, block.Number()) switch i { case 0: @@ -991,13 +995,14 @@ func TestEIP2027AccountStorageSizeExceptionUpdate(t *testing.T) { var contractAddress common.Address var eipContract *contracts.Eip2027 - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 6, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 6, func(i int, block *core.BlockGen) { var ( tx *types.Transaction err error ) - ctx := gspec.Config.WithEIPsFlags(context.Background(), block.Number()) + ctx = gspec.Config.WithEIPsFlags(ctx, block.Number()) switch i { case 0: @@ -1168,7 +1173,8 @@ func TestSelfDestructReceive(t *testing.T) { // effectively turning it from contract account to a non-contract account // The second block is empty and is only used to force the newly created blockchain object to reload the trie // from the database. - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, genesisDb, 2, func(i int, block *core.BlockGen) { + ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1)) + blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, genesisDb, 2, func(i int, block *core.BlockGen) { var tx *types.Transaction switch i { diff --git a/trie/resolver_test.go b/trie/resolver_test.go index 5458b7dd08a..17c6da6e7e9 100644 --- a/trie/resolver_test.go +++ b/trie/resolver_test.go @@ -12,9 +12,9 @@ import ( "github.com/ledgerwatch/turbo-geth/rlp" ) -var testbucket = []byte("test") +func TestRebuild(t *testing.T) { + t.Skip("should be restored. skipped for turbo-geth") -func testRebuild(t *testing.T) { db := ethdb.NewMemDatabase() defer db.Close() bucket := dbutils.AccountsBucket