2019-02-06 16:01:04 +00:00
|
|
|
import times, chronos
|
2019-02-05 15:40:29 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
FullNodeSyncer* = ref object
|
|
|
|
chaindb: ChainDB
|
|
|
|
FastChainSyncer = ref object
|
|
|
|
RegularChainSyncer = ref object
|
|
|
|
|
|
|
|
# How old (in seconds) must our local head be to cause us to start with a fast-sync before we
|
|
|
|
# switch to regular-sync.
|
|
|
|
const FAST_SYNC_CUTOFF = 60 * 60 * 24
|
|
|
|
|
|
|
|
|
|
|
|
proc run(s: FullNodeSyncer) {.async.} =
|
|
|
|
let head = await s.chaindb.getCanonicalHead()
|
|
|
|
|
|
|
|
# We're still too slow at block processing, so if our local head is older than
|
|
|
|
# FAST_SYNC_CUTOFF we first do a fast-sync run to catch up with the rest of the network.
|
|
|
|
# See https://github.com/ethereum/py-evm/issues/654 for more details
|
|
|
|
if head.timestamp < epochTime() - FAST_SYNC_CUTOFF:
|
|
|
|
# Fast-sync chain data.
|
|
|
|
self.logger.info("Starting fast-sync; current head: #%d", head.block_number)
|
|
|
|
chain_syncer = FastChainSyncer(self.chaindb, self.peer_pool, self.cancel_token)
|
|
|
|
await chain_syncer.run()
|
|
|
|
|
|
|
|
# Ensure we have the state for our current head.
|
|
|
|
head = await self.wait(self.chaindb.coro_get_canonical_head())
|
|
|
|
if head.state_root != BLANK_ROOT_HASH and head.state_root not in self.base_db:
|
|
|
|
self.logger.info(
|
|
|
|
"Missing state for current head (#%d), downloading it", head.block_number)
|
|
|
|
downloader = StateDownloader(
|
|
|
|
self.base_db, head.state_root, self.peer_pool, self.cancel_token)
|
|
|
|
await downloader.run()
|
|
|
|
|
|
|
|
# Now, loop forever, fetching missing blocks and applying them.
|
|
|
|
self.logger.info("Starting regular sync; current head: #%d", head.block_number)
|
|
|
|
# This is a bit of a hack, but self.chain is stuck in the past as during the fast-sync we
|
|
|
|
# did not use it to import the blocks, so we need this to get a Chain instance with our
|
|
|
|
# latest head so that we can start importing blocks.
|
|
|
|
new_chain = type(self.chain)(self.base_db)
|
|
|
|
chain_syncer = RegularChainSyncer(
|
|
|
|
new_chain, self.chaindb, self.peer_pool, self.cancel_token)
|
|
|
|
await chain_syncer.run()
|