Description
Background
After doing some differential fuzzing between CLN
, rust-lightning
, LND
and Eclair
using bitcoinfuzz
I noticed that Eclair
(LND
too) currently accepts bolt11 invoices with empty routing hints in the r
field, while CLN
and rust-lightning
rejects. This violates BOLT 11 specification requirements.
BOLT 11 Requirements:
r
field "MUST contain one or more ordered entries, indicating the forward route from a public node to the final destination"- Each hop must contain exactly 51 bytes (408 bits) (pubkey: 33B, short_channel_id: 8B, fee_base_msat: 4B, fee_proportional_millionths: 4B, cltv_expiry_delta: 2B)
Current Behavior: Eclair currently accepts BOLT 11 invoices with empty routing hints (r
fields) due to how the codec is implemented
- Length Calculation Logic
TheextraHopsLengthCodec
uses this logic:
val extraHopsLengthCodec = Codec[Int](
(_: Int) => Attempt.successful(BitVector.empty),
(wire: BitVector) => Attempt.successful(DecodeResult(wire.size.toInt / 408, wire)) // decoding: infers count from size
)
Key Issue: wire.size.toInt / 408
when wire.size = 0
results in 0, which means zero hops.
-
List Decoding
ThelistOfN(extraHopsLengthCodec, extraHopCodec)
creates a list with the calculated length -
RoutingInfo Construction
case class RoutingInfo(path: List[ExtraHop]) extends TaggedField
An empty List[ExtraHop]
creates a valid RoutingInfo
object with zero routing hints.
Expected Behavior: Reject invoices with empty r
fields.
Impact:
- Spec non-compliance
- Inconsistent behavior between Lightning implementations
Example invoice:
lnbc1p5q54jjpp5fe0dhqdt4m97psq0fv3wjlk95cclnatvuvq49xtnc8rzrp0dysusdqqcqzzsxqrrs0fppqy6uew5229e67r9xzzm9mjyfwseclstdgsp5rnanj9x5rnanj9xnq28hhgd6c7yxlmh6lta047h6lqqqqqqqqqqqrqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6qqqqqqqqqqqqqqqqqqq9kvnknh7ug5mttnqqqqqqqqq8849gwfhvnp9rqpe0cy97
Proposed Fix:
Add validation in the RoutingInfo
case class:
case class RoutingInfo(path: List[ExtraHop]) extends TaggedField {
require(path.nonEmpty, "routing info must contain one or more entries")
}