Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lightning-invoice/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,11 @@ impl FromStr for Bolt11Invoice {
/// let parsed_1 = invoice.parse::<Bolt11Invoice>();
///
/// let parsed_2 = match invoice.parse::<SignedRawBolt11Invoice>() {
/// Ok(signed) => match Bolt11Invoice::from_signed(signed) {
/// Ok(invoice) => Ok(invoice),
/// Err(e) => Err(ParseOrSemanticError::SemanticError(e)),
/// },
/// Err(e) => Err(ParseOrSemanticError::ParseError(e)),
/// Ok(signed) => match Bolt11Invoice::from_signed(signed) {
/// Ok(invoice) => Ok(invoice),
/// Err(e) => Err(ParseOrSemanticError::SemanticError(e)),
/// },
/// Err(e) => Err(ParseOrSemanticError::ParseError(e)),
/// };
///
/// assert!(parsed_1.is_ok());
Expand Down
97 changes: 40 additions & 57 deletions lightning-invoice/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,26 +196,26 @@ impl Checksum for Bolt11Bech32 {
/// # #[cfg(feature = "std")]
/// # fn main() {
/// let private_key = SecretKey::from_slice(
/// &[
/// 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();
/// &[
/// 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();
///
/// let payment_hash = PaymentHash([0; 32]);
/// let payment_secret = PaymentSecret([42u8; 32]);
///
/// let invoice = InvoiceBuilder::new(Currency::Bitcoin)
/// .description("Coins pls!".into())
/// .payment_hash(payment_hash)
/// .payment_secret(payment_secret)
/// .current_timestamp()
/// .min_final_cltv_expiry_delta(144)
/// .build_signed(|hash| {
/// Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
/// })
/// .unwrap();
/// .description("Coins pls!".into())
/// .payment_hash(payment_hash)
/// .payment_secret(payment_secret)
/// .current_timestamp()
/// .min_final_cltv_expiry_delta(144)
/// .build_signed(|hash| {
/// Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
/// })
/// .unwrap();
///
/// assert!(invoice.to_string().starts_with("lnbc1"));
/// # }
Expand Down Expand Up @@ -325,10 +325,10 @@ pub struct SignedRawBolt11Invoice {
/// Hash of the [`RawBolt11Invoice`] that will be used to check the signature.
///
/// * if the `SignedRawBolt11Invoice` was deserialized the hash is of from the original encoded form,
/// since it's not guaranteed that encoding it again will lead to the same result since integers
/// could have been encoded with leading zeroes etc.
/// since it's not guaranteed that encoding it again will lead to the same result since integers
/// could have been encoded with leading zeroes etc.
/// * if the `SignedRawBolt11Invoice` was constructed manually the hash will be the calculated hash
/// from the [`RawBolt11Invoice`]
/// from the [`RawBolt11Invoice`]
hash: [u8; 32],

/// signature of the payment request
Expand Down Expand Up @@ -368,7 +368,7 @@ impl RawHrp {
/// Convert to bech32::Hrp
pub fn to_hrp(&self) -> bech32::Hrp {
let hrp_str = self.to_string();
let s = core::str::from_utf8(&hrp_str.as_bytes()).expect("HRP bytes should be ASCII");
let s = core::str::from_utf8(hrp_str.as_bytes()).expect("HRP bytes should be ASCII");
debug_assert!(bech32::Hrp::parse(s).is_ok(), "We should always build BIP 173-valid HRPs");
bech32::Hrp::parse_unchecked(s)
}
Expand Down Expand Up @@ -736,11 +736,8 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool>

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::<Vec<_>>();
let tagged_fields =
self.tagged_fields.into_iter().map(RawTaggedField::KnownSemantics).collect::<Vec<_>>();

let data = RawDataPart { timestamp, tagged_fields };

Expand Down Expand Up @@ -1037,8 +1034,8 @@ impl SignedRawBolt11Invoice {
///
/// ```ignore
/// enum Enum {
/// A(u8),
/// B(u16)
/// A(u8),
/// B(u16)
/// }
///
/// let elements = vec![Enum::A(1), Enum::A(2), Enum::B(3), Enum::A(4)];
Expand All @@ -1058,15 +1055,15 @@ macro_rules! find_extract {
///
/// ```ignore
/// enum Enum {
/// A(u8),
/// B(u16)
/// A(u8),
/// B(u16)
/// }
///
/// let elements = vec![Enum::A(1), Enum::A(2), Enum::B(3), Enum::A(4)];
///
/// assert_eq!(
/// find_all_extract!(elements.iter(), Enum::A(x), x).collect::<Vec<u8>>(),
/// vec![1u8, 2u8, 4u8]
/// find_all_extract!(elements.iter(), Enum::A(x), x).collect::<Vec<u8>>(),
/// vec![1u8, 2u8, 4u8]
/// );
/// ```
macro_rules! find_all_extract {
Expand Down Expand Up @@ -1144,6 +1141,7 @@ 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
#[allow(clippy::type_complexity)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This #[allow(clippy::type_complexity)] is redundant — ci/check-lint.sh already globally suppresses clippy::type_complexity with -A clippy::type_complexity (line 99). Adding per-function #[allow] attributes just adds noise without any effect under the project's CI configuration.

pub fn known_tagged_fields(
&self,
) -> FilterMap<Iter<'_, RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>> {
Expand Down Expand Up @@ -1313,13 +1311,8 @@ 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| matches!(*tf, TaggedField::PaymentHash(_))).count();
if payment_hash_cnt < 1 {
return Err(Bolt11SemanticError::NoPaymentHash);
} else if payment_hash_cnt > 1 {
Expand All @@ -1329,9 +1322,8 @@ 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,
.filter(|&tf| {
matches!(*tf, TaggedField::Description(_) | TaggedField::DescriptionHash(_))
})
.count();
if description_cnt < 1 {
Expand All @@ -1348,13 +1340,8 @@ 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| matches!(*tf, TaggedField::PaymentSecret(_))).count();
if payment_secret_count < 1 {
return Err(Bolt11SemanticError::NoPaymentSecret);
} else if payment_secret_count > 1 {
Expand All @@ -1381,16 +1368,11 @@ impl Bolt11Invoice {
// "A writer MUST set an s field if and only if the payment_secret feature is set."
// (this requirement has been since removed, and we now require the payment secret
// feature bit always).
let features = self.tagged_fields().find(|&tf| match *tf {
TaggedField::Features(_) => true,
_ => false,
});
let features = self.tagged_fields().find(|&tf| matches!(*tf, TaggedField::Features(_)));
match features {
None => Err(Bolt11SemanticError::InvalidFeatures),
Some(TaggedField::Features(features)) => {
if features.requires_unknown_bits() {
Err(Bolt11SemanticError::InvalidFeatures)
} else if !features.supports_payment_secret() {
if features.requires_unknown_bits() || !features.supports_payment_secret() {
Err(Bolt11SemanticError::InvalidFeatures)
} else {
Ok(())
Expand Down Expand Up @@ -1455,6 +1437,7 @@ 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
#[allow(clippy::type_complexity)]
pub fn tagged_fields(
&self,
) -> FilterMap<Iter<'_, RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>> {
Expand Down Expand Up @@ -1553,15 +1536,15 @@ impl Bolt11Invoice {
/// Returns the Duration remaining until the invoice expires given the current time.
/// `time` is the timestamp as a duration since the Unix epoch.
pub fn expiration_remaining_from_epoch(&self, time: Duration) -> Duration {
self.expires_at().map(|x| x.checked_sub(time)).flatten().unwrap_or(Duration::from_nanos(0))
self.expires_at().and_then(|x| x.checked_sub(time)).unwrap_or(Duration::from_nanos(0))
}

/// Returns whether the expiry time would pass at the given point in time.
/// `at_time` is the timestamp as a duration since the Unix epoch.
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))
.unwrap_or_else(|| Duration::new(u64::MAX, 1_000_000_000 - 1))
< at_time
}

Expand All @@ -1586,7 +1569,7 @@ impl Bolt11Invoice {
let filter_fn = |fallback: &&Fallback| {
let address = match fallback {
Fallback::SegWitProgram { version, program } => {
match WitnessProgram::new(*version, &program) {
match WitnessProgram::new(*version, program) {
Ok(witness_program) => {
Address::from_witness_program(witness_program, self.network())
},
Expand Down
4 changes: 2 additions & 2 deletions lightning-invoice/src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ fn encoded_int_be_base32_size(int: u64) -> usize {
impl Base32Iterable for RawDataPart {
fn fe_iter<'s>(&'s self) -> impl Iterator<Item = Fe32> + 's {
let ts_iter = self.timestamp.fe_iter();
let fields_iter = self.tagged_fields.iter().map(RawTaggedField::fe_iter).flatten();
let fields_iter = self.tagged_fields.iter().flat_map(RawTaggedField::fe_iter);
ts_iter.chain(fields_iter)
}
}
Expand Down Expand Up @@ -405,7 +405,7 @@ impl Base32Iterable for PrivateRoute {
i1.chain(i2).chain(i3).chain(i4).chain(i5)
}

self.0 .0.iter().map(serialize_to_iter).flatten().bytes_to_fes()
self.0 .0.iter().flat_map(serialize_to_iter).bytes_to_fes()
}
}

Expand Down
20 changes: 10 additions & 10 deletions lightning-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ fn process_fields(group: Group) -> proc_macro::TokenStream {
/// `: $field_ty` after each field name.
/// ```ignore
/// match self {
/// Enum::Variant {
/// ref field1: option,
/// ref field2: (option, explicit_type: u64),
/// ref field3: (legacy, u64, {}, {}), // will be skipped
/// ..
/// } => expression
/// }
/// Enum::Variant {
/// ref field1: option,
/// ref field2: (option, explicit_type: u64),
/// ref field3: (legacy, u64, {}, {}), // will be skipped
/// ..
/// } => expression
/// }
/// ```
#[proc_macro]
pub fn skip_legacy_fields(expr: TokenStream) -> TokenStream {
Expand Down Expand Up @@ -248,8 +248,8 @@ pub fn skip_legacy_fields(expr: TokenStream) -> TokenStream {
/// Is expected to wrap a struct definition like
/// ```ignore
/// drop_legacy_field_definition!(Self {
/// field1: $crate::_init_tlv_based_struct_field!(field1, option),
/// field2: $crate::_init_tlv_based_struct_field!(field2, (legacy, u64, {})),
/// field1: $crate::_init_tlv_based_struct_field!(field1, option),
/// field2: $crate::_init_tlv_based_struct_field!(field2, (legacy, u64, {})),
/// })
/// ```
/// and will drop fields defined like `field2` with a type starting with `legacy`.
Expand Down Expand Up @@ -281,7 +281,7 @@ pub fn drop_legacy_field_definition(expr: TokenStream) -> TokenStream {
let macro_name = mac.path.segments.last().unwrap().ident.to_string();
let is_init = macro_name == "_init_tlv_based_struct_field";
// Skip `field_name` and `:`, giving us just the type's group
let ty_tokens = mac.tokens.clone().into_iter().skip(2).next();
let ty_tokens = mac.tokens.clone().into_iter().nth(2);
if let Some(proc_macro2::TokenTree::Group(group)) = ty_tokens {
let first_token = group.stream().into_iter().next();
if let Some(proc_macro2::TokenTree::Ident(ident)) = first_token {
Expand Down
14 changes: 7 additions & 7 deletions lightning-types/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ impl Deref for FeatureFlags {
fn deref(&self) -> &[u8] {
match self {
FeatureFlags::Held { bytes, len } => &bytes[..*len as usize],
FeatureFlags::Heap(vec) => &vec,
FeatureFlags::Heap(vec) => vec,
}
}
}
Expand Down Expand Up @@ -1179,12 +1179,12 @@ impl<T: sealed::Context> Features<T> {
let mut known_chunks = T::KNOWN_FEATURE_MASK.chunks(8);
for chunk in self.flags.chunks(8) {
let mut flag_bytes = [0; 8];
flag_bytes[..chunk.len()].copy_from_slice(&chunk);
flag_bytes[..chunk.len()].copy_from_slice(chunk);
let flag_int = u64::from_le_bytes(flag_bytes);

let known_chunk = known_chunks.next().unwrap_or(&[0; 0]);
let mut known_bytes = [0; 8];
known_bytes[..known_chunk.len()].copy_from_slice(&known_chunk);
known_bytes[..known_chunk.len()].copy_from_slice(known_chunk);
let known_int = u64::from_le_bytes(known_bytes);

const REQ_MASK: u64 = u64::from_le_bytes([ANY_REQUIRED_FEATURES_MASK; 8]);
Expand Down Expand Up @@ -1268,10 +1268,10 @@ impl<T: sealed::Context> Features<T> {
fn set_bit(&mut self, bit: usize, custom: bool) -> Result<(), ()> {
let byte_offset = bit / 8;
let mask = 1 << (bit - 8 * byte_offset);
if byte_offset < T::KNOWN_FEATURE_MASK.len() && custom {
if (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0 {
return Err(());
}
if byte_offset < T::KNOWN_FEATURE_MASK.len()
&& custom && (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0
{
return Err(());
}

if self.flags.len() <= byte_offset {
Expand Down
Loading