A previous commit qualified the BOLT 12 parse error type. Qualify the
BOLT 11 parse error type for consistency.
use secp256k1::PublicKey;
use super::{Bolt11Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
use secp256k1::PublicKey;
use super::{Bolt11Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
- SemanticError, PrivateRoute, ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawBolt11Invoice,
+ SemanticError, PrivateRoute, Bolt11ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawBolt11Invoice,
constants, SignedRawBolt11Invoice, RawDataPart, InvoiceFeatures};
use self::hrp_sm::parse_hrp;
constants, SignedRawBolt11Invoice, RawDataPart, InvoiceFeatures};
use self::hrp_sm::parse_hrp;
- fn next_state(&self, read_symbol: char) -> Result<States, super::ParseError> {
+ fn next_state(&self, read_symbol: char) -> Result<States, super::Bolt11ParseError> {
match *self {
States::Start => {
if read_symbol == 'l' {
Ok(States::ParseL)
} else {
match *self {
States::Start => {
if read_symbol == 'l' {
Ok(States::ParseL)
} else {
- Err(super::ParseError::MalformedHRP)
+ Err(super::Bolt11ParseError::MalformedHRP)
}
}
States::ParseL => {
if read_symbol == 'n' {
Ok(States::ParseN)
} else {
}
}
States::ParseL => {
if read_symbol == 'n' {
Ok(States::ParseN)
} else {
- Err(super::ParseError::MalformedHRP)
+ Err(super::Bolt11ParseError::MalformedHRP)
} else if ['m', 'u', 'n', 'p'].contains(&read_symbol) {
Ok(States::ParseAmountSiPrefix)
} else {
} else if ['m', 'u', 'n', 'p'].contains(&read_symbol) {
Ok(States::ParseAmountSiPrefix)
} else {
- Err(super::ParseError::UnknownSiPrefix)
+ Err(super::Bolt11ParseError::UnknownSiPrefix)
- States::ParseAmountSiPrefix => Err(super::ParseError::MalformedHRP),
+ States::ParseAmountSiPrefix => Err(super::Bolt11ParseError::MalformedHRP),
*range = Some(new_range);
}
*range = Some(new_range);
}
- fn step(&mut self, c: char) -> Result<(), super::ParseError> {
+ fn step(&mut self, c: char) -> Result<(), super::Bolt11ParseError> {
let next_state = self.state.next_state(c)?;
match next_state {
States::ParseCurrencyPrefix => {
let next_state = self.state.next_state(c)?;
match next_state {
States::ParseCurrencyPrefix => {
- pub fn parse_hrp(input: &str) -> Result<(&str, &str, &str), super::ParseError> {
+ pub fn parse_hrp(input: &str) -> Result<(&str, &str, &str), super::Bolt11ParseError> {
let mut sm = StateMachine::new();
for c in input.chars() {
sm.step(c)?;
}
if !sm.is_final() {
let mut sm = StateMachine::new();
for c in input.chars() {
sm.step(c)?;
}
if !sm.is_final() {
- return Err(super::ParseError::MalformedHRP);
+ return Err(super::Bolt11ParseError::MalformedHRP);
}
let currency = sm.currency_prefix().clone()
}
let currency = sm.currency_prefix().clone()
impl FromStr for super::Currency {
impl FromStr for super::Currency {
+ type Err = Bolt11ParseError;
- fn from_str(currency_prefix: &str) -> Result<Self, ParseError> {
+ fn from_str(currency_prefix: &str) -> Result<Self, Bolt11ParseError> {
match currency_prefix {
"bc" => Ok(Currency::Bitcoin),
"tb" => Ok(Currency::BitcoinTestnet),
"bcrt" => Ok(Currency::Regtest),
"sb" => Ok(Currency::Simnet),
"tbs" => Ok(Currency::Signet),
match currency_prefix {
"bc" => Ok(Currency::Bitcoin),
"tb" => Ok(Currency::BitcoinTestnet),
"bcrt" => Ok(Currency::Regtest),
"sb" => Ok(Currency::Simnet),
"tbs" => Ok(Currency::Signet),
- _ => Err(ParseError::UnknownCurrency)
+ _ => Err(Bolt11ParseError::UnknownCurrency)
}
}
}
impl FromStr for SiPrefix {
}
}
}
impl FromStr for SiPrefix {
+ type Err = Bolt11ParseError;
- fn from_str(currency_prefix: &str) -> Result<Self, ParseError> {
+ fn from_str(currency_prefix: &str) -> Result<Self, Bolt11ParseError> {
use crate::SiPrefix::*;
match currency_prefix {
"m" => Ok(Milli),
"u" => Ok(Micro),
"n" => Ok(Nano),
"p" => Ok(Pico),
use crate::SiPrefix::*;
match currency_prefix {
"m" => Ok(Milli),
"u" => Ok(Micro),
"n" => Ok(Nano),
"p" => Ok(Pico),
- _ => Err(ParseError::UnknownSiPrefix)
+ _ => Err(Bolt11ParseError::UnknownSiPrefix)
/// assert_eq!(parsed_1, parsed_2);
/// ```
impl FromStr for SignedRawBolt11Invoice {
/// assert_eq!(parsed_1, parsed_2);
/// ```
impl FromStr for SignedRawBolt11Invoice {
+ type Err = Bolt11ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (hrp, data, var) = bech32::decode(s)?;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (hrp, data, var) = bech32::decode(s)?;
if var == bech32::Variant::Bech32m {
// Consider Bech32m addresses to be "Invalid Checksum", since that is what we'd get if
// we didn't support Bech32m (which lightning does not use).
if var == bech32::Variant::Bech32m {
// Consider Bech32m addresses to be "Invalid Checksum", since that is what we'd get if
// we didn't support Bech32m (which lightning does not use).
- return Err(ParseError::Bech32Error(bech32::Error::InvalidChecksum));
+ return Err(Bolt11ParseError::Bech32Error(bech32::Error::InvalidChecksum));
- return Err(ParseError::TooShortDataPart);
+ return Err(Bolt11ParseError::TooShortDataPart);
}
let raw_hrp: RawHrp = hrp.parse()?;
}
let raw_hrp: RawHrp = hrp.parse()?;
}
impl FromStr for RawHrp {
}
impl FromStr for RawHrp {
+ type Err = Bolt11ParseError;
fn from_str(hrp: &str) -> Result<Self, <Self as FromStr>::Err> {
let parts = parse_hrp(hrp)?;
fn from_str(hrp: &str) -> Result<Self, <Self as FromStr>::Err> {
let parts = parse_hrp(hrp)?;
let si: SiPrefix = parts.2.parse()?;
if let Some(amt) = amount {
if amt.checked_mul(si.multiplier()).is_none() {
let si: SiPrefix = parts.2.parse()?;
if let Some(amt) = amount {
if amt.checked_mul(si.multiplier()).is_none() {
- return Err(ParseError::IntegerOverflowError);
+ return Err(Bolt11ParseError::IntegerOverflowError);
}
impl FromBase32 for RawDataPart {
}
impl FromBase32 for RawDataPart {
+ type Err = Bolt11ParseError;
fn from_base32(data: &[u5]) -> Result<Self, Self::Err> {
if data.len() < 7 { // timestamp length
fn from_base32(data: &[u5]) -> Result<Self, Self::Err> {
if data.len() < 7 { // timestamp length
- return Err(ParseError::TooShortDataPart);
+ return Err(Bolt11ParseError::TooShortDataPart);
}
let timestamp = PositiveTimestamp::from_base32(&data[0..7])?;
}
let timestamp = PositiveTimestamp::from_base32(&data[0..7])?;
}
impl FromBase32 for PositiveTimestamp {
}
impl FromBase32 for PositiveTimestamp {
+ type Err = Bolt11ParseError;
fn from_base32(b32: &[u5]) -> Result<Self, Self::Err> {
if b32.len() != 7 {
fn from_base32(b32: &[u5]) -> Result<Self, Self::Err> {
if b32.len() != 7 {
- return Err(ParseError::InvalidSliceLength("PositiveTimestamp::from_base32()".into()));
+ return Err(Bolt11ParseError::InvalidSliceLength("PositiveTimestamp::from_base32()".into()));
}
let timestamp: u64 = parse_int_be(b32, 32)
.expect("7*5bit < 64bit, no overflow possible");
}
let timestamp: u64 = parse_int_be(b32, 32)
.expect("7*5bit < 64bit, no overflow possible");
}
impl FromBase32 for InvoiceSignature {
}
impl FromBase32 for InvoiceSignature {
+ type Err = Bolt11ParseError;
fn from_base32(signature: &[u5]) -> Result<Self, Self::Err> {
if signature.len() != 104 {
fn from_base32(signature: &[u5]) -> Result<Self, Self::Err> {
if signature.len() != 104 {
- return Err(ParseError::InvalidSliceLength("InvoiceSignature::from_base32()".into()));
+ return Err(Bolt11ParseError::InvalidSliceLength("InvoiceSignature::from_base32()".into()));
}
let recoverable_signature_bytes = Vec::<u8>::from_base32(signature)?;
let signature = &recoverable_signature_bytes[0..64];
}
let recoverable_signature_bytes = Vec::<u8>::from_base32(signature)?;
let signature = &recoverable_signature_bytes[0..64];
-fn parse_tagged_parts(data: &[u5]) -> Result<Vec<RawTaggedField>, ParseError> {
+fn parse_tagged_parts(data: &[u5]) -> Result<Vec<RawTaggedField>, Bolt11ParseError> {
let mut parts = Vec::<RawTaggedField>::new();
let mut data = data;
while !data.is_empty() {
if data.len() < 3 {
let mut parts = Vec::<RawTaggedField>::new();
let mut data = data;
while !data.is_empty() {
if data.len() < 3 {
- return Err(ParseError::UnexpectedEndOfTaggedFields);
+ return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields);
}
// Ignore tag at data[0], it will be handled in the TaggedField parsers and
}
// Ignore tag at data[0], it will be handled in the TaggedField parsers and
let last_element = 3 + len;
if data.len() < last_element {
let last_element = 3 + len;
if data.len() < last_element {
- return Err(ParseError::UnexpectedEndOfTaggedFields);
+ return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields);
}
// Get the tagged field's data slice
}
// Get the tagged field's data slice
Ok(field) => {
parts.push(RawTaggedField::KnownSemantics(field))
},
Ok(field) => {
parts.push(RawTaggedField::KnownSemantics(field))
},
- Err(ParseError::Skip)|Err(ParseError::Bech32Error(bech32::Error::InvalidLength)) => {
+ Err(Bolt11ParseError::Skip)|Err(Bolt11ParseError::Bech32Error(bech32::Error::InvalidLength)) => {
parts.push(RawTaggedField::UnknownSemantics(field.into()))
},
Err(e) => {return Err(e)}
parts.push(RawTaggedField::UnknownSemantics(field.into()))
},
Err(e) => {return Err(e)}
}
impl FromBase32 for TaggedField {
}
impl FromBase32 for TaggedField {
+ type Err = Bolt11ParseError;
- fn from_base32(field: &[u5]) -> Result<TaggedField, ParseError> {
+ fn from_base32(field: &[u5]) -> Result<TaggedField, Bolt11ParseError> {
- return Err(ParseError::UnexpectedEndOfTaggedFields);
+ return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields);
Ok(TaggedField::Features(InvoiceFeatures::from_base32(field_data)?)),
_ => {
// "A reader MUST skip over unknown fields"
Ok(TaggedField::Features(InvoiceFeatures::from_base32(field_data)?)),
_ => {
// "A reader MUST skip over unknown fields"
+ Err(Bolt11ParseError::Skip)
}
}
}
}
impl FromBase32 for Sha256 {
}
}
}
}
impl FromBase32 for Sha256 {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<Sha256, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<Sha256, Bolt11ParseError> {
if field_data.len() != 52 {
// "A reader MUST skip over […] a p, [or] h […] field that does not have data_length 52 […]."
if field_data.len() != 52 {
// "A reader MUST skip over […] a p, [or] h […] field that does not have data_length 52 […]."
+ Err(Bolt11ParseError::Skip)
} else {
Ok(Sha256(sha256::Hash::from_slice(&Vec::<u8>::from_base32(field_data)?)
.expect("length was checked before (52 u5 -> 32 u8)")))
} else {
Ok(Sha256(sha256::Hash::from_slice(&Vec::<u8>::from_base32(field_data)?)
.expect("length was checked before (52 u5 -> 32 u8)")))
}
impl FromBase32 for Description {
}
impl FromBase32 for Description {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<Description, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<Description, Bolt11ParseError> {
let bytes = Vec::<u8>::from_base32(field_data)?;
let description = String::from(str::from_utf8(&bytes)?);
Ok(Description::new(description).expect(
let bytes = Vec::<u8>::from_base32(field_data)?;
let description = String::from(str::from_utf8(&bytes)?);
Ok(Description::new(description).expect(
}
impl FromBase32 for PayeePubKey {
}
impl FromBase32 for PayeePubKey {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<PayeePubKey, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<PayeePubKey, Bolt11ParseError> {
if field_data.len() != 53 {
// "A reader MUST skip over […] a n […] field that does not have data_length 53 […]."
if field_data.len() != 53 {
// "A reader MUST skip over […] a n […] field that does not have data_length 53 […]."
+ Err(Bolt11ParseError::Skip)
} else {
let data_bytes = Vec::<u8>::from_base32(field_data)?;
let pub_key = PublicKey::from_slice(&data_bytes)?;
} else {
let data_bytes = Vec::<u8>::from_base32(field_data)?;
let pub_key = PublicKey::from_slice(&data_bytes)?;
}
impl FromBase32 for ExpiryTime {
}
impl FromBase32 for ExpiryTime {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<ExpiryTime, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<ExpiryTime, Bolt11ParseError> {
match parse_int_be::<u64, u5>(field_data, 32)
.map(ExpiryTime::from_seconds)
{
Some(t) => Ok(t),
match parse_int_be::<u64, u5>(field_data, 32)
.map(ExpiryTime::from_seconds)
{
Some(t) => Ok(t),
- None => Err(ParseError::IntegerOverflowError),
+ None => Err(Bolt11ParseError::IntegerOverflowError),
}
}
}
impl FromBase32 for MinFinalCltvExpiryDelta {
}
}
}
impl FromBase32 for MinFinalCltvExpiryDelta {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<MinFinalCltvExpiryDelta, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<MinFinalCltvExpiryDelta, Bolt11ParseError> {
let expiry = parse_int_be::<u64, u5>(field_data, 32);
if let Some(expiry) = expiry {
Ok(MinFinalCltvExpiryDelta(expiry))
} else {
let expiry = parse_int_be::<u64, u5>(field_data, 32);
if let Some(expiry) = expiry {
Ok(MinFinalCltvExpiryDelta(expiry))
} else {
- Err(ParseError::IntegerOverflowError)
+ Err(Bolt11ParseError::IntegerOverflowError)
}
}
}
impl FromBase32 for Fallback {
}
}
}
impl FromBase32 for Fallback {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<Fallback, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<Fallback, Bolt11ParseError> {
if field_data.is_empty() {
if field_data.is_empty() {
- return Err(ParseError::UnexpectedEndOfTaggedFields);
+ return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields);
}
let version = field_data[0];
}
let version = field_data[0];
match version.to_u8() {
0..=16 => {
if bytes.len() < 2 || bytes.len() > 40 {
match version.to_u8() {
0..=16 => {
if bytes.len() < 2 || bytes.len() > 40 {
- return Err(ParseError::InvalidSegWitProgramLength);
+ return Err(Bolt11ParseError::InvalidSegWitProgramLength);
}
let version = WitnessVersion::try_from(version).expect("0 through 16 are valid SegWit versions");
Ok(Fallback::SegWitProgram {
}
let version = WitnessVersion::try_from(version).expect("0 through 16 are valid SegWit versions");
Ok(Fallback::SegWitProgram {
17 => {
let pkh = match PubkeyHash::from_slice(&bytes) {
Ok(pkh) => pkh,
17 => {
let pkh = match PubkeyHash::from_slice(&bytes) {
Ok(pkh) => pkh,
- Err(bitcoin_hashes::Error::InvalidLength(_, _)) => return Err(ParseError::InvalidPubKeyHashLength),
+ Err(bitcoin_hashes::Error::InvalidLength(_, _)) => return Err(Bolt11ParseError::InvalidPubKeyHashLength),
};
Ok(Fallback::PubKeyHash(pkh))
}
18 => {
let sh = match ScriptHash::from_slice(&bytes) {
Ok(sh) => sh,
};
Ok(Fallback::PubKeyHash(pkh))
}
18 => {
let sh = match ScriptHash::from_slice(&bytes) {
Ok(sh) => sh,
- Err(bitcoin_hashes::Error::InvalidLength(_, _)) => return Err(ParseError::InvalidScriptHashLength),
+ Err(bitcoin_hashes::Error::InvalidLength(_, _)) => return Err(Bolt11ParseError::InvalidScriptHashLength),
};
Ok(Fallback::ScriptHash(sh))
}
};
Ok(Fallback::ScriptHash(sh))
}
- _ => Err(ParseError::Skip)
+ _ => Err(Bolt11ParseError::Skip)
}
}
}
impl FromBase32 for PrivateRoute {
}
}
}
impl FromBase32 for PrivateRoute {
+ type Err = Bolt11ParseError;
- fn from_base32(field_data: &[u5]) -> Result<PrivateRoute, ParseError> {
+ fn from_base32(field_data: &[u5]) -> Result<PrivateRoute, Bolt11ParseError> {
let bytes = Vec::<u8>::from_base32(field_data)?;
if bytes.len() % 51 != 0 {
let bytes = Vec::<u8>::from_base32(field_data)?;
if bytes.len() % 51 != 0 {
- return Err(ParseError::UnexpectedEndOfTaggedFields);
+ return Err(Bolt11ParseError::UnexpectedEndOfTaggedFields);
}
let mut route_hops = Vec::<RouteHintHop>::new();
}
let mut route_hops = Vec::<RouteHintHop>::new();
-impl Display for ParseError {
+impl Display for Bolt11ParseError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
// TODO: find a way to combine the first three arms (e as error::Error?)
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
// TODO: find a way to combine the first three arms (e as error::Error?)
- ParseError::Bech32Error(ref e) => {
+ Bolt11ParseError::Bech32Error(ref e) => {
write!(f, "Invalid bech32: {}", e)
}
write!(f, "Invalid bech32: {}", e)
}
- ParseError::ParseAmountError(ref e) => {
+ Bolt11ParseError::ParseAmountError(ref e) => {
write!(f, "Invalid amount in hrp ({})", e)
}
write!(f, "Invalid amount in hrp ({})", e)
}
- ParseError::MalformedSignature(ref e) => {
+ Bolt11ParseError::MalformedSignature(ref e) => {
write!(f, "Invalid secp256k1 signature: {}", e)
}
write!(f, "Invalid secp256k1 signature: {}", e)
}
- ParseError::DescriptionDecodeError(ref e) => {
+ Bolt11ParseError::DescriptionDecodeError(ref e) => {
write!(f, "Description is not a valid utf-8 string: {}", e)
}
write!(f, "Description is not a valid utf-8 string: {}", e)
}
- ParseError::InvalidSliceLength(ref function) => {
+ Bolt11ParseError::InvalidSliceLength(ref function) => {
write!(f, "Slice in function {} had the wrong length", function)
}
write!(f, "Slice in function {} had the wrong length", function)
}
- ParseError::BadPrefix => f.write_str("did not begin with 'ln'"),
- ParseError::UnknownCurrency => f.write_str("currency code unknown"),
- ParseError::UnknownSiPrefix => f.write_str("unknown SI prefix"),
- ParseError::MalformedHRP => f.write_str("malformed human readable part"),
- ParseError::TooShortDataPart => {
+ Bolt11ParseError::BadPrefix => f.write_str("did not begin with 'ln'"),
+ Bolt11ParseError::UnknownCurrency => f.write_str("currency code unknown"),
+ Bolt11ParseError::UnknownSiPrefix => f.write_str("unknown SI prefix"),
+ Bolt11ParseError::MalformedHRP => f.write_str("malformed human readable part"),
+ Bolt11ParseError::TooShortDataPart => {
f.write_str("data part too short (should be at least 111 bech32 chars long)")
},
f.write_str("data part too short (should be at least 111 bech32 chars long)")
},
- ParseError::UnexpectedEndOfTaggedFields => {
+ Bolt11ParseError::UnexpectedEndOfTaggedFields => {
f.write_str("tagged fields part ended unexpectedly")
},
f.write_str("tagged fields part ended unexpectedly")
},
- ParseError::PaddingError => f.write_str("some data field had bad padding"),
- ParseError::IntegerOverflowError => {
+ Bolt11ParseError::PaddingError => f.write_str("some data field had bad padding"),
+ Bolt11ParseError::IntegerOverflowError => {
f.write_str("parsed integer doesn't fit into receiving type")
},
f.write_str("parsed integer doesn't fit into receiving type")
},
- ParseError::InvalidSegWitProgramLength => {
+ Bolt11ParseError::InvalidSegWitProgramLength => {
f.write_str("fallback SegWit program is too long or too short")
},
f.write_str("fallback SegWit program is too long or too short")
},
- ParseError::InvalidPubKeyHashLength => {
+ Bolt11ParseError::InvalidPubKeyHashLength => {
f.write_str("fallback public key hash has a length unequal 20 bytes")
},
f.write_str("fallback public key hash has a length unequal 20 bytes")
},
- ParseError::InvalidScriptHashLength => {
+ Bolt11ParseError::InvalidScriptHashLength => {
f.write_str("fallback script hash has a length unequal 32 bytes")
},
f.write_str("fallback script hash has a length unequal 32 bytes")
},
- ParseError::InvalidRecoveryId => {
+ Bolt11ParseError::InvalidRecoveryId => {
f.write_str("recovery id is out of range (should be in [0,3])")
},
f.write_str("recovery id is out of range (should be in [0,3])")
},
+ Bolt11ParseError::Skip => {
f.write_str("the tagged field has to be skipped because of an unexpected, but allowed property")
},
}
f.write_str("the tagged field has to be skipped because of an unexpected, but allowed property")
},
}
}
#[cfg(feature = "std")]
}
#[cfg(feature = "std")]
-impl error::Error for ParseError {}
+impl error::Error for Bolt11ParseError {}
#[cfg(feature = "std")]
impl error::Error for ParseOrSemanticError {}
macro_rules! from_error {
($my_error:expr, $extern_error:ty) => {
#[cfg(feature = "std")]
impl error::Error for ParseOrSemanticError {}
macro_rules! from_error {
($my_error:expr, $extern_error:ty) => {
- impl From<$extern_error> for ParseError {
+ impl From<$extern_error> for Bolt11ParseError {
fn from(e: $extern_error) -> Self {
$my_error(e)
}
fn from(e: $extern_error) -> Self {
$my_error(e)
}
-from_error!(ParseError::MalformedSignature, secp256k1::Error);
-from_error!(ParseError::ParseAmountError, ParseIntError);
-from_error!(ParseError::DescriptionDecodeError, str::Utf8Error);
+from_error!(Bolt11ParseError::MalformedSignature, secp256k1::Error);
+from_error!(Bolt11ParseError::ParseAmountError, ParseIntError);
+from_error!(Bolt11ParseError::DescriptionDecodeError, str::Utf8Error);
-impl From<bech32::Error> for ParseError {
+impl From<bech32::Error> for Bolt11ParseError {
fn from(e: bech32::Error) -> Self {
match e {
fn from(e: bech32::Error) -> Self {
match e {
- bech32::Error::InvalidPadding => ParseError::PaddingError,
- _ => ParseError::Bech32Error(e)
+ bech32::Error::InvalidPadding => Bolt11ParseError::PaddingError,
+ _ => Bolt11ParseError::Bech32Error(e)
-impl From<ParseError> for ParseOrSemanticError {
- fn from(e: ParseError) -> Self {
+impl From<Bolt11ParseError> for ParseOrSemanticError {
+ fn from(e: Bolt11ParseError) -> Self {
ParseOrSemanticError::ParseError(e)
}
}
ParseOrSemanticError::ParseError(e)
}
}
- use crate::de::ParseError;
+ use crate::de::Bolt11ParseError;
use secp256k1::PublicKey;
use bech32::u5;
use bitcoin_hashes::hex::FromHex;
use secp256k1::PublicKey;
use bech32::u5;
use bitcoin_hashes::hex::FromHex;
assert_eq!("bcrt".parse::<Currency>(), Ok(Currency::Regtest));
assert_eq!("sb".parse::<Currency>(), Ok(Currency::Simnet));
assert_eq!("tbs".parse::<Currency>(), Ok(Currency::Signet));
assert_eq!("bcrt".parse::<Currency>(), Ok(Currency::Regtest));
assert_eq!("sb".parse::<Currency>(), Ok(Currency::Simnet));
assert_eq!("tbs".parse::<Currency>(), Ok(Currency::Signet));
- assert_eq!("something_else".parse::<Currency>(), Err(ParseError::UnknownCurrency))
+ assert_eq!("something_else".parse::<Currency>(), Err(Bolt11ParseError::UnknownCurrency))
let input_unexpected_length = from_bech32(
"qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypyq".as_bytes()
);
let input_unexpected_length = from_bech32(
"qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypyq".as_bytes()
);
- assert_eq!(Sha256::from_base32(&input_unexpected_length), Err(ParseError::Skip));
+ assert_eq!(Sha256::from_base32(&input_unexpected_length), Err(Bolt11ParseError::Skip));
let input_unexpected_length = from_bech32(
"q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhvq".as_bytes()
);
let input_unexpected_length = from_bech32(
"q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhvq".as_bytes()
);
- assert_eq!(PayeePubKey::from_base32(&input_unexpected_length), Err(ParseError::Skip));
+ assert_eq!(PayeePubKey::from_base32(&input_unexpected_length), Err(Bolt11ParseError::Skip));
assert_eq!(ExpiryTime::from_base32(&input), expected);
let input_too_large = from_bech32("sqqqqqqqqqqqq".as_bytes());
assert_eq!(ExpiryTime::from_base32(&input), expected);
let input_too_large = from_bech32("sqqqqqqqqqqqq".as_bytes());
- assert_eq!(ExpiryTime::from_base32(&input_too_large), Err(ParseError::IntegerOverflowError));
+ assert_eq!(ExpiryTime::from_base32(&input_too_large), Err(Bolt11ParseError::IntegerOverflowError));
),
(
vec![u5::try_from_u8(21).unwrap(); 41],
),
(
vec![u5::try_from_u8(21).unwrap(); 41],
+ Err(Bolt11ParseError::Skip)
- Err(ParseError::UnexpectedEndOfTaggedFields)
+ Err(Bolt11ParseError::UnexpectedEndOfTaggedFields)
),
(
vec![u5::try_from_u8(1).unwrap(); 81],
),
(
vec![u5::try_from_u8(1).unwrap(); 81],
- Err(ParseError::InvalidSegWitProgramLength)
+ Err(Bolt11ParseError::InvalidSegWitProgramLength)
),
(
vec![u5::try_from_u8(17).unwrap(); 1],
),
(
vec![u5::try_from_u8(17).unwrap(); 1],
- Err(ParseError::InvalidPubKeyHashLength)
+ Err(Bolt11ParseError::InvalidPubKeyHashLength)
),
(
vec![u5::try_from_u8(18).unwrap(); 1],
),
(
vec![u5::try_from_u8(18).unwrap(); 1],
- Err(ParseError::InvalidScriptHashLength)
+ Err(Bolt11ParseError::InvalidScriptHashLength)
assert_eq!(
PrivateRoute::from_base32(&[u5::try_from_u8(0).unwrap(); 40][..]),
assert_eq!(
PrivateRoute::from_base32(&[u5::try_from_u8(0).unwrap(); 40][..]),
- Err(ParseError::UnexpectedEndOfTaggedFields)
+ Err(Bolt11ParseError::UnexpectedEndOfTaggedFields)
/// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
#[allow(missing_docs)]
#[derive(PartialEq, Eq, Debug, Clone)]
/// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
#[allow(missing_docs)]
#[derive(PartialEq, Eq, Debug, Clone)]
+pub enum Bolt11ParseError {
Bech32Error(bech32::Error),
ParseAmountError(ParseIntError),
MalformedSignature(secp256k1::Error),
Bech32Error(bech32::Error),
ParseAmountError(ParseIntError),
MalformedSignature(secp256k1::Error),
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum ParseOrSemanticError {
/// The invoice couldn't be decoded
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum ParseOrSemanticError {
/// The invoice couldn't be decoded
- ParseError(ParseError),
+ ParseError(Bolt11ParseError),
/// The invoice could be decoded but violates the BOLT11 standard
SemanticError(crate::SemanticError),
/// The invoice could be decoded but violates the BOLT11 standard
SemanticError(crate::SemanticError),
), Err(ParseOrSemanticError::SemanticError(SemanticError::InvalidFeatures)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt"
), Err(ParseOrSemanticError::SemanticError(SemanticError::InvalidFeatures)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt"
- ), Err(ParseOrSemanticError::ParseError(ParseError::Bech32Error(bech32::Error::InvalidChecksum))));
+ ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::InvalidChecksum))));
assert_eq!(Bolt11Invoice::from_str(
"pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
assert_eq!(Bolt11Invoice::from_str(
"pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
- ), Err(ParseOrSemanticError::ParseError(ParseError::Bech32Error(bech32::Error::MissingSeparator))));
+ ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MissingSeparator))));
assert_eq!(Bolt11Invoice::from_str(
"LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
assert_eq!(Bolt11Invoice::from_str(
"LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
- ), Err(ParseOrSemanticError::ParseError(ParseError::Bech32Error(bech32::Error::MixedCase))));
+ ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MixedCase))));
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqwgt7mcn5yqw3yx0w94pswkpq6j9uh6xfqqqtsk4tnarugeektd4hg5975x9am52rz4qskukxdmjemg92vvqz8nvmsye63r5ykel43pgz7zq0g2"
), Err(ParseOrSemanticError::SemanticError(SemanticError::InvalidSignature)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh"
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqwgt7mcn5yqw3yx0w94pswkpq6j9uh6xfqqqtsk4tnarugeektd4hg5975x9am52rz4qskukxdmjemg92vvqz8nvmsye63r5ykel43pgz7zq0g2"
), Err(ParseOrSemanticError::SemanticError(SemanticError::InvalidSignature)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh"
- ), Err(ParseOrSemanticError::ParseError(ParseError::TooShortDataPart)));
+ ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::TooShortDataPart)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqrrzc4cvfue4zp3hggxp47ag7xnrlr8vgcmkjxk3j5jqethnumgkpqp23z9jclu3v0a7e0aruz366e9wqdykw6dxhdzcjjhldxq0w6wgqcnu43j"
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqrrzc4cvfue4zp3hggxp47ag7xnrlr8vgcmkjxk3j5jqethnumgkpqp23z9jclu3v0a7e0aruz366e9wqdykw6dxhdzcjjhldxq0w6wgqcnu43j"
- ), Err(ParseOrSemanticError::ParseError(ParseError::UnknownSiPrefix)));
+ ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::UnknownSiPrefix)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x"
), Err(ParseOrSemanticError::SemanticError(SemanticError::ImpreciseAmount)));
assert_eq!(Bolt11Invoice::from_str(
"lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x"
), Err(ParseOrSemanticError::SemanticError(SemanticError::ImpreciseAmount)));