Skip to content

Commit 1872fa5

Browse files
committed
Error handling improvements
1 parent 3872564 commit 1872fa5

File tree

2 files changed

+16
-16
lines changed

2 files changed

+16
-16
lines changed

lightning-invoice/src/de.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::str;
99
use core::str::FromStr;
1010

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

1414
use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
1515
use bitcoin::hashes::Hash;
@@ -39,27 +39,28 @@ pub trait FromBase32: Sized {
3939
// FromBase32 implementations are here, because the trait is in this module.
4040

4141
impl FromBase32 for Vec<u8> {
42-
type Err = CheckedHrpstringError;
42+
type Err = Bolt11ParseError;
4343

4444
fn from_base32(data: &[Fe32]) -> Result<Self, Self::Err> {
4545
Ok(data.iter().copied().fes_to_bytes().collect::<Self>())
4646
}
4747
}
4848

4949
impl<const N: usize> FromBase32 for [u8; N] {
50-
type Err = CheckedHrpstringError;
50+
type Err = Bolt11ParseError;
5151

5252
fn from_base32(data: &[Fe32]) -> Result<Self, Self::Err> {
53-
Ok(data.iter().copied().fes_to_bytes().collect::<Vec<_>>().try_into().unwrap())
53+
data.iter().copied().fes_to_bytes().collect::<Vec<_>>().try_into()
54+
.map_err(|_| Bolt11ParseError::InvalidSliceLength(data.len(), (N * 8 + 4) / 5, "<[u8; N]>::from_base32()".into()))
5455
}
5556
}
5657

5758
impl FromBase32 for PaymentSecret {
58-
type Err = CheckedHrpstringError;
59+
type Err = Bolt11ParseError;
5960

6061
fn from_base32(field_data: &[Fe32]) -> Result<Self, Self::Err> {
6162
if field_data.len() != 52 {
62-
return Err(CheckedHrpstringError::Checksum(ChecksumError::InvalidLength)) // TODO(bech32): not entirely accurate
63+
return Err(Bolt11ParseError::InvalidSliceLength(field_data.len(), 52, "PaymentSecret::from_base32()".into()));
6364
}
6465
let data_bytes = Vec::<u8>::from_base32(field_data)?;
6566
let mut payment_secret = [0; 32];
@@ -69,7 +70,7 @@ impl FromBase32 for PaymentSecret {
6970
}
7071

7172
impl FromBase32 for Bolt11InvoiceFeatures {
72-
type Err = CheckedHrpstringError;
73+
type Err = Bolt11ParseError;
7374

7475
/// Convert to byte values, by packing the 5-bit groups,
7576
/// putting the 5-bit values from left to-right (reverse order),
@@ -440,7 +441,7 @@ impl FromBase32 for PositiveTimestamp {
440441

441442
fn from_base32(b32: &[Fe32]) -> Result<Self, Self::Err> {
442443
if b32.len() != 7 {
443-
return Err(Bolt11ParseError::InvalidSliceLength("PositiveTimestamp::from_base32()".into()));
444+
return Err(Bolt11ParseError::InvalidSliceLength(b32.len(), 7, "PositiveTimestamp::from_base32()".into()));
444445
}
445446
let timestamp: u64 = parse_u64_be(b32)
446447
.expect("7*5bit < 64bit, no overflow possible");
@@ -455,7 +456,7 @@ impl FromBase32 for Bolt11InvoiceSignature {
455456
type Err = Bolt11ParseError;
456457
fn from_base32(signature: &[Fe32]) -> Result<Self, Self::Err> {
457458
if signature.len() != 104 {
458-
return Err(Bolt11ParseError::InvalidSliceLength("Bolt11InvoiceSignature::from_base32()".into()));
459+
return Err(Bolt11ParseError::InvalidSliceLength(signature.len(), 104, "Bolt11InvoiceSignature::from_base32()".into()));
459460
}
460461
let recoverable_signature_bytes = Vec::<u8>::from_base32(signature)?;
461462
let signature = &recoverable_signature_bytes[0..64];
@@ -508,7 +509,7 @@ fn parse_tagged_parts(data: &[Fe32]) -> Result<Vec<RawTaggedField>, Bolt11ParseE
508509
Ok(field) => {
509510
parts.push(RawTaggedField::KnownSemantics(field))
510511
},
511-
Err(Bolt11ParseError::Skip)|Err(Bolt11ParseError::Bech32Error(_)) => {
512+
Err(Bolt11ParseError::Skip) | Err(Bolt11ParseError::InvalidSliceLength(_, _, _)) | Err(Bolt11ParseError::Bech32Error(_)) => {
512513
parts.push(RawTaggedField::UnknownSemantics(field.into()))
513514
},
514515
Err(e) => {return Err(e)}
@@ -725,8 +726,8 @@ impl Display for Bolt11ParseError {
725726
Bolt11ParseError::DescriptionDecodeError(ref e) => {
726727
write!(f, "Description is not a valid utf-8 string: {}", e)
727728
}
728-
Bolt11ParseError::InvalidSliceLength(ref function) => {
729-
write!(f, "Slice in function {} had the wrong length", function)
729+
Bolt11ParseError::InvalidSliceLength(ref len, ref expected, ref function) => {
730+
write!(f, "Slice had length {} instead of {} in function {}", len, expected, function)
730731
}
731732
Bolt11ParseError::BadPrefix => f.write_str("did not begin with 'ln'"),
732733
Bolt11ParseError::UnknownCurrency => f.write_str("currency code unknown"),
@@ -792,9 +793,7 @@ from_error!(Bolt11ParseError::DescriptionDecodeError, str::Utf8Error);
792793

793794
impl From<CheckedHrpstringError> for Bolt11ParseError {
794795
fn from(e: CheckedHrpstringError) -> Self {
795-
match e {
796-
_ => Bolt11ParseError::Bech32Error(e)
797-
}
796+
Self::Bech32Error(e)
798797
}
799798
}
800799

lightning-invoice/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ pub enum Bolt11ParseError {
105105
InvalidPubKeyHashLength,
106106
InvalidScriptHashLength,
107107
InvalidRecoveryId,
108-
InvalidSliceLength(String),
108+
// Invalid length, with actual length, expected length, and function info
109+
InvalidSliceLength(usize, usize, String),
109110

110111
/// Not an error, but used internally to signal that a part of the invoice should be ignored
111112
/// according to BOLT11

0 commit comments

Comments
 (0)