Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core, trie: intermediate mempool between trie and database #15857

Merged
merged 33 commits into from
Feb 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
33cca2b
core, trie: intermediate mempool between trie and database
karalabe Jan 11, 2018
0e91a17
core, trie: commit trie mempool on close, fix dao test
karalabe Jan 11, 2018
d2ec96e
core, trie: minor cleanups, test fixes
karalabe Jan 12, 2018
34d766a
core, trie: finalize the new trie node-caching db layer
karalabe Jan 17, 2018
80eb5be
core, trie: thread-safe triedb commit, configurable caches
karalabe Jan 17, 2018
e065755
core, trie: fix some dereferencing issues
karalabe Jan 18, 2018
bb40af2
trie: make databse more Go GC friendly
karalabe Jan 19, 2018
be674fa
cmd, core, eth: support restarting with missing states
karalabe Jan 19, 2018
c03e94c
core: garbage collect side fork tries too
karalabe Jan 22, 2018
b46b291
core: only store pruned sidechains until they beat canonical
karalabe Jan 24, 2018
4315480
core, trie: fix duplicate references, sanity check on shutdown
karalabe Jan 24, 2018
b2d8f14
trie: fix the double reference fix (i.e. roots *can* be double refed)
karalabe Jan 24, 2018
507f20d
core: make trie critical periods verbose, add failsafes
karalabe Jan 25, 2018
f0db662
eth: switch hacky tracer pruning to triedb garbage collector
karalabe Jan 25, 2018
a3cd57e
core, trie: fix all the linters
karalabe Jan 25, 2018
7dc1f18
core: add current cache size to import logs
karalabe Jan 25, 2018
615145e
trie: count preimages in memuse, commit in KB batches
karalabe Jan 26, 2018
cfb510c
core: only count canonical blocks for GC processing time
karalabe Jan 26, 2018
abd9983
eth/dwonloader: moving pivot and capped memory usage
karalabe Jan 30, 2018
a7bae8c
trie: use batch reset instead of recreation
karalabe Jan 30, 2018
a2b7866
core, les, light, trie: correctly use the memdb for tries
karalabe Jan 31, 2018
20369b0
eth/downloader: reduce a log level back to debug
karalabe Jan 31, 2018
a14bfec
light: make the trie mempool play nice with CHTs
karalabe Jan 31, 2018
a4cff48
core: warn the user that we're saving state on shutdown
karalabe Feb 1, 2018
4aeed07
core: report pretty storage sizes for receipt inserts
karalabe Feb 1, 2018
92716dd
eth/downloader: termiante state sync cleanly
karalabe Feb 1, 2018
87a37c3
core: make receipt and headers have the same log format
karalabe Feb 1, 2018
104ccf5
core, eth, les, light: hide triedb behind state database
karalabe Feb 2, 2018
3c30b28
core: remote a debugging warning log
karalabe Feb 2, 2018
5f253f6
eth/downloader: fix statesync fast restart race, hang test
karalabe Feb 2, 2018
30ddc90
cmd: drop trie cache timeout flag (available via config)
karalabe Feb 2, 2018
49bdc8b
core, eth: avoid RLP serialization in downloader queue
karalabe Feb 2, 2018
54b8ded
cmd, core, eth, light, trie: gcmode flag + supress archive logs
karalabe Feb 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
database, _ := ethdb.NewMemDatabase()
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, Alloc: alloc}
genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, genesis.Config, ethash.NewFaker(), vm.Config{})
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{})

backend := &SimulatedBackend{
database: database,
Expand Down Expand Up @@ -102,8 +102,10 @@ func (b *SimulatedBackend) Rollback() {

func (b *SimulatedBackend) rollback() {
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
statedb, _ := b.blockchain.State()

b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.database))
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
}

// CodeAt returns the code associated with a certain account in the blockchain.
Expand Down Expand Up @@ -309,8 +311,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
}
block.AddTx(tx)
})
statedb, _ := b.blockchain.State()

b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.database))
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
return nil
}

Expand Down Expand Up @@ -386,8 +390,10 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
}
block.OffsetTime(int64(adjustment.Seconds()))
})
statedb, _ := b.blockchain.State()

b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.database))
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())

return nil
}
Expand Down
4 changes: 3 additions & 1 deletion cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ func runCmd(ctx *cli.Context) error {
}
if ctx.GlobalString(GenesisFlag.Name) != "" {
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
_, statedb = gen.ToBlock()
db, _ := ethdb.NewMemDatabase()
genesis := gen.ToBlock(db)
statedb, _ = state.New(genesis.Root(), state.NewDatabase(db))
chainConfig = gen.Config
} else {
db, _ := ethdb.NewMemDatabase()
Expand Down
4 changes: 2 additions & 2 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func importChain(ctx *cli.Context) error {

if len(ctx.Args()) == 1 {
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
utils.Fatalf("Import error: %v", err)
log.Error("Import error", "err", err)
}
} else {
for _, arg := range ctx.Args() {
Expand All @@ -211,7 +211,7 @@ func importChain(ctx *cli.Context) error {
}
}
}

chain.Stop()
fmt.Printf("Import done in %v.\n\n", time.Since(start))

// Output pre-compaction stats mostly to see the import trashing
Expand Down
3 changes: 3 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,13 @@ var (
utils.FastSyncFlag,
utils.LightModeFlag,
utils.SyncModeFlag,
utils.GCModeFlag,
utils.LightServFlag,
utils.LightPeersFlag,
utils.LightKDFFlag,
utils.CacheFlag,
utils.CacheDatabaseFlag,
utils.CacheGCFlag,
utils.TrieCacheGenFlag,
utils.ListenPortFlag,
utils.MaxPeersFlag,
Expand Down
6 changes: 5 additions & 1 deletion cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ import (
"io"
"sort"

"strings"

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/internal/debug"
"gopkg.in/urfave/cli.v1"
"strings"
)

// AppHelpTemplate is the test template for the default, global app help topic.
Expand Down Expand Up @@ -74,6 +75,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.TestnetFlag,
utils.RinkebyFlag,
utils.SyncModeFlag,
utils.GCModeFlag,
utils.EthStatsURLFlag,
utils.IdentityFlag,
utils.LightServFlag,
Expand Down Expand Up @@ -127,6 +129,8 @@ var AppHelpFlagGroups = []flagGroup{
Name: "PERFORMANCE TUNING",
Flags: []cli.Flag{
utils.CacheFlag,
utils.CacheDatabaseFlag,
utils.CacheGCFlag,
utils.TrieCacheGenFlag,
},
},
Expand Down
26 changes: 17 additions & 9 deletions cmd/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ func ImportChain(chain *core.BlockChain, fn string) error {
return err
}
}

stream := rlp.NewStream(reader, 0)

// Run actual the import.
Expand Down Expand Up @@ -150,25 +149,34 @@ func ImportChain(chain *core.BlockChain, fn string) error {
if checkInterrupt() {
return fmt.Errorf("interrupted")
}
if hasAllBlocks(chain, blocks[:i]) {
missing := missingBlocks(chain, blocks[:i])
if len(missing) == 0 {
log.Info("Skipping batch as all blocks present", "batch", batch, "first", blocks[0].Hash(), "last", blocks[i-1].Hash())
continue
}

if _, err := chain.InsertChain(blocks[:i]); err != nil {
if _, err := chain.InsertChain(missing); err != nil {
return fmt.Errorf("invalid block %d: %v", n, err)
}
}
return nil
}

func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
for _, b := range bs {
if !chain.HasBlock(b.Hash(), b.NumberU64()) {
return false
func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block {
head := chain.CurrentBlock()
for i, block := range blocks {
// If we're behind the chain head, only check block, state is available at head
if head.NumberU64() > block.NumberU64() {
if !chain.HasBlock(block.Hash(), block.NumberU64()) {
return blocks[i:]
}
continue
}
// If we're above the chain head, state availability is a must
if !chain.HasBlockAndState(block.Hash(), block.NumberU64()) {
return blocks[i:]
}
}
return true
return nil
}

func ExportChain(blockchain *core.BlockChain, fn string) error {
Expand Down
47 changes: 40 additions & 7 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,11 @@ var (
Usage: `Blockchain sync mode ("fast", "full", or "light")`,
Value: &defaultSyncMode,
}

GCModeFlag = cli.StringFlag{
Name: "gcmode",
Usage: `Blockchain garbage collection mode ("full", "archive")`,
Value: "full",
}
LightServFlag = cli.IntFlag{
Name: "lightserv",
Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
Expand Down Expand Up @@ -293,8 +297,18 @@ var (
// Performance tuning settings
CacheFlag = cli.IntFlag{
Name: "cache",
Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
Value: 128,
Usage: "Megabytes of memory allocated to internal caching",
Value: 1024,
}
CacheDatabaseFlag = cli.IntFlag{
Name: "cache.database",
Usage: "Percentage of cache memory allowance to use for database io",
Value: 75,
}
CacheGCFlag = cli.IntFlag{
Name: "cache.gc",
Usage: "Percentage of cache memory allowance to use for trie pruning",
Value: 25,
}
TrieCacheGenFlag = cli.IntFlag{
Name: "trie-cache-gens",
Expand Down Expand Up @@ -1021,11 +1035,19 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
}

if ctx.GlobalIsSet(CacheFlag.Name) {
cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name)
if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
}
cfg.DatabaseHandles = makeDatabaseHandles()

if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"

if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
}
if ctx.GlobalIsSet(MinerThreadsFlag.Name) {
cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name)
}
Expand Down Expand Up @@ -1157,7 +1179,7 @@ func SetupNetwork(ctx *cli.Context) {
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
var (
cache = ctx.GlobalInt(CacheFlag.Name)
cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
handles = makeDatabaseHandles()
)
name := "chaindata"
Expand Down Expand Up @@ -1209,8 +1231,19 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
})
}
}
if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
cache := &core.CacheConfig{
Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive",
TrieNodeLimit: eth.DefaultConfig.TrieCache,
TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
}
if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
}
vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
chain, err = core.NewBlockChain(chainDb, config, engine, vmcfg)
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg)
if err != nil {
Fatalf("Can't create BlockChain: %v", err)
}
Expand Down
27 changes: 19 additions & 8 deletions common/size.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,29 @@ import (
"fmt"
)

// StorageSize is a wrapper around a float value that supports user friendly
// formatting.
type StorageSize float64

func (self StorageSize) String() string {
if self > 1000000 {
return fmt.Sprintf("%.2f mB", self/1000000)
} else if self > 1000 {
return fmt.Sprintf("%.2f kB", self/1000)
// String implements the stringer interface.
func (s StorageSize) String() string {
if s > 1000000 {
return fmt.Sprintf("%.2f mB", s/1000000)
} else if s > 1000 {
return fmt.Sprintf("%.2f kB", s/1000)
} else {
return fmt.Sprintf("%.2f B", self)
return fmt.Sprintf("%.2f B", s)
}
}

func (self StorageSize) Int64() int64 {
return int64(self)
// TerminalString implements log.TerminalStringer, formatting a string for console
// output during logging.
func (s StorageSize) TerminalString() string {
if s > 1000000 {
return fmt.Sprintf("%.2fmB", s/1000000)
} else if s > 1000 {
return fmt.Sprintf("%.2fkB", s/1000)
} else {
return fmt.Sprintf("%.2fB", s)
}
}
4 changes: 4 additions & 0 deletions consensus/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ var (
// that is unknown.
ErrUnknownAncestor = errors.New("unknown ancestor")

// ErrPrunedAncestor is returned when validating a block requires an ancestor
// that is known, but the state of which is not available.
ErrPrunedAncestor = errors.New("pruned ancestor")

// ErrFutureBlock is returned when a block's timestamp is in the future according
// to the current node.
ErrFutureBlock = errors.New("block in the future")
Expand Down
4 changes: 2 additions & 2 deletions core/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {

// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
chainman, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
Expand Down Expand Up @@ -283,7 +283,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
chain, err := NewBlockChain(db, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
if err != nil {
b.Fatalf("error creating chain: %v", err)
}
Expand Down
9 changes: 6 additions & 3 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
// validated at this point.
func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Check whether the block's known, and if not, that it's linkable
if v.bc.HasBlockAndState(block.Hash()) {
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock
}
if !v.bc.HasBlockAndState(block.ParentHash()) {
return consensus.ErrUnknownAncestor
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
return consensus.ErrUnknownAncestor
}
return consensus.ErrPrunedAncestor
}
// Header validity is known at this point, check the uncles and transactions
header := block.Header()
Expand Down
8 changes: 4 additions & 4 deletions core/block_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header()
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
defer chain.Stop()

for i := 0; i < len(blocks); i++ {
Expand Down Expand Up @@ -106,11 +106,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
var results <-chan error

if valid {
chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
} else {
chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{})
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{})
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
}
Expand Down Expand Up @@ -173,7 +173,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
defer runtime.GOMAXPROCS(old)

// Start the verifications and immediately abort
chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
defer chain.Stop()

abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
Expand Down
Loading