From 3d133cf3801cdc353a61fa8454f281acdaba0127 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:10:56 +0000 Subject: [PATCH 01/27] [UPSTREAM] Skip `BestBlock::new` in bindings as we already have one --- lightning/src/chain/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lightning/src/chain/mod.rs b/lightning/src/chain/mod.rs index a8afc7a1acb..947530085cf 100644 --- a/lightning/src/chain/mod.rs +++ b/lightning/src/chain/mod.rs @@ -52,6 +52,9 @@ impl BestBlock { } /// Returns a `BestBlock` as identified by the given block hash and height. + /// + /// This is not exported to bindings users directly as the bindings auto-generate an + /// equivalent `new`. pub fn new(block_hash: BlockHash, height: u32) -> Self { BestBlock { block_hash, height } } From 2cbf86936f7398e7fb15bed4f901774d7d795232 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:16:12 +0000 Subject: [PATCH 02/27] [UPSTREAM] Export `ChannelId` in bindings rather than `[u8; 32]` Now that `ChannelId` has useful constructors and methods we need to start exposing it to bindings users rather than relying on using `[u8; 32]`. --- lightning/src/ln/types.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/lightning/src/ln/types.rs b/lightning/src/ln/types.rs index 14774fb5e66..5966b371164 100644 --- a/lightning/src/ln/types.rs +++ b/lightning/src/ln/types.rs @@ -35,8 +35,6 @@ use core::ops::Deref; /// A _temporary_ ID is generated randomly. /// (Later revocation-point-based _v2_ is a possibility.) /// The variety (context) is not stored, it is relevant only at creation. -/// -/// This is not exported to bindings users as we just use [u8; 32] directly. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct ChannelId(pub [u8; 32]); From b5b6346fd56c17ad74219c2b64006c9c4dba6a28 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 15:55:36 +0000 Subject: [PATCH 03/27] [UPSTREAM] Use prelude by universal import, rather than single import This avoids the bindings trying to figure out what a `lightning::prelude::Vec` is rather than matching it as a `Vec`. --- lightning/src/util/sweep.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightning/src/util/sweep.rs b/lightning/src/util/sweep.rs index 5135549689c..dd26a8ef844 100644 --- a/lightning/src/util/sweep.rs +++ b/lightning/src/util/sweep.rs @@ -14,7 +14,7 @@ use crate::chain::{self, BestBlock, Confirm, Filter, Listen, WatchedOutput}; use crate::io; use crate::ln::msgs::DecodeError; use crate::ln::types::ChannelId; -use crate::prelude::Vec; +use crate::prelude::*; use crate::sign::{ChangeDestinationSource, OutputSpender, SpendableOutputDescriptor}; use crate::sync::Mutex; use crate::util::logger::Logger; From bc7dc7ad8c7d91ffda5c356bef81c5b349fae6e8 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 18:51:48 +0000 Subject: [PATCH 04/27] [UPSTREAM] Make `offers::Amount` `Copy` and export it in bindings `Amount` is less than two pointers long, so there's no reason it shouldn't be `Copy`. Further, because its an enum, bindings can't map a reference to it in an `Option`. Thus, here, we simply make it `Copy` and return it in `Option`s rather than a reference to it. --- lightning/src/offers/invoice.rs | 4 ++-- lightning/src/offers/offer.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 6f907d785c7..1f19c5971b3 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -697,7 +697,7 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => { /// /// [`Offer`]: crate::offers::offer::Offer /// [`Offer::amount`]: crate::offers::offer::Offer::amount - pub fn amount(&$self) -> Option<&Amount> { + pub fn amount(&$self) -> Option { $contents.amount() } @@ -944,7 +944,7 @@ impl InvoiceContents { } } - fn amount(&self) -> Option<&Amount> { + fn amount(&self) -> Option { match self { InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.inner.offer.amount(), diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 6df9b30a4ef..2a492fc91be 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -582,7 +582,7 @@ macro_rules! offer_accessors { ($self: ident, $contents: expr) => { } /// The minimum amount required for a successful payment of a single item. - pub fn amount(&$self) -> Option<&$crate::offers::offer::Amount> { + pub fn amount(&$self) -> Option<$crate::offers::offer::Amount> { $contents.amount() } @@ -808,8 +808,8 @@ impl OfferContents { self.metadata.as_ref().and_then(|metadata| metadata.as_bytes()) } - pub fn amount(&self) -> Option<&Amount> { - self.amount.as_ref() + pub fn amount(&self) -> Option { + self.amount } pub fn description(&self) -> Option { @@ -982,7 +982,7 @@ impl Writeable for OfferContents { /// The minimum amount required for an item in an [`Offer`], denominated in either bitcoin or /// another currency. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum Amount { /// An amount of bitcoin. Bitcoin { From 658e81ac9eb41d69e85106ccd195164d237eda0c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 12 May 2024 00:26:19 +0000 Subject: [PATCH 05/27] [UPSTREAM] Mark `io_extras` as no-bindings-export as its not pub --- lightning/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 3bcd5d72c64..be3da45528b 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -96,6 +96,8 @@ pub use core2::io; #[cfg(not(feature = "std"))] #[doc(hidden)] /// IO utilities public only for use by in-crate macros. These should not be used externally +/// +/// This is not exported to bindings users as it is not intended for public consumption. pub mod io_extras { use core2::io::{self, Read, Write}; @@ -158,6 +160,8 @@ pub mod io_extras { #[cfg(feature = "std")] #[doc(hidden)] /// IO utilities public only for use by in-crate macros. These should not be used externally +/// +/// This is not exported to bindings users as it is not intended for public consumption. mod io_extras { pub fn read_to_end(mut d: D) -> Result, ::std::io::Error> { let mut buf = Vec::new(); From 4244f6650ce6a9d756053dbd88f63310c67678a2 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 13 May 2024 14:35:34 +0000 Subject: [PATCH 06/27] [UPSTREAM] Expose `ChannelManager` offer constructors in bindings --- lightning/src/ln/channelmanager.rs | 4 ---- lightning/src/offers/offer.rs | 4 ---- 2 files changed, 8 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index c39818bd432..8fb29b394cb 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -8560,8 +8560,6 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => { /// /// Errors if the parameterized [`Router`] is unable to create a blinded path for the offer. /// - /// This is not exported to bindings users as builder patterns don't map outside of move semantics. - /// /// [`Offer`]: crate::offers::offer::Offer /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> { @@ -8624,8 +8622,6 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { /// - `amount_msats` is invalid, or /// - the parameterized [`Router`] is unable to create a blinded path for the refund. /// - /// This is not exported to bindings users as builder patterns don't map outside of move semantics. - /// /// [`Refund`]: crate::offers::refund::Refund /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 2a492fc91be..2b61a55a8a0 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -163,8 +163,6 @@ pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> { /// /// See [module-level documentation] for usage. /// -/// This is not exported to bindings users as builder patterns don't map outside of move semantics. -/// /// [module-level documentation]: self #[cfg(c_bindings)] pub struct OfferWithExplicitMetadataBuilder<'a> { @@ -177,8 +175,6 @@ pub struct OfferWithExplicitMetadataBuilder<'a> { /// /// See [module-level documentation] for usage. /// -/// This is not exported to bindings users as builder patterns don't map outside of move semantics. -/// /// [module-level documentation]: self #[cfg(c_bindings)] pub struct OfferWithDerivedMetadataBuilder<'a> { From 0380c65afc2caf3346498fae67e5f302ad2159eb Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 13 May 2024 14:36:01 +0000 Subject: [PATCH 07/27] [UPSTREAM] impl `Clone` on unsigned BOLT12 types This is required for bindings as passing types from Rust to GC'd languages can't map the concept of a type that has a lifetime of the called function but instead needs to clone for safety. --- lightning/src/ln/onion_payment.rs | 2 +- lightning/src/offers/invoice.rs | 1 + lightning/src/offers/invoice_request.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lightning/src/ln/onion_payment.rs b/lightning/src/ln/onion_payment.rs index 8293a32021e..20a1e1dbb62 100644 --- a/lightning/src/ln/onion_payment.rs +++ b/lightning/src/ln/onion_payment.rs @@ -26,7 +26,7 @@ use crate::prelude::*; use core::ops::Deref; /// Invalid inbound onion payment. -#[derive(Debug)] +#[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct InboundHTLCErr { /// BOLT 4 error code. pub err_code: u16, diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 1f19c5971b3..c1ad5b3201a 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -503,6 +503,7 @@ for InvoiceBuilder<'a, DerivedSigningPubkey> { /// /// This is serialized as a TLV stream, which includes TLV records from the originating message. As /// such, it may include unknown, odd TLV records. +#[derive(Clone)] pub struct UnsignedBolt12Invoice { bytes: Vec, contents: InvoiceContents, diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index faeef26c82f..9041fa8a9bf 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -487,6 +487,7 @@ for InvoiceRequestBuilder<'a, 'b, DerivedPayerId, secp256k1::All> { /// /// This is serialized as a TLV stream, which includes TLV records from the originating message. As /// such, it may include unknown, odd TLV records. +#[derive(Clone)] pub struct UnsignedInvoiceRequest { bytes: Vec, contents: InvoiceRequestContents, From 7efbfa1e16c57ef35d6cbbff6f12adaa623a1c7d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 13 May 2024 14:39:19 +0000 Subject: [PATCH 08/27] [UPSTREAM] impl `Clone` on BOLT12 builders in bindings This is required for GC'd languages which need to be able to clone in order to pass owned objects to Rust. --- lightning/src/offers/offer.rs | 2 ++ lightning/src/offers/refund.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 2b61a55a8a0..3462823528e 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -165,6 +165,7 @@ pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> { /// /// [module-level documentation]: self #[cfg(c_bindings)] +#[derive(Clone)] pub struct OfferWithExplicitMetadataBuilder<'a> { offer: OfferContents, metadata_strategy: core::marker::PhantomData, @@ -177,6 +178,7 @@ pub struct OfferWithExplicitMetadataBuilder<'a> { /// /// [module-level documentation]: self #[cfg(c_bindings)] +#[derive(Clone)] pub struct OfferWithDerivedMetadataBuilder<'a> { offer: OfferContents, metadata_strategy: core::marker::PhantomData, diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index 6a1d24106e9..1988a92aaa7 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -141,6 +141,7 @@ pub struct RefundBuilder<'a, T: secp256k1::Signing> { /// /// [module-level documentation]: self #[cfg(c_bindings)] +#[derive(Clone)] pub struct RefundMaybeWithDerivedMetadataBuilder<'a> { refund: RefundContents, secp_ctx: Option<&'a Secp256k1>, From d41d87caf31d30e0fad1f6a9064fc0ba8b2a1ee3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 13 May 2024 18:01:20 +0000 Subject: [PATCH 09/27] [UPSTREAM] Allow any `Deref` to an `EntropySource` in `BlindedPath` This matches our normal API semantics and allows, for example, `Arc`s to `EntropySource`s. --- lightning/src/blinded_path/mod.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/lightning/src/blinded_path/mod.rs b/lightning/src/blinded_path/mod.rs index 3dc6b121b00..a61eb12b9ae 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -15,6 +15,8 @@ pub(crate) mod utils; use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; +use core::ops::Deref; + use crate::ln::msgs::DecodeError; use crate::offers::invoice::BlindedPayInfo; use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph}; @@ -115,9 +117,9 @@ pub struct BlindedHop { impl BlindedPath { /// Create a one-hop blinded path for a message. - pub fn one_hop_for_message( - recipient_node_id: PublicKey, entropy_source: &ES, secp_ctx: &Secp256k1 - ) -> Result { + pub fn one_hop_for_message( + recipient_node_id: PublicKey, entropy_source: ES, secp_ctx: &Secp256k1 + ) -> Result where ES::Target: EntropySource { Self::new_for_message(&[recipient_node_id], entropy_source, secp_ctx) } @@ -126,9 +128,9 @@ impl BlindedPath { /// /// Errors if no hops are provided or if `node_pk`(s) are invalid. // TODO: make all payloads the same size with padding + add dummy hops - pub fn new_for_message( - node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1 - ) -> Result { + pub fn new_for_message( + node_pks: &[PublicKey], entropy_source: ES, secp_ctx: &Secp256k1 + ) -> Result where ES::Target: EntropySource { if node_pks.is_empty() { return Err(()) } let blinding_secret_bytes = entropy_source.get_secure_random_bytes(); let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); @@ -142,10 +144,10 @@ impl BlindedPath { } /// Create a one-hop blinded path for a payment. - pub fn one_hop_for_payment( + pub fn one_hop_for_payment( payee_node_id: PublicKey, payee_tlvs: payment::ReceiveTlvs, min_final_cltv_expiry_delta: u16, - entropy_source: &ES, secp_ctx: &Secp256k1 - ) -> Result<(BlindedPayInfo, Self), ()> { + entropy_source: ES, secp_ctx: &Secp256k1 + ) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource { // This value is not considered in pathfinding for 1-hop blinded paths, because it's intended to // be in relation to a specific channel. let htlc_maximum_msat = u64::max_value(); @@ -164,11 +166,11 @@ impl BlindedPath { /// /// [`ForwardTlvs`]: crate::blinded_path::payment::ForwardTlvs // TODO: make all payloads the same size with padding + add dummy hops - pub fn new_for_payment( + pub fn new_for_payment( intermediate_nodes: &[payment::ForwardNode], payee_node_id: PublicKey, payee_tlvs: payment::ReceiveTlvs, htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16, - entropy_source: &ES, secp_ctx: &Secp256k1 - ) -> Result<(BlindedPayInfo, Self), ()> { + entropy_source: ES, secp_ctx: &Secp256k1 + ) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource { let introduction_node = IntroductionNode::NodeId( intermediate_nodes.first().map_or(payee_node_id, |n| n.node_id) ); From 1d2cb76fd45d3fa76e0850269f378e9019d28f23 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 23 Jan 2024 19:55:24 +0000 Subject: [PATCH 10/27] Stop relying on a `Clone`able `NetworkGraph` ref in `DefaultRouter` While there's not really much harm in requiring a `Clone`able reference (they almost always are), it does make our bindings struggle a bit as they don't support multi-trait bounds (as it would require synthesizing a new C trait, which the bindings don't do automatically). Luckily, there's really no reason for it, and we can just call the `DefaultMessageRouter` directly when we want to route a message. --- lightning/src/onion_message/messenger.rs | 39 ++++++++++++++++++------ lightning/src/routing/router.rs | 16 +++++----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 476655ebeb8..57e76d1cf8a 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -315,15 +315,15 @@ where } } -impl>, L: Deref, ES: Deref> MessageRouter for DefaultMessageRouter +impl>, L: Deref, ES: Deref> DefaultMessageRouter where L::Target: Logger, ES::Target: EntropySource, { - fn find_path( - &self, sender: PublicKey, peers: Vec, mut destination: Destination + pub(crate) fn find_path( + network_graph: &G, sender: PublicKey, peers: Vec, mut destination: Destination ) -> Result { - let network_graph = self.network_graph.deref().read_only(); + let network_graph = network_graph.deref().read_only(); destination.resolve(&network_graph); let first_node = match destination.first_node() { @@ -354,10 +354,11 @@ where } } - fn create_blinded_paths< + pub(crate) fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, peers: Vec, secp_ctx: &Secp256k1, + network_graph: &G, recipient: PublicKey, peers: Vec, entropy_source: &ES, + secp_ctx: &Secp256k1, ) -> Result, ()> { // Limit the number of blinded paths that are computed. const MAX_PATHS: usize = 3; @@ -366,7 +367,7 @@ where // recipient's node_id. const MIN_PEER_CHANNELS: usize = 3; - let network_graph = self.network_graph.deref().read_only(); + let network_graph = network_graph.deref().read_only(); let is_recipient_announced = network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)); @@ -389,7 +390,7 @@ where let paths = peer_info.into_iter() .map(|(pubkey, _, _)| vec![pubkey, recipient]) - .map(|node_pks| BlindedPath::new_for_message(&node_pks, &*self.entropy_source, secp_ctx)) + .map(|node_pks| BlindedPath::new_for_message(&node_pks, &**entropy_source, secp_ctx)) .take(MAX_PATHS) .collect::, _>>(); @@ -397,7 +398,7 @@ where Ok(paths) if !paths.is_empty() => Ok(paths), _ => { if is_recipient_announced { - BlindedPath::one_hop_for_message(recipient, &*self.entropy_source, secp_ctx) + BlindedPath::one_hop_for_message(recipient, &**entropy_source, secp_ctx) .map(|path| vec![path]) } else { Err(()) @@ -407,6 +408,26 @@ where } } +impl>, L: Deref, ES: Deref> MessageRouter for DefaultMessageRouter +where + L::Target: Logger, + ES::Target: EntropySource, +{ + fn find_path( + &self, sender: PublicKey, peers: Vec, destination: Destination + ) -> Result { + Self::find_path(&self.network_graph, sender, peers, destination) + } + + fn create_blinded_paths< + T: secp256k1::Signing + secp256k1::Verification + >( + &self, recipient: PublicKey, peers: Vec, secp_ctx: &Secp256k1, + ) -> Result, ()> { + Self::create_blinded_paths(&self.network_graph, recipient, peers, &self.entropy_source, secp_ctx) + } +} + /// A path for sending an [`OnionMessage`]. #[derive(Clone)] pub struct OnionMessagePath { diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 8744761e72d..607e0fb3741 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -33,7 +33,7 @@ use core::{cmp, fmt}; use core::ops::Deref; /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter> + Clone, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where +pub struct DefaultRouter>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, @@ -43,22 +43,20 @@ pub struct DefaultRouter> + Clone, L: Deref, E entropy_source: ES, scorer: S, score_params: SP, - message_router: DefaultMessageRouter, } -impl> + Clone, L: Deref, ES: Deref + Clone, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where +impl>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, { /// Creates a new router. pub fn new(network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: SP) -> Self { - let message_router = DefaultMessageRouter::new(network_graph.clone(), entropy_source.clone()); - Self { network_graph, logger, entropy_source, scorer, score_params, message_router } + Self { network_graph, logger, entropy_source, scorer, score_params } } } -impl> + Clone, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where +impl>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, @@ -156,7 +154,7 @@ impl> + Clone, L: Deref, ES: Deref, S: Deref, } } -impl< G: Deref> + Clone, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> MessageRouter for DefaultRouter where +impl< G: Deref>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> MessageRouter for DefaultRouter where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, @@ -164,7 +162,7 @@ impl< G: Deref> + Clone, L: Deref, ES: Deref, S: Deref, fn find_path( &self, sender: PublicKey, peers: Vec, destination: Destination ) -> Result { - self.message_router.find_path(sender, peers, destination) + DefaultMessageRouter::<_, _, ES>::find_path(&self.network_graph, sender, peers, destination) } fn create_blinded_paths< @@ -172,7 +170,7 @@ impl< G: Deref> + Clone, L: Deref, ES: Deref, S: Deref, > ( &self, recipient: PublicKey, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - self.message_router.create_blinded_paths(recipient, peers, secp_ctx) + DefaultMessageRouter::create_blinded_paths(&self.network_graph, recipient, peers, &self.entropy_source, secp_ctx) } } From 76c137d8138a84d3f01f8f52cbd79992e2b973a4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 1 Mar 2022 03:46:52 +0000 Subject: [PATCH 11/27] Make `as_directed_to` non-public ...as the bindings generation does not currently have the ability to map a reference to a `NodeId` inside a tuple. --- lightning/src/routing/gossip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index db35ff01bf0..e1cc24f831a 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -878,7 +878,7 @@ pub struct ChannelInfo { impl ChannelInfo { /// Returns a [`DirectedChannelInfo`] for the channel directed to the given `target` from a /// returned `source`, or `None` if `target` is not one of the channel's counterparties. - pub fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> { + pub(crate) fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> { let (direction, source, outbound) = { if target == &self.node_one { (self.two_to_one.as_ref(), &self.node_two, false) From 0c0383ce79f72fd3669e2b403f857689cfb5b6a4 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Tue, 29 Mar 2022 10:20:39 -0500 Subject: [PATCH 12/27] Restrict ChannelInfo::as_directed_from visibility Bindings can't handle references in return types, so reduce the visibility to pub(crate). --- lightning/src/routing/gossip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index e1cc24f831a..7831e20fa03 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -893,7 +893,7 @@ impl ChannelInfo { /// Returns a [`DirectedChannelInfo`] for the channel directed from the given `source` to a /// returned `target`, or `None` if `source` is not one of the channel's counterparties. - pub fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> { + pub(crate) fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> { let (direction, target, outbound) = { if source == &self.node_one { (self.one_to_two.as_ref(), &self.node_two, true) From 662c9e9eb692c568fc8e2fe1a85e28bcdd907cbc Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 24 Dec 2022 04:16:48 +0000 Subject: [PATCH 13/27] Use an explicit `Sign` type on the `ChannelMonitor` read tuple The bindings currently get confused by the implicit `Sign` type, so we temporarily remove it on the `impl` here. --- lightning/src/chain/channelmonitor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index b8598eabb97..f3e2653844d 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -4468,8 +4468,8 @@ where const MAX_ALLOC_SIZE: usize = 64*1024; -impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)> - for (BlockHash, ChannelMonitor) { +impl<'a, 'b, ES: EntropySource, Signer: WriteableEcdsaChannelSigner, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)> + for (BlockHash, ChannelMonitor) { fn read(reader: &mut R, args: (&'a ES, &'b SP)) -> Result { macro_rules! unwrap_obj { ($key: expr) => { From a9b8c753530114b894e33f4e51437cc914d93353 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 28 Feb 2023 21:45:14 +0000 Subject: [PATCH 14/27] Export `outbound_payment` structs in their respective modules Re-exports in Rust make `use` statements a little shorter, but for otherwise don't materially change a crate's API. Sadly, the C bindings generator currently can't figure out re-exports, but it also exports everything into one global namespace, so it doesn't matter much anyway. --- fuzz/src/chanmon_consistency.rs | 3 ++- fuzz/src/full_stack.rs | 3 ++- lightning-invoice/src/payment.rs | 5 +++-- lightning-invoice/src/utils.rs | 3 ++- lightning/src/ln/channelmanager.rs | 2 +- lightning/src/ln/mod.rs | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index b3cf867d6e3..ba8ba3e1dc7 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -41,7 +41,8 @@ use lightning::sign::{KeyMaterial, InMemorySigner, Recipient, EntropySource, Nod use lightning::events; use lightning::events::MessageSendEventsProvider; use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; -use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs, PaymentId, RecipientOnionFields}; +use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, ChannelManagerReadArgs, PaymentId}; +use lightning::ln::outbound_payment::{RecipientOnionFields, PaymentSendFailure}; use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE; use lightning::ln::msgs::{self, CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init}; use lightning::ln::script::ShutdownScript; diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index d07def30ff9..09e5b430d5f 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -37,7 +37,8 @@ use lightning::chain::transaction::OutPoint; use lightning::sign::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider}; use lightning::events::Event; use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; -use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId}; +use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId, InterceptId}; +use lightning::ln::outbound_payment::{RecipientOnionFields, Retry}; use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler}; use lightning::ln::msgs::{self, DecodeError}; use lightning::ln::script::ShutdownScript; diff --git a/lightning-invoice/src/payment.rs b/lightning-invoice/src/payment.rs index a8ffce7bbd9..57b9f9b844a 100644 --- a/lightning-invoice/src/payment.rs +++ b/lightning-invoice/src/payment.rs @@ -13,7 +13,7 @@ use crate::Bolt11Invoice; use bitcoin::hashes::Hash; use lightning::ln::types::PaymentHash; -use lightning::ln::channelmanager::RecipientOnionFields; +use lightning::ln::outbound_payment::RecipientOnionFields; use lightning::routing::router::{PaymentParameters, RouteParameters}; /// Builds the necessary parameters to pay or pre-flight probe the given zero-amount @@ -170,7 +170,8 @@ mod tests { #[cfg(feature = "std")] fn payment_metadata_end_to_end() { use lightning::events::Event; - use lightning::ln::channelmanager::{Retry, PaymentId}; + use lightning::ln::channelmanager::PaymentId; + use lightning::ln::outbound_payment::Retry; use lightning::ln::msgs::ChannelMessageHandler; use lightning::ln::functional_test_utils::*; // Test that a payment metadata read from an invoice passed to `pay_invoice` makes it all diff --git a/lightning-invoice/src/utils.rs b/lightning-invoice/src/utils.rs index 22e493ae1c5..1dda97fb49b 100644 --- a/lightning-invoice/src/utils.rs +++ b/lightning-invoice/src/utils.rs @@ -827,7 +827,8 @@ mod test { use lightning::ln::types::PaymentHash; #[cfg(feature = "std")] use lightning::ln::types::PaymentPreimage; - use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields, Retry}; + use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId}; + use lightning::ln::outbound_payment::{RecipientOnionFields, Retry}; use lightning::ln::functional_test_utils::*; use lightning::ln::msgs::ChannelMessageHandler; use lightning::routing::router::{PaymentParameters, RouteParameters}; diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 8fb29b394cb..04acfa1a2ea 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -103,7 +103,7 @@ use core::time::Duration; use core::ops::Deref; // Re-export this for use in the public API. -pub use crate::ln::outbound_payment::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; +pub(crate) use crate::ln::outbound_payment::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; use crate::ln::script::ShutdownScript; // We hold various information about HTLC relay in the HTLC objects in Channel itself: diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index 7cbb2ce5ebe..987275c5b24 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -37,7 +37,7 @@ pub mod channel; pub(crate) mod channel; pub(crate) mod onion_utils; -mod outbound_payment; +pub mod outbound_payment; pub mod wire; pub use onion_utils::create_payment_onion; From fb6e90dc610cb5a9c79775867ac55042b2ced933 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 5 Mar 2023 20:38:42 +0000 Subject: [PATCH 15/27] Avoid enums containing references with lifetimes Having struct fields with references to other structs is tough in our bindings logic, but even worse if the fields are in an enum. Its simplest to just take the clone penalty here. --- lightning/src/ln/channel.rs | 4 ++-- lightning/src/ln/channelmanager.rs | 2 +- lightning/src/ln/msgs.rs | 11 ++++++----- lightning/src/ln/peer_handler.rs | 2 +- lightning/src/ln/priv_short_conf_tests.rs | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 880d2ae6ab1..14d7b5ee212 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -6762,7 +6762,7 @@ impl Channel where return None; } }; - let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) { + let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(announcement.clone())) { Err(_) => { log_error!(logger, "Failed to generate node signature for channel_announcement. Channel will not be announced!"); return None; @@ -6808,7 +6808,7 @@ impl Channel where .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?); let were_node_one = announcement.node_id_1 == our_node_key; - let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) + let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(announcement.clone())) .map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?; match &self.context.holder_signer { ChannelSignerType::Ecdsa(ecdsa) => { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 04acfa1a2ea..bc418f118a9 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -4071,7 +4071,7 @@ where // If we returned an error and the `node_signer` cannot provide a signature for whatever // reason`, we wouldn't be able to receive inbound payments through the corresponding // channel. - let sig = self.node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&unsigned)).unwrap(); + let sig = self.node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(unsigned.clone())).unwrap(); Ok(msgs::ChannelUpdate { signature: sig, diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 87e8a814d33..2de0397eb2f 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -1113,16 +1113,17 @@ impl FromStr for SocketAddress { } /// Represents the set of gossip messages that require a signature from a node's identity key. -pub enum UnsignedGossipMessage<'a> { +#[derive(Clone)] +pub enum UnsignedGossipMessage { /// An unsigned channel announcement. - ChannelAnnouncement(&'a UnsignedChannelAnnouncement), + ChannelAnnouncement(UnsignedChannelAnnouncement), /// An unsigned channel update. - ChannelUpdate(&'a UnsignedChannelUpdate), + ChannelUpdate(UnsignedChannelUpdate), /// An unsigned node announcement. - NodeAnnouncement(&'a UnsignedNodeAnnouncement) + NodeAnnouncement(UnsignedNodeAnnouncement) } -impl<'a> Writeable for UnsignedGossipMessage<'a> { +impl Writeable for UnsignedGossipMessage { fn write(&self, writer: &mut W) -> Result<(), io::Error> { match self { UnsignedGossipMessage::ChannelAnnouncement(ref msg) => msg.write(writer), diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 17e46a274b1..3f20a07b394 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -2638,7 +2638,7 @@ impl sig, Err(_) => { diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index fba97eae382..d01a9574073 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -516,7 +516,7 @@ fn test_scid_alias_returned() { fee_proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths, excess_data: Vec::new(), }; - let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&contents)).unwrap(); + let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(contents.clone())).unwrap(); let msg = msgs::ChannelUpdate { signature, contents }; let mut err_data = Vec::new(); From 1eb3520ad4be64d8f27e2f3113523554c9709639 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 20:05:15 +0000 Subject: [PATCH 16/27] Mark a few offers fields no-export as we have no mapping for them --- lightning/src/offers/invoice.rs | 2 ++ lightning/src/offers/parse.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index c1ad5b3201a..2c0d3420474 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -836,6 +836,8 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => { /// Fallback addresses for paying the invoice on-chain, in order of most-preferred to /// least-preferred. + /// + /// This is not exported to bindings users as Address is not yet mapped pub fn fallbacks(&$self) -> Vec
{ $contents.fallbacks() } diff --git a/lightning/src/offers/parse.rs b/lightning/src/offers/parse.rs index 3b9b04a5c06..cefaaf186bb 100644 --- a/lightning/src/offers/parse.rs +++ b/lightning/src/offers/parse.rs @@ -125,7 +125,8 @@ pub enum Bolt12ParseError { /// being parsed. InvalidBech32Hrp, /// The string could not be bech32 decoded. - Bech32(bech32::Error), + Bech32(/// This is not exported to bindings users as the details don't matter much + bech32::Error), /// The bech32 decoded string could not be decoded as the expected message type. Decode(DecodeError), /// The parsed message has invalid semantics. From b202d91212f481645bb584ed9b3fa7ac4ff1a8be Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 20:05:26 +0000 Subject: [PATCH 17/27] Use `[u8; 3]` not `CurrencyCode` to skip type aliases to primitives --- lightning/src/offers/offer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 3462823528e..574effb56bb 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -990,14 +990,14 @@ pub enum Amount { /// An amount of currency specified using ISO 4712. Currency { /// The currency that the amount is denominated in. - iso4217_code: CurrencyCode, + iso4217_code: [u8; 3], /// The amount in the currency unit adjusted by the ISO 4712 exponent (e.g., USD cents). amount: u64, }, } /// An ISO 4712 three-letter currency code (e.g., USD). -pub type CurrencyCode = [u8; 3]; +pub(crate) type CurrencyCode = [u8; 3]; /// Quantity of items supported by an [`Offer`]. #[derive(Clone, Copy, Debug, PartialEq)] From 2456605bf482c2443713b2ea0e00eabde08a0476 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 21 Oct 2023 02:28:53 +0000 Subject: [PATCH 18/27] Hard-code scorer parameters to `ProbabilisticScoringFeeParameters` The scorer currently relies on an associated type for the fee parameters. This isn't supportable at all in bindings, and for lack of a better option we simply hard-code the parameter for all scorers to `ProbabilisticScoringFeeParameters`. --- lightning-background-processor/src/lib.rs | 7 ++-- lightning/src/ln/channelmanager.rs | 4 --- lightning/src/routing/router.rs | 40 +++++++++++++---------- lightning/src/routing/scoring.rs | 16 ++++++--- lightning/src/util/test_utils.rs | 3 +- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index ad1056ea922..601ed296b37 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -989,9 +989,7 @@ mod tests { Arc>>, Arc, Arc, - Arc>, - (), - TestScorer> + Arc>> >, Arc>; @@ -1151,9 +1149,10 @@ mod tests { } impl ScoreLookUp for TestScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); fn channel_penalty_msat( - &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &lightning::routing::scoring::ProbabilisticScoringFeeParameters ) -> u64 { unimplemented!(); } } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index bc418f118a9..5bca7b4e066 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -1002,8 +1002,6 @@ pub type SimpleArcChannelManager = ChannelManager< Arc, Arc, Arc>>, Arc>>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer>>, Arc>, >>, Arc >; @@ -1033,8 +1031,6 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> = &'g L, &'c KeysManager, &'h RwLock, &'g L>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L> >, &'g L >; diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 607e0fb3741..53a12ed914f 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -33,32 +33,32 @@ use core::{cmp, fmt}; use core::ops::Deref; /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where +pub struct DefaultRouter>, L: Deref, ES: Deref, S: Deref> where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for <'a> LockableScore<'a>, ES::Target: EntropySource, { network_graph: G, logger: L, entropy_source: ES, scorer: S, - score_params: SP, + score_params: crate::routing::scoring::ProbabilisticScoringFeeParameters, } -impl>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where +impl>, L: Deref, ES: Deref, S: Deref> DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for <'a> LockableScore<'a>, ES::Target: EntropySource, { /// Creates a new router. - pub fn new(network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: SP) -> Self { + pub fn new(network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: crate::routing::scoring::ProbabilisticScoringFeeParameters) -> Self { Self { network_graph, logger, entropy_source, scorer, score_params } } } -impl>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where +impl>, L: Deref, ES: Deref, S: Deref> Router for DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for <'a> LockableScore<'a>, ES::Target: EntropySource, { fn find_route( @@ -154,9 +154,9 @@ impl>, L: Deref, ES: Deref, S: Deref, SP: Size } } -impl< G: Deref>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> MessageRouter for DefaultRouter where +impl< G: Deref>, L: Deref, ES: Deref, S: Deref> MessageRouter for DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for <'a> LockableScore<'a>, ES::Target: EntropySource, { fn find_path( @@ -233,8 +233,9 @@ impl<'a, S: Deref> ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: Scor } impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp { + #[cfg(not(c_bindings))] type ScoreParams = ::ScoreParams; - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 { let target = match candidate.target() { Some(target) => target, None => return self.scorer.channel_penalty_msat(candidate, usage, score_params), @@ -1829,7 +1830,7 @@ fn sort_first_hop_channels( pub fn find_route( our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &NetworkGraph, first_hops: Option<&[&ChannelDetails]>, logger: L, - scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32] + scorer: &S, score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters, random_seed_bytes: &[u8; 32] ) -> Result where L::Target: Logger, GL::Target: Logger { let graph_lock = network_graph.read_only(); @@ -1841,7 +1842,7 @@ where L::Target: Logger, GL::Target: Logger { pub(crate) fn get_route( our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &ReadOnlyNetworkGraph, - first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams, + first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters, _random_seed_bytes: &[u8; 32] ) -> Result where L::Target: Logger { @@ -3236,9 +3237,10 @@ fn build_route_from_hops_internal( } impl ScoreLookUp for HopScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, - _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 + _usage: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 { let mut cur_id = self.our_node_id; for i in 0..self.hop_ids.len() { @@ -6593,8 +6595,9 @@ mod tests { fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } } impl ScoreLookUp for BadChannelScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 { if candidate.short_channel_id() == Some(self.short_channel_id) { u64::max_value() } else { 0 } } } @@ -6609,8 +6612,9 @@ mod tests { } impl ScoreLookUp for BadNodeScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 { if candidate.target() == Some(self.node_id) { u64::max_value() } else { 0 } } } @@ -8504,7 +8508,7 @@ pub(crate) mod bench_utils { } pub(crate) fn generate_test_routes(graph: &NetworkGraph<&TestLogger>, scorer: &mut S, - score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, mut seed: u64, + score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters, features: Bolt11InvoiceFeatures, mut seed: u64, starting_amount: u64, route_count: usize, ) -> Vec<(ChannelDetails, PaymentParameters, u64)> { let payer = payer_pubkey(); @@ -8689,7 +8693,7 @@ pub mod benches { fn generate_routes( bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, mut scorer: S, - score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, starting_amount: u64, + score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters, features: Bolt11InvoiceFeatures, starting_amount: u64, bench_name: &'static str, ) { let payer = bench_utils::payer_pubkey(); diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 4cb9144d339..349f5b9719d 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -92,9 +92,13 @@ macro_rules! define_score { ($($supertrait: path)*) => { /// /// Scoring is in terms of fees willing to be paid in order to avoid routing through a channel. pub trait ScoreLookUp { + #[cfg(not(c_bindings))] /// A configurable type which should contain various passed-in parameters for configuring the scorer, /// on a per-routefinding-call basis through to the scorer methods, /// which are used to determine the parameters for the suitability of channels for use. + /// + /// Note that due to limitations in many other languages' generics features, language bindings + /// use [`ProbabilisticScoringFeeParameters`] for the parameters on all scorers. type ScoreParams; /// Returns the fee in msats willing to be paid to avoid routing `send_amt_msat` through the /// given channel in the direction from `source` to `target`. @@ -105,7 +109,7 @@ pub trait ScoreLookUp { /// [`u64::max_value`] is given to indicate sufficient capacity for the invoice's full amount. /// Thus, implementations should be overflow-safe. fn channel_penalty_msat( - &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters ) -> u64; } @@ -143,9 +147,10 @@ impl Score for T {} #[cfg(not(c_bindings))] impl> ScoreLookUp for T { + #[cfg(not(c_bindings))] type ScoreParams = S::ScoreParams; fn channel_penalty_msat( - &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters ) -> u64 { self.deref().channel_penalty_msat(candidate, usage, score_params) } @@ -326,8 +331,9 @@ impl<'a, T: 'a + Score> Deref for MultiThreadedScoreLockRead<'a, T> { #[cfg(c_bindings)] impl<'a, T: Score> ScoreLookUp for MultiThreadedScoreLockRead<'a, T> { + #[cfg(not(c_bindings))] type ScoreParams = T::ScoreParams; - fn channel_penalty_msat(&self, candidate:&CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams + fn channel_penalty_msat(&self, candidate:&CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters ) -> u64 { self.0.channel_penalty_msat(candidate, usage, score_params) } @@ -408,8 +414,9 @@ impl FixedPenaltyScorer { } impl ScoreLookUp for FixedPenaltyScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); - fn channel_penalty_msat(&self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat(&self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &ProbabilisticScoringFeeParameters) -> u64 { self.penalty_msat } } @@ -1318,6 +1325,7 @@ DirectedChannelLiquidity { } impl>, L: Deref> ScoreLookUp for ProbabilisticScorer where L::Target: Logger { + #[cfg(not(c_bindings))] type ScoreParams = ProbabilisticScoringFeeParameters; fn channel_penalty_msat( &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 6b4d2acd4d9..9a340db905e 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -1440,9 +1440,10 @@ impl crate::util::ser::Writeable for TestScorer { } impl ScoreLookUp for TestScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); fn channel_penalty_msat( - &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters ) -> u64 { let short_channel_id = match candidate.globally_unique_short_channel_id() { Some(scid) => scid, From a93e17c3300993e47ba5630d0e513cf53da24f5d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 19 Jul 2023 20:09:23 +0000 Subject: [PATCH 19/27] Mark several types no-export which should be exported eventually --- lightning/src/events/bump_transaction.rs | 4 ++++ lightning/src/ln/features.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/lightning/src/events/bump_transaction.rs b/lightning/src/events/bump_transaction.rs index 9c24e00f13e..b34189c58c1 100644 --- a/lightning/src/events/bump_transaction.rs +++ b/lightning/src/events/bump_transaction.rs @@ -274,6 +274,8 @@ impl Utxo { } /// Returns a `Utxo` with the `satisfaction_weight` estimate for a P2WPKH nested in P2SH output. + /// + /// This is not exported to bindings users as WPubkeyHash is not yet exported pub fn new_nested_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self { let script_sig_size = 1 /* script_sig length */ + 1 /* OP_0 */ + @@ -290,6 +292,8 @@ impl Utxo { } /// Returns a `Utxo` with the `satisfaction_weight` estimate for a SegWit v0 P2WPKH output. + /// + /// This is not exported to bindings users as WPubkeyHash is not yet exported pub fn new_v0_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self { Self { outpoint, diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index ff91654a3f7..a860d1ac530 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -454,6 +454,7 @@ pub struct Features { mark: PhantomData, } +/// This is not exported to bindings users but probably should be. impl> core::ops::BitOrAssign for Features { fn bitor_assign(&mut self, rhs: Rhs) { let total_feature_len = cmp::max(self.flags.len(), rhs.borrow().flags.len()); @@ -464,6 +465,7 @@ impl> core::ops::BitOrAssign for Feat } } +/// This is not exported to bindings users but probably should be. impl core::ops::BitOr for Features { type Output = Self; From 7721b8d4db5351629fb17509a1a71a1772f605e4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 28 Sep 2023 03:03:38 +0000 Subject: [PATCH 20/27] `crate`-only several BOLT12 methods that require unbounded generics These are not expressible in C/most languages, and thus must be hidden. --- lightning/src/offers/invoice.rs | 4 +++- lightning/src/offers/invoice_request.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 2c0d3420474..94c0439faa5 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -561,7 +561,9 @@ macro_rules! unsigned_invoice_sign_method { ($self: ident, $self_type: ty $(, $s /// Signs the [`TaggedHash`] of the invoice using the given function. /// /// Note: The hash computation may have included unknown, odd TLV records. - pub fn sign( + /// + /// This is not exported to bindings users as functions aren't currently mapped. + pub(crate) fn sign( $($self_mut)* $self: $self_type, sign: F ) -> Result { let pubkey = $self.contents.fields().signing_pubkey; diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 9041fa8a9bf..14c1786614b 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -547,7 +547,9 @@ macro_rules! unsigned_invoice_request_sign_method { ( /// Signs the [`TaggedHash`] of the invoice request using the given function. /// /// Note: The hash computation may have included unknown, odd TLV records. - pub fn sign( + /// + /// This is not exported to bindings users as functions are not yet mapped. + pub(crate) fn sign( $($self_mut)* $self: $self_type, sign: F ) -> Result { let pubkey = $self.contents.payer_id; From 7ba202b1aeadbde7733e4c44ee4864d8fab2763f Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 31 Jan 2021 20:12:50 -0500 Subject: [PATCH 21/27] Make ChannelMonitor always clonable Rather than `ChannelMonitor` only being clonable when the signer is clonable, we require all signers to be clonable and then make all `ChannelMonitor`s clonable. --- lightning/src/chain/channelmonitor.rs | 2 +- lightning/src/sign/ecdsa.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index f3e2653844d..d84d673cf01 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -781,7 +781,7 @@ pub struct ChannelMonitor { pub(super) inner: Mutex>, } -impl Clone for ChannelMonitor where Signer: Clone { +impl Clone for ChannelMonitor { fn clone(&self) -> Self { let inner = self.inner.lock().unwrap().clone(); ChannelMonitor::from_impl(inner) diff --git a/lightning/src/sign/ecdsa.rs b/lightning/src/sign/ecdsa.rs index a0409e54505..0ca322263bd 100644 --- a/lightning/src/sign/ecdsa.rs +++ b/lightning/src/sign/ecdsa.rs @@ -219,4 +219,4 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor -pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable {} +pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable + Clone {} From 8ba5202797d1765d08a6cc41c078c4436433f868 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 24 Sep 2021 18:44:32 +0000 Subject: [PATCH 22/27] Make the custom message traits cloneable as they're deep in nested structs --- lightning/src/ln/wire.rs | 14 +++++++------- lightning/src/onion_message/functional_tests.rs | 2 +- lightning/src/onion_message/messenger.rs | 4 ++-- lightning/src/onion_message/packet.rs | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lightning/src/ln/wire.rs b/lightning/src/ln/wire.rs index 55e31399ae1..8f76c8720d0 100644 --- a/lightning/src/ln/wire.rs +++ b/lightning/src/ln/wire.rs @@ -45,9 +45,9 @@ impl TestEq for T {} /// A Lightning message returned by [`read`] when decoding bytes received over the wire. Each /// variant contains a message from [`msgs`] or otherwise the message type if unknown. #[allow(missing_docs)] -#[derive(Debug)] +#[derive(Clone, Debug)] #[cfg_attr(test, derive(PartialEq))] -pub(crate) enum Message where T: core::fmt::Debug + Type + TestEq { +pub(crate) enum Message where T: Clone + core::fmt::Debug + Type + TestEq { Init(msgs::Init), Error(msgs::ErrorMessage), Warning(msgs::WarningMessage), @@ -419,13 +419,13 @@ pub(crate) use self::encode::Encode; /// Defines a type identifier for sending messages over the wire. /// /// Messages implementing this trait specify a type and must be [`Writeable`]. -pub trait Type: core::fmt::Debug + Writeable { +pub trait Type: core::fmt::Debug + Writeable + Clone { /// Returns the type identifying the message payload. fn type_id(&self) -> u16; } #[cfg(test)] -pub trait Type: core::fmt::Debug + Writeable + PartialEq { +pub trait Type: core::fmt::Debug + Writeable + Clone + PartialEq { fn type_id(&self) -> u16; } @@ -435,12 +435,12 @@ impl Type for () { } #[cfg(test)] -impl Type for T where T: Encode { +impl Type for T where T: Encode { fn type_id(&self) -> u16 { T::TYPE } } #[cfg(not(test))] -impl Type for T where T: Encode { +impl Type for T where T: Encode { fn type_id(&self) -> u16 { T::TYPE } } @@ -786,7 +786,7 @@ mod tests { } } - #[derive(Eq, PartialEq, Debug)] + #[derive(Clone, Eq, PartialEq, Debug)] struct TestCustomMessage {} const CUSTOM_MESSAGE_TYPE : u16 = 9000; diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index acf34a3a8c8..c9798f1209c 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -415,7 +415,7 @@ fn reply_path() { fn invalid_custom_message_type() { let nodes = create_nodes(2); - #[derive(Debug)] + #[derive(Debug, Clone)] struct InvalidCustomMessage{} impl OnionMessageContents for InvalidCustomMessage { fn tlv_type(&self) -> u64 { diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 57e76d1cf8a..ade64295700 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -121,8 +121,8 @@ pub(super) const MAX_TIMER_TICKS: usize = 2; /// &keys_manager, &keys_manager, logger, &node_id_lookup, message_router, /// &offers_message_handler, &custom_message_handler /// ); - -/// # #[derive(Debug)] +/// +/// # #[derive(Debug, Clone)] /// # struct YourCustomMessage {} /// impl Writeable for YourCustomMessage { /// fn write(&self, w: &mut W) -> Result<(), io::Error> { diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs index deda1acb7e9..8924865e3c9 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -147,7 +147,7 @@ impl Writeable for ParsedOnionMessageContents { } /// The contents of an onion message. -pub trait OnionMessageContents: Writeable + core::fmt::Debug { +pub trait OnionMessageContents: Writeable + core::fmt::Debug + Clone { /// Returns the TLV type identifying the message contents. MUST be >= 64. fn tlv_type(&self) -> u64; } From 0897e7fbb42596c9a890d5366b4b0b7df126b760 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 17 Dec 2023 19:43:28 +0000 Subject: [PATCH 23/27] Replace `EventsProvider` on `OnionMessageHandler` with a single fn `OnionMessageHandler`s are expected to regularly release a set of nodes which we need to directly connect to to deliver onion messages. In order to do so, they currently extend `EventsProvider`, returning that set as `Event::ConnectionNeeded`s. While this works fine in Rust, the `EventsProvider` interface doesn't map well in bindings due to it taking a flexible trait impl as a method argument. Instead, here, we convert `OnionMessageHandler` to include a single function which returns nodes in the form of a `node_id` and `Vec`. This is a bit simpler, if less flexible, API, and while largely equivalent, is easier to map in bindings. --- lightning-background-processor/src/lib.rs | 31 +++++++++-------------- lightning/src/ln/msgs.rs | 11 +++++++- lightning/src/ln/peer_handler.rs | 1 + lightning/src/onion_message/messenger.rs | 20 ++++----------- 4 files changed, 28 insertions(+), 35 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 601ed296b37..79493a697ff 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -704,7 +704,10 @@ where persister, chain_monitor, chain_monitor.process_pending_events_async(async_event_handler).await, channel_manager, channel_manager.get_cm().process_pending_events_async(async_event_handler).await, - peer_manager, process_onion_message_handler_events_async(&peer_manager, async_event_handler).await, + peer_manager, + for event in onion_message_handler_events(peer_manager) { + handler(event).await + }, gossip_sync, logger, scorer, should_break, { let fut = Selector { a: channel_manager.get_cm().get_event_or_persistence_needed_future(), @@ -729,23 +732,11 @@ where ) } -#[cfg(feature = "futures")] -async fn process_onion_message_handler_events_async< - EventHandlerFuture: core::future::Future, - EventHandler: Fn(Event) -> EventHandlerFuture, - PM: 'static + Deref + Send + Sync, ->( - peer_manager: &PM, handler: EventHandler -) -where - PM::Target: APeerManager + Send + Sync, -{ - let events = core::cell::RefCell::new(Vec::new()); - peer_manager.onion_message_handler().process_pending_events(&|e| events.borrow_mut().push(e)); - - for event in events.into_inner() { - handler(event).await - } +fn onion_message_handler_events( + peer_manager: &PM +) -> impl Iterator where PM::Target: APeerManager + Send + Sync { + peer_manager.onion_message_handler().get_and_clear_connections_needed() + .into_iter().map(|(node_id, addresses)| Event::ConnectionNeeded { node_id, addresses }) } #[cfg(feature = "std")] @@ -852,7 +843,9 @@ impl BackgroundProcessor { persister, chain_monitor, chain_monitor.process_pending_events(&event_handler), channel_manager, channel_manager.get_cm().process_pending_events(&event_handler), peer_manager, - peer_manager.onion_message_handler().process_pending_events(&event_handler), + for event in onion_message_handler_events(&peer_manager) { + event_handler.handle_event(event); + }, gossip_sync, logger, scorer, stop_thread.load(Ordering::Acquire), { Sleeper::from_two_futures( &channel_manager.get_cm().get_event_or_persistence_needed_future(), diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 2de0397eb2f..7e42799bf75 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -1624,7 +1624,16 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider { } /// A handler for received [`OnionMessage`]s and for providing generated ones to send. -pub trait OnionMessageHandler: EventsProvider { +pub trait OnionMessageHandler { + /// Because much of the lightning network does not yet support forwarding onion messages, we + /// may need to directly connect to a node which will forward a message for us. In such a case, + /// this method will return the set of nodes which need connection by node_id and the + /// corresponding socket addresses where they may accept incoming connections. + /// + /// Thus, this method should be polled regularly to detect messages await such a direct + /// connection. + fn get_and_clear_connections_needed(&self) -> Vec<(PublicKey, Vec)>; + /// Handle an incoming `onion_message` message from the given peer. fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage); diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 3f20a07b394..e5b583a9c15 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -124,6 +124,7 @@ impl RoutingMessageHandler for IgnoringMessageHandler { fn processing_queue_high(&self) -> bool { false } } impl OnionMessageHandler for IgnoringMessageHandler { + fn get_and_clear_connections_needed(&self) -> Vec<(PublicKey, Vec)> { Vec::new() } fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {} fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option { None } fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) } diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index ade64295700..6ddb5ddea8b 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -1006,7 +1006,7 @@ fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap EventsProvider +impl OnionMessageHandler for OnionMessenger where ES::Target: EntropySource, @@ -1017,28 +1017,18 @@ where OMH::Target: OffersMessageHandler, CMH::Target: CustomOnionMessageHandler, { - fn process_pending_events(&self, handler: H) where H::Target: EventHandler { + fn get_and_clear_connections_needed(&self) -> Vec<(PublicKey, Vec)> { + let mut res = Vec::new(); for (node_id, recipient) in self.message_recipients.lock().unwrap().iter_mut() { if let OnionMessageRecipient::PendingConnection(_, addresses, _) = recipient { if let Some(addresses) = addresses.take() { - handler.handle_event(Event::ConnectionNeeded { node_id: *node_id, addresses }); + res.push((*node_id, addresses)); } } } + res } -} -impl OnionMessageHandler -for OnionMessenger -where - ES::Target: EntropySource, - NS::Target: NodeSigner, - L::Target: Logger, - NL::Target: NodeIdLookUp, - MR::Target: MessageRouter, - OMH::Target: OffersMessageHandler, - CMH::Target: CustomOnionMessageHandler, -{ fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) { let logger = WithContext::from(&self.logger, Some(*peer_node_id), None); match self.peel_onion_message(msg) { From 174fb7a440e6df36639e637311793e2373507e01 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 28 Sep 2023 03:05:09 +0000 Subject: [PATCH 24/27] Avoid slices without inner references As we cannot express slices without inner references in bindings wrappers. --- lightning/src/blinded_path/mod.rs | 8 ++++---- lightning/src/ln/channelmanager.rs | 8 ++++---- lightning/src/routing/gossip.rs | 2 +- lightning/src/routing/router.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lightning/src/blinded_path/mod.rs b/lightning/src/blinded_path/mod.rs index a61eb12b9ae..672a0273793 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -152,7 +152,7 @@ impl BlindedPath { // be in relation to a specific channel. let htlc_maximum_msat = u64::max_value(); Self::new_for_payment( - &[], payee_node_id, payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta, + Vec::new(), payee_node_id, payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta, entropy_source, secp_ctx ) } @@ -167,7 +167,7 @@ impl BlindedPath { /// [`ForwardTlvs`]: crate::blinded_path::payment::ForwardTlvs // TODO: make all payloads the same size with padding + add dummy hops pub fn new_for_payment( - intermediate_nodes: &[payment::ForwardNode], payee_node_id: PublicKey, + intermediate_nodes: Vec, payee_node_id: PublicKey, payee_tlvs: payment::ReceiveTlvs, htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16, entropy_source: ES, secp_ctx: &Secp256k1 ) -> Result<(BlindedPayInfo, Self), ()> where ES::Target: EntropySource { @@ -178,13 +178,13 @@ impl BlindedPath { let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); let blinded_payinfo = payment::compute_payinfo( - intermediate_nodes, &payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta + &intermediate_nodes, &payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta )?; Ok((blinded_payinfo, BlindedPath { introduction_node, blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), blinded_hops: payment::blinded_hops( - secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret + secp_ctx, &intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret ).map_err(|_| ())?, })) } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5bca7b4e066..cc69a3e3158 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -4772,7 +4772,7 @@ where /// [`ChannelUnavailable`]: APIError::ChannelUnavailable /// [`APIMisuseError`]: APIError::APIMisuseError pub fn update_partial_channel_config( - &self, counterparty_node_id: &PublicKey, channel_ids: &[ChannelId], config_update: &ChannelConfigUpdate, + &self, counterparty_node_id: &PublicKey, channel_ids: Vec, config_update: &ChannelConfigUpdate, ) -> Result<(), APIError> { if config_update.cltv_expiry_delta.map(|delta| delta < MIN_CLTV_EXPIRY_DELTA).unwrap_or(false) { return Err(APIError::APIMisuseError { @@ -4787,14 +4787,14 @@ where let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - for channel_id in channel_ids { + for channel_id in channel_ids.iter() { if !peer_state.has_channel(channel_id) { return Err(APIError::ChannelUnavailable { err: format!("Channel with id {} not found for the passed counterparty node_id {}", channel_id, counterparty_node_id), }); }; } - for channel_id in channel_ids { + for channel_id in channel_ids.iter() { if let Some(channel_phase) = peer_state.channel_by_id.get_mut(channel_id) { let mut config = channel_phase.context().config(); config.apply(config_update); @@ -4849,7 +4849,7 @@ where /// [`ChannelUnavailable`]: APIError::ChannelUnavailable /// [`APIMisuseError`]: APIError::APIMisuseError pub fn update_channel_config( - &self, counterparty_node_id: &PublicKey, channel_ids: &[ChannelId], config: &ChannelConfig, + &self, counterparty_node_id: &PublicKey, channel_ids: Vec, config: &ChannelConfig, ) -> Result<(), APIError> { return self.update_partial_channel_config(counterparty_node_id, channel_ids, &(*config).into()); } diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index 7831e20fa03..39a7a2185af 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -89,7 +89,7 @@ impl NodeId { } /// Get the public key as an array from this NodeId - pub fn as_array(&self) -> &[u8; PUBLIC_KEY_SIZE] { + pub fn as_array(&self) -> &[u8; 33] { &self.0 } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 53a12ed914f..e8fb7d404e6 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -132,7 +132,7 @@ impl>, L: Deref, ES: Deref, S: Deref> Router f }) .map(|forward_node| { BlindedPath::new_for_payment( - &[forward_node], recipient, tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, + vec![forward_node], recipient, tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source, secp_ctx ) }) From 82e8d3bda504f09e3a8069dc07a7df9dad47dd98 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:12:39 +0000 Subject: [PATCH 25/27] Hide `Direction::select_node_id` due to lifetimes --- lightning/src/blinded_path/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning/src/blinded_path/mod.rs b/lightning/src/blinded_path/mod.rs index 672a0273793..42a9f71652b 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -268,7 +268,7 @@ impl_writeable!(BlindedHop, { impl Direction { /// Returns the [`NodeId`] from the inputs corresponding to the direction. - pub fn select_node_id<'a>(&self, node_a: &'a NodeId, node_b: &'a NodeId) -> &'a NodeId { + pub(crate) fn select_node_id<'a>(&self, node_a: &'a NodeId, node_b: &'a NodeId) -> &'a NodeId { match self { Direction::NodeOne => core::cmp::min(node_a, node_b), Direction::NodeTwo => core::cmp::max(node_a, node_b), @@ -276,7 +276,7 @@ impl Direction { } /// Returns the [`PublicKey`] from the inputs corresponding to the direction. - pub fn select_pubkey<'a>(&self, node_a: &'a PublicKey, node_b: &'a PublicKey) -> &'a PublicKey { + pub(crate) fn select_pubkey<'a>(&self, node_a: &'a PublicKey, node_b: &'a PublicKey) -> &'a PublicKey { let (node_one, node_two) = if NodeId::from_pubkey(node_a) < NodeId::from_pubkey(node_b) { (node_a, node_b) } else { From 25f2633597d36a6873d22db6d95270e12c0446b3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:13:02 +0000 Subject: [PATCH 26/27] Drop `SerialId` type as bindings don't support primitive aliasing --- lightning/src/ln/interactivetxs.rs | 2 +- lightning/src/ln/msgs.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/lightning/src/ln/interactivetxs.rs b/lightning/src/ln/interactivetxs.rs index 60341620887..20e89cd0020 100644 --- a/lightning/src/ln/interactivetxs.rs +++ b/lightning/src/ln/interactivetxs.rs @@ -23,8 +23,8 @@ use crate::chain::chaininterface::fee_for_weight; use crate::events::bump_transaction::{BASE_INPUT_WEIGHT, EMPTY_SCRIPT_SIG_WEIGHT}; use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS; use crate::ln::msgs; -use crate::ln::msgs::SerialId; use crate::ln::types::ChannelId; +type SerialId = u64; use crate::sign::{EntropySource, P2TR_KEY_PATH_WITNESS_WEIGHT, P2WPKH_WITNESS_WEIGHT}; use crate::util::ser::TransactionU16LenLimited; diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 7e42799bf75..3c1c8f4b8bf 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -406,10 +406,6 @@ pub struct ChannelReady { pub short_channel_id_alias: Option, } -/// A randomly chosen number that is used to identify inputs within an interactive transaction -/// construction. -pub type SerialId = u64; - /// An stfu (quiescence) message to be sent by or received from the stfu initiator. // TODO(splicing): Add spec link for `stfu`; still in draft, using from https://github.com/lightning/bolts/pull/863 #[derive(Clone, Debug, PartialEq, Eq)] @@ -473,7 +469,7 @@ pub struct TxAddInput { pub channel_id: ChannelId, /// A randomly chosen unique identifier for this input, which is even for initiators and odd for /// non-initiators. - pub serial_id: SerialId, + pub serial_id: u64, /// Serialized transaction that contains the output this input spends to verify that it is non /// malleable. pub prevtx: TransactionU16LenLimited, @@ -492,7 +488,7 @@ pub struct TxAddOutput { pub channel_id: ChannelId, /// A randomly chosen unique identifier for this output, which is even for initiators and odd for /// non-initiators. - pub serial_id: SerialId, + pub serial_id: u64, /// The satoshi value of the output pub sats: u64, /// The scriptPubKey for the output @@ -507,7 +503,7 @@ pub struct TxRemoveInput { /// The channel ID pub channel_id: ChannelId, /// The serial ID of the input to be removed - pub serial_id: SerialId, + pub serial_id: u64, } /// A tx_remove_output message for removing an output during interactive transaction construction. @@ -518,7 +514,7 @@ pub struct TxRemoveOutput { /// The channel ID pub channel_id: ChannelId, /// The serial ID of the output to be removed - pub serial_id: SerialId, + pub serial_id: u64, } /// A tx_complete message signalling the conclusion of a peer's transaction contributions during From 4f8f9b4d9e7dbfbb014c6f7d06d4d31a2f89914c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:01:32 +0000 Subject: [PATCH 27/27] Move `Persister` back to lots of generic bounds ...as we currently struggle with `AChannelManager` on it --- lightning-background-processor/src/lib.rs | 8 +++--- lightning/src/util/persist.rs | 32 +++++++++++++++-------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 79493a697ff..5a8bf4c2e16 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -338,7 +338,7 @@ macro_rules! define_run_body { if $channel_manager.get_cm().get_and_clear_needs_persistence() { log_trace!($logger, "Persisting ChannelManager..."); - $persister.persist_manager(&$channel_manager)?; + $persister.persist_manager($channel_manager.get_cm())?; log_trace!($logger, "Done persisting ChannelManager."); } if $timer_elapsed(&mut last_freshness_call, FRESHNESS_TIMER) { @@ -440,7 +440,7 @@ macro_rules! define_run_body { // After we exit, ensure we persist the ChannelManager one final time - this avoids // some races where users quit while channel updates were in-flight, with // ChannelMonitor update(s) persisted without a corresponding ChannelManager update. - $persister.persist_manager(&$channel_manager)?; + $persister.persist_manager($channel_manager.get_cm())?; // Persist Scorer on exit if let Some(ref scorer) = $scorer { @@ -814,8 +814,8 @@ impl BackgroundProcessor { F::Target: 'static + FeeEstimator, L::Target: 'static + Logger, P::Target: 'static + Persist<::Signer>, - PS::Target: 'static + Persister<'a, CM, L, SC>, - CM::Target: AChannelManager + Send + Sync, + PS::Target: 'static + Persister<'a, <::Target as AChannelManager>::M, <::Target as AChannelManager>::T, <::Target as AChannelManager>::ES, <::Target as AChannelManager>::NS, <::Target as AChannelManager>::SP, <::Target as AChannelManager>::F, <::Target as AChannelManager>::R, L, SC>, + CM::Target: AChannelManager + Send + Sync, PM::Target: APeerManager + Send + Sync, { let stop_thread = Arc::new(AtomicBool::new(false)); diff --git a/lightning/src/util/persist.rs b/lightning/src/util/persist.rs index 249a089cd48..febe8c35903 100644 --- a/lightning/src/util/persist.rs +++ b/lightning/src/util/persist.rs @@ -154,18 +154,24 @@ pub trait KVStore { fn list(&self, primary_namespace: &str, secondary_namespace: &str) -> Result, io::Error>; } + /// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk. /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager -pub trait Persister<'a, CM: Deref, L: Deref, S: WriteableScore<'a>> -where - CM::Target: 'static + AChannelManager, - L::Target: 'static + Logger, +pub trait Persister<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref, S: WriteableScore<'a>> + where M::Target: 'static + chain::Watch<::EcdsaSigner>, + T::Target: 'static + BroadcasterInterface, + ES::Target: 'static + EntropySource, + NS::Target: 'static + crate::sign::NodeSigner, + SP::Target: 'static + SignerProvider, + F::Target: 'static + FeeEstimator, + R::Target: 'static + crate::routing::router::Router, + L::Target: 'static + Logger, { /// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed. /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager - fn persist_manager(&self, channel_manager: &CM) -> Result<(), io::Error>; + fn persist_manager(&self, channel_manager: &crate::ln::channelmanager::ChannelManager) -> Result<(), io::Error>; /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed. fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), io::Error>; @@ -174,13 +180,17 @@ where fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error>; } - -impl<'a, A: KVStore + ?Sized, CM: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, CM, L, S> for A -where - CM::Target: 'static + AChannelManager, - L::Target: 'static + Logger, +impl<'a, A: KVStore + ?Sized, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, M, T, ES, NS, SP, F, R, L, S> for A + where M::Target: 'static + chain::Watch<::EcdsaSigner>, + T::Target: 'static + BroadcasterInterface, + ES::Target: 'static + EntropySource, + NS::Target: 'static + crate::sign::NodeSigner, + SP::Target: 'static + SignerProvider, + F::Target: 'static + FeeEstimator, + R::Target: 'static + crate::routing::router::Router, + L::Target: 'static + Logger, { - fn persist_manager(&self, channel_manager: &CM) -> Result<(), io::Error> { + fn persist_manager(&self, channel_manager: &crate::ln::channelmanager::ChannelManager) -> Result<(), io::Error> { self.write(CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_KEY,