Skip to content

ltc(v36): advertise raw head at handshake + re-advertise on best-change (root-2) - #103

Closed
frstrtr wants to merge 1 commit into
masterfrom
ltc-doge/root2-genesis-null-advert
Closed

ltc(v36): advertise raw head at handshake + re-advertise on best-change (root-2)#103
frstrtr wants to merge 1 commit into
masterfrom
ltc-doge/root2-genesis-null-advert

Conversation

@frstrtr

@frstrtr frstrtr commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Root-2: genesis-null head advertisement

(a) Bug fixed — genesis-null-advert

On a fresh (--genesis) LTC node the verified share set is empty at the moment of the version handshake. best_share_hash() is verified-only and deliberately collapses to uint256::ZERO once peers exist (so work/template never builds on a MAX_TARGET head). As a side effect the node advertised ZERO in send_version(), so a connecting peer never learned we had a chain and never issued download_shares() for our shares — the chain failed to propagate from a genesis node.

Fix: introduce a separate advertised_best_share() used only on the wire (handshake + re-advertisement). It returns our tallest raw chain head (think's current best, else the tallest m_chain head, else ZERO at true genesis). Work/template selection is untouched and still rides verified-only best_share_hash(). The two concerns are now cleanly split and documented at both declarations.

Re-advertisement: a peer that handshook before we had a chain saw a ZERO advert. readvertise_best() re-announces the head whenever think/clean updates the best share, so that peer pulls our shares on the next cycle.

(b) Livelock-safety — confirmed, no new lock

This change acquires no mutex. advertised_best_share() and readvertise_best() are pure reads over m_best_share_hash/m_chain, invoked from inside run_think() and clean_tracker() which already hold their execution context. No new exclusive lock, no new try_lock, nothing on the compute-thread hot path that could reintroduce the phase2 livelock signature. Net diff is +65/-2 across 2 files.

(c) Deviation from explicit timer — flag for operator

The spec called for an explicit re-advert timer (~10s). This PR instead re-advertises on think-cycle cadence: run_think() after a work refresh, and clean_tracker() when the best share changes. Rationale: it reuses existing event points (no new timer/thread, keeps the no-new-lock guarantee) and re-announces exactly when our head actually moves. If the operator prefers a fixed 10s timer (e.g. to cover a peer that connects during a long quiescent gap with no head change), say so and I will add it as a follow-up.

Scope: LTC only. BTC mirror is tracked separately by btc-heap-opt. Commit b56bfb2 is GPG-signed.

…ge (root-2)

On a --genesis node the verified share set is empty at the version
handshake, so send_version advertised best_share_hash()==ZERO and the
connecting peer never issued download_shares() for our chain. Add
advertised_best_share(): returns think()s current best, else the tallest
raw chain head, else ZERO only at true genesis. Wire it into
send_version so a peer always learns we have a chain and pulls it, while
work/template selection stays on the verified-only best_share_hash().

Re-advertise the head via readvertise_best() on every successful think
IO-phase work refresh and on clean_tracker best-change, so a peer that
handshook during the verified-empty window still gets our head. Guarded
on non-empty peers and non-ZERO head; broadcast_share keeps its
try_to_lock so this cannot reintroduce the think/broadcast livelock.
@frstrtr

frstrtr commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #104 (e01c160 on ltc-doge/root2-advert-readvert) — the complete Root-2 fix incl. the explicit 10s re-advert timer. This branch (b56bfb2) carries only the on-think/best-change re-advert (half-fix that regresses under a wedged think()). Hold/close pending integrator call on the gated+deploy artifact.

@frstrtr

frstrtr commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

Closing per integrator coordination decision: #103 (b56bfb2) is the half-fix. It regresses on the run_think livelock wedge and is superseded by #104 (e01c160), which folds in the 10s core::Timer (removing the deviation that needed an operator opt-in) and the genesis-null-advert raw-head fix. Gate and deploy proceed on #104. Keep closed — do not reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant