2022-08-04 08:04:30 +00:00
|
|
|
# Nimbus
|
2022-05-09 14:04:48 +00:00
|
|
|
# Copyright (c) 2021 Status Research & Development GmbH
|
|
|
|
# Licensed under either of
|
2022-05-13 16:30:10 +00:00
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
|
|
# http://opensource.org/licenses/MIT)
|
|
|
|
# at your option. This file may not be copied, modified, or distributed
|
|
|
|
# except according to those terms.
|
2022-05-09 14:04:48 +00:00
|
|
|
|
|
|
|
import
|
2022-10-19 10:04:06 +00:00
|
|
|
std/[hashes, math, options, sets, strutils],
|
2022-05-17 11:09:49 +00:00
|
|
|
chronicles,
|
|
|
|
chronos,
|
2022-08-04 08:04:30 +00:00
|
|
|
eth/[common/eth_types, p2p],
|
|
|
|
stew/[interval_set, keyed_queue],
|
2022-08-12 15:42:07 +00:00
|
|
|
../../db/select_backend,
|
2022-10-19 14:03:55 +00:00
|
|
|
".."/[handlers, misc/best_pivot, protocol, sync_desc],
|
2022-10-19 10:04:06 +00:00
|
|
|
./worker/[heal_accounts, heal_storages, store_accounts, store_storages,
|
|
|
|
ticker],
|
2022-10-08 17:20:50 +00:00
|
|
|
./worker/com/[com_error, get_block_header],
|
2022-10-14 16:40:32 +00:00
|
|
|
./worker/db/snapdb_desc,
|
2022-08-04 08:04:30 +00:00
|
|
|
"."/[range_desc, worker_desc]
|
2022-05-24 08:07:39 +00:00
|
|
|
|
2022-09-16 07:24:12 +00:00
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
2022-05-23 16:53:19 +00:00
|
|
|
logScope:
|
2022-08-04 08:04:30 +00:00
|
|
|
topics = "snap-sync"
|
2022-05-23 16:53:19 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
const
|
|
|
|
extraTraceMessages = false or true
|
|
|
|
## Enabled additional logging noise
|
|
|
|
|
2022-05-24 08:07:39 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Private helpers
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
proc meanStdDev(sum, sqSum: float; length: int): (float,float) =
|
|
|
|
if 0 < length:
|
|
|
|
result[0] = sum / length.float
|
|
|
|
result[1] = sqrt(sqSum / length.float - result[0] * result[0])
|
2022-05-17 11:09:49 +00:00
|
|
|
|
2022-08-24 13:44:18 +00:00
|
|
|
template noExceptionOops(info: static[string]; code: untyped) =
|
|
|
|
try:
|
|
|
|
code
|
|
|
|
except CatchableError as e:
|
|
|
|
raiseAssert "Inconveivable (" & info & ": name=" & $e.name & " msg=" & e.msg
|
|
|
|
except Defect as e:
|
|
|
|
raise e
|
|
|
|
except Exception as e:
|
|
|
|
raiseAssert "Ooops " & info & ": name=" & $e.name & " msg=" & e.msg
|
|
|
|
|
2022-09-30 08:22:14 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
2022-10-08 17:20:50 +00:00
|
|
|
# Private helpers: integration of pivot finder
|
2022-09-30 08:22:14 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2022-10-19 14:03:55 +00:00
|
|
|
proc pivot(ctx: SnapCtxRef): BestPivotCtxRef =
|
2022-10-08 17:20:50 +00:00
|
|
|
# Getter
|
2022-10-19 14:03:55 +00:00
|
|
|
ctx.data.pivotFinderCtx.BestPivotCtxRef
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-19 14:03:55 +00:00
|
|
|
proc `pivot=`(ctx: SnapCtxRef; val: BestPivotCtxRef) =
|
2022-10-08 17:20:50 +00:00
|
|
|
# Setter
|
|
|
|
ctx.data.pivotFinderCtx = val
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-19 14:03:55 +00:00
|
|
|
proc pivot(buddy: SnapBuddyRef): BestPivotWorkerRef =
|
2022-10-08 17:20:50 +00:00
|
|
|
# Getter
|
2022-10-19 14:03:55 +00:00
|
|
|
buddy.data.pivotFinder.BestPivotWorkerRef
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-19 14:03:55 +00:00
|
|
|
proc `pivot=`(buddy: SnapBuddyRef; val: BestPivotWorkerRef) =
|
2022-10-08 17:20:50 +00:00
|
|
|
# Setter
|
|
|
|
buddy.data.pivotFinder = val
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Private functions
|
|
|
|
# ------------------------------------------------------------------------------
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-14 16:40:32 +00:00
|
|
|
proc init(batch: var SnapTrieRangeBatch; ctx: SnapCtxRef) =
|
|
|
|
## Returns a pair of account hash range lists with the full range of hashes
|
|
|
|
## smartly spread across the mutually disjunct interval sets.
|
|
|
|
for n in 0 ..< batch.unprocessed.len:
|
|
|
|
batch.unprocessed[n] = NodeTagRangeSet.init()
|
2022-10-08 17:20:50 +00:00
|
|
|
|
|
|
|
# Initialise accounts range fetch batch, the pair of `fetchAccounts[]`
|
|
|
|
# range sets.
|
|
|
|
if ctx.data.coveredAccounts.total == 0 and
|
|
|
|
ctx.data.coveredAccounts.chunks == 1:
|
2022-10-14 16:40:32 +00:00
|
|
|
# All (i.e. 100%) of accounts hashes are covered by completed range fetch
|
|
|
|
# processes for all pivot environments. Do a random split distributing the
|
|
|
|
# full accounts hash range across the pair of range sats.
|
2022-10-08 17:20:50 +00:00
|
|
|
var nodeKey: NodeKey
|
|
|
|
ctx.data.rng[].generate(nodeKey.ByteArray32)
|
|
|
|
|
|
|
|
let partition = nodeKey.to(NodeTag)
|
2022-10-14 16:40:32 +00:00
|
|
|
discard batch.unprocessed[0].merge(partition, high(NodeTag))
|
2022-10-08 17:20:50 +00:00
|
|
|
if low(NodeTag) < partition:
|
2022-10-14 16:40:32 +00:00
|
|
|
discard batch.unprocessed[1].merge(low(NodeTag), partition - 1.u256)
|
2022-09-30 08:22:14 +00:00
|
|
|
else:
|
2022-10-08 17:20:50 +00:00
|
|
|
# Not all account hashes are covered, yet. So keep the uncovered
|
|
|
|
# account hashes in the first range set, and the other account hashes
|
|
|
|
# in the second range set.
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
# Pre-filled with the first range set with largest possible interval
|
2022-10-14 16:40:32 +00:00
|
|
|
discard batch.unprocessed[0].merge(low(NodeTag),high(NodeTag))
|
2022-09-30 08:22:14 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
# Move covered account ranges (aka intervals) to the second set.
|
|
|
|
for iv in ctx.data.coveredAccounts.increasing:
|
2022-10-14 16:40:32 +00:00
|
|
|
discard batch.unprocessed[0].reduce(iv)
|
|
|
|
discard batch.unprocessed[1].merge(iv)
|
2022-05-17 11:09:49 +00:00
|
|
|
|
2022-06-06 13:42:08 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
proc appendPivotEnv(buddy: SnapBuddyRef; header: BlockHeader) =
|
|
|
|
## Activate environment for state root implied by `header` argument. This
|
|
|
|
## function appends a new environment unless there was any not far enough
|
|
|
|
## apart.
|
|
|
|
##
|
|
|
|
## Note that this function relies on a queue sorted by the block numbers of
|
|
|
|
## the pivot header. To maintain the sort order, the function `lruFetch()`
|
|
|
|
## must not be called and only records appended with increasing block
|
|
|
|
## numbers.
|
|
|
|
let
|
|
|
|
ctx = buddy.ctx
|
|
|
|
minNumber = block:
|
|
|
|
let rc = ctx.data.pivotTable.lastValue
|
|
|
|
if rc.isOk: rc.value.stateHeader.blockNumber + minPivotBlockDistance
|
|
|
|
else: 1.toBlockNumber
|
|
|
|
|
|
|
|
# Check whether the new header follows minimum depth requirement. This is
|
|
|
|
# where the queue is assumed to have increasing block numbers.
|
|
|
|
if minNumber <= header.blockNumber:
|
|
|
|
# Ok, append a new environment
|
2022-10-14 16:40:32 +00:00
|
|
|
let env = SnapPivotRef(stateHeader: header)
|
|
|
|
env.fetchAccounts.init(ctx)
|
2022-10-08 17:20:50 +00:00
|
|
|
|
|
|
|
# Append per-state root environment to LRU queue
|
|
|
|
discard ctx.data.pivotTable.lruAppend(header.stateRoot, env, ctx.buddiesMax)
|
|
|
|
|
|
|
|
|
2022-10-19 14:03:55 +00:00
|
|
|
proc updateSinglePivot(buddy: SnapBuddyRef): Future[bool] {.async.} =
|
2022-10-08 17:20:50 +00:00
|
|
|
## Helper, negotiate pivot unless present
|
|
|
|
if buddy.pivot.pivotHeader.isOk:
|
|
|
|
return true
|
2022-06-06 13:42:08 +00:00
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
let
|
|
|
|
ctx = buddy.ctx
|
2022-10-08 17:20:50 +00:00
|
|
|
peer = buddy.peer
|
|
|
|
env = ctx.data.pivotTable.lastValue.get(otherwise = nil)
|
|
|
|
nMin = if env.isNil: none(BlockNumber)
|
|
|
|
else: some(env.stateHeader.blockNumber)
|
|
|
|
|
|
|
|
if await buddy.pivot.pivotNegotiate(nMin):
|
|
|
|
var header = buddy.pivot.pivotHeader.value
|
|
|
|
|
|
|
|
# Check whether there is no environment change needed
|
|
|
|
when noPivotEnvChangeIfComplete:
|
|
|
|
let rc = ctx.data.pivotTable.lastValue
|
|
|
|
if rc.isOk and rc.value.serialSync:
|
|
|
|
# No neede to change
|
|
|
|
if extraTraceMessages:
|
|
|
|
trace "No need to change snap pivot", peer,
|
|
|
|
pivot=("#" & $rc.value.stateHeader.blockNumber),
|
|
|
|
multiOk=buddy.ctrl.multiOk, runState=buddy.ctrl.state
|
|
|
|
return true
|
|
|
|
|
|
|
|
when 0 < backPivotBlockDistance:
|
|
|
|
# Backtrack, do not use the very latest pivot header
|
|
|
|
if backPivotBlockThreshold.toBlockNumber < header.blockNumber:
|
|
|
|
let
|
|
|
|
backNum = header.blockNumber - backPivotBlockDistance.toBlockNumber
|
|
|
|
rc = await buddy.getBlockHeader(backNum)
|
|
|
|
if rc.isErr:
|
|
|
|
if rc.error in {ComNoHeaderAvailable, ComTooManyHeaders}:
|
|
|
|
buddy.ctrl.zombie = true
|
|
|
|
return false
|
|
|
|
header = rc.value
|
|
|
|
|
|
|
|
buddy.appendPivotEnv(header)
|
|
|
|
|
|
|
|
trace "Snap pivot initialised", peer, pivot=("#" & $header.blockNumber),
|
|
|
|
multiOk=buddy.ctrl.multiOk, runState=buddy.ctrl.state
|
|
|
|
|
2022-09-16 07:24:12 +00:00
|
|
|
return true
|
2022-08-04 08:04:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
proc tickerUpdate*(ctx: SnapCtxRef): TickerStatsUpdater =
|
|
|
|
result = proc: TickerStats =
|
|
|
|
var
|
2022-10-19 10:04:06 +00:00
|
|
|
aSum, aSqSum, uSum, uSqSum, sSum, sSqSum, wSum, wSqSum: float
|
2022-08-04 08:04:30 +00:00
|
|
|
count = 0
|
|
|
|
for kvp in ctx.data.pivotTable.nextPairs:
|
|
|
|
|
|
|
|
# Accounts mean & variance
|
|
|
|
let aLen = kvp.data.nAccounts.float
|
|
|
|
if 0 < aLen:
|
|
|
|
count.inc
|
|
|
|
aSum += aLen
|
|
|
|
aSqSum += aLen * aLen
|
|
|
|
|
|
|
|
# Fill utilisation mean & variance
|
2022-10-14 16:40:32 +00:00
|
|
|
let fill = kvp.data.fetchAccounts.unprocessed.emptyFactor
|
2022-08-04 08:04:30 +00:00
|
|
|
uSum += fill
|
|
|
|
uSqSum += fill * fill
|
|
|
|
|
2022-09-02 18:16:09 +00:00
|
|
|
let sLen = kvp.data.nStorage.float
|
|
|
|
sSum += sLen
|
|
|
|
sSqSum += sLen * sLen
|
|
|
|
|
2022-10-19 10:04:06 +00:00
|
|
|
# Storage queue size for that account
|
|
|
|
var stoFill: float
|
|
|
|
for stoKvp in kvp.data.fetchStorage.nextPairs:
|
|
|
|
if stoKvp.data.slots.isNil:
|
|
|
|
stoFill += 1.0
|
|
|
|
else:
|
|
|
|
stoFill += stoKvp.data.slots.unprocessed.fullFactor
|
|
|
|
wSum += stoFill
|
|
|
|
wSqSum += stoFill * stoFill
|
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
let
|
2022-10-08 17:20:50 +00:00
|
|
|
env = ctx.data.pivotTable.lastValue.get(otherwise = nil)
|
|
|
|
pivotBlock = if env.isNil: none(BlockNumber)
|
|
|
|
else: some(env.stateHeader.blockNumber)
|
2022-08-24 13:44:18 +00:00
|
|
|
accCoverage = ctx.data.coveredAccounts.fullFactor
|
2022-09-02 18:16:09 +00:00
|
|
|
accFill = meanStdDev(uSum, uSqSum, count)
|
2022-08-24 13:44:18 +00:00
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
TickerStats(
|
|
|
|
pivotBlock: pivotBlock,
|
2022-10-08 17:20:50 +00:00
|
|
|
nQueues: ctx.data.pivotTable.len,
|
2022-09-02 18:16:09 +00:00
|
|
|
nAccounts: meanStdDev(aSum, aSqSum, count),
|
|
|
|
nStorage: meanStdDev(sSum, sSqSum, count),
|
2022-10-19 10:04:06 +00:00
|
|
|
accountsFill: (accFill[0], accFill[1], accCoverage),
|
|
|
|
storageQueue: meanStdDev(wSum, wSqSum, count))
|
2022-06-06 13:42:08 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public start/stop and admin functions
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
proc setup*(ctx: SnapCtxRef; tickerOK: bool): bool =
|
2022-06-06 13:42:08 +00:00
|
|
|
## Global set up
|
2022-10-19 10:04:06 +00:00
|
|
|
noExceptionOops("worker.setup()"):
|
|
|
|
ctx.ethWireCtx.poolEnabled(false)
|
2022-10-14 16:40:32 +00:00
|
|
|
ctx.data.coveredAccounts = NodeTagRangeSet.init()
|
2022-10-08 17:20:50 +00:00
|
|
|
ctx.data.snapDb =
|
2022-10-10 02:31:28 +00:00
|
|
|
if ctx.data.dbBackend.isNil: SnapDbRef.init(ctx.chain.db.db)
|
2022-10-08 17:20:50 +00:00
|
|
|
else: SnapDbRef.init(ctx.data.dbBackend)
|
2022-10-19 14:03:55 +00:00
|
|
|
ctx.pivot = BestPivotCtxRef.init(ctx.data.rng)
|
2022-08-04 08:04:30 +00:00
|
|
|
if tickerOK:
|
|
|
|
ctx.data.ticker = TickerRef.init(ctx.tickerUpdate)
|
|
|
|
else:
|
|
|
|
trace "Ticker is disabled"
|
2022-08-24 13:44:18 +00:00
|
|
|
result = true
|
2022-08-04 08:04:30 +00:00
|
|
|
|
|
|
|
proc release*(ctx: SnapCtxRef) =
|
2022-06-06 13:42:08 +00:00
|
|
|
## Global clean up
|
2022-10-19 14:03:55 +00:00
|
|
|
ctx.pivot = nil
|
2022-08-04 08:04:30 +00:00
|
|
|
if not ctx.data.ticker.isNil:
|
|
|
|
ctx.data.ticker.stop()
|
|
|
|
ctx.data.ticker = nil
|
2022-06-16 08:58:50 +00:00
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
proc start*(buddy: SnapBuddyRef): bool =
|
|
|
|
## Initialise worker peer
|
|
|
|
let
|
|
|
|
ctx = buddy.ctx
|
|
|
|
peer = buddy.peer
|
|
|
|
if peer.supports(protocol.snap) and
|
|
|
|
peer.supports(protocol.eth) and
|
|
|
|
peer.state(protocol.eth).initialized:
|
2022-10-19 14:03:55 +00:00
|
|
|
buddy.pivot = BestPivotWorkerRef.init(
|
|
|
|
buddy.ctx.pivot, buddy.ctrl, buddy.peer)
|
2022-10-08 17:20:50 +00:00
|
|
|
buddy.data.errors = ComErrorStatsRef()
|
2022-08-04 08:04:30 +00:00
|
|
|
if not ctx.data.ticker.isNil:
|
|
|
|
ctx.data.ticker.startBuddy()
|
2022-06-06 13:42:08 +00:00
|
|
|
return true
|
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
proc stop*(buddy: SnapBuddyRef) =
|
2022-06-06 13:42:08 +00:00
|
|
|
## Clean up this peer
|
2022-08-04 08:04:30 +00:00
|
|
|
let
|
|
|
|
ctx = buddy.ctx
|
|
|
|
peer = buddy.peer
|
|
|
|
buddy.ctrl.stopped = true
|
2022-10-19 14:03:55 +00:00
|
|
|
buddy.pivot.clear()
|
2022-08-04 08:04:30 +00:00
|
|
|
if not ctx.data.ticker.isNil:
|
|
|
|
ctx.data.ticker.stopBuddy()
|
2022-06-06 13:42:08 +00:00
|
|
|
|
2022-05-17 11:09:49 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
proc runSingle*(buddy: SnapBuddyRef) {.async.} =
|
|
|
|
## This peer worker is invoked if the peer-local flag `buddy.ctrl.multiOk`
|
|
|
|
## is set `false` which is the default mode. This flag is updated by the
|
|
|
|
## worker when deemed appropriate.
|
|
|
|
## * For all workers, there can be only one `runSingle()` function active
|
|
|
|
## simultaneously for all worker peers.
|
|
|
|
## * There will be no `runMulti()` function active for the same worker peer
|
|
|
|
## simultaneously
|
|
|
|
## * There will be no `runPool()` iterator active simultaneously.
|
2022-05-09 14:04:48 +00:00
|
|
|
##
|
2022-08-04 08:04:30 +00:00
|
|
|
## Note that this function runs in `async` mode.
|
2022-05-09 14:04:48 +00:00
|
|
|
##
|
2022-10-19 14:03:55 +00:00
|
|
|
let peer = buddy.peer
|
|
|
|
# This pivot finder one harmonises assigned difficulties of at least two
|
|
|
|
# peers. There can only be one `pivot2Exec()` instance active/unfinished
|
|
|
|
# (which is wrapped into the helper function `updateSinglePivot()`.)
|
|
|
|
if not await buddy.updateSinglePivot():
|
|
|
|
# Wait if needed, then return => repeat
|
|
|
|
if not buddy.ctrl.stopped:
|
|
|
|
await sleepAsync(2.seconds)
|
|
|
|
return
|
2022-10-08 17:20:50 +00:00
|
|
|
|
|
|
|
buddy.ctrl.multiOk = true
|
2022-05-09 14:04:48 +00:00
|
|
|
|
|
|
|
|
2022-08-24 13:44:18 +00:00
|
|
|
proc runPool*(buddy: SnapBuddyRef, last: bool) =
|
2022-08-04 08:04:30 +00:00
|
|
|
## Ocne started, the function `runPool()` is called for all worker peers in
|
|
|
|
## a row (as the body of an iteration.) There will be no other worker peer
|
|
|
|
## functions activated simultaneously.
|
|
|
|
##
|
|
|
|
## This procedure is started if the global flag `buddy.ctx.poolMode` is set
|
|
|
|
## `true` (default is `false`.) It is the responsibility of the `runPool()`
|
|
|
|
## instance to reset the flag `buddy.ctx.poolMode`, typically at the first
|
2022-08-24 13:44:18 +00:00
|
|
|
## peer instance.
|
|
|
|
##
|
|
|
|
## The argument `last` is set `true` if the last entry is reached.
|
2022-08-04 08:04:30 +00:00
|
|
|
##
|
|
|
|
## Note that this function does not run in `async` mode.
|
|
|
|
##
|
2022-08-24 13:44:18 +00:00
|
|
|
let ctx = buddy.ctx
|
|
|
|
if ctx.poolMode:
|
|
|
|
ctx.poolMode = false
|
2022-10-08 17:20:50 +00:00
|
|
|
|
|
|
|
let rc = ctx.data.pivotTable.lastValue
|
|
|
|
if rc.isOk:
|
|
|
|
# Check whether accounts and storage might be complete.
|
|
|
|
let env = rc.value
|
|
|
|
if not env.serialSync:
|
|
|
|
# Check whether accounts download is complete
|
|
|
|
block checkAccountsComplete:
|
2022-10-14 16:40:32 +00:00
|
|
|
for ivSet in env.fetchAccounts.unprocessed:
|
2022-10-08 17:20:50 +00:00
|
|
|
if ivSet.chunks != 0:
|
|
|
|
break checkAccountsComplete
|
|
|
|
env.accountsDone = true
|
|
|
|
# Check whether storage slots are complete
|
|
|
|
if env.fetchStorage.len == 0:
|
|
|
|
env.serialSync = true
|
2022-05-09 14:04:48 +00:00
|
|
|
|
2022-05-17 11:09:49 +00:00
|
|
|
|
2022-08-04 08:04:30 +00:00
|
|
|
proc runMulti*(buddy: SnapBuddyRef) {.async.} =
|
|
|
|
## This peer worker is invoked if the `buddy.ctrl.multiOk` flag is set
|
|
|
|
## `true` which is typically done after finishing `runSingle()`. This
|
|
|
|
## instance can be simultaneously active for all peer workers.
|
|
|
|
##
|
|
|
|
let
|
|
|
|
ctx = buddy.ctx
|
|
|
|
peer = buddy.peer
|
2022-08-24 13:44:18 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
# Set up current state root environment for accounts snapshot
|
|
|
|
let env = block:
|
|
|
|
let rc = ctx.data.pivotTable.lastValue
|
|
|
|
if rc.isErr:
|
|
|
|
return # nothing to do
|
|
|
|
rc.value
|
2022-09-16 07:24:12 +00:00
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
buddy.data.pivotEnv = env
|
|
|
|
|
|
|
|
if env.serialSync:
|
|
|
|
trace "Snap serial sync -- not implemented yet", peer
|
|
|
|
await sleepAsync(5.seconds)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# Snapshot sync processing. Note that *serialSync => accountsDone*.
|
|
|
|
await buddy.storeAccounts()
|
2022-10-14 16:40:32 +00:00
|
|
|
if buddy.ctrl.stopped: return
|
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
await buddy.storeStorages()
|
2022-10-14 16:40:32 +00:00
|
|
|
if buddy.ctrl.stopped: return
|
2022-10-08 17:20:50 +00:00
|
|
|
|
2022-10-19 10:04:06 +00:00
|
|
|
# Pivot might have changed, so restart with the latest one
|
|
|
|
if env != ctx.data.pivotTable.lastValue.value: return
|
|
|
|
|
2022-10-08 17:20:50 +00:00
|
|
|
# If the current database is not complete yet
|
2022-10-14 16:40:32 +00:00
|
|
|
if 0 < env.fetchAccounts.unprocessed[0].chunks or
|
|
|
|
0 < env.fetchAccounts.unprocessed[1].chunks:
|
2022-10-08 17:20:50 +00:00
|
|
|
|
2022-10-19 10:04:06 +00:00
|
|
|
await buddy.healAccountsDb()
|
|
|
|
if buddy.ctrl.stopped: return
|
2022-10-08 17:20:50 +00:00
|
|
|
|
2022-10-19 10:04:06 +00:00
|
|
|
await buddy.healStoragesDb()
|
|
|
|
if buddy.ctrl.stopped: return
|
2022-10-08 17:20:50 +00:00
|
|
|
|
|
|
|
# Check whether accounts might be complete.
|
|
|
|
if env.fetchStorage.len == 0:
|
|
|
|
# Possibly done but some buddies might wait for an account range to be
|
|
|
|
# received from the network. So we need to sync.
|
|
|
|
buddy.ctx.poolMode = true
|
2022-05-23 16:53:19 +00:00
|
|
|
|
2022-05-17 11:09:49 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|