From f4d0584a3694ee3a414e95d58649f13b3b62e7e1 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 14 Nov 2024 11:45:45 +0100 Subject: [PATCH 01/13] `rustfmt`: Prepare `lightning-invoice/src/de.rs` --- lightning-invoice/src/de.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lightning-invoice/src/de.rs b/lightning-invoice/src/de.rs index da43edc5b6b..8e06f326ccd 100644 --- a/lightning-invoice/src/de.rs +++ b/lightning-invoice/src/de.rs @@ -446,12 +446,13 @@ impl FromBase32 for RawDataPart { type Err = Bolt11ParseError; fn from_base32(data: &[Fe32]) -> Result { - if data.len() < 7 { // timestamp length + const TIMESTAMP_LEN: usize = 7; + if data.len() < TIMESTAMP_LEN { return Err(Bolt11ParseError::TooShortDataPart); } - let timestamp = PositiveTimestamp::from_base32(&data[0..7])?; - let tagged = parse_tagged_parts(&data[7..])?; + let timestamp = PositiveTimestamp::from_base32(&data[0..TIMESTAMP_LEN])?; + let tagged = parse_tagged_parts(&data[TIMESTAMP_LEN..])?; Ok(RawDataPart { timestamp, From 97537c5ac97b434e111ae0c049cea1128a2d3a6b Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:08:41 +0100 Subject: [PATCH 02/13] `rustfmt`: Run on `lightning-invoice/src/de.rs` --- lightning-invoice/src/de.rs | 494 ++++++++++++++++++------------------ 1 file changed, 242 insertions(+), 252 deletions(-) diff --git a/lightning-invoice/src/de.rs b/lightning-invoice/src/de.rs index 8e06f326ccd..ee071d6349a 100644 --- a/lightning-invoice/src/de.rs +++ b/lightning-invoice/src/de.rs @@ -1,29 +1,32 @@ use alloc::string; -#[cfg(feature = "std")] -use std::error; #[cfg(not(feature = "std"))] use core::convert::TryFrom; use core::fmt; use core::fmt::{Display, Formatter}; use core::num::ParseIntError; use core::str::FromStr; +#[cfg(feature = "std")] +use std::error; use bech32::primitives::decode::{CheckedHrpstring, CheckedHrpstringError}; use bech32::{Bech32, Fe32, Fe32IterExt}; -use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion}; -use bitcoin::hashes::Hash; -use bitcoin::hashes::sha256; use crate::prelude::*; +use bitcoin::hashes::sha256; +use bitcoin::hashes::Hash; +use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion}; use lightning_types::payment::PaymentSecret; -use lightning_types::routing::{RoutingFees, RouteHint, RouteHintHop}; +use lightning_types::routing::{RouteHint, RouteHintHop, RoutingFees}; -use bitcoin::secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; +use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; use bitcoin::secp256k1::PublicKey; -use super::{Bolt11Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, Bolt11InvoiceSignature, PositiveTimestamp, - Bolt11SemanticError, PrivateRoute, Bolt11ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawBolt11Invoice, - constants, SignedRawBolt11Invoice, RawDataPart, Bolt11InvoiceFeatures}; +use super::{ + constants, Bolt11Invoice, Bolt11InvoiceFeatures, Bolt11InvoiceSignature, Bolt11ParseError, + Bolt11SemanticError, Currency, Description, ExpiryTime, Fallback, MinFinalCltvExpiryDelta, + ParseOrSemanticError, PayeePubKey, PositiveTimestamp, PrivateRoute, RawBolt11Invoice, + RawDataPart, RawHrp, RawTaggedField, Sha256, SiPrefix, SignedRawBolt11Invoice, TaggedField, +}; use self::hrp_sm::parse_hrp; @@ -63,9 +66,7 @@ impl FromBase32 for [u8; N] { count += 1; } if count != N { - return Err(Bolt11ParseError::InvalidSliceLength( - count, N, "<[u8; N]>", - )); + return Err(Bolt11ParseError::InvalidSliceLength(count, N, "<[u8; N]>")); } Ok(res_arr) } @@ -165,7 +166,7 @@ mod hrp_sm { } else { Err(super::Bolt11ParseError::MalformedHRP) } - } + }, States::ParseL => { if read_symbol == 'n' { Ok(States::ParseN) @@ -205,7 +206,6 @@ mod hrp_sm { } } - struct StateMachine { state: States, position: usize, @@ -227,8 +227,8 @@ mod hrp_sm { fn update_range(range: &mut Option>, position: usize) { let new_range = match *range { - None => Range {start: position, end: position + 1}, - Some(ref r) => Range {start: r.start, end: r.end + 1}, + None => Range { start: position, end: position + 1 }, + Some(ref r) => Range { start: r.start, end: r.end + 1 }, }; *range = Some(new_range); } @@ -238,14 +238,14 @@ mod hrp_sm { match next_state { States::ParseCurrencyPrefix => { StateMachine::update_range(&mut self.currency_prefix, self.position) - } + }, States::ParseAmountNumber => { StateMachine::update_range(&mut self.amount_number, self.position) }, States::ParseAmountSiPrefix => { StateMachine::update_range(&mut self.amount_si_prefix, self.position) }, - _ => {} + _ => {}, } self.position += 1; @@ -280,18 +280,14 @@ mod hrp_sm { return Err(super::Bolt11ParseError::MalformedHRP); } - let currency = sm.currency_prefix().clone() - .map(|r| &input[r]).unwrap_or(""); - let amount = sm.amount_number().clone() - .map(|r| &input[r]).unwrap_or(""); - let si = sm.amount_si_prefix().clone() - .map(|r| &input[r]).unwrap_or(""); + let currency = sm.currency_prefix().clone().map(|r| &input[r]).unwrap_or(""); + let amount = sm.amount_number().clone().map(|r| &input[r]).unwrap_or(""); + let si = sm.amount_si_prefix().clone().map(|r| &input[r]).unwrap_or(""); Ok((currency, amount, si)) } } - impl FromStr for super::Currency { type Err = Bolt11ParseError; @@ -302,7 +298,7 @@ impl FromStr for super::Currency { "bcrt" => Ok(Currency::Regtest), "sb" => Ok(Currency::Simnet), "tbs" => Ok(Currency::Signet), - _ => Err(Bolt11ParseError::UnknownCurrency) + _ => Err(Bolt11ParseError::UnknownCurrency), } } } @@ -317,7 +313,7 @@ impl FromStr for SiPrefix { "u" => Ok(Micro), "n" => Ok(Nano), "p" => Ok(Pico), - _ => Err(Bolt11ParseError::UnknownSiPrefix) + _ => Err(Bolt11ParseError::UnknownSiPrefix), } } } @@ -394,10 +390,7 @@ impl FromStr for SignedRawBolt11Invoice { let raw_hrp: RawHrp = hrp.to_string().to_lowercase().parse()?; let data_part = RawDataPart::from_base32(&data[..data.len() - SIGNATURE_LEN_5])?; - let raw_invoice = RawBolt11Invoice { - hrp: raw_hrp, - data: data_part, - }; + let raw_invoice = RawBolt11Invoice { hrp: raw_hrp, data: data_part }; let hash = raw_invoice.signable_hash(); Ok(SignedRawBolt11Invoice { @@ -416,11 +409,7 @@ impl FromStr for RawHrp { let currency = parts.0.parse::()?; - let amount = if !parts.1.is_empty() { - Some(parts.1.parse::()?) - } else { - None - }; + let amount = if !parts.1.is_empty() { Some(parts.1.parse::()?) } else { None }; let si_prefix: Option = if parts.2.is_empty() { None @@ -434,11 +423,7 @@ impl FromStr for RawHrp { Some(si) }; - Ok(RawHrp { - currency, - raw_amount: amount, - si_prefix, - }) + Ok(RawHrp { currency, raw_amount: amount, si_prefix }) } } @@ -454,10 +439,7 @@ impl FromBase32 for RawDataPart { let timestamp = PositiveTimestamp::from_base32(&data[0..TIMESTAMP_LEN])?; let tagged = parse_tagged_parts(&data[TIMESTAMP_LEN..])?; - Ok(RawDataPart { - timestamp, - tagged_fields: tagged, - }) + Ok(RawDataPart { timestamp, tagged_fields: tagged }) } } @@ -466,14 +448,9 @@ impl FromBase32 for PositiveTimestamp { fn from_base32(b32: &[Fe32]) -> Result { if b32.len() != 7 { - return Err(Bolt11ParseError::InvalidSliceLength( - b32.len(), - 7, - "PositiveTimestamp", - )); + return Err(Bolt11ParseError::InvalidSliceLength(b32.len(), 7, "PositiveTimestamp")); } - let timestamp: u64 = parse_u64_be(b32) - .expect("7*5bit < 64bit, no overflow possible"); + let timestamp: u64 = parse_u64_be(b32).expect("7*5bit < 64bit, no overflow possible"); match PositiveTimestamp::from_unix_timestamp(timestamp) { Ok(t) => Ok(t), Err(_) => unreachable!(), @@ -495,22 +472,20 @@ impl FromBase32 for Bolt11InvoiceSignature { let signature = &recoverable_signature_bytes[0..64]; let recovery_id = RecoveryId::from_i32(recoverable_signature_bytes[64] as i32)?; - Ok(Bolt11InvoiceSignature(RecoverableSignature::from_compact( - signature, - recovery_id - )?)) + Ok(Bolt11InvoiceSignature(RecoverableSignature::from_compact(signature, recovery_id)?)) } } -macro_rules! define_parse_int_be { ($name: ident, $ty: ty) => { - fn $name(digits: &[Fe32]) -> Option<$ty> { - digits.iter().fold(Some(Default::default()), |acc, b| - acc - .and_then(|x| x.checked_mul(32)) - .and_then(|x| x.checked_add((Into::::into(*b)).into())) - ) - } -} } +macro_rules! define_parse_int_be { + ($name: ident, $ty: ty) => { + fn $name(digits: &[Fe32]) -> Option<$ty> { + digits.iter().fold(Some(Default::default()), |acc, b| { + acc.and_then(|x| x.checked_mul(32)) + .and_then(|x| x.checked_add((Into::::into(*b)).into())) + }) + } + }; +} define_parse_int_be!(parse_u16_be, u16); define_parse_int_be!(parse_u64_be, u64); @@ -539,15 +514,13 @@ fn parse_tagged_parts(data: &[Fe32]) -> Result, Bolt11ParseE data = &data[last_element..]; match TaggedField::from_base32(field) { - Ok(field) => { - parts.push(RawTaggedField::KnownSemantics(field)) - }, + Ok(field) => parts.push(RawTaggedField::KnownSemantics(field)), Err(Bolt11ParseError::Skip) | Err(Bolt11ParseError::InvalidSliceLength(_, _, _)) | Err(Bolt11ParseError::Bech32Error(_)) => { parts.push(RawTaggedField::UnknownSemantics(field.into())) }, - Err(e) => {return Err(e)} + Err(e) => return Err(e), } } Ok(parts) @@ -562,35 +535,46 @@ impl FromBase32 for TaggedField { } let tag = field[0]; - let field_data = &field[3..]; + let field_data = &field[3..]; match tag.to_u8() { - constants::TAG_PAYMENT_HASH => - Ok(TaggedField::PaymentHash(Sha256::from_base32(field_data)?)), - constants::TAG_DESCRIPTION => - Ok(TaggedField::Description(Description::from_base32(field_data)?)), - constants::TAG_PAYEE_PUB_KEY => - Ok(TaggedField::PayeePubKey(PayeePubKey::from_base32(field_data)?)), - constants::TAG_DESCRIPTION_HASH => - Ok(TaggedField::DescriptionHash(Sha256::from_base32(field_data)?)), - constants::TAG_EXPIRY_TIME => - Ok(TaggedField::ExpiryTime(ExpiryTime::from_base32(field_data)?)), - constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA => - Ok(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta::from_base32(field_data)?)), - constants::TAG_FALLBACK => - Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)), - constants::TAG_PRIVATE_ROUTE => - Ok(TaggedField::PrivateRoute(PrivateRoute::from_base32(field_data)?)), - constants::TAG_PAYMENT_SECRET => - Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)), - constants::TAG_PAYMENT_METADATA => - Ok(TaggedField::PaymentMetadata(Vec::::from_base32(field_data)?)), - constants::TAG_FEATURES => - Ok(TaggedField::Features(Bolt11InvoiceFeatures::from_base32(field_data)?)), + constants::TAG_PAYMENT_HASH => { + Ok(TaggedField::PaymentHash(Sha256::from_base32(field_data)?)) + }, + constants::TAG_DESCRIPTION => { + Ok(TaggedField::Description(Description::from_base32(field_data)?)) + }, + constants::TAG_PAYEE_PUB_KEY => { + Ok(TaggedField::PayeePubKey(PayeePubKey::from_base32(field_data)?)) + }, + constants::TAG_DESCRIPTION_HASH => { + Ok(TaggedField::DescriptionHash(Sha256::from_base32(field_data)?)) + }, + constants::TAG_EXPIRY_TIME => { + Ok(TaggedField::ExpiryTime(ExpiryTime::from_base32(field_data)?)) + }, + constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA => Ok(TaggedField::MinFinalCltvExpiryDelta( + MinFinalCltvExpiryDelta::from_base32(field_data)?, + )), + constants::TAG_FALLBACK => { + Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)) + }, + constants::TAG_PRIVATE_ROUTE => { + Ok(TaggedField::PrivateRoute(PrivateRoute::from_base32(field_data)?)) + }, + constants::TAG_PAYMENT_SECRET => { + Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)) + }, + constants::TAG_PAYMENT_METADATA => { + Ok(TaggedField::PaymentMetadata(Vec::::from_base32(field_data)?)) + }, + constants::TAG_FEATURES => { + Ok(TaggedField::Features(Bolt11InvoiceFeatures::from_base32(field_data)?)) + }, _ => { // "A reader MUST skip over unknown fields" Err(Bolt11ParseError::Skip) - } + }, } } } @@ -603,8 +587,10 @@ impl FromBase32 for Sha256 { // "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(&<[u8; 32]>::from_base32(field_data)?) - .expect("length was checked before (52 u5 -> 32 u8)"))) + Ok(Sha256( + sha256::Hash::from_slice(&<[u8; 32]>::from_base32(field_data)?) + .expect("length was checked before (52 u5 -> 32 u8)"), + )) } } } @@ -615,9 +601,8 @@ impl FromBase32 for Description { fn from_base32(field_data: &[Fe32]) -> Result { let bytes = Vec::::from_base32(field_data)?; let description = String::from_utf8(bytes)?; - Ok(Description::new(description).expect( - "Max len is 639=floor(1023*5/8) since the len field is only 10bits long" - )) + Ok(Description::new(description) + .expect("Max len is 639=floor(1023*5/8) since the len field is only 10bits long")) } } @@ -640,9 +625,7 @@ impl FromBase32 for ExpiryTime { type Err = Bolt11ParseError; fn from_base32(field_data: &[Fe32]) -> Result { - match parse_u64_be(field_data) - .map(ExpiryTime::from_seconds) - { + match parse_u64_be(field_data).map(ExpiryTime::from_seconds) { Some(t) => Ok(t), None => Err(Bolt11ParseError::IntegerOverflowError), } @@ -678,11 +661,9 @@ impl FromBase32 for Fallback { if bytes.len() < 2 || bytes.len() > 40 { return Err(Bolt11ParseError::InvalidSegWitProgramLength); } - let version = WitnessVersion::try_from(version).expect("0 through 16 are valid SegWit versions"); - Ok(Fallback::SegWitProgram { - version, - program: bytes - }) + let version = WitnessVersion::try_from(version) + .expect("0 through 16 are valid SegWit versions"); + Ok(Fallback::SegWitProgram { version, program: bytes }) }, 17 => { let pkh = match PubkeyHash::from_slice(&bytes) { @@ -690,15 +671,15 @@ impl FromBase32 for Fallback { Err(_) => return Err(Bolt11ParseError::InvalidPubKeyHashLength), }; Ok(Fallback::PubKeyHash(pkh)) - } + }, 18 => { let sh = match ScriptHash::from_slice(&bytes) { Ok(sh) => sh, Err(_) => return Err(Bolt11ParseError::InvalidScriptHashLength), }; Ok(Fallback::ScriptHash(sh)) - } - _ => Err(Bolt11ParseError::Skip) + }, + _ => Err(Bolt11ParseError::Skip), } } } @@ -727,10 +708,16 @@ impl FromBase32 for PrivateRoute { src_node_id: PublicKey::from_slice(&hop_bytes[0..33])?, short_channel_id: u64::from_be_bytes(channel_id), fees: RoutingFees { - base_msat: u32::from_be_bytes(hop_bytes[41..45].try_into().expect("slice too big?")), - proportional_millionths: u32::from_be_bytes(hop_bytes[45..49].try_into().expect("slice too big?")), + base_msat: u32::from_be_bytes( + hop_bytes[41..45].try_into().expect("slice too big?"), + ), + proportional_millionths: u32::from_be_bytes( + hop_bytes[45..49].try_into().expect("slice too big?"), + ), }, - cltv_expiry_delta: u16::from_be_bytes(hop_bytes[49..51].try_into().expect("slice too big?")), + cltv_expiry_delta: u16::from_be_bytes( + hop_bytes[49..51].try_into().expect("slice too big?"), + ), htlc_minimum_msat: None, htlc_maximum_msat: None, }; @@ -748,22 +735,18 @@ impl Display for Bolt11ParseError { // TODO: find a way to combine the first three arms (e as error::Error?) Bolt11ParseError::Bech32Error(ref e) => { write!(f, "Invalid bech32: {}", e) - } + }, Bolt11ParseError::ParseAmountError(ref e) => { write!(f, "Invalid amount in hrp ({})", e) - } + }, Bolt11ParseError::MalformedSignature(ref e) => { write!(f, "Invalid secp256k1 signature: {}", e) - } + }, Bolt11ParseError::DescriptionDecodeError(ref e) => { write!(f, "Description is not a valid utf-8 string: {}", e) - } + }, Bolt11ParseError::InvalidSliceLength(ref len, ref expected, ref elemen) => { - write!( - f, - "Slice had length {} instead of {} for element {}", - len, expected, elemen - ) + write!(f, "Slice had length {} instead of {} for element {}", len, expected, elemen) }, Bolt11ParseError::BadPrefix => f.write_str("did not begin with 'ln'"), Bolt11ParseError::UnknownCurrency => f.write_str("currency code unknown"), @@ -791,9 +774,9 @@ impl Display for Bolt11ParseError { Bolt11ParseError::InvalidRecoveryId => { 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") - }, + Bolt11ParseError::Skip => f.write_str( + "the tagged field has to be skipped because of an unexpected, but allowed property", + ), } } } @@ -814,13 +797,13 @@ impl error::Error for Bolt11ParseError {} impl error::Error for ParseOrSemanticError {} macro_rules! from_error { - ($my_error:expr, $extern_error:ty) => { - impl From<$extern_error> for Bolt11ParseError { - fn from(e: $extern_error) -> Self { - $my_error(e) - } - } - } + ($my_error:expr, $extern_error:ty) => { + impl From<$extern_error> for Bolt11ParseError { + fn from(e: $extern_error) -> Self { + $my_error(e) + } + } + }; } from_error!(Bolt11ParseError::MalformedSignature, bitcoin::secp256k1::Error); @@ -849,27 +832,22 @@ impl From for ParseOrSemanticError { mod test { use super::FromBase32; use crate::de::Bolt11ParseError; - use bitcoin::secp256k1::PublicKey; use bech32::Fe32; use bitcoin::hashes::sha256; + use bitcoin::secp256k1::PublicKey; use std::str::FromStr; const CHARSET_REV: [i8; 128] = [ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, + 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, + -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, + 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, ]; fn from_bech32(bytes_5b: &[u8]) -> Vec { - bytes_5b - .iter() - .map(|c| Fe32::try_from(CHARSET_REV[*c as usize] as u8).unwrap()) - .collect() + bytes_5b.iter().map(|c| Fe32::try_from(CHARSET_REV[*c as usize] as u8).unwrap()).collect() } #[test] @@ -888,35 +866,43 @@ mod test { fn test_parse_int_from_bytes_be() { use crate::de::parse_u16_be; - assert_eq!(parse_u16_be(&[ - Fe32::try_from(1).unwrap(), Fe32::try_from(2).unwrap(), - Fe32::try_from(3).unwrap(), Fe32::try_from(4).unwrap(), - ]), Some(34916)); - assert_eq!(parse_u16_be(&[ - Fe32::try_from(2).unwrap(), Fe32::try_from(0).unwrap(), - Fe32::try_from(0).unwrap(), Fe32::try_from(0).unwrap(), - ]), None); + assert_eq!( + parse_u16_be(&[ + Fe32::try_from(1).unwrap(), + Fe32::try_from(2).unwrap(), + Fe32::try_from(3).unwrap(), + Fe32::try_from(4).unwrap(), + ]), + Some(34916) + ); + assert_eq!( + parse_u16_be(&[ + Fe32::try_from(2).unwrap(), + Fe32::try_from(0).unwrap(), + Fe32::try_from(0).unwrap(), + Fe32::try_from(0).unwrap(), + ]), + None + ); } #[test] fn test_parse_sha256_hash() { use crate::Sha256; - let input = from_bech32( - "qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq".as_bytes() - ); + let input = from_bech32("qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq".as_bytes()); let hash = sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap(); + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(); let expected = Ok(Sha256(hash)); assert_eq!(Sha256::from_base32(&input), expected); // make sure hashes of unknown length get skipped - 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(Bolt11ParseError::Skip)); } @@ -937,18 +923,15 @@ mod test { let pk_bytes = [ 0x03, 0xe7, 0x15, 0x6a, 0xe3, 0x3b, 0x0a, 0x20, 0x8d, 0x07, 0x44, 0x19, 0x91, 0x63, 0x17, 0x7e, 0x90, 0x9e, 0x80, 0x17, 0x6e, 0x55, 0xd9, 0x7a, 0x2f, 0x22, 0x1e, 0xde, - 0x0f, 0x93, 0x4d, 0xd9, 0xad + 0x0f, 0x93, 0x4d, 0xd9, 0xad, ]; - let expected = Ok(PayeePubKey( - PublicKey::from_slice(&pk_bytes[..]).unwrap() - )); + let expected = Ok(PayeePubKey(PublicKey::from_slice(&pk_bytes[..]).unwrap())); assert_eq!(PayeePubKey::from_base32(&input), expected); // expects 33 bytes - 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(Bolt11ParseError::Skip)); } @@ -961,7 +944,10 @@ mod test { 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(Bolt11ParseError::IntegerOverflowError)); + assert_eq!( + ExpiryTime::from_base32(&input_too_large), + Err(Bolt11ParseError::IntegerOverflowError) + ); } #[test] @@ -977,54 +963,50 @@ mod test { #[test] fn test_parse_fallback() { use crate::Fallback; - use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion}; use bitcoin::hashes::Hash; + use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion}; let cases = vec![ ( from_bech32("3x9et2e20v6pu37c5d9vax37wxq72un98".as_bytes()), - Ok(Fallback::PubKeyHash(PubkeyHash::from_slice(&[ - 0x31, 0x72, 0xb5, 0x65, 0x4f, 0x66, 0x83, 0xc8, 0xfb, 0x14, 0x69, 0x59, 0xd3, - 0x47, 0xce, 0x30, 0x3c, 0xae, 0x4c, 0xa7 - ]).unwrap())) + Ok(Fallback::PubKeyHash( + PubkeyHash::from_slice(&[ + 0x31, 0x72, 0xb5, 0x65, 0x4f, 0x66, 0x83, 0xc8, 0xfb, 0x14, 0x69, 0x59, + 0xd3, 0x47, 0xce, 0x30, 0x3c, 0xae, 0x4c, 0xa7, + ]) + .unwrap(), + )), ), ( from_bech32("j3a24vwu6r8ejrss3axul8rxldph2q7z9".as_bytes()), - Ok(Fallback::ScriptHash(ScriptHash::from_slice(&[ - 0x8f, 0x55, 0x56, 0x3b, 0x9a, 0x19, 0xf3, 0x21, 0xc2, 0x11, 0xe9, 0xb9, 0xf3, - 0x8c, 0xdf, 0x68, 0x6e, 0xa0, 0x78, 0x45 - ]).unwrap())) + Ok(Fallback::ScriptHash( + ScriptHash::from_slice(&[ + 0x8f, 0x55, 0x56, 0x3b, 0x9a, 0x19, 0xf3, 0x21, 0xc2, 0x11, 0xe9, 0xb9, + 0xf3, 0x8c, 0xdf, 0x68, 0x6e, 0xa0, 0x78, 0x45, + ]) + .unwrap(), + )), ), ( from_bech32("qw508d6qejxtdg4y5r3zarvary0c5xw7k".as_bytes()), Ok(Fallback::SegWitProgram { version: WitnessVersion::V0, - program: Vec::from(&[ - 0x75u8, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, 0x45, - 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6 - ][..]) - }) - ), - ( - vec![Fe32::try_from(21).unwrap(); 41], - Err(Bolt11ParseError::Skip) - ), - ( - vec![], - Err(Bolt11ParseError::UnexpectedEndOfTaggedFields) + program: Vec::from( + &[ + 0x75u8, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, + 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6, + ][..], + ), + }), ), + (vec![Fe32::try_from(21).unwrap(); 41], Err(Bolt11ParseError::Skip)), + (vec![], Err(Bolt11ParseError::UnexpectedEndOfTaggedFields)), ( vec![Fe32::try_from(1).unwrap(); 81], - Err(Bolt11ParseError::InvalidSegWitProgramLength) + Err(Bolt11ParseError::InvalidSegWitProgramLength), ), - ( - vec![Fe32::try_from(17).unwrap(); 1], - Err(Bolt11ParseError::InvalidPubKeyHashLength) - ), - ( - vec![Fe32::try_from(18).unwrap(); 1], - Err(Bolt11ParseError::InvalidScriptHashLength) - ) + (vec![Fe32::try_from(17).unwrap(); 1], Err(Bolt11ParseError::InvalidPubKeyHashLength)), + (vec![Fe32::try_from(18).unwrap(); 1], Err(Bolt11ParseError::InvalidScriptHashLength)), ]; for (input, expected) in cases.into_iter() { @@ -1034,8 +1016,8 @@ mod test { #[test] fn test_parse_route() { - use lightning_types::routing::{RoutingFees, RouteHint, RouteHintHop}; use crate::PrivateRoute; + use lightning_types::routing::{RouteHint, RouteHintHop, RoutingFees}; let input = from_bech32( "q20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqa\ @@ -1048,34 +1030,30 @@ mod test { &[ 0x02u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3, - 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55 - ][..] - ).unwrap(), + 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55, + ][..], + ) + .unwrap(), short_channel_id: 0x0102030405060708, - fees: RoutingFees { - base_msat: 1, - proportional_millionths: 20, - }, + fees: RoutingFees { base_msat: 1, proportional_millionths: 20 }, cltv_expiry_delta: 3, htlc_minimum_msat: None, - htlc_maximum_msat: None + htlc_maximum_msat: None, }); expected.push(RouteHintHop { src_node_id: PublicKey::from_slice( &[ 0x03u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3, - 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55 - ][..] - ).unwrap(), + 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55, + ][..], + ) + .unwrap(), short_channel_id: 0x030405060708090a, - fees: RoutingFees { - base_msat: 2, - proportional_millionths: 30, - }, + fees: RoutingFees { base_msat: 2, proportional_millionths: 30 }, cltv_expiry_delta: 4, htlc_minimum_msat: None, - htlc_maximum_msat: None + htlc_maximum_msat: None, }); assert_eq!(PrivateRoute::from_base32(&input), Ok(PrivateRoute(RouteHint(expected)))); @@ -1088,57 +1066,69 @@ mod test { #[test] fn test_payment_secret_and_features_de_and_ser() { - use lightning_types::features::Bolt11InvoiceFeatures; - use bitcoin::secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; use crate::TaggedField::*; - use crate::{SiPrefix, SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, - Currency, Sha256, PositiveTimestamp}; + use crate::{ + Bolt11InvoiceSignature, Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, + RawHrp, Sha256, SiPrefix, SignedRawBolt11Invoice, + }; + use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; + use lightning_types::features::Bolt11InvoiceFeatures; // Feature bits 9, 15, and 99 are set. - let expected_features = Bolt11InvoiceFeatures::from_le_bytes(vec![0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8]); + let expected_features = + Bolt11InvoiceFeatures::from_le_bytes(vec![0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8]); let invoice_str = "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqsq67gye39hfg3zd8rgc80k32tvy9xk2xunwm5lzexnvpx6fd77en8qaq424dxgt56cag2dpt359k3ssyhetktkpqh24jqnjyw6uqd08sgptq44qu"; - let invoice = SignedRawBolt11Invoice { - raw_invoice: RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: Some(25), - si_prefix: Some(SiPrefix::Milli) - }, - data: RawDataPart { - timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), - tagged_fields: vec ! [ + let invoice = + SignedRawBolt11Invoice { + raw_invoice: RawBolt11Invoice { + hrp: RawHrp { + currency: Currency::Bitcoin, + raw_amount: Some(25), + si_prefix: Some(SiPrefix::Milli), + }, + data: RawDataPart { + timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), + tagged_fields: vec ! [ PaymentHash(Sha256(sha256::Hash::from_str( "0001020304050607080900010203040506070809000102030405060708090102" ).unwrap())).into(), Description(crate::Description::new("coffee beans".to_owned()).unwrap()).into(), PaymentSecret(crate::PaymentSecret([17; 32])).into(), - Features(expected_features).into()]} - }, - hash: [0xb1, 0x96, 0x46, 0xc3, 0xbc, 0x56, 0x76, 0x1d, 0x20, 0x65, 0x6e, 0x0e, 0x32, - 0xec, 0xd2, 0x69, 0x27, 0xb7, 0x62, 0x6e, 0x2a, 0x8b, 0xe6, 0x97, 0x71, 0x9f, - 0xf8, 0x7e, 0x44, 0x54, 0x55, 0xb9], - signature: Bolt11InvoiceSignature(RecoverableSignature::from_compact( - &[0xd7, 0x90, 0x4c, 0xc4, 0xb7, 0x4a, 0x22, 0x26, 0x9c, 0x68, 0xc1, 0xdf, 0x68, - 0xa9, 0x6c, 0x21, 0x4d, 0x65, 0x1b, 0x93, 0x76, 0xe9, 0xf1, 0x64, 0xd3, 0x60, - 0x4d, 0xa4, 0xb7, 0xde, 0xcc, 0xce, 0x0e, 0x82, 0xaa, 0xab, 0x4c, 0x85, 0xd3, - 0x58, 0xea, 0x14, 0xd0, 0xae, 0x34, 0x2d, 0xa3, 0x08, 0x12, 0xf9, 0x5d, 0x97, - 0x60, 0x82, 0xea, 0xac, 0x81, 0x39, 0x11, 0xda, 0xe0, 0x1a, 0xf3, 0xc1], - RecoveryId::from_i32(1).unwrap() - ).unwrap()), + Features(expected_features).into()], + }, + }, + hash: [ + 0xb1, 0x96, 0x46, 0xc3, 0xbc, 0x56, 0x76, 0x1d, 0x20, 0x65, 0x6e, 0x0e, 0x32, + 0xec, 0xd2, 0x69, 0x27, 0xb7, 0x62, 0x6e, 0x2a, 0x8b, 0xe6, 0x97, 0x71, 0x9f, + 0xf8, 0x7e, 0x44, 0x54, 0x55, 0xb9, + ], + signature: Bolt11InvoiceSignature( + RecoverableSignature::from_compact( + &[ + 0xd7, 0x90, 0x4c, 0xc4, 0xb7, 0x4a, 0x22, 0x26, 0x9c, 0x68, 0xc1, 0xdf, + 0x68, 0xa9, 0x6c, 0x21, 0x4d, 0x65, 0x1b, 0x93, 0x76, 0xe9, 0xf1, 0x64, + 0xd3, 0x60, 0x4d, 0xa4, 0xb7, 0xde, 0xcc, 0xce, 0x0e, 0x82, 0xaa, 0xab, + 0x4c, 0x85, 0xd3, 0x58, 0xea, 0x14, 0xd0, 0xae, 0x34, 0x2d, 0xa3, 0x08, + 0x12, 0xf9, 0x5d, 0x97, 0x60, 0x82, 0xea, 0xac, 0x81, 0x39, 0x11, 0xda, + 0xe0, 0x1a, 0xf3, 0xc1, + ], + RecoveryId::from_i32(1).unwrap(), + ) + .unwrap(), + ), }; assert_eq!(invoice_str, invoice.to_string()); - assert_eq!( - invoice_str.parse(), - Ok(invoice) - ); + assert_eq!(invoice_str.parse(), Ok(invoice)); } #[test] fn test_raw_signed_invoice_deserialization() { use crate::TaggedField::*; - use bitcoin::secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; - use crate::{SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, - PositiveTimestamp}; + use crate::{ + Bolt11InvoiceSignature, Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, + RawHrp, Sha256, SignedRawBolt11Invoice, + }; + use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; assert_eq!( "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmw\ From 323571db904f7a401e2c9eea824e54019e937830 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:08:41 +0100 Subject: [PATCH 03/13] `rustfmt`: Drop `lightning-invoice/src/de.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 4bb7fe0f3bf..cdc1f5d25f5 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -1,5 +1,4 @@ lightning-invoice/fuzz/fuzz_targets/serde_data_part.rs -lightning-invoice/src/de.rs lightning-invoice/src/lib.rs lightning-invoice/src/payment.rs lightning-invoice/src/ser.rs From 1fcd36385f9bea4d746d49e1429ab7c6994be257 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:08:46 +0100 Subject: [PATCH 04/13] `rustfmt`: Run on `lightning-invoice/src/ser.rs` --- lightning-invoice/src/ser.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lightning-invoice/src/ser.rs b/lightning-invoice/src/ser.rs index 66571ee35f9..6da172c7220 100644 --- a/lightning-invoice/src/ser.rs +++ b/lightning-invoice/src/ser.rs @@ -1,13 +1,17 @@ +use alloc::boxed::Box; use core::fmt; use core::fmt::{Display, Formatter}; use core::{array, iter}; -use alloc::boxed::Box; -use bech32::{ByteIterExt, Fe32, Fe32IterExt}; use crate::prelude::*; +use bech32::{ByteIterExt, Fe32, Fe32IterExt}; -use super::{Bolt11Invoice, Bolt11InvoiceFeatures, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, Bolt11InvoiceSignature, PaymentSecret, PositiveTimestamp, - PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, constants, SignedRawBolt11Invoice, RawDataPart, RouteHintHop}; +use super::{ + constants, Bolt11Invoice, Bolt11InvoiceFeatures, Bolt11InvoiceSignature, Currency, Description, + ExpiryTime, Fallback, MinFinalCltvExpiryDelta, PayeePubKey, PaymentSecret, PositiveTimestamp, + PrivateRoute, RawDataPart, RawHrp, RawTaggedField, RouteHintHop, Sha256, SiPrefix, + SignedRawBolt11Invoice, TaggedField, +}; /// Objects that can be encoded to base32 (bech32). /// @@ -181,13 +185,7 @@ impl Display for RawHrp { None => String::new(), }; - write!( - f, - "ln{}{}{}", - self.currency, - amount, - si_prefix - ) + write!(f, "ln{}{}{}", self.currency, amount, si_prefix) } } @@ -206,7 +204,9 @@ impl Display for Currency { impl Display for SiPrefix { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", + write!( + f, + "{}", match *self { SiPrefix::Milli => "m", SiPrefix::Micro => "u", @@ -218,7 +218,7 @@ impl Display for SiPrefix { } /// Encode an integer to base32, big endian, without leading zeros -fn encode_int_be_base32(int: u64) -> impl ExactSizeIterator { +fn encode_int_be_base32(int: u64) -> impl ExactSizeIterator { let base = 32u64; // (64 + 4) / 5 == 13 @@ -282,13 +282,13 @@ impl Base32Len for Sha256 { impl Base32Iterable for Description { fn fe_iter<'s>(&'s self) -> Box + 's> { - Box::new(self.0.0.as_bytes().fe_iter()) + Box::new(self.0 .0.as_bytes().fe_iter()) } } impl Base32Len for Description { fn base32_len(&self) -> usize { - self.0.0.as_bytes().base32_len() + self.0 .0.as_bytes().base32_len() } } @@ -381,7 +381,7 @@ impl Base32Iterable for PrivateRoute { i1.chain(i2).chain(i3).chain(i4).chain(i5) } - Box::new(self.0.0.iter().map(serialize_to_iter).flatten().bytes_to_fes()) + Box::new(self.0 .0.iter().map(serialize_to_iter).flatten().bytes_to_fes()) } } From d29c787019c52ea5faf93860a243167a61559f17 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:08:47 +0100 Subject: [PATCH 05/13] `rustfmt`: Drop `lightning-invoice/src/ser.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index cdc1f5d25f5..86bd9ba227a 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -1,7 +1,6 @@ lightning-invoice/fuzz/fuzz_targets/serde_data_part.rs lightning-invoice/src/lib.rs lightning-invoice/src/payment.rs -lightning-invoice/src/ser.rs lightning-invoice/src/tb.rs lightning-invoice/src/utils.rs lightning-invoice/tests/ser_de.rs From 8397671e70d518641f8d94987177835d1ca80071 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:08:49 +0100 Subject: [PATCH 06/13] `rustfmt`: Run on `lightning-invoice/src/tb.rs` --- lightning-invoice/src/tb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightning-invoice/src/tb.rs b/lightning-invoice/src/tb.rs index dde8a53f99c..9f8a5135906 100644 --- a/lightning-invoice/src/tb.rs +++ b/lightning-invoice/src/tb.rs @@ -7,4 +7,4 @@ pub struct True {} pub struct False {} impl Bool for True {} -impl Bool for False {} \ No newline at end of file +impl Bool for False {} From bb518018fe11714362a6baf23e264a1a37007fd9 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:08:50 +0100 Subject: [PATCH 07/13] `rustfmt`: Drop `lightning-invoice/src/tb.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 86bd9ba227a..bd181ef61d7 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -1,7 +1,6 @@ lightning-invoice/fuzz/fuzz_targets/serde_data_part.rs lightning-invoice/src/lib.rs lightning-invoice/src/payment.rs -lightning-invoice/src/tb.rs lightning-invoice/src/utils.rs lightning-invoice/tests/ser_de.rs lightning/src/blinded_path/message.rs From f121508f3bb66afcb7309705732233a31cda9d59 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 14 Nov 2024 11:52:44 +0100 Subject: [PATCH 08/13] `rustfmt`: Prepare `lightning-invoice/src/lib.rs` --- lightning-invoice/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 6f7ec225337..744548f2c6d 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -629,7 +629,8 @@ impl Self { - let amount = match amount_msat.checked_mul(10) { // Invoices are denominated in "pico BTC" + // Invoices are denominated in "pico BTC" + let amount = match amount_msat.checked_mul(10) { Some(amt) => amt, None => { self.error = Some(CreationError::InvalidAmount); @@ -1504,7 +1505,7 @@ impl Bolt11Invoice { /// Returns a list of all fallback addresses as [`Address`]es pub fn fallback_addresses(&self) -> Vec
{ - self.fallbacks().iter().filter_map(|fallback| { + let filter_fn = |fallback: &&Fallback| { let address = match fallback { Fallback::SegWitProgram { version, program } => { match WitnessProgram::new(*version, &program) { @@ -1521,7 +1522,8 @@ impl Bolt11Invoice { }; Some(address) - }).collect() + }; + self.fallbacks().iter().filter_map(filter_fn).collect() } /// Returns a list of all routes included in the invoice From 7ed62510faad5233a20dd783d17d6f0a0eb1e6b1 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:09:05 +0100 Subject: [PATCH 09/13] `rustfmt`: Run on `lightning-invoice/src/lib.rs` --- lightning-invoice/src/lib.rs | 675 +++++++++++++++++++---------------- 1 file changed, 374 insertions(+), 301 deletions(-) diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 744548f2c6d..348f87909da 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -1,14 +1,11 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![deny(non_upper_case_globals)] #![deny(non_camel_case_types)] #![deny(non_snake_case)] #![deny(unused_mut)] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] - #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] //! This crate provides data structures to represent @@ -22,11 +19,11 @@ //! //! [`Bolt11Invoice::from_str`]: crate::Bolt11Invoice#impl-FromStr -extern crate bech32; -extern crate lightning_types; extern crate alloc; +extern crate bech32; #[cfg(any(test, feature = "std"))] extern crate core; +extern crate lightning_types; #[cfg(feature = "serde")] extern crate serde; @@ -35,31 +32,31 @@ use std::time::SystemTime; use bech32::primitives::decode::CheckedHrpstringError; use bech32::Fe32; +use bitcoin::hashes::{sha256, Hash}; use bitcoin::{Address, Network, PubkeyHash, ScriptHash, WitnessProgram, WitnessVersion}; -use bitcoin::hashes::{Hash, sha256}; use lightning_types::features::Bolt11InvoiceFeatures; +use bitcoin::secp256k1::ecdsa::RecoverableSignature; use bitcoin::secp256k1::PublicKey; use bitcoin::secp256k1::{Message, Secp256k1}; -use bitcoin::secp256k1::ecdsa::RecoverableSignature; use alloc::boxed::Box; +use alloc::string; use core::cmp::Ordering; -use core::fmt::{Display, Formatter, self}; +use core::fmt::{self, Display, Formatter}; use core::iter::FilterMap; use core::num::ParseIntError; use core::ops::Deref; use core::slice::Iter; use core::time::Duration; -use alloc::string; #[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer,Serialize, Serializer, de::Error}; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; #[doc(no_inline)] pub use lightning_types::payment::PaymentSecret; #[doc(no_inline)] -pub use lightning_types::routing::{RoutingFees, RouteHint, RouteHintHop}; +pub use lightning_types::routing::{RouteHint, RouteHintHop, RoutingFees}; use lightning_types::string::UntrustedString; mod de; @@ -71,7 +68,7 @@ mod test_ser_de; #[allow(unused_imports)] mod prelude { - pub use alloc::{vec, vec::Vec, string::String}; + pub use alloc::{string::String, vec, vec::Vec}; pub use alloc::string::ToString; } @@ -204,7 +201,14 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18; /// /// This is not exported to bindings users as we likely need to manually select one set of boolean type parameters. #[derive(Eq, PartialEq, Debug, Clone)] -pub struct InvoiceBuilder { +pub struct InvoiceBuilder< + D: tb::Bool, + H: tb::Bool, + T: tb::Bool, + C: tb::Bool, + S: tb::Bool, + M: tb::Bool, +> { currency: Currency, amount: Option, si_prefix: Option, @@ -501,8 +505,10 @@ pub enum TaggedField { /// SHA-256 hash #[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] -pub struct Sha256(/// This is not exported to bindings users as the native hash types are not currently mapped - pub sha256::Hash); +pub struct Sha256( + /// This is not exported to bindings users as the native hash types are not currently mapped + pub sha256::Hash, +); impl Sha256 { /// Constructs a new [`Sha256`] from the given bytes, which are assumed to be the output of a @@ -537,10 +543,7 @@ pub struct MinFinalCltvExpiryDelta(pub u64); #[allow(missing_docs)] #[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] pub enum Fallback { - SegWitProgram { - version: WitnessVersion, - program: Vec, - }, + SegWitProgram { version: WitnessVersion, program: Vec }, PubKeyHash(PubkeyHash), ScriptHash(ScriptHash), } @@ -607,9 +610,20 @@ impl InvoiceBuilder InvoiceBuilder { +impl + InvoiceBuilder +{ /// Helper function to set the completeness flags. - fn set_flags(self) -> InvoiceBuilder { + fn set_flags< + DN: tb::Bool, + HN: tb::Bool, + TN: tb::Bool, + CN: tb::Bool, + SN: tb::Bool, + MN: tb::Bool, + >( + self, + ) -> InvoiceBuilder { InvoiceBuilder:: { currency: self.currency, amount: self.amount, @@ -634,8 +648,8 @@ impl amt, None => { self.error = Some(CreationError::InvalidAmount); - return self - } + return self; + }, }; let biggest_possible_si_prefix = SiPrefix::values_desc() .iter() @@ -675,41 +689,37 @@ impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Builds a [`RawBolt11Invoice`] if no [`CreationError`] occurred while construction any of the /// fields. pub fn build_raw(self) -> Result { - // If an error occurred at any time before, return it now if let Some(e) = self.error { return Err(e); } - let hrp = RawHrp { - currency: self.currency, - raw_amount: self.amount, - si_prefix: self.si_prefix, - }; + let hrp = + RawHrp { currency: self.currency, raw_amount: self.amount, si_prefix: self.si_prefix }; let timestamp = self.timestamp.expect("ensured to be Some(t) by type T"); - let tagged_fields = self.tagged_fields.into_iter().map(|tf| { - RawTaggedField::KnownSemantics(tf) - }).collect::>(); + let tagged_fields = self + .tagged_fields + .into_iter() + .map(|tf| RawTaggedField::KnownSemantics(tf)) + .collect::>(); - let data = RawDataPart { - timestamp, - tagged_fields, - }; + let data = RawDataPart { timestamp, tagged_fields }; - Ok(RawBolt11Invoice { - hrp, - data, - }) + Ok(RawBolt11Invoice { hrp, data }) } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Set the description. This function is only available if no description (hash) was set. pub fn description(mut self, description: String) -> InvoiceBuilder { match Description::new(description) { @@ -720,25 +730,27 @@ impl InvoiceBui } /// Set the description hash. This function is only available if no description (hash) was set. - pub fn description_hash(mut self, description_hash: sha256::Hash) -> InvoiceBuilder { + pub fn description_hash( + mut self, description_hash: sha256::Hash, + ) -> InvoiceBuilder { self.tagged_fields.push(TaggedField::DescriptionHash(Sha256(description_hash))); self.set_flags() } /// Set the description or description hash. This function is only available if no description (hash) was set. - pub fn invoice_description(self, description: Bolt11InvoiceDescription) -> InvoiceBuilder { + pub fn invoice_description( + self, description: Bolt11InvoiceDescription, + ) -> InvoiceBuilder { match description { - Bolt11InvoiceDescription::Direct(desc) => { - self.description(desc.0.0) - } - Bolt11InvoiceDescription::Hash(hash) => { - self.description_hash(hash.0) - } + Bolt11InvoiceDescription::Direct(desc) => self.description(desc.0 .0), + Bolt11InvoiceDescription::Hash(hash) => self.description_hash(hash.0), } } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Set the payment hash. This function is only available if no payment hash was set. pub fn payment_hash(mut self, hash: sha256::Hash) -> InvoiceBuilder { self.tagged_fields.push(TaggedField::PaymentHash(Sha256(hash))); @@ -746,7 +758,9 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the timestamp to a specific [`SystemTime`]. #[cfg(feature = "std")] pub fn timestamp(mut self, time: SystemTime) -> InvoiceBuilder { @@ -760,7 +774,9 @@ impl InvoiceBui /// Sets the timestamp to a duration since the Unix epoch, dropping the subsecond part (which /// is not representable in BOLT 11 invoices). - pub fn duration_since_epoch(mut self, time: Duration) -> InvoiceBuilder { + pub fn duration_since_epoch( + mut self, time: Duration, + ) -> InvoiceBuilder { match PositiveTimestamp::from_duration_since_epoch(time) { Ok(t) => self.timestamp = Some(t), Err(e) => self.error = Some(e), @@ -778,17 +794,27 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets `min_final_cltv_expiry_delta`. - pub fn min_final_cltv_expiry_delta(mut self, min_final_cltv_expiry_delta: u64) -> InvoiceBuilder { - self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta(min_final_cltv_expiry_delta))); + pub fn min_final_cltv_expiry_delta( + mut self, min_final_cltv_expiry_delta: u64, + ) -> InvoiceBuilder { + self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta( + min_final_cltv_expiry_delta, + ))); self.set_flags() } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the payment secret and relevant features. - pub fn payment_secret(mut self, payment_secret: PaymentSecret) -> InvoiceBuilder { + pub fn payment_secret( + mut self, payment_secret: PaymentSecret, + ) -> InvoiceBuilder { let mut found_features = false; for field in self.tagged_fields.iter_mut() { if let TaggedField::Features(f) = field { @@ -808,14 +834,18 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the payment metadata. /// /// By default features are set to *optionally* allow the sender to include the payment metadata. /// If you wish to require that the sender include the metadata (and fail to parse the invoice if /// they don't support payment metadata fields), you need to call /// [`InvoiceBuilder::require_payment_metadata`] after this. - pub fn payment_metadata(mut self, payment_metadata: Vec) -> InvoiceBuilder { + pub fn payment_metadata( + mut self, payment_metadata: Vec, + ) -> InvoiceBuilder { self.tagged_fields.push(TaggedField::PaymentMetadata(payment_metadata)); let mut found_features = false; for field in self.tagged_fields.iter_mut() { @@ -833,7 +863,9 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets forwarding of payment metadata as required. A reader of the invoice which does not /// support sending payment metadata will fail to read the invoice. pub fn require_payment_metadata(mut self) -> InvoiceBuilder { @@ -846,7 +878,9 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the `basic_mpp` feature as optional. pub fn basic_mpp(mut self) -> Self { for field in self.tagged_fields.iter_mut() { @@ -863,11 +897,10 @@ impl InvoiceBuilder(self, sign_function: F) -> Result - where F: FnOnce(&Message) -> RecoverableSignature + where + F: FnOnce(&Message) -> RecoverableSignature, { - let invoice = self.try_build_signed::<_, ()>(|hash| { - Ok(sign_function(hash)) - }); + let invoice = self.try_build_signed::<_, ()>(|hash| Ok(sign_function(hash))); match invoice { Ok(i) => Ok(i), @@ -879,8 +912,11 @@ impl InvoiceBuilder(self, sign_function: F) -> Result> - where F: FnOnce(&Message) -> Result + pub fn try_build_signed( + self, sign_function: F, + ) -> Result> + where + F: FnOnce(&Message) -> Result, { let raw = match self.build_raw() { Ok(r) => r, @@ -892,9 +928,7 @@ impl InvoiceBuilder return Err(SignOrCreationError::SignError(e)), }; - let invoice = Bolt11Invoice { - signed_invoice: signed, - }; + let invoice = Bolt11Invoice { signed_invoice: signed }; invoice.check_field_counts().expect("should be ensured by type signature of builder"); invoice.check_feature_bits().expect("should be ensured by type signature of builder"); @@ -904,7 +938,6 @@ impl InvoiceBuilder Result { let hash = Message::from_digest(self.hash); - Ok(PayeePubKey(Secp256k1::new().recover_ecdsa( - &hash, - &self.signature - )?)) + Ok(PayeePubKey(Secp256k1::new().recover_ecdsa(&hash, &self.signature)?)) } /// Checks if the signature is valid for the included payee public key or if none exists if it's @@ -953,17 +983,14 @@ impl SignedRawBolt11Invoice { recovered_pub_key = Some(recovered); } - let pub_key = included_pub_key.or(recovered_pub_key.as_ref()) - .expect("One is always present"); + let pub_key = + included_pub_key.or(recovered_pub_key.as_ref()).expect("One is always present"); let hash = Message::from_digest(self.hash); let secp_context = Secp256k1::new(); - let verification_result = secp_context.verify_ecdsa( - &hash, - &self.signature.to_standard(), - pub_key - ); + let verification_result = + secp_context.verify_ecdsa(&hash, &self.signature.to_standard(), pub_key); match verification_result { Ok(()) => true, @@ -1023,7 +1050,9 @@ macro_rules! find_all_extract { #[allow(missing_docs)] impl RawBolt11Invoice { /// Hash the HRP (as bytes) and signatureless data part (as Fe32 iterator) - fn hash_from_parts<'s>(hrp_bytes: &[u8], data_without_signature: Box + 's>) -> [u8; 32] { + fn hash_from_parts<'s>( + hrp_bytes: &[u8], data_without_signature: Box + 's>, + ) -> [u8; 32] { use crate::bech32::Fe32IterExt; use bitcoin::hashes::HashEngine; @@ -1047,7 +1076,7 @@ impl RawBolt11Invoice { // Iterate over data // Note: if it was not for padding, this could go on the supplied original iterator // (see https://github.com/rust-bitcoin/rust-bech32/issues/198) - data_part.into_iter().fes_to_bytes().for_each(|v| { engine.input(&[v])}); + data_part.into_iter().fes_to_bytes().for_each(|v| engine.input(&[v])); let raw_hash = sha256::Hash::from_engine(engine); let mut hash: [u8; 32] = Default::default(); @@ -1059,10 +1088,7 @@ impl RawBolt11Invoice { pub fn signable_hash(&self) -> [u8; 32] { use crate::ser::Base32Iterable; - Self::hash_from_parts( - self.hrp.to_string().as_bytes(), - self.data.fe_iter(), - ) + Self::hash_from_parts(self.hrp.to_string().as_bytes(), self.data.fe_iter()) } /// Signs the invoice using the supplied `sign_method`. This function MAY fail with an error of @@ -1072,7 +1098,8 @@ impl RawBolt11Invoice { /// This is not exported to bindings users as we don't currently support passing function pointers into methods /// explicitly. pub fn sign(self, sign_method: F) -> Result - where F: FnOnce(&Message) -> Result + where + F: FnOnce(&Message) -> Result, { let raw_hash = self.signable_hash(); let hash = Message::from_digest(raw_hash); @@ -1088,9 +1115,9 @@ impl RawBolt11Invoice { /// Returns an iterator over all tagged fields with known semantics. /// /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap - pub fn known_tagged_fields(&self) - -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> - { + pub fn known_tagged_fields( + &self, + ) -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> { // For 1.14.0 compatibility: closures' types can't be written an fn()->() in the // function's type signature. // TODO: refactor once impl Trait is available @@ -1101,7 +1128,7 @@ impl RawBolt11Invoice { } } - self.data.tagged_fields.iter().filter_map(match_raw ) + self.data.tagged_fields.iter().filter_map(match_raw) } pub fn payment_hash(&self) -> Option<&Sha256> { @@ -1152,7 +1179,9 @@ impl RawBolt11Invoice { /// Returns `None` if no amount is set or on overflow. pub fn amount_pico_btc(&self) -> Option { self.hrp.raw_amount.and_then(|v| { - v.checked_mul(self.hrp.si_prefix.as_ref().map_or(1_000_000_000_000, |si| { si.multiplier() })) + v.checked_mul( + self.hrp.si_prefix.as_ref().map_or(1_000_000_000_000, |si| si.multiplier()), + ) }) } @@ -1240,10 +1269,13 @@ impl Bolt11Invoice { /// Check that all mandatory fields are present fn check_field_counts(&self) -> Result<(), Bolt11SemanticError> { // "A writer MUST include exactly one p field […]." - let payment_hash_cnt = self.tagged_fields().filter(|&tf| match *tf { - TaggedField::PaymentHash(_) => true, - _ => false, - }).count(); + let payment_hash_cnt = self + .tagged_fields() + .filter(|&tf| match *tf { + TaggedField::PaymentHash(_) => true, + _ => false, + }) + .count(); if payment_hash_cnt < 1 { return Err(Bolt11SemanticError::NoPaymentHash); } else if payment_hash_cnt > 1 { @@ -1251,14 +1283,17 @@ impl Bolt11Invoice { } // "A writer MUST include either exactly one d or exactly one h field." - let description_cnt = self.tagged_fields().filter(|&tf| match *tf { - TaggedField::Description(_) | TaggedField::DescriptionHash(_) => true, - _ => false, - }).count(); - if description_cnt < 1 { + let description_cnt = self + .tagged_fields() + .filter(|&tf| match *tf { + TaggedField::Description(_) | TaggedField::DescriptionHash(_) => true, + _ => false, + }) + .count(); + if description_cnt < 1 { return Err(Bolt11SemanticError::NoDescription); } else if description_cnt > 1 { - return Err(Bolt11SemanticError::MultipleDescriptions); + return Err(Bolt11SemanticError::MultipleDescriptions); } self.check_payment_secret()?; @@ -1269,10 +1304,13 @@ impl Bolt11Invoice { /// Checks that there is exactly one payment secret field fn check_payment_secret(&self) -> Result<(), Bolt11SemanticError> { // "A writer MUST include exactly one `s` field." - let payment_secret_count = self.tagged_fields().filter(|&tf| match *tf { - TaggedField::PaymentSecret(_) => true, - _ => false, - }).count(); + let payment_secret_count = self + .tagged_fields() + .filter(|&tf| match *tf { + TaggedField::PaymentSecret(_) => true, + _ => false, + }) + .count(); if payment_secret_count < 1 { return Err(Bolt11SemanticError::NoPaymentSecret); } else if payment_secret_count > 1 { @@ -1321,10 +1359,12 @@ impl Bolt11Invoice { /// Check that the invoice is signed correctly and that key recovery works pub fn check_signature(&self) -> Result<(), Bolt11SemanticError> { match self.signed_invoice.recover_payee_pub_key() { - Err(bitcoin::secp256k1::Error::InvalidRecoveryId) => - return Err(Bolt11SemanticError::InvalidRecoveryId), - Err(bitcoin::secp256k1::Error::InvalidSignature) => - return Err(Bolt11SemanticError::InvalidSignature), + Err(bitcoin::secp256k1::Error::InvalidRecoveryId) => { + return Err(Bolt11SemanticError::InvalidRecoveryId) + }, + Err(bitcoin::secp256k1::Error::InvalidSignature) => { + return Err(Bolt11SemanticError::InvalidSignature) + }, Err(e) => panic!("no other error may occur, got {:?}", e), Ok(_) => {}, } @@ -1356,10 +1396,10 @@ impl Bolt11Invoice { /// /// assert!(Bolt11Invoice::from_signed(signed).is_ok()); /// ``` - pub fn from_signed(signed_invoice: SignedRawBolt11Invoice) -> Result { - let invoice = Bolt11Invoice { - signed_invoice, - }; + pub fn from_signed( + signed_invoice: SignedRawBolt11Invoice, + ) -> Result { + let invoice = Bolt11Invoice { signed_invoice }; invoice.check_field_counts()?; invoice.check_feature_bits()?; invoice.check_signature()?; @@ -1382,8 +1422,9 @@ impl Bolt11Invoice { /// Returns an iterator over all tagged fields of this `Bolt11Invoice`. /// /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap - pub fn tagged_fields(&self) - -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> { + pub fn tagged_fields( + &self, + ) -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> { self.signed_invoice.raw_invoice().known_tagged_fields() } @@ -1434,7 +1475,7 @@ impl Bolt11Invoice { pub fn get_payee_pub_key(&self) -> PublicKey { match self.payee_pub_key() { Some(pk) => *pk, - None => self.recover_payee_pub_key() + None => self.recover_payee_pub_key(), } } @@ -1446,7 +1487,8 @@ impl Bolt11Invoice { /// Returns the invoice's expiry time, if present, otherwise [`DEFAULT_EXPIRY_TIME`]. pub fn expiry_time(&self) -> Duration { - self.signed_invoice.expiry_time() + self.signed_invoice + .expiry_time() .map(|x| x.0) .unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME)) } @@ -1469,7 +1511,8 @@ impl Bolt11Invoice { /// Returns the Duration remaining until the invoice expires. #[cfg(feature = "std")] pub fn duration_until_expiry(&self) -> Duration { - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) .map(|now| self.expiration_remaining_from_epoch(now)) .unwrap_or(Duration::from_nanos(0)) } @@ -1485,13 +1528,15 @@ impl Bolt11Invoice { pub fn would_expire(&self, at_time: Duration) -> bool { self.duration_since_epoch() .checked_add(self.expiry_time()) - .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) < at_time + .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) + < at_time } /// Returns the invoice's `min_final_cltv_expiry_delta` time, if present, otherwise /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA`]. pub fn min_final_cltv_expiry_delta(&self) -> u64 { - self.signed_invoice.min_final_cltv_expiry_delta() + self.signed_invoice + .min_final_cltv_expiry_delta() .map(|x| x.0) .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA) } @@ -1509,16 +1554,14 @@ impl Bolt11Invoice { let address = match fallback { Fallback::SegWitProgram { version, program } => { match WitnessProgram::new(*version, &program) { - Ok(witness_program) => Address::from_witness_program(witness_program, self.network()), + Ok(witness_program) => { + Address::from_witness_program(witness_program, self.network()) + }, Err(_) => return None, } - } - Fallback::PubKeyHash(pkh) => { - Address::p2pkh(*pkh, self.network()) - } - Fallback::ScriptHash(sh) => { - Address::p2sh_from_hash(*sh, self.network()) - } + }, + Fallback::PubKeyHash(pkh) => Address::p2pkh(*pkh, self.network()), + Fallback::ScriptHash(sh) => Address::p2sh_from_hash(*sh, self.network()), }; Some(address) @@ -1534,8 +1577,12 @@ impl Bolt11Invoice { /// Returns a list of all routes included in the invoice as the underlying hints pub fn route_hints(&self) -> Vec { find_all_extract!( - self.signed_invoice.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x - ).map(|route| (**route).clone()).collect() + self.signed_invoice.known_tagged_fields(), + TaggedField::PrivateRoute(ref x), + x + ) + .map(|route| (**route).clone()) + .collect() } /// Returns the currency for which the invoice was issued @@ -1589,7 +1636,6 @@ impl TaggedField { } impl Description { - /// Creates a new `Description` if `description` is at most 1023 * 5 bits (i.e., 639 bytes) /// long, and returns [`CreationError::DescriptionTooLong`] otherwise. /// @@ -1745,7 +1791,7 @@ impl Display for CreationError { } #[cfg(feature = "std")] -impl std::error::Error for CreationError { } +impl std::error::Error for CreationError {} /// Errors that may occur when converting a [`RawBolt11Invoice`] to a [`Bolt11Invoice`]. They relate to /// the requirements sections in BOLT #11 @@ -1801,7 +1847,7 @@ impl Display for Bolt11SemanticError { } #[cfg(feature = "std")] -impl std::error::Error for Bolt11SemanticError { } +impl std::error::Error for Bolt11SemanticError {} /// When signing using a fallible method either an user-supplied `SignError` or a [`CreationError`] /// may occur. @@ -1825,13 +1871,19 @@ impl Display for SignOrCreationError { #[cfg(feature = "serde")] impl Serialize for Bolt11Invoice { - fn serialize(&self, serializer: S) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { serializer.serialize_str(self.to_string().as_str()) } } #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for Bolt11Invoice { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let bolt11 = String::deserialize(deserializer)? .parse::() .map_err(|e| D::Error::custom(format_args!("{:?}", e)))?; @@ -1842,8 +1894,8 @@ impl<'de> Deserialize<'de> for Bolt11Invoice { #[cfg(test)] mod test { - use bitcoin::ScriptBuf; use bitcoin::hashes::sha256; + use bitcoin::ScriptBuf; use std::str::FromStr; #[test] @@ -1856,24 +1908,28 @@ mod test { #[test] fn test_calc_invoice_hash() { - use crate::{RawBolt11Invoice, RawHrp, RawDataPart, Currency, PositiveTimestamp}; use crate::TaggedField::*; + use crate::{Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, RawHrp}; let invoice = RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: None, - si_prefix: None, - }, + hrp: RawHrp { currency: Currency::Bitcoin, raw_amount: None, si_prefix: None }, data: RawDataPart { timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), tagged_fields: vec![ - PaymentHash(crate::Sha256(sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap())).into(), - Description(crate::Description::new( - "Please consider supporting this project".to_owned() - ).unwrap()).into(), + PaymentHash(crate::Sha256( + sha256::Hash::from_str( + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(), + )) + .into(), + Description( + crate::Description::new( + "Please consider supporting this project".to_owned(), + ) + .unwrap(), + ) + .into(), ], }, }; @@ -1881,7 +1937,7 @@ mod test { let expected_hash = [ 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, 0xb2, 0xec, - 0xd5, 0x18, 0xe1, 0xc9 + 0xd5, 0x18, 0xe1, 0xc9, ]; assert_eq!(invoice.signable_hash(), expected_hash) @@ -1890,22 +1946,21 @@ mod test { #[test] fn test_check_signature() { use crate::TaggedField::*; + use crate::{ + Bolt11InvoiceSignature, Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, + RawHrp, Sha256, SignedRawBolt11Invoice, + }; + use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; use bitcoin::secp256k1::Secp256k1; - use bitcoin::secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; - use bitcoin::secp256k1::{SecretKey, PublicKey}; - use crate::{SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, - PositiveTimestamp}; - - let invoice = SignedRawBolt11Invoice { - raw_invoice: RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: None, - si_prefix: None, - }, - data: RawDataPart { - timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), - tagged_fields: vec ! [ + use bitcoin::secp256k1::{PublicKey, SecretKey}; + + let invoice = + SignedRawBolt11Invoice { + raw_invoice: RawBolt11Invoice { + hrp: RawHrp { currency: Currency::Bitcoin, raw_amount: None, si_prefix: None }, + data: RawDataPart { + timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), + tagged_fields: vec ! [ PaymentHash(Sha256(sha256::Hash::from_str( "0001020304050607080900010203040506070809000102030405060708090102" ).unwrap())).into(), @@ -1915,25 +1970,28 @@ mod test { ).unwrap() ).into(), ], + }, }, - }, - hash: [ - 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, - 0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, - 0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9 - ], - signature: Bolt11InvoiceSignature(RecoverableSignature::from_compact( - & [ - 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a, - 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43, - 0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f, - 0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad, - 0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9, - 0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f + hash: [ + 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, + 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, + 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9, ], - RecoveryId::from_i32(0).unwrap() - ).unwrap()), - }; + signature: Bolt11InvoiceSignature( + RecoverableSignature::from_compact( + &[ + 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a, + 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43, 0x4e, + 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f, 0x42, 0x5f, + 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad, 0x0d, 0x6e, 0x35, + 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9, 0xaa, 0xb1, 0x5e, 0x57, + 0x38, 0xb1, 0x1f, 0x12, 0x7f, + ], + RecoveryId::from_i32(0).unwrap(), + ) + .unwrap(), + ), + }; assert!(invoice.check_signature()); @@ -1941,17 +1999,18 @@ mod test { &[ 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2, 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca, - 0x3b, 0x2d, 0xb7, 0x34 - ][..] - ).unwrap(); + 0x3b, 0x2d, 0xb7, 0x34, + ][..], + ) + .unwrap(); let public_key = PublicKey::from_secret_key(&Secp256k1::new(), &private_key); assert_eq!(invoice.recover_payee_pub_key(), Ok(crate::PayeePubKey(public_key))); let (raw_invoice, _, _) = invoice.into_parts(); - let new_signed = raw_invoice.sign::<_, ()>(|hash| { - Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) - }).unwrap(); + let new_signed = raw_invoice + .sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) + .unwrap(); assert!(new_signed.check_signature()); } @@ -1959,31 +2018,35 @@ mod test { #[test] fn test_check_feature_bits() { use crate::TaggedField::*; - use lightning_types::features::Bolt11InvoiceFeatures; + use crate::{ + Bolt11Invoice, Bolt11SemanticError, Currency, PositiveTimestamp, RawBolt11Invoice, + RawDataPart, RawHrp, Sha256, + }; use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::SecretKey; - use crate::{Bolt11Invoice, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, PositiveTimestamp, - Bolt11SemanticError}; + use lightning_types::features::Bolt11InvoiceFeatures; let private_key = SecretKey::from_slice(&[42; 32]).unwrap(); let payment_secret = lightning_types::payment::PaymentSecret([21; 32]); let invoice_template = RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: None, - si_prefix: None, - }, + hrp: RawHrp { currency: Currency::Bitcoin, raw_amount: None, si_prefix: None }, data: RawDataPart { timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), - tagged_fields: vec ! [ - PaymentHash(Sha256(sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap())).into(), + tagged_fields: vec![ + PaymentHash(Sha256( + sha256::Hash::from_str( + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(), + )) + .into(), Description( crate::Description::new( - "Please consider supporting this project".to_owned() - ).unwrap() - ).into(), + "Please consider supporting this project".to_owned(), + ) + .unwrap(), + ) + .into(), ], }, }; @@ -1992,8 +2055,11 @@ mod test { let invoice = { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::InvalidFeatures)); // Missing feature bits @@ -2001,8 +2067,11 @@ mod test { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); invoice.data.tagged_fields.push(Features(Bolt11InvoiceFeatures::empty()).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::InvalidFeatures)); let mut payment_secret_features = Bolt11InvoiceFeatures::empty(); @@ -2013,31 +2082,43 @@ mod test { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); invoice.data.tagged_fields.push(Features(payment_secret_features.clone()).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert!(Bolt11Invoice::from_signed(invoice).is_ok()); // No payment secret or features let invoice = { let invoice = invoice_template.clone(); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::NoPaymentSecret)); // No payment secret or feature bits let invoice = { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(Features(Bolt11InvoiceFeatures::empty()).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::NoPaymentSecret)); // Missing payment secret let invoice = { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(Features(payment_secret_features).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::NoPaymentSecret)); // Multiple payment secrets @@ -2045,9 +2126,15 @@ mod test { let mut invoice = invoice_template; invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); - assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::MultiplePaymentSecrets)); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); + assert_eq!( + Bolt11Invoice::from_signed(invoice), + Err(Bolt11SemanticError::MultiplePaymentSecrets) + ); } #[test] @@ -2056,22 +2143,15 @@ mod test { let builder = InvoiceBuilder::new(Currency::Bitcoin) .description("Test".into()) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .duration_since_epoch(Duration::from_secs(1234567)); - let invoice = builder.clone() - .amount_milli_satoshis(1500) - .build_raw() - .unwrap(); + let invoice = builder.clone().amount_milli_satoshis(1500).build_raw().unwrap(); assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Nano)); assert_eq!(invoice.hrp.raw_amount, Some(15)); - - let invoice = builder - .amount_milli_satoshis(150) - .build_raw() - .unwrap(); + let invoice = builder.amount_milli_satoshis(150).build_raw().unwrap(); assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Pico)); assert_eq!(invoice.hrp.raw_amount, Some(1500)); @@ -2080,63 +2160,53 @@ mod test { #[test] fn test_builder_fail() { use crate::*; + use bitcoin::secp256k1::PublicKey; use lightning_types::routing::RouteHintHop; use std::iter::FromIterator; - use bitcoin::secp256k1::PublicKey; let builder = InvoiceBuilder::new(Currency::Bitcoin) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .duration_since_epoch(Duration::from_secs(1234567)) .min_final_cltv_expiry_delta(144); - let too_long_string = String::from_iter( - (0..1024).map(|_| '?') - ); + let too_long_string = String::from_iter((0..1024).map(|_| '?')); - let long_desc_res = builder.clone() - .description(too_long_string) - .build_raw(); + let long_desc_res = builder.clone().description(too_long_string).build_raw(); assert_eq!(long_desc_res, Err(CreationError::DescriptionTooLong)); let route_hop = RouteHintHop { src_node_id: PublicKey::from_slice( - &[ - 0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, - 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, - 0x95, 0xc3, 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55 - ][..] - ).unwrap(), + &[ + 0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c, + 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3, + 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55, + ][..], + ) + .unwrap(), short_channel_id: 0, - fees: RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, cltv_expiry_delta: 0, htlc_minimum_msat: None, htlc_maximum_msat: None, }; let too_long_route = RouteHint(vec![route_hop; 13]); - let long_route_res = builder.clone() - .description("Test".into()) - .private_route(too_long_route) - .build_raw(); + let long_route_res = + builder.clone().description("Test".into()).private_route(too_long_route).build_raw(); assert_eq!(long_route_res, Err(CreationError::RouteTooLong)); let sign_error_res = builder .description("Test".into()) .payment_secret(PaymentSecret([0; 32])) - .try_build_signed(|_| { - Err("ImaginaryError") - }); + .try_build_signed(|_| Err("ImaginaryError")); assert_eq!(sign_error_res, Err(SignOrCreationError::SignError("ImaginaryError"))); } #[test] fn test_builder_ok() { use crate::*; - use lightning_types::routing::RouteHintHop; use bitcoin::secp256k1::Secp256k1; - use bitcoin::secp256k1::{SecretKey, PublicKey}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + use lightning_types::routing::RouteHintHop; use std::time::Duration; let secp_ctx = Secp256k1::new(); @@ -2145,19 +2215,17 @@ mod test { &[ 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2, 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca, - 0x3b, 0x2d, 0xb7, 0x34 - ][..] - ).unwrap(); + 0x3b, 0x2d, 0xb7, 0x34, + ][..], + ) + .unwrap(); let public_key = PublicKey::from_secret_key(&secp_ctx, &private_key); let route_1 = RouteHint(vec![ RouteHintHop { src_node_id: public_key, short_channel_id: u64::from_be_bytes([123; 8]), - fees: RoutingFees { - base_msat: 2, - proportional_millionths: 1, - }, + fees: RoutingFees { base_msat: 2, proportional_millionths: 1 }, cltv_expiry_delta: 145, htlc_minimum_msat: None, htlc_maximum_msat: None, @@ -2165,24 +2233,18 @@ mod test { RouteHintHop { src_node_id: public_key, short_channel_id: u64::from_be_bytes([42; 8]), - fees: RoutingFees { - base_msat: 3, - proportional_millionths: 2, - }, + fees: RoutingFees { base_msat: 3, proportional_millionths: 2 }, cltv_expiry_delta: 146, htlc_minimum_msat: None, htlc_maximum_msat: None, - } + }, ]); let route_2 = RouteHint(vec![ RouteHintHop { src_node_id: public_key, short_channel_id: 0, - fees: RoutingFees { - base_msat: 4, - proportional_millionths: 3, - }, + fees: RoutingFees { base_msat: 4, proportional_millionths: 3 }, cltv_expiry_delta: 147, htlc_minimum_msat: None, htlc_maximum_msat: None, @@ -2190,14 +2252,11 @@ mod test { RouteHintHop { src_node_id: public_key, short_channel_id: u64::from_be_bytes([1; 8]), - fees: RoutingFees { - base_msat: 5, - proportional_millionths: 4, - }, + fees: RoutingFees { base_msat: 5, proportional_millionths: 4 }, cltv_expiry_delta: 148, htlc_minimum_msat: None, htlc_maximum_msat: None, - } + }, ]); let builder = InvoiceBuilder::new(Currency::BitcoinTestnet) @@ -2206,17 +2265,18 @@ mod test { .payee_pub_key(public_key) .expiry_time(Duration::from_secs(54321)) .min_final_cltv_expiry_delta(144) - .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())) + .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0; 20]).unwrap())) .private_route(route_1.clone()) .private_route(route_2.clone()) - .description_hash(sha256::Hash::from_slice(&[3;32][..]).unwrap()) - .payment_hash(sha256::Hash::from_slice(&[21;32][..]).unwrap()) + .description_hash(sha256::Hash::from_slice(&[3; 32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[21; 32][..]).unwrap()) .payment_secret(PaymentSecret([42; 32])) .basic_mpp(); - let invoice = builder.clone().build_signed(|hash| { - secp_ctx.sign_ecdsa_recoverable(hash, &private_key) - }).unwrap(); + let invoice = builder + .clone() + .build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key)) + .unwrap(); assert!(invoice.check_signature().is_ok()); assert_eq!(invoice.tagged_fields().count(), 10); @@ -2232,15 +2292,24 @@ mod test { assert_eq!(invoice.payee_pub_key(), Some(&public_key)); assert_eq!(invoice.expiry_time(), Duration::from_secs(54321)); assert_eq!(invoice.min_final_cltv_expiry_delta(), 144); - assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())]); - let address = Address::from_script(&ScriptBuf::new_p2pkh(&PubkeyHash::from_slice(&[0;20]).unwrap()), Network::Testnet).unwrap(); + assert_eq!( + invoice.fallbacks(), + vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0; 20]).unwrap())] + ); + let address = Address::from_script( + &ScriptBuf::new_p2pkh(&PubkeyHash::from_slice(&[0; 20]).unwrap()), + Network::Testnet, + ) + .unwrap(); assert_eq!(invoice.fallback_addresses(), vec![address]); assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]); assert_eq!( invoice.description(), - Bolt11InvoiceDescriptionRef::Hash(&Sha256(sha256::Hash::from_slice(&[3;32][..]).unwrap())) + Bolt11InvoiceDescriptionRef::Hash(&Sha256( + sha256::Hash::from_slice(&[3; 32][..]).unwrap() + )) ); - assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21;32][..]).unwrap()); + assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21; 32][..]).unwrap()); assert_eq!(invoice.payment_secret(), &PaymentSecret([42; 32])); let mut expected_features = Bolt11InvoiceFeatures::empty(); @@ -2261,7 +2330,7 @@ mod test { let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin) .description("Test".into()) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .payment_secret(PaymentSecret([0; 32])) .duration_since_epoch(Duration::from_secs(1234567)) .build_raw() @@ -2287,7 +2356,7 @@ mod test { let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin) .description("Test".into()) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .payment_secret(PaymentSecret([0; 32])) .duration_since_epoch(Duration::from_secs(1234567)) .build_raw() @@ -2319,7 +2388,8 @@ mod test { j5r6drg6k6zcqj0fcwg"; let invoice = invoice_str.parse::().unwrap(); let serialized_invoice = serde_json::to_string(&invoice).unwrap(); - let deserialized_invoice: super::Bolt11Invoice = serde_json::from_str(serialized_invoice.as_str()).unwrap(); + let deserialized_invoice: super::Bolt11Invoice = + serde_json::from_str(serialized_invoice.as_str()).unwrap(); assert_eq!(invoice, deserialized_invoice); assert_eq!(invoice_str, deserialized_invoice.to_string().as_str()); assert_eq!(invoice_str, serialized_invoice.as_str().trim_matches('\"')); @@ -2327,16 +2397,19 @@ mod test { #[test] fn raw_tagged_field_ordering() { - use crate::{Description, Fe32, RawTaggedField, TaggedField, Sha256, sha256, UntrustedString}; + use crate::{ + sha256, Description, Fe32, RawTaggedField, Sha256, TaggedField, UntrustedString, + }; - let field10 = RawTaggedField::KnownSemantics( - TaggedField::PaymentHash(Sha256(sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap())) - ); - let field11 = RawTaggedField::KnownSemantics( - TaggedField::Description(Description(UntrustedString("Description".to_string()))) - ); + let field10 = RawTaggedField::KnownSemantics(TaggedField::PaymentHash(Sha256( + sha256::Hash::from_str( + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(), + ))); + let field11 = RawTaggedField::KnownSemantics(TaggedField::Description(Description( + UntrustedString("Description".to_string()), + ))); let field20 = RawTaggedField::UnknownSemantics(vec![Fe32::Q]); let field21 = RawTaggedField::UnknownSemantics(vec![Fe32::R]); From 4dff397e2fb7205f87f73cdf315e9da6580da30a Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:09:05 +0100 Subject: [PATCH 10/13] `rustfmt`: Drop `lightning-invoice/src/lib.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index bd181ef61d7..dfb6e7b3757 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -1,5 +1,4 @@ lightning-invoice/fuzz/fuzz_targets/serde_data_part.rs -lightning-invoice/src/lib.rs lightning-invoice/src/payment.rs lightning-invoice/src/utils.rs lightning-invoice/tests/ser_de.rs From 611be778d2529a4df69d71d53fcf563a38bd5c8c Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 14 Nov 2024 13:51:09 +0100 Subject: [PATCH 11/13] `rustfmt`: Run on `lightning-invoice/tests/ser_de.rs` --- lightning-invoice/tests/ser_de.rs | 47 ++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/lightning-invoice/tests/ser_de.rs b/lightning-invoice/tests/ser_de.rs index 290b8ce6607..2266706652c 100644 --- a/lightning-invoice/tests/ser_de.rs +++ b/lightning-invoice/tests/ser_de.rs @@ -1,15 +1,15 @@ extern crate bech32; extern crate lightning_invoice; -use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion}; -use bitcoin::hex::FromHex; use bitcoin::hashes::{sha256, Hash}; -use lightning_invoice::*; -use bitcoin::secp256k1::PublicKey; +use bitcoin::hex::FromHex; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; +use bitcoin::secp256k1::PublicKey; +use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion}; +use lightning_invoice::*; use std::collections::HashSet; -use std::time::Duration; use std::str::FromStr; +use std::time::Duration; fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { vec![ @@ -379,7 +379,8 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { #[test] fn invoice_deserialize() { - for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() { + for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() + { eprintln!("Testing invoice {}...", serialized); let parsed = serialized.parse::().unwrap(); @@ -390,17 +391,33 @@ fn invoice_deserialize() { assert_eq!(deserialized_invoice.hrp, parsed_invoice.hrp); assert_eq!(deserialized_invoice.data.timestamp, parsed_invoice.data.timestamp); - let mut deserialized_hunks: HashSet<_> = deserialized_invoice.data.tagged_fields.iter().collect(); + let mut deserialized_hunks: HashSet<_> = + deserialized_invoice.data.tagged_fields.iter().collect(); let mut parsed_hunks: HashSet<_> = parsed_invoice.data.tagged_fields.iter().collect(); if ignore_feature_diff { - deserialized_hunks.retain(|h| - if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true }); - parsed_hunks.retain(|h| - if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true }); + deserialized_hunks.retain(|h| { + if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { + false + } else { + true + } + }); + parsed_hunks.retain(|h| { + if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { + false + } else { + true + } + }); } if ignore_unknown_fields { - parsed_hunks.retain(|h| - if let RawTaggedField::UnknownSemantics(_) = h { false } else { true }); + parsed_hunks.retain(|h| { + if let RawTaggedField::UnknownSemantics(_) = h { + false + } else { + true + } + }); } assert_eq!(deserialized_hunks, parsed_hunks); @@ -410,7 +427,9 @@ fn invoice_deserialize() { #[test] fn test_bolt_invalid_invoices() { - use bech32::primitives::decode::{CharError, ChecksumError, CheckedHrpstringError, UncheckedHrpstringError}; + use bech32::primitives::decode::{ + CharError, CheckedHrpstringError, ChecksumError, UncheckedHrpstringError, + }; // Tests the BOLT 11 invalid invoice test vectors assert_eq!(Bolt11Invoice::from_str( From 754f393f187176c5571728e4bf51c5cd1bbe33e4 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 14 Nov 2024 13:51:09 +0100 Subject: [PATCH 12/13] `rustfmt`: Drop `lightning-invoice/tests/ser_de.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index dfb6e7b3757..b1b214d077b 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -1,7 +1,6 @@ lightning-invoice/fuzz/fuzz_targets/serde_data_part.rs lightning-invoice/src/payment.rs lightning-invoice/src/utils.rs -lightning-invoice/tests/ser_de.rs lightning/src/blinded_path/message.rs lightning/src/blinded_path/mod.rs lightning/src/blinded_path/payment.rs From b5b70e763157e016c80dfd542def7ddc2f086c62 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Tue, 5 Nov 2024 10:09:27 +0100 Subject: [PATCH 13/13] `rustfmt`: Remove remaining `lightning-invoice` files from exclusion list --- rustfmt_excluded_files | 3 --- 1 file changed, 3 deletions(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index b1b214d077b..a71a16f6e8d 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -1,6 +1,3 @@ -lightning-invoice/fuzz/fuzz_targets/serde_data_part.rs -lightning-invoice/src/payment.rs -lightning-invoice/src/utils.rs lightning/src/blinded_path/message.rs lightning/src/blinded_path/mod.rs lightning/src/blinded_path/payment.rs