8000 BOLT 11 Compliance: Invoice `r` field don't reject empty routing hints · Issue #3104 · ACINQ/eclair · GitHub 10000
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
BOLT 11 Compliance: Invoice r field don't reject empty routing hints #3104
Closed
@erickcestari

Description

@erickcestari

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

  1. Length Calculation Logic
    The extraHopsLengthCodec 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.

  1. List Decoding
    The listOfN(extraHopsLengthCodec, extraHopCodec) creates a list with the calculated length

  2. 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")
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0