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

lightningd: don't assert on funding feerates read from the db

Public commit record

What the developer wrote

Authored by cdecker

86/100 · Strong
lightningd: don't assert on funding feerates read from the db

The 25/24 RBF escalation from BOLT #2 is computed on a u32 in three
places, and two of them assert that the result came out larger than the
input. It doesn't, for anything above UINT_MAX/25: the multiplication
wraps and the assert fires. That value comes out of
channel_funding_inflights, which is to say out of whatever fee estimator
(ours or a peer's) produced it, so it is not an invariant we were ever in
a position to state.

The worse of the two is in json_add_channel. listpeerchannels is
read-only introspection that plugins call at startup, so one bad row
turns into a crash-loop with no RPC left to repair it with.

check_funding_feerate() in dualopend already had the right shape for
this, so hoist it into bitcoin/feerate.c as next_funding_feerate() and
use it at all three sites rather than keeping three copies of the
calculation. It also rejects a last feerate of 0, which is the other end
of the same problem: assert(last_feerate > 0) sits immediately above the
overflow one.

That makes next_feerate a field we can fail to produce, so the schema no
longer requires it: a last feerate of 0, or one below 24 where rounding
down lands back on itself, admits no valid next feerate, and there is no
honest value to print for one. The bindings already modelled it that
way (Option<String> in cln-rpc, optional in the proto), so the required
list was the outlier.

The preceding commits bound every path a feerate arrives on, and the
migration repaired what was already stored, so the invariant does now
hold. This is the belt to their braces: a future unbounded write path
should not be able to turn straight back into a crash-loop, and finding
out about it in listpeerchannels is finding out too late. Since the
stored value is in range, the output is unchanged in every reachable
case. openchannel_bump fails the command rather than the daemon.

Changelog-Fixed: lightningd: `listpeerchannels` no longer aborts when a channel has an out-of-range funding feerate stored for an in-progress open.
Changelog-Changed: JSON-RPC: `listpeerchannels`.`next_feerate` is now optional: it is omitted for an in-progress open whose stored feerate admits no valid next feerate.
(cherry picked from commit 84443b55fc4a5cc2d6e3a557f2c58dca60f8f264)
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
The short version

What changed, and why it matters

This update fixes a crash bug in Core Lightning. When the software tried to list details of a channel opening in progress, it could crash if a stored fee rate was extremely large or zero. The crash happened because the code used an internal sanity check (an 'assert') that treated bad stored data as an impossible condition. The fix replaces that hard crash with a safe failure: it either skips the optional 'next fee rate' field in the output, or returns an error for the specific command. This prevents a single bad database row from making the whole node crash repeatedly at startup.

Recommended action

Apply the patch. It is a defensive hardening fix that prevents crash-loops from malformed or out-of-range stored funding feerates. No immediate incident response is indicated unless the node has already entered a crash-loop, in which case the patch or the preceding migration commits are needed to restore service.

Security signals we found

01

Integer overflow in RBF escalation (u32 * 25 / 24) leading to assertion failure

02

Assertion failure in read-only introspection RPC (listpeerchannels) causing crash-loop at startup

03

Database value treated as invariant despite originating from external fee estimator

04

Replacement of asserts with explicit error handling and optional output

05

Schema change making next_feerate optional

Risk score

Why this scored 64/100

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