AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
Moderate 64 Bitcoin

discovery+funding+peer+server: migrate gossip result to actor.Future[error]

Public commit record

What the developer wrote

Authored by Olaoluwa Osuntokun

85/100 · Strong
discovery+funding+peer+server: migrate gossip result to actor.Future[error]

In this commit, we eliminate the three buffered chan error patterns in
the discovery package and replace them with actor.Promise[error]/
actor.Future[error]. The old pattern is error-prone: if a channel is
completed more than once (e.g. when a deferred message copy is
re-enqueued and processed again), the second write to a capacity-1
channel blocks forever. actor.Promise.Complete() is idempotent via
sync.Once, so the second call is always a safe no-op regardless of
whether anyone holds a reference to the Future.

Additionally, PropagateChanPolicyUpdate previously blocked on <-errChan
after enqueuing a policy update with no quit-channel check, creating a
latent deadlock if the gossiper shut down between enqueue and send. It
now uses AwaitGossipResult with a ContextFromQuit-derived context, so
shutdown is always respected.

This is an atomic migration that updates all callers in the same
commit so each commit builds standalone. The three main pieces are:

discovery

networkMsg.err chan error becomes errPromise actor.Promise[error].
chanPolicyUpdateRequest.errChan chan error becomes errPromise.
syncTransitionReq.errChan chan error becomes errPromise. All ~65 sites
that previously wrote to the error channel now call
completeGossipResult(nMsg.errPromise, err) instead.

ProcessRemoteAnnouncement and ProcessLocalAnnouncement now return
actor.Future[error] instead of chan error. The capacity-2 buffer
comment on ProcessRemoteAnnouncement, which was itself a workaround
for the old pattern, is removed along with the TODO referencing the
actor model redesign. ProcessSyncTransition in syncer.go follows the
same pattern: the errChan select is replaced with AwaitGossipResult
using a ContextFromQuit-derived context.

funding

The SendAnnouncement function type in funding.Config changes from
returning chan error to returning actor.Future[error]. The call sites
in addToGraph and announceChannel are updated to await the future with
AwaitGossipResult, passing a context derived from f.quit via
ContextFromQuit. Shutdown signals (context.Canceled and
discovery.ErrGossiperShuttingDown) are both mapped to
ErrFundingManagerShuttingDown via the new mapGossipError helper, which
also factors out the duplicated graph-rejected / unknown-error
handling. The three mock SendAnnouncement implementations in
manager_test.go are updated accordingly.

peer+server

In peer/brontide.go, the ProcessRemoteAnnouncement call in the gossip
stream handler intentionally discards the result since remote gossip
messages are fire-and-forget from the peer's perspective. The old
comment explaining why the chan error was unsafe to use is replaced
with a note that an unawaited Future[error] carries no overhead.

In server.go (applyChannelUpdate), the previous select on errChan and
the quit channel is replaced with ContextFromQuit + AwaitGossipResult.
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode
The short version

What changed, and why it matters

This commit refactors how LND's gossip subsystem reports errors back to callers. Previously, code used buffered Go channels to carry a single error result. That pattern could deadlock if a deferred gossip message was processed twice, because the second write to an already-full channel would block forever. The change replaces those channels with a new 'actor.Promise/Future' abstraction whose completion is idempotent (safe to call many times). It also makes shutdown handling more uniform by deriving contexts from quit channels, preventing another latent deadlock in channel-policy propagation. The commit includes regression tests for premature-announcement reprocessing and shutdown paths.

Recommended action

Review the actor.Promise implementation for correct sync.Once behavior and memory visibility; ensure AwaitGossipResult handles context cancellation and future completion races safely. Monitor for any third-party callers or plugins that still expect a chan error return from ProcessRemoteAnnouncement/ProcessLocalAnnouncement. Consider backporting to supported release branches because the deadlock could stall the gossip handler and affect routing state.

Security signals we found

01

Eliminates latent goroutine/channel deadlock in gossip result reporting

02

Replaces non-idempotent buffered error channels with idempotent actor.Promise.Complete

03

Adds shutdown-aware context bridging via ContextFromQuit to prevent blocking awaits

04

Fixes latent deadlock in PropagateChanPolicyUpdate during gossiper shutdown

05

Adds regression tests explicitly referencing 'Network Isolation Attack' and premature-announcement reprocessing deadlock

Risk score

Why this scored 64/100

Our methodology →
Potential impact 18/30
Exploitability 10/25
Stealth signal 12/15
Affected reach 12/15
Confidence 8/10
Evidence quality 4/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.