main: backport per-peer pindexBestKnownBlock tracking into CNodeState (enables Sync Height) #18

Closed
opened 2026-06-06 23:00:05 +00:00 by dobbscoin · 0 comments
dobbscoin commented 2026-06-06 23:00:05 +00:00

Do-not-merge-pre-Codex. Tracked here for post-fork implementation. Companion to #15 (Peers tab polish — drops the unused Sync Height widgets) and #13 (the Peers tab itself).

What's missing

(BOB)'s CNodeState (dobbscoin-source/src/main.cpp:252) carries a CBlockIndex *pindexBestKnownBlock per peer — the highest-known block index of that peer based on the headers / inv messages they've sent. Modern upstream block-sync uses it for FindNextBlocksToDownload() (deciding which peer to ask for which blocks).

OFF's CNodeState (src/main.cpp:206) is the older 0.10-era shape — no pindexBestKnownBlock, no pindexLastCommonBlock. The block-sync state machine in OFF is the older vBlocksToDownload / vBlocksInFlight style, which works but doesn't expose per-peer best-known-block information.

Consequence: OFF's CNodeStateStats (src/main.h:214) only tracks nMisbehavior. There's no nSyncHeight field, so the Peers tab can't show how high each peer thinks the chain is.

Why post-Codex

This touches the block-sync state machine — the code path responsible for downloading blocks from peers. The Codex inscription window (blocks 999,991 → 1,050,666, ~35 days) depends on block-sync staying boring. Even a benign-looking touch to CNodeState initialization or update logic could subtly affect block-download timing, especially under low-peer-count conditions where the Conclave miner is the source of new blocks.

Hard freeze: not merging until block 1,050,667 or later.

Once the inscription window closes, this becomes a safe, scoped backport.

Scope (estimate)

~50–80 LOC across src/main.cpp and src/main.h. Pattern from (BOB) is well-defined:

1. src/main.h::CNodeStateStats (~2 LOC)

struct CNodeStateStats {
    int nMisbehavior;
    int nSyncHeight;     // NEW: -1 if unknown
};

2. src/main.cpp::CNodeState (~1 LOC + constructor init)

struct CNodeState {
    int nMisbehavior;
    bool fShouldBan;
    std::string name;
    /* ... existing fields ... */
    CBlockIndex *pindexBestKnownBlock;   // NEW

    CNodeState() {
        nMisbehavior = 0;
        fShouldBan = false;
        /* ... */
        pindexBestKnownBlock = NULL;     // NEW
    }
};

3. src/main.cpp::GetNodeStateStats (~1 LOC)

stats.nSyncHeight = state->pindexBestKnownBlock ?
                    state->pindexBestKnownBlock->nHeight : -1;

4. Update sites for pindexBestKnownBlock (the actual work — ~40-60 LOC)

(BOB)'s dobbscoin-source/src/main.cpp updates the field in two places (main.cpp:369, main.cpp:386) — both in the per-peer block-header processing path. The fields are updated when:

  • A headers message arrives and we extend the peer's known headers list (ProcessNewBlockHeaders callback)
  • An inv block announcement arrives with a hash we already have indexed and the work is higher than the peer's previous best-known

These call sites have to be ported into OFF's equivalent functions. Verify the function names match between vintages (OFF is pre-ProcessNewBlockHeaders, may need a different hook point).

5. Qt re-add of the Sync Height widgets (after this lands)

After this issue is implemented, re-add the Sync Height widgets that #15 drops. Detail pane back to 13 fields. Wire-up is one line:

ui->peerSyncHeight->setText(stats->nodeStateStats.nSyncHeight > -1
    ? QString::number(stats->nodeStateStats.nSyncHeight)
    : tr("Unknown"));

Open design questions

  • pindexLastCommonBlock too? (BOB) carries both. pindexLastCommonBlock is needed for the modern FindNextBlocksToDownload(); if we're not modernizing block-sync wholesale, we may not need it. Scope-defending lean: just pindexBestKnownBlock for the Sync Height display, defer LastCommon to a separate block-sync modernization issue.
  • OFF's existing vBlocksToDownload machinery — does it conflict with maintaining pindexBestKnownBlock in parallel, or do they coexist cleanly? Should be fine (they don't share state), but verify during implementation.
  • Lock ordering. pindexBestKnownBlock access needs cs_main. All the update sites identified are already under cs_main, so no new lock surface; document this in a comment.

What this isn't

  • Not consensus-changing. Block-sync is peer-policy; consensus rules are unchanged.
  • Not a wholesale modernization of OFF's block-sync state machine. That's a much bigger separate epic if anyone ever wants it. This issue is the minimum backport needed to surface Sync Height in the Peers tab.

References

  • dobbscoin-source/src/main.h:229 — nSyncHeight field shape
  • dobbscoin-source/src/main.cpp:252 — pindexBestKnownBlock field
  • dobbscoin-source/src/main.cpp:369,386 — update sites
  • dobbscoin-source/src/main.cpp:504 — GetNodeStateStats populating nSyncHeight
  • src/main.cpp:206 — OFF's CNodeState (current, missing the field)
  • src/main.cpp:324 — OFF's GetNodeStateStats (current, only nMisbehavior)
  • #15 — Peers tab polish (drops the widget pre-this-issue)
  • #13 — Peers tab itself (lands the infrastructure)

The Old One sleeps, but knows how far each acolyte has climbed. Iä Iä.

**Do-not-merge-pre-Codex.** Tracked here for post-fork implementation. Companion to #15 (Peers tab polish — drops the unused Sync Height widgets) and #13 (the Peers tab itself). ## What's missing (BOB)'s `CNodeState` (`dobbscoin-source/src/main.cpp:252`) carries a `CBlockIndex *pindexBestKnownBlock` per peer — the highest-known block index of that peer based on the headers / inv messages they've sent. Modern upstream block-sync uses it for `FindNextBlocksToDownload()` (deciding which peer to ask for which blocks). OFF's `CNodeState` (`src/main.cpp:206`) is the older 0.10-era shape — no `pindexBestKnownBlock`, no `pindexLastCommonBlock`. The block-sync state machine in OFF is the older `vBlocksToDownload` / `vBlocksInFlight` style, which works but doesn't expose per-peer best-known-block information. Consequence: OFF's `CNodeStateStats` (`src/main.h:214`) only tracks `nMisbehavior`. There's no `nSyncHeight` field, so the Peers tab can't show how high each peer thinks the chain is. ## Why post-Codex This touches the block-sync state machine — the code path responsible for downloading blocks from peers. The Codex inscription window (blocks 999,991 → 1,050,666, ~35 days) depends on block-sync staying *boring*. Even a benign-looking touch to `CNodeState` initialization or update logic could subtly affect block-download timing, especially under low-peer-count conditions where the Conclave miner is the source of new blocks. **Hard freeze: not merging until block 1,050,667 or later.** Once the inscription window closes, this becomes a safe, scoped backport. ## Scope (estimate) ~50–80 LOC across `src/main.cpp` and `src/main.h`. Pattern from (BOB) is well-defined: ### 1. `src/main.h::CNodeStateStats` (~2 LOC) ```cpp struct CNodeStateStats { int nMisbehavior; int nSyncHeight; // NEW: -1 if unknown }; ``` ### 2. `src/main.cpp::CNodeState` (~1 LOC + constructor init) ```cpp struct CNodeState { int nMisbehavior; bool fShouldBan; std::string name; /* ... existing fields ... */ CBlockIndex *pindexBestKnownBlock; // NEW CNodeState() { nMisbehavior = 0; fShouldBan = false; /* ... */ pindexBestKnownBlock = NULL; // NEW } }; ``` ### 3. `src/main.cpp::GetNodeStateStats` (~1 LOC) ```cpp stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1; ``` ### 4. Update sites for `pindexBestKnownBlock` (the actual work — ~40-60 LOC) (BOB)'s `dobbscoin-source/src/main.cpp` updates the field in two places (`main.cpp:369`, `main.cpp:386`) — both in the per-peer block-header processing path. The fields are updated when: - A `headers` message arrives and we extend the peer's known headers list (`ProcessNewBlockHeaders` callback) - An `inv` block announcement arrives with a hash we already have indexed and the work is higher than the peer's previous best-known These call sites have to be ported into OFF's equivalent functions. Verify the function names match between vintages (OFF is pre-`ProcessNewBlockHeaders`, may need a different hook point). ### 5. Qt re-add of the Sync Height widgets (after this lands) After this issue is implemented, **re-add** the Sync Height widgets that #15 drops. Detail pane back to 13 fields. Wire-up is one line: ```cpp ui->peerSyncHeight->setText(stats->nodeStateStats.nSyncHeight > -1 ? QString::number(stats->nodeStateStats.nSyncHeight) : tr("Unknown")); ``` ## Open design questions - **`pindexLastCommonBlock` too?** (BOB) carries both. `pindexLastCommonBlock` is needed for the modern `FindNextBlocksToDownload()`; if we're not modernizing block-sync wholesale, we may not need it. Scope-defending lean: just `pindexBestKnownBlock` for the Sync Height display, defer LastCommon to a separate block-sync modernization issue. - **OFF's existing `vBlocksToDownload` machinery** — does it conflict with maintaining `pindexBestKnownBlock` in parallel, or do they coexist cleanly? Should be fine (they don't share state), but verify during implementation. - **Lock ordering.** `pindexBestKnownBlock` access needs `cs_main`. All the update sites identified are already under `cs_main`, so no new lock surface; document this in a comment. ## What this isn't - **Not consensus-changing.** Block-sync is peer-policy; consensus rules are unchanged. - **Not a wholesale modernization of OFF's block-sync state machine.** That's a much bigger separate epic if anyone ever wants it. This issue is the *minimum* backport needed to surface Sync Height in the Peers tab. ## References - `dobbscoin-source/src/main.h:229` — `nSyncHeight` field shape - `dobbscoin-source/src/main.cpp:252` — `pindexBestKnownBlock` field - `dobbscoin-source/src/main.cpp:369,386` — update sites - `dobbscoin-source/src/main.cpp:504` — `GetNodeStateStats` populating `nSyncHeight` - `src/main.cpp:206` — OFF's `CNodeState` (current, missing the field) - `src/main.cpp:324` — OFF's `GetNodeStateStats` (current, only `nMisbehavior`) - #15 — Peers tab polish (drops the widget pre-this-issue) - #13 — Peers tab itself (lands the infrastructure) --- *The Old One sleeps, but knows how far each acolyte has climbed. Iä Iä.*
dobbscoin closed this issue 2026-08-12 16:51:36 +00:00
Sign in to join this conversation.
No labels
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
SubGeniusFinance/Offerings-to-Cthulhu#18
No description provided.