[v0.1.x-branch] Backport #895: multi: reorg-aware chain observation (chainsource + backends) - #981
Closed
github-actions[bot] wants to merge 6 commits into
Closed
[v0.1.x-branch] Backport #895: multi: reorg-aware chain observation (chainsource + backends)#981github-actions[bot] wants to merge 6 commits into
github-actions[bot] wants to merge 6 commits into
Conversation
Add the reorg-aware chain-observation substrate the rest of the reorg-safety stack consumes: a seq-ordered conf/spend watch lifecycle (Confirmed -> Reorged -> re-Confirmed -> Done) with height-based finality synthesis for backends that cannot deliver a native Done (gRPC lndclient and lwwallet). Finality synthesis is armed off the select loop, tied to the sub-actor's long-lived context (a per-attempt timeout would tear the in-process block-epoch forwarder down the instant it armed), retried with a capped exponential backoff until it succeeds or the watch's context is cancelled (a single-confirmation tx has no later event to piggy-back a retry on), and evaluated against the best height captured at arm time so a tx already buried past FinalityDepth when the watch arms finalizes immediately instead of hanging for the next block. (cherry picked from commit 583663c)
Deliver the full TxConfirmed/TxReorged/re-TxConfirmed/TxFinalized/ TxFailed cycle while a terminal seal keeps reversible notifications from trailing finality. Keep the initial TxConfirmed delivery reliable across mailbox failures. A subscriber attaching after finality receives only the authoritative TxFinalized result. This prevents a retry from inventing a provisional confirmation after the transaction has already sealed. (cherry picked from commit 8faf207)
Forward the lnd and lndclient chain-notifier reorg/finality signals (NegativeConf -> reorg) into the reorg-aware chainsource lifecycle with buffered forwarding. (cherry picked from commit 3340fed)
Detect same-height, shorter, deeper, and mid-catch-up reorgs using a bounded hash history and PrevBlock continuity checks at every walked height. Checking every height prevents a chain replacement that lands mid-walk from permanently stitching together blocks from two forks. Publish replacements through one ordered ChainEvent stream. This lets btcwallet see every BlockDisconnected before the new canonical TipBlock events. (cherry picked from commit 0db4ff2)
Forward Neutrino chain-notifier reorg signals into the reorg-aware chainsource lifecycle. (cherry picked from commit 7a7fa36)
Consume the reorg-aware substrate at the edges: make the wallet boarding sweep reorg-aware, enable height-based finality on the darepod chainsource actor, add the harness GetRawTransaction / SignedV3Tx helpers, and add the end-to-end reorg systests for chainsource and txconfirm. (cherry picked from commit 233abdd)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backport of #895
Summary
PR 1 of the six-PR basic-v1 reorg-safety stack tracked by
lightninglabs/lumos#454.
This PR is the chain-observation layer. It makes confirmation and spend
observation reversible end to end:
For
txconfirm:The first positive observation is no longer terminal. Higher layers can keep a
fact provisional, react when it leaves the best chain, and observe it again
after reconfirmation.
What is included
chainsource: multi-shot confirmation/spend actors, reorg and doneevents, ordered delivery, and height-based finality synthesis for transports
that do not provide native
Done. Transport boundaries explicitly defer abuffered
Doneuntil the positive confirmation/spend identity has crossedfirst.
txconfirm: reversible confirmation notifications, a distinct terminalTxFinalizedstate, and correct terminal-only replay for late subscribers.terminating after the first positive event. Today this transport supplies a
payload-less reorg ping, so
chainsourcesynthesizes finality from blockheight.
replacements, then forward disconnected/connected blocks in order.
txconfirmsubscriber to the new four-event lifecycle. Without this,
TxReorgedandTxFinalizedfall through the old mapper as failure-shaped notifications.Broader boarding spend-watch recovery belongs to Client PR 2.
Native LND transport completion
This PR remains compatible with today's released lnd/lndclient by synthesizing
terminal
Doneat thechainsourceboundary. The proper native transport pathis being completed in parallel:
carries confirmation re-org depth and explicit confirmation/spend
Doneonthe
ChainNotifiergRPC streams.exposes those native fields/events through lndclient.
After both land and Wavelength bumps the dependencies, the LND backend can use
native depth/Done directly while height synthesis remains a compatibility
fallback for older transports.
Deliberate boundary
This PR does not implement:
FinalityDepthis configurable observation policy. This PR retains theinterim default of 6 because no one-confirmation lineage is exposed by it.
Client PR 2 makes the shared basic-v1 terminal boundary configurable so a
deployment can choose how deep a reorg remains recoverable.
This is necessary observation plumbing; it does not, by itself, claim
end-to-end reorg safety through the configured policy depth.
Basic-v1 stack
compatibility.
disabled capability.
restart reconciliation, and objective conditional restore.
lineage admission/pre-side-effect gate.
complete evidence/admission/pre-side-effect gates.
test depth, sealing at that policy boundary, and the final S1-S5/R2/F9
contract across both sides.
Generic automatic replay, durable lineage waiters, per-operation usability
depths, and detection after the configured safety horizon remain follow-ups.
Validation
At
233abdd6:go test ./lwwallet ./txconfirm -count=1go test -race ./lwwallet -run TestTipPollerReorgDuringMultiBlockAdvance -count=10go test -race ./lwwallet -run TestTipPollerDeeperForwardReorg -count=100go test -race ./lwwallet -count=10go test -race ./txconfirm -run TestLateFinalizedSubscriberRetrySkipsConfirmed -count=10go test -race ./chainsource ./chainbackends ./btcwbackend -count=5Doneregressions across those three packages,-count=20make lint-changed-local— 0 issuesThe prior
unit-racefailure exposed nondeterminism in the deeper-forwardTipPoller test harness: its background poll could observe the deliberately
mutated stub chain between the test's two intended snapshots. That test now
drives the two observations manually and passed 100 focused race runs plus ten
full-package race runs. Fresh full CI is running for this rewritten head. A
human approving review remains the final merge gate.