diff options
author | Péter Szilágyi <peterke@gmail.com> | 2019-05-13 20:28:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-13 20:28:01 +0800 |
commit | 9effd642901e13765dcc1396392ba55a18f66ccf (patch) | |
tree | 57355cff7ea6c5efbb5702c6e62ec7b698d4ff15 /eth/downloader | |
parent | 40cdcf8c47ff094775aca08fd5d94051f9cf1dbb (diff) | |
download | go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.tar go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.tar.gz go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.tar.bz2 go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.tar.lz go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.tar.xz go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.tar.zst go-tangerine-9effd642901e13765dcc1396392ba55a18f66ccf.zip |
core, eth, trie: bloom filter for trie node dedup during fast sync (#19489)
* core, eth, trie: bloom filter for trie node dedup during fast sync
* eth/downloader, trie: address review comments
* core, ethdb, trie: restart fast-sync bloom construction now and again
* eth/downloader: initialize fast sync bloom on startup
* eth: reenable eth/62 until we properly remove it
Diffstat (limited to 'eth/downloader')
-rw-r--r-- | eth/downloader/downloader.go | 36 | ||||
-rw-r--r-- | eth/downloader/downloader_test.go | 2 | ||||
-rw-r--r-- | eth/downloader/statesync.go | 3 |
3 files changed, 32 insertions, 9 deletions
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 95f2c2aee..0e19fe9e6 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" ) var ( @@ -104,7 +105,9 @@ type Downloader struct { genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT) queue *queue // Scheduler for selecting the hashes to download peers *peerSet // Set of active peers from which download can proceed - stateDB ethdb.Database + + stateDB ethdb.Database // Database to state sync into (and deduplicate via) + stateBloom *trie.SyncBloom // Bloom filter for fast trie node existence checks rttEstimate uint64 // Round trip time to target for download requests rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops) @@ -207,13 +210,13 @@ type BlockChain interface { } // New creates a new downloader to fetch hashes and blocks from remote peers. -func New(mode SyncMode, checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader { +func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader { if lightchain == nil { lightchain = chain } dl := &Downloader{ - mode: mode, stateDB: stateDb, + stateBloom: stateBloom, mux: mux, checkpoint: checkpoint, queue: newQueue(), @@ -255,13 +258,15 @@ func (d *Downloader) Progress() ethereum.SyncProgress { defer d.syncStatsLock.RUnlock() current := uint64(0) - switch d.mode { - case FullSync: + switch { + case d.blockchain != nil && d.mode == FullSync: current = d.blockchain.CurrentBlock().NumberU64() - case FastSync: + case d.blockchain != nil && d.mode == FastSync: current = d.blockchain.CurrentFastBlock().NumberU64() - case LightSync: + case d.lightchain != nil: current = d.lightchain.CurrentHeader().Number.Uint64() + default: + log.Error("Unknown downloader chain/mode combo", "light", d.lightchain != nil, "full", d.blockchain != nil, "mode", d.mode) } return ethereum.SyncProgress{ StartingBlock: d.syncStatsChainOrigin, @@ -363,6 +368,12 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode if atomic.CompareAndSwapInt32(&d.notified, 0, 1) { log.Info("Block synchronisation started") } + // If we are already full syncing, but have a fast-sync bloom filter laying + // around, make sure it does't use memory any more. This is a special case + // when the user attempts to fast sync a new empty network. + if mode == FullSync && d.stateBloom != nil { + d.stateBloom.Close() + } // Reset the queue, peer set and wake channels to clean any internal leftover state d.queue.Reset() d.peers.Reset() @@ -1662,6 +1673,8 @@ func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *state func (d *Downloader) commitPivotBlock(result *fetchResult) error { block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles) log.Debug("Committing fast sync pivot as new head", "number", block.Number(), "hash", block.Hash()) + + // Commit the pivot block as the new head, will require full sync from here on if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}); err != nil { return err } @@ -1669,6 +1682,15 @@ func (d *Downloader) commitPivotBlock(result *fetchResult) error { return err } atomic.StoreInt32(&d.committed, 1) + + // If we had a bloom filter for the state sync, deallocate it now. Note, we only + // deallocate internally, but keep the empty wrapper. This ensures that if we do + // a rollback after committing the pivot and restarting fast sync, we don't end + // up using a nil bloom. Empty bloom is fine, it just returns that it does not + // have the info we need, so reach down to the database instead. + if d.stateBloom != nil { + d.stateBloom.Close() + } return nil } diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index ec45eb06d..ac7f48abd 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -75,7 +75,7 @@ func newTester() *downloadTester { tester.stateDb = rawdb.NewMemoryDatabase() tester.stateDb.Put(testGenesis.Root().Bytes(), []byte{0x00}) - tester.downloader = New(FullSync, 0, tester.stateDb, new(event.TypeMux), tester, nil, tester.dropPeer) + tester.downloader = New(0, tester.stateDb, trie.NewSyncBloom(1, tester.stateDb), new(event.TypeMux), tester, nil, tester.dropPeer) return tester } diff --git a/eth/downloader/statesync.go b/eth/downloader/statesync.go index f294600b3..7e156f46e 100644 --- a/eth/downloader/statesync.go +++ b/eth/downloader/statesync.go @@ -59,6 +59,7 @@ type stateSyncStats struct { // syncState starts downloading state with the given root hash. func (d *Downloader) syncState(root common.Hash) *stateSync { + // Create the state sync s := newStateSync(d, root) select { case d.stateSyncStart <- s: @@ -239,7 +240,7 @@ type stateTask struct { func newStateSync(d *Downloader, root common.Hash) *stateSync { return &stateSync{ d: d, - sched: state.NewStateSync(root, d.stateDB), + sched: state.NewStateSync(root, d.stateDB, d.stateBloom), keccak: sha3.NewLegacyKeccak256(), tasks: make(map[common.Hash]*stateTask), deliver: make(chan *stateReq), |