mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-21 09:39:09 +00:00
dd888deadb
* Cosmetics, update log and exception messages * Update `FC` base tree updater `updateBase()` why: Correct `forkJunction` of canonical cursor head record. When moving the `base`, this field would be below `base` unless updated. * Fix `FC` chain selector `findCanonicalHead()` why: Given a sample ref `hash` the function searched for the unique chain containing the block header referenced by `hash`. Unfortunately, when searching down the ancestry lineage, the function did not necessarily stop an the end of the sub-chain. Rather it continued with the parent chain without noticing. So returning the wrong result. * When calculating new a base it must reside on cursor arc (or leg.) why: The finalised block argument (that will eventually be the new base) might be moved further down the cursor arc if it is too close to the cursor head (typically smaller than 128 blocks.) So the finalised block selection is shifted down he cursor arc. And it might happen that the cursor arc itself is too small and one would end up at a parent cursor arc. This is rejected. * Not starting a new cursor arc with a block already on another arc why: This leads to an inconsistent set of cursor arcs which are supposed to be mutually disjunct. * Tighten condition: A block that is not on the base tree must be on the DB * One less TODO item
156 lines
5.2 KiB
Nim
156 lines
5.2 KiB
Nim
# Nimbus - Fetch account and storage states from peers efficiently
|
|
#
|
|
# Copyright (c) 2021-2024 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * 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.
|
|
|
|
{.push raises: [].}
|
|
|
|
import
|
|
std/strutils,
|
|
pkg/[chronos, chronicles, eth/common, stint],
|
|
../../../../utils/prettify,
|
|
../helpers
|
|
|
|
logScope:
|
|
topics = "beacon ticker"
|
|
|
|
type
|
|
TickerStatsUpdater* = proc: TickerStats {.gcsafe, raises: [].}
|
|
## Full sync state update function
|
|
|
|
TickerStats* = object
|
|
## Full sync state (see `TickerFullStatsUpdater`)
|
|
base*: BlockNumber
|
|
latest*: BlockNumber
|
|
coupler*: BlockNumber
|
|
dangling*: BlockNumber
|
|
head*: BlockNumber
|
|
headOk*: bool
|
|
target*: BlockNumber
|
|
targetOk*: bool
|
|
|
|
hdrUnprocTop*: BlockNumber
|
|
nHdrUnprocessed*: uint64
|
|
nHdrUnprocFragm*: int
|
|
nHdrStaged*: int
|
|
hdrStagedTop*: BlockNumber
|
|
|
|
blkUnprocBottom*: BlockNumber
|
|
nBlkUnprocessed*: uint64
|
|
nBlkUnprocFragm*: int
|
|
nBlkStaged*: int
|
|
blkStagedBottom*: BlockNumber
|
|
|
|
reorg*: int
|
|
nBuddies*: int
|
|
|
|
TickerRef* = ref object
|
|
## Ticker descriptor object
|
|
started: Moment
|
|
visited: Moment
|
|
prettyPrint: proc(t: TickerRef) {.gcsafe, raises: [].}
|
|
statsCb: TickerStatsUpdater
|
|
lastStats: TickerStats
|
|
|
|
const
|
|
tickerStartDelay = chronos.milliseconds(100)
|
|
tickerLogInterval = chronos.seconds(1)
|
|
tickerLogSuppressMax = chronos.seconds(100)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private functions: printing ticker messages
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc tickerLogger(t: TickerRef) {.gcsafe.} =
|
|
let
|
|
data = t.statsCb()
|
|
now = Moment.now()
|
|
|
|
if data != t.lastStats or
|
|
tickerLogSuppressMax < (now - t.visited):
|
|
let
|
|
B = if data.base == data.latest: "L" else: data.base.bnStr
|
|
L = if data.latest == data.coupler: "C" else: data.latest.bnStr
|
|
C = if data.coupler == data.dangling: "D" else: data.coupler.bnStr
|
|
D = if data.dangling == data.head: "H"
|
|
else: data.dangling.bnStr
|
|
H = if data.headOk:
|
|
if data.head == data.target: "T" else: data.head.bnStr
|
|
else:
|
|
if data.head == data.target: "?T" else: "?" & $data.head
|
|
T = if data.targetOk: data.target.bnStr else: "?" & $data.target
|
|
|
|
hS = if data.nHdrStaged == 0: "n/a"
|
|
else: data.hdrStagedTop.bnStr & "(" & $data.nHdrStaged & ")"
|
|
hU = if data.nHdrUnprocFragm == 0 and data.nHdrUnprocessed == 0: "n/a"
|
|
elif data.hdrUnprocTop == 0:
|
|
"(" & data.nHdrUnprocessed.toSI & "," & $data.nHdrUnprocFragm & ")"
|
|
else: data.hdrUnprocTop.bnStr & "(" &
|
|
data.nHdrUnprocessed.toSI & "," & $data.nHdrUnprocFragm & ")"
|
|
|
|
bS = if data.nBlkStaged == 0: "n/a"
|
|
else: data.blkStagedBottom.bnStr & "(" & $data.nBlkStaged & ")"
|
|
bU = if data.nBlkUnprocFragm == 0 and data.nBlkUnprocessed == 0: "n/a"
|
|
elif data.blkUnprocBottom == high(BlockNumber):
|
|
"(" & data.nBlkUnprocessed.toSI & "," & $data.nBlkUnprocFragm & ")"
|
|
else: data.blkUnprocBottom.bnStr & "(" &
|
|
data.nBlkUnprocessed.toSI & "," & $data.nBlkUnprocFragm & ")"
|
|
|
|
rrg = data.reorg
|
|
peers = data.nBuddies
|
|
|
|
# With `int64`, there are more than 29*10^10 years range for seconds
|
|
up = (now - t.started).seconds.uint64.toSI
|
|
mem = getTotalMem().uint.toSI
|
|
|
|
t.lastStats = data
|
|
t.visited = now
|
|
|
|
debug "Sync state", up, peers, B, L, C, D, H, T, hS, hU, bS, bU, rrg, mem
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private functions: ticking log messages
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc setLogTicker(t: TickerRef; at: Moment) {.gcsafe.}
|
|
|
|
proc runLogTicker(t: TickerRef) {.gcsafe.} =
|
|
if not t.statsCb.isNil:
|
|
t.prettyPrint(t)
|
|
t.setLogTicker(Moment.fromNow(tickerLogInterval))
|
|
|
|
proc setLogTicker(t: TickerRef; at: Moment) =
|
|
if t.statsCb.isNil:
|
|
debug "Ticker stopped"
|
|
else:
|
|
# Store the `runLogTicker()` in a closure to avoid some garbage collection
|
|
# memory corruption issues that might occur otherwise.
|
|
discard setTimer(at, proc(ign: pointer) = runLogTicker(t))
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public constructor and start/stop functions
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc init*(T: type TickerRef; cb: TickerStatsUpdater): T =
|
|
## Constructor
|
|
result = TickerRef(
|
|
prettyPrint: tickerLogger,
|
|
statsCb: cb,
|
|
started: Moment.now())
|
|
result.setLogTicker Moment.fromNow(tickerStartDelay)
|
|
|
|
proc destroy*(t: TickerRef) =
|
|
## Stop ticker unconditionally
|
|
if not t.isNil:
|
|
t.statsCb = TickerStatsUpdater(nil)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# End
|
|
# ------------------------------------------------------------------------------
|