Skip to content

Commit e3bd553

Browse files
committed
lightning-invoice: increase max length to 7089
1 parent dd33a5a commit e3bd553

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

Diff for: lightning-invoice/src/de.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use core::str::FromStr;
99
use std::error;
1010

1111
use bech32::primitives::decode::{CheckedHrpstring, CheckedHrpstringError};
12-
use bech32::{Bech32, Fe32, Fe32IterExt};
12+
use bech32::{Fe32, Fe32IterExt};
1313

14-
use crate::prelude::*;
14+
use crate::{prelude::*, Bolt11Bech32};
1515
use bitcoin::hashes::sha256;
1616
use bitcoin::hashes::Hash;
1717
use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
@@ -377,7 +377,7 @@ impl FromStr for SignedRawBolt11Invoice {
377377
type Err = Bolt11ParseError;
378378

379379
fn from_str(s: &str) -> Result<Self, Self::Err> {
380-
let parsed = CheckedHrpstring::new::<Bech32>(s)?;
380+
let parsed = CheckedHrpstring::new::<Bolt11Bech32>(s)?;
381381
let hrp = parsed.hrp();
382382
// Access original non-packed 32 byte values (as Fe32s)
383383
// Note: the type argument is needed due to the API peculiarities, but it's not used

Diff for: lightning-invoice/src/lib.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ extern crate serde;
3131
use std::time::SystemTime;
3232

3333
use bech32::primitives::decode::CheckedHrpstringError;
34-
use bech32::Fe32;
34+
use bech32::{Checksum, Fe32};
3535
use bitcoin::hashes::{sha256, Hash};
3636
use bitcoin::{Address, Network, PubkeyHash, ScriptHash, WitnessProgram, WitnessVersion};
3737
use lightning_types::features::Bolt11InvoiceFeatures;
@@ -147,6 +147,32 @@ pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
147147
/// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
148148
pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
149149

150+
/// lightning-invoice will reject BOLT11 invoices that are longer than 7089 bytes.
151+
///
152+
/// ### Rationale
153+
///
154+
/// This value matches LND's implementation, which was chosen to be "the max number
155+
/// of bytes that can fit in a QR code". LND's rationale is technically incorrect
156+
/// as QR codes actually have a max capacity of 7089 _numeric_ characters and only
157+
/// support up to 4296 all-uppercase alphanumeric characters. However, ecosystem-wide
158+
/// consistency is more important.
159+
pub const MAX_LENGTH: usize = 7089;
160+
161+
/// The [`bech32::Bech32`] checksum algorithm, with extended max length suitable
162+
/// for BOLT11 invoices.
163+
pub enum Bolt11Bech32 {}
164+
165+
impl Checksum for Bolt11Bech32 {
166+
/// Extend the max length from the 1023 bytes default.
167+
const CODE_LENGTH: usize = MAX_LENGTH;
168+
169+
// Inherit the other fields from `bech32::Bech32`.
170+
type MidstateRepr = <bech32::Bech32 as Checksum>::MidstateRepr;
171+
const CHECKSUM_LENGTH: usize = bech32::Bech32::CHECKSUM_LENGTH;
172+
const GENERATOR_SH: [Self::MidstateRepr; 5] = bech32::Bech32::GENERATOR_SH;
173+
const TARGET_RESIDUE: Self::MidstateRepr = bech32::Bech32::TARGET_RESIDUE;
174+
}
175+
150176
/// Builder for [`Bolt11Invoice`]s. It's the most convenient and advised way to use this library. It
151177
/// ensures that only a semantically and syntactically correct invoice can be built using it.
152178
///

0 commit comments

Comments
 (0)