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

graph/db: fix SetSourceNode race with lenient upsert

Public commit record

What the developer wrote

Authored by Elle Mouton

83/100 · Strong
graph/db: fix SetSourceNode race with lenient upsert

This commit fixes a race condition where multiple goroutines call
SetSourceNode concurrently during startup, causing sql.ErrNoRows
errors. The race occurs when multiple code paths (setSelfNode,
createNewHiddenService, RPC updates) read the same old timestamp,
independently increment it to the same new value (T+1), and race to
write.

The fix uses the new UpsertSourceNode SQL query (without strict
timestamp constraint) instead of UpsertNode. This allows
last-write-wins semantics for our own node, ensuring all parameter
changes persist even when timestamps collide.

Refactored sql_store.go for reusability:
- upsertNodeAncillaryData: common logic for features/addresses/extras
- populateNodeParams: common parameter building with callback pattern
- buildNodeUpsertParams: builds params for strict UpsertNode
- buildSourceNodeUpsertParams: builds params for lenient UpsertSourceNode
- upsertSourceNode: new function using lenient query

Updated TestSetSourceNodeSameTimestamp to verify that concurrent
updates with the same timestamp now succeed and parameter changes
persist.

Fixes the itest error:
"unable to upsert source node: upserting node(...): sql: no rows in
result set"
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification
The short version

What changed, and why it matters

This commit fixes a race condition in LND's graph database code. During startup, multiple internal routines could try to update the node's own information at the same time, using the same timestamp. The old SQL upsert required a strictly newer timestamp, so these concurrent updates sometimes failed with 'sql: no rows in result set'. The fix uses a more lenient upsert for the local node so that last-write-wins and parameter changes persist even when timestamps collide. It is a reliability/availability fix rather than a vulnerability that external attackers can exploit.

Recommended action

No immediate security response is required. This is a defensive fix for a startup race condition. Operators should upgrade to a release containing this commit if they observed 'unable to upsert source node: sql: no rows in result set' errors during startup. Reviewers may want to inspect the new UpsertSourceNode SQL definition to confirm it does not weaken timestamp validation for gossip from remote peers, which should remain strict.

Security signals we found

01

Race condition in source node upsert causing sql.ErrNoRows

02

Strict timestamp comparison in UpsertNode rejected same-timestamp updates

03

Concurrent startup paths (setSelfNode, createNewHiddenService, RPC updates) colliding on timestamp

04

Fix uses lenient UpsertSourceNode with last-write-wins semantics for own node only

05

Test updated to verify persistence despite identical timestamps

Risk score

Why this scored 32/100

Our methodology →
Potential impact 8/30
Exploitability 3/25
Stealth signal 4/15
Affected reach 5/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.