diff --git a/nimbus/core/chain/forked_chain.nim b/nimbus/core/chain/forked_chain.nim index d7c3e15caf..6562ec3f1e 100644 --- a/nimbus/core/chain/forked_chain.nim +++ b/nimbus/core/chain/forked_chain.nim @@ -38,6 +38,8 @@ type header: Header CanonicalDesc = object + ## Designate some `header` entry on a `CursorDesc` sub-chain named + ## `cursorDesc` identified by `cursorHash == cursorDesc.hash`. cursorHash: Hash32 header: Header @@ -59,13 +61,31 @@ const BaseDistance = 128 # ------------------------------------------------------------------------------ -# Private +# Private helpers # ------------------------------------------------------------------------------ -template shouldNotKeyError(body: untyped) = + +template shouldNotKeyError(info: string, body: untyped) = try: body except KeyError as exc: - raiseAssert exc.msg + raiseAssert info & ": name=" & $exc.name & " msg=" & exc.msg + +proc deleteLineage(c: ForkedChainRef; top: Hash32) = + ## Starting at argument `top`, delete all entries from `c.blocks[]` along + ## the ancestor chain. + ## + var parent = top + while true: + c.blocks.withValue(parent, val): + let w = parent + parent = val.blk.header.parentHash + c.blocks.del(w) + continue + break + +# ------------------------------------------------------------------------------ +# Private functions +# ------------------------------------------------------------------------------ proc processBlock(c: ForkedChainRef, parent: Header, @@ -135,11 +155,16 @@ func updateCursor(c: ForkedChainRef, c.cursorHeader = header c.cursorHash = header.blockHash - c.blocks[c.cursorHash] = BlockDesc( - blk: blk, - receipts: move(receipts) - ) - c.updateCursorHeads(c.cursorHash, header) + + c.blocks.withValue(c.cursorHash, val): + # Block exists alrady, so update only + val.receipts = receipts + do: + # New block => update head + c.blocks[c.cursorHash] = BlockDesc( + blk: blk, + receipts: move(receipts)) + c.updateCursorHeads(c.cursorHash, header) proc validateBlock(c: ForkedChainRef, parent: Header, @@ -169,7 +194,7 @@ proc replaySegment*(c: ForkedChainRef, target: Hash32) = prevHash = target chain = newSeq[Block]() - shouldNotKeyError: + shouldNotKeyError "replaySegment(target)": while prevHash != c.baseHash: chain.add c.blocks[prevHash].blk prevHash = chain[^1].header.parentHash @@ -193,7 +218,7 @@ proc replaySegment(c: ForkedChainRef, prevHash = target chain = newSeq[Block]() - shouldNotKeyError: + shouldNotKeyError "replaySegment(target,parent)": while prevHash != parentHash: chain.add c.blocks[prevHash].blk prevHash = chain[^1].header.parentHash @@ -210,7 +235,7 @@ proc writeBaggage(c: ForkedChainRef, target: Hash32) = template header(): Header = blk.blk.header - shouldNotKeyError: + shouldNotKeyError "writeBaggage": var prevHash = target var count = 0'u64 while prevHash != c.baseHash: @@ -237,67 +262,65 @@ func updateBase(c: ForkedChainRef, newBaseHash: Hash32, newBaseHeader: Header, canonicalCursorHash: Hash32) = - var cursorHeadsLen = c.cursorHeads.len - # Remove obsolete chains, example: - # -- A1 - A2 - A3 -- D5 - D6 - # / / - # base - B1 - B2 - [B3] - B4 - # \ - # --- C3 - C4 - # If base move to B3, both A and C will be removed - # but not D - - for i in 0.. c.cursorHeader.number: @@ -668,7 +711,7 @@ proc headerByNumber*(c: ForkedChainRef, number: BlockNumber): Result[Header, str if number < c.baseHeader.number: return c.db.getBlockHeader(number) - shouldNotKeyError: + shouldNotKeyError "headerByNumber": var prevHash = c.cursorHeader.parentHash while prevHash != c.baseHash: let header = c.blocks[prevHash].blk.header @@ -702,7 +745,7 @@ proc blockByNumber*(c: ForkedChainRef, number: BlockNumber): Result[Block, strin if number < c.baseHeader.number: return c.db.getEthBlock(number) - shouldNotKeyError: + shouldNotKeyError "blockByNumber": var prevHash = c.cursorHash while prevHash != c.baseHash: c.blocks.withValue(prevHash, item): @@ -713,7 +756,7 @@ proc blockByNumber*(c: ForkedChainRef, number: BlockNumber): Result[Block, strin func blockFromBaseTo*(c: ForkedChainRef, number: BlockNumber): seq[Block] = # return block in reverse order - shouldNotKeyError: + shouldNotKeyError "blockFromBaseTo": var prevHash = c.cursorHash while prevHash != c.baseHash: c.blocks.withValue(prevHash, item): @@ -725,7 +768,7 @@ func isCanonical*(c: ForkedChainRef, blockHash: Hash32): bool = if blockHash == c.baseHash: return true - shouldNotKeyError: + shouldNotKeyError "isCanonical": var prevHash = c.cursorHash while prevHash != c.baseHash: c.blocks.withValue(prevHash, item): @@ -745,7 +788,7 @@ proc isCanonicalAncestor*(c: ForkedChainRef, if c.baseHeader.number < c.cursorHeader.number: # The current canonical chain in memory is headed by # cursorHeader - shouldNotKeyError: + shouldNotKeyError "isCanonicalAncestor": var prevHash = c.cursorHeader.parentHash while prevHash != c.baseHash: var header = c.blocks[prevHash].blk.header diff --git a/nimbus/sync/beacon/TODO.md b/nimbus/sync/beacon/TODO.md index 983bb81cc6..9bf37d5cac 100644 --- a/nimbus/sync/beacon/TODO.md +++ b/nimbus/sync/beacon/TODO.md @@ -8,19 +8,7 @@ See issue [#2816](https://github.com/status-im/nimbus-eth1/issues/2816) -### 2. Some assert - - Error: unhandled exception: key not found: 0x441a0f..027bc96a [AssertionDefect] - -which happened on several `holesky` tests immediately after loging somehing like - - NTC 2024-10-31 21:37:34.728 Finalized blocks persisted file=forked_chain.nim:231 numberOfBlocks=129 last=044d22843cbe baseNumber=2646764 baseHash=21ec11c1deac - -or from another machine with literally the same exception text (but the stack-trace differs) - - NTC 2024-10-31 21:58:07.616 Finalized blocks persisted file=forked_chain.nim:231 numberOfBlocks=129 last=9cbcc52953a8 baseNumber=2646857 baseHash=9db5c2ac537b - -### 3. Mem overflow possible on small breasted systems +### 2. Mem overflow possible on small breasted systems Running the exe client, a 1.5G response message was opbserved (on my 8G test system this kills the program as it has already 80% mem load. It happens while syncing holesky at around block #184160 and is reproducible on the 8G system but not yet on the an 80G system.) diff --git a/nimbus/sync/beacon/worker.nim b/nimbus/sync/beacon/worker.nim index a347393318..eb327b33f9 100644 --- a/nimbus/sync/beacon/worker.nim +++ b/nimbus/sync/beacon/worker.nim @@ -87,7 +87,7 @@ proc start*(buddy: BeaconBuddyRef; info: static[string]): bool = proc stop*(buddy: BeaconBuddyRef; info: static[string]) = ## Clean up this peer if not buddy.ctx.hibernate: debug info & ": release peer", peer=buddy.peer, - ctrl=buddy.ctrl.state, nInvocations=buddy.only.nMultiLoop, + ctrl=buddy.ctrl.state, nLaps=buddy.only.nMultiLoop, lastIdleGap=buddy.only.multiRunIdle.toStr buddy.stopBuddy() diff --git a/nimbus/sync/beacon/worker/blocks_staged.nim b/nimbus/sync/beacon/worker/blocks_staged.nim index c2152b7100..b898d8a372 100644 --- a/nimbus/sync/beacon/worker/blocks_staged.nim +++ b/nimbus/sync/beacon/worker/blocks_staged.nim @@ -25,7 +25,7 @@ import # ------------------------------------------------------------------------------ formatIt(Hash32): - it.data.short + it.short # ------------------------------------------------------------------------------ # Private functions diff --git a/nimbus/sync/beacon/worker/start_stop/ticker.nim b/nimbus/sync/beacon/worker/start_stop/ticker.nim index 07e543ad74..963bc15e54 100644 --- a/nimbus/sync/beacon/worker/start_stop/ticker.nim +++ b/nimbus/sync/beacon/worker/start_stop/ticker.nim @@ -89,12 +89,16 @@ proc tickerLogger(t: TickerRef) {.gcsafe.} = 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 & ")"