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

Pass a `BestBlock` to `init::synchronize_listeners`

Public commit record

What the developer wrote

Authored by Matt Corallo

85/100 · Strong
Pass a `BestBlock` to `init::synchronize_listeners`

On restart, LDK expects the chain to be replayed starting from
where it was when objects were last serialized. This is fine in the
normal case, but if there was a reorg and the node which we were
syncing from either resynced or was changed, the last block that we
were synced as of might no longer be available. As a result, it
becomes impossible to figure out where the fork point is, and thus
to replay the chain.

Luckily, changing the block source during a reorg isn't exactly
common, but we shouldn't end up with a bricked node.

To address this, `lightning-block-sync` allows the user to pass in
`Cache` which can be used to cache recent blocks and thus allow for
reorg handling in this case. However, serialization for, and a
reasonable default implementation of a `Cache` was never built.

Instead, here, we start taking a different approach. To avoid
developers having to persist yet another object, we move
`BestBlock` to storing some number of recent block hashes. This
allows us to find the fork point with just the serialized state.

In a previous commit, we moved deserialization of various structs
to return the `BestBlock` rather than a `BlockHash`. Here we move
to actually using it, taking a `BestBlock` in place of `BlockHash`
to `init::synchronize_listeners` and walking the `previous_blocks`
list to find the fork point rather than relying on the `Cache`.
✓ 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 changes how a Bitcoin Lightning node (LDK) recovers after a restart when the blockchain has split/reorganized. Previously, the node only remembered its last known block hash. If that block was no longer available from the block source after a reorg, the node could get stuck ('bricked'). The fix makes the node keep a short history of recent block hashes inside its stored 'BestBlock' state, so it can find the fork point and replay the chain without relying on an extra cache object. This is a robustness improvement, not a typical exploitable vulnerability.

Recommended action

Review downstream callers of `synchronize_listeners` to ensure they now pass a `BestBlock` rather than a raw `BlockHash`. Verify that persisted `BestBlock` state includes the new `previous_blocks` field and that the height hint logic does not introduce off-by-one errors or panic paths. Consider adding tests for the case where the tip hash is unavailable but an older `previous_blocks` entry resolves successfully.

Security signals we found

01

Denial-of-service / node bricking: prior behavior could leave a node unable to locate the fork point after a reorg if the synced block source changed or resynced

02

Data structure change: `BestBlock` now stores recent block hashes to aid fork-point resolution

03

New fallback resolution path: `find_difference_from_best_block` walks previous block hashes with height hints

04

API change: `synchronize_listeners` signature changed from `Vec<(BlockHash, &L)>` to `Vec<(BestBlock, &L)>`

Risk score

Why this scored 45/100

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