chainbackends: consume real reorg depth and Done from lndclient#834
chainbackends: consume real reorg depth and Done from lndclient#834ellemouton wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request integrates temporary forks of lnd and lndclient to surface chain-notifier reorganization depth and terminal Done events over gRPC. Specifically, RegisterConfirmationsNtfn now tracks and forwards the actual reorganization depth using WithReOrgDepthChan and handles the terminal safety signal via WithDoneChan. Similarly, RegisterSpendNtfn has been updated to utilize WithDoneChan. Unit tests have been adjusted to accommodate these channel and signature changes, using unbuffered downstream channels to prevent race conditions. No review comments were provided, so there is no additional feedback.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
521cc46 to
841afe1
Compare
3eb6f61 to
449b6cf
Compare
32871de to
4a1f9b1
Compare
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.
Deliver the full TxConfirmed/TxReorged/re-TxConfirmed/TxFinalized/ TxFailed cycle on confirmation watches, with a terminal seal guarding the reversible fire-and-forget deliveries and a catch-up TxReorged when a reorg lands while a subscriber's initial TxConfirmed is still parked on the async notify path.
Forward the lnd and lndclient chain-notifier reorg/finality signals (NegativeConf -> reorg) into the reorg-aware chainsource lifecycle with buffered forwarding.
Reorg-aware lwwallet/Esplora backend: TipPoller same-height and deeper reorg detection via PrevBlock continuity, a unified ChainEvent stream, and BlockDisconnected emission to btcwallet before connecting the replacement tip.
Forward Neutrino chain-notifier reorg signals into the reorg-aware chainsource lifecycle.
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.
Temporary replaces onto the lnd and lndclient branches that add the reorg depth and Done events to the chain notifier, now rebased onto btcd v2 so they resolve against the current module graph. Allow-listed in the gomoddirectives linter config. Drop all three once those changes land upstream and tag (tracked in darepo-client#827).
The lndclient adapter previously forwarded a sentinel reorg depth of 0 on NegativeConf and never wrote the Done channel, because lnd's gRPC notifier dropped the depth and surfaced its past-reorg-safety-depth signal only by closing the stream. With the forked lndclient now exposing both via WithReOrgDepthChan and WithDoneChan, forward the real reorg depth through the ordered confirmation bridge and wire the terminal Done straight through to the ConfirmationEvent/SpendEvent Done channels. The spend path has no depth (lnd does not track one) so its bare reorg ping is unchanged.
841afe1 to
246992e
Compare
292394e to
233abdd
Compare
Summary
Upgrades the lndclient chain-notifier adapter introduced in #422 to consume the
real re-org depth and finality (Done) signals, replacing the two
client-side workarounds that #422 had to use because lnd's gRPC transport
dropped that information.
This addresses the lndclient-related review feedback on #422, tracked in #827.
Changes
chainbackends/lndclient_adapters.go:NegativeConf(was a sentinel0),via lndclient's new
WithReOrgDepthChan.Donestraight through to theConfirmationEvent/SpendEventDonechannels viaWithDoneChan(was allocated-but-never-written, forcing height-based synthesis as the only finality source).
chainbackends/lndclient_ordering_test.go: assert the forwarded depth;make the ordering tests use unbuffered downstream channels so the forwarder
cannot run ahead of the in-order consumer (removes a latent parallel-run
flake).
go.mod/.golangci.yml: temporaryreplacepins onto the lnd + lndclientfork branches, allow-listed in
gomoddirectives.Notes
Drop the three temporary pins (two
replaces + the allowlist entries) onceboth land upstream and tag. Tracked in lndclient: surface real reorg depth + finality (Done) over gRPC (follow-up to #422) #827.
reorg-safe-chainsource).fallback for backends that do not emit a real Done.