From f239e2f116ff1572048142e61c3ca428da3db434 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 5 Dec 2025 20:18:48 +0000 Subject: [PATCH 01/28] Add missing `Clone` (and `Copy`) derives to config structs Various new structs in 0.2 were missing `Clone` and `Copy` derives, which we add here. --- lightning/src/util/config.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index 0856dc96394..0ad290c59ce 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -726,7 +726,7 @@ impl crate::util::ser::Readable for ChannelConfig { } /// A parallel struct to [`ChannelConfig`] to define partial updates. -#[derive(Default)] +#[derive(Copy, Clone, Default)] pub struct ChannelConfigUpdate { /// Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound over the channel. See /// [`ChannelConfig::forwarding_fee_proportional_millionths`]. @@ -859,7 +859,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig { /// /// `Default::default()` provides sane defaults for most configurations /// (but currently with zero relay fees!) -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub struct UserConfig { /// Channel handshake config that we propose to our counterparty. pub channel_handshake_config: ChannelHandshakeConfig, @@ -1033,7 +1033,7 @@ impl Readable for UserConfig { } /// Config structure for overriding channel parameters. -#[derive(Default)] +#[derive(Copy, Clone, Default)] pub struct ChannelConfigOverrides { /// Overrides for channel handshake parameters. pub handshake_overrides: Option, @@ -1056,7 +1056,7 @@ impl UserConfig { } /// Config structure for overriding channel handshake parameters. -#[derive(Default)] +#[derive(Copy, Clone, Default)] pub struct ChannelHandshakeConfigUpdate { /// Overrides the percentage of the channel value we will cap the total value of outstanding inbound HTLCs to. See /// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`]. From 2b2f4c3e4b273c80ccfb381588e9e6d0744f9301 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 3 Nov 2025 00:14:53 +0000 Subject: [PATCH 02/28] Don't bother `clone`'ing a `Secp256k1` context into the offers flow The new `OffersMessageFlow` stores yet another `Secp256k1` context internally, but to initialize requires passing one in explicitly. We call this in `ChannelManager` by `clone`ing the context we have before passing it in, allowing us to keep the randomization we do in `ChannelManager::new`. This isn't really worth the API annoyance of passing in a `Secp256k1` context, though, and luckily the contexts are eventually going to go away upstream eventually, so we just drop the argument from `OffersMessageFlow::new`, building an unrandomized `Secp256k1` context internally instead. --- lightning/src/ln/channelmanager.rs | 3 +-- lightning/src/offers/flow.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 82a45dcb1a6..305b8c39331 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -3962,7 +3962,7 @@ where let flow = OffersMessageFlow::new( ChainHash::using_genesis_block(params.network), params.best_block, our_network_pubkey, current_timestamp, expanded_inbound_key, - node_signer.get_receive_auth_key(), secp_ctx.clone(), message_router, logger.clone(), + node_signer.get_receive_auth_key(), message_router, logger.clone(), ); ChannelManager { @@ -17997,7 +17997,6 @@ where highest_seen_timestamp, expanded_inbound_key, args.node_signer.get_receive_auth_key(), - secp_ctx.clone(), args.message_router, args.logger.clone(), ) diff --git a/lightning/src/offers/flow.rs b/lightning/src/offers/flow.rs index 15e744e1a7a..863bbfa5d5c 100644 --- a/lightning/src/offers/flow.rs +++ b/lightning/src/offers/flow.rs @@ -118,7 +118,7 @@ where pub fn new( chain_hash: ChainHash, best_block: BestBlock, our_network_pubkey: PublicKey, current_timestamp: u32, inbound_payment_key: inbound_payment::ExpandedKey, - receive_auth_key: ReceiveAuthKey, secp_ctx: Secp256k1, message_router: MR, + receive_auth_key: ReceiveAuthKey, message_router: MR, logger: L, ) -> Self { Self { @@ -131,7 +131,7 @@ where receive_auth_key, - secp_ctx, + secp_ctx: Secp256k1::new(), message_router, pending_offers_messages: Mutex::new(Vec::new()), From 78f4152efe00150739775e22292268dfa476a9bb Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 1 Mar 2022 03:46:52 +0000 Subject: [PATCH 03/28] 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 80ffbf9fb6c..9f0f7ab96cc 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -1056,7 +1056,7 @@ impl PartialEq for 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)> { if self.one_to_two.is_none() || self.two_to_one.is_none() { return None; } From 28ed4a56fa4cc4ef43a20a459820bfc2f4ea218e Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Tue, 29 Mar 2022 10:20:39 -0500 Subject: [PATCH 04/28] 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 9f0f7ab96cc..f3f81f812a0 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -1075,7 +1075,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)> { if self.one_to_two.is_none() || self.two_to_one.is_none() { return None; } From 577dcfbd13277946b2feed51b0b7e6aaeeeb2066 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 24 Dec 2022 04:16:48 +0000 Subject: [PATCH 05/28] 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 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index ab695ee3530..72bfde9e629 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -6434,8 +6434,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: EcdsaChannelSigner, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)> + for (BlockHash, ChannelMonitor) { fn read(reader: &mut R, args: (&'a ES, &'b SP)) -> Result { match >::read(reader, args) { @@ -6446,8 +6446,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } } -impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)> - for Option<(BlockHash, ChannelMonitor)> +impl<'a, 'b, ES: EntropySource, Signer: EcdsaChannelSigner, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)> + for Option<(BlockHash, ChannelMonitor)> { #[rustfmt::skip] fn read(reader: &mut R, args: (&'a ES, &'b SP)) -> Result { From e14e58d821e8981b44cd779568c12024615d6008 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 23 Dec 2024 22:08:16 +0000 Subject: [PATCH 06/28] 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 | 1 + fuzz/src/full_stack.rs | 5 ++--- lightning-liquidity/tests/lsps2_integration_tests.rs | 2 +- lightning/src/ln/channelmanager.rs | 8 +++++--- lightning/src/ln/invoice_utils.rs | 3 ++- lightning/src/ln/mod.rs | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 943e1f2d63a..649132c879e 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -58,6 +58,7 @@ use lightning::ln::msgs::{ BaseMessageHandler, ChannelMessageHandler, CommitmentUpdate, Init, MessageSendEvent, UpdateAddHTLC, }; +use lightning::ln::outbound_payment::{RecipientOnionFields, Retry}; use lightning::ln::script::ShutdownScript; use lightning::ln::types::ChannelId; use lightning::offers::invoice::UnsignedBolt12Invoice; diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 97a74871ea4..9306760fea2 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -39,11 +39,10 @@ use lightning::chain::transaction::OutPoint; use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen}; use lightning::events::Event; use lightning::ln::channel_state::ChannelDetails; -use lightning::ln::channelmanager::{ - ChainParameters, ChannelManager, InterceptId, PaymentId, RecipientOnionFields, Retry, -}; +use lightning::ln::channelmanager::{ChainParameters, ChannelManager, InterceptId, PaymentId}; use lightning::ln::functional_test_utils::*; use lightning::ln::inbound_payment::ExpandedKey; +use lightning::ln::outbound_payment::{RecipientOnionFields, Retry}; use lightning::ln::peer_handler::{ IgnoringMessageHandler, MessageHandler, PeerManager, SocketDescriptor, }; diff --git a/lightning-liquidity/tests/lsps2_integration_tests.rs b/lightning-liquidity/tests/lsps2_integration_tests.rs index 82f93b5990c..5391c0e0870 100644 --- a/lightning-liquidity/tests/lsps2_integration_tests.rs +++ b/lightning-liquidity/tests/lsps2_integration_tests.rs @@ -11,7 +11,7 @@ use lightning::check_added_monitors; use lightning::events::{ClosureReason, Event}; use lightning::get_event_msg; use lightning::ln::channelmanager::PaymentId; -use lightning::ln::channelmanager::Retry; +use lightning::ln::outbound_payment::Retry; use lightning::ln::functional_test_utils::create_funding_transaction; use lightning::ln::functional_test_utils::do_commitment_signed_dance; use lightning::ln::functional_test_utils::expect_channel_pending_event; diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 305b8c39331..ef23d1f8448 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -187,7 +187,7 @@ use core::{cmp, mem}; // Re-export this for use in the public API. #[cfg(any(test, feature = "_externalize_tests"))] pub(crate) use crate::ln::outbound_payment::PaymentSendFailure; -pub use crate::ln::outbound_payment::{ +pub(crate) use crate::ln::outbound_payment::{ Bolt11PaymentError, Bolt12PaymentError, ProbeSendFailure, RecipientOnionFields, Retry, RetryableSendFailure, }; @@ -2280,7 +2280,8 @@ where /// # use bitcoin::hashes::Hash; /// # use lightning::events::{Event, EventsProvider}; /// # use lightning::types::payment::PaymentHash; -/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry}; +/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails}; +/// # use lightning::ln::outbound_payment::Retry; /// # use lightning::routing::router::RouteParametersConfig; /// # use lightning_invoice::Bolt11Invoice; /// # @@ -2438,7 +2439,8 @@ where /// ``` /// # use core::time::Duration; /// # use lightning::events::{Event, EventsProvider}; -/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry}; +/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails}; +/// # use lightning::ln::outbound_payment::Retry; /// # use lightning::offers::parse::Bolt12SemanticError; /// # use lightning::routing::router::RouteParametersConfig; /// # diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index 7c0190a23a9..cfa05f56482 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -625,9 +625,10 @@ mod test { use super::*; use crate::chain::channelmonitor::HTLC_FAIL_BACK_BUFFER; use crate::ln::channelmanager::{ - Bolt11InvoiceParameters, PaymentId, PhantomRouteHints, RecipientOnionFields, Retry, + Bolt11InvoiceParameters, PaymentId, PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, }; + use crate::ln::outbound_payment::{RecipientOnionFields, Retry}; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent}; use crate::routing::router::{PaymentParameters, RouteParameters}; diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index 9473142cfed..333ae451aca 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -42,7 +42,7 @@ pub mod channel; pub(crate) mod channel; pub(crate) mod onion_utils; -mod outbound_payment; +pub mod outbound_payment; pub mod wire; #[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled. From f9592547af4c33c929b336f772f2a3d6c231c89d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 13 Dec 2024 21:20:17 +0000 Subject: [PATCH 07/28] 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/offers_tests.rs | 2 +- lightning/src/ln/peer_handler.rs | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index e47b5492efd..b18a4a59062 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -11633,7 +11633,7 @@ 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; @@ -11682,7 +11682,7 @@ 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 ef23d1f8448..75b2c2a8e93 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -5182,7 +5182,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 354273f7170..75577ae0e32 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -1357,16 +1357,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/offers_tests.rs b/lightning/src/ln/offers_tests.rs index b7d64df4063..8735c628630 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -132,7 +132,7 @@ fn announce_node_address<'a, 'b, 'c>( excess_data: Vec::new(), }; let signature = node.keys_manager.sign_gossip_message( - UnsignedGossipMessage::NodeAnnouncement(&announcement) + UnsignedGossipMessage::NodeAnnouncement(announcement.clone()) ).unwrap(); let msg = NodeAnnouncement { diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 74f081b03ae..6ef7191e603 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -3650,7 +3650,7 @@ where }; let node_announce_sig = match self .node_signer - .sign_gossip_message(msgs::UnsignedGossipMessage::NodeAnnouncement(&announcement)) + .sign_gossip_message(msgs::UnsignedGossipMessage::NodeAnnouncement(announcement.clone())) { Ok(sig) => sig, Err(_) => { From 2a77d9ad111b096d1147e02d1929ebe05446558d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 16 Oct 2025 18:58:35 +0000 Subject: [PATCH 08/28] 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 | 10 ++---- lightning/src/ln/channelmanager.rs | 6 +--- lightning/src/routing/router.rs | 40 +++++++++++------------ lightning/src/routing/scoring.rs | 17 +++++++--- lightning/src/util/test_utils.rs | 5 ++- 5 files changed, 37 insertions(+), 41 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 19333c5823a..6ec3bf5c046 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -348,11 +348,6 @@ type DynRouter = lightning::routing::router::DefaultRouter< &'static (dyn Logger + Send + Sync), >, >, - lightning::routing::scoring::ProbabilisticScoringFeeParameters, - lightning::routing::scoring::ProbabilisticScorer< - &'static NetworkGraph<&'static (dyn Logger + Send + Sync)>, - &'static (dyn Logger + Send + Sync), - >, >; #[cfg(not(c_bindings))] @@ -1899,8 +1894,6 @@ mod tests { Arc, Arc, Arc>, - (), - TestScorer, >, >, Arc< @@ -2187,10 +2180,11 @@ 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, + _score_params: &lightning::routing::scoring::ProbabilisticScoringFeeParameters, ) -> u64 { unimplemented!(); } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 75b2c2a8e93..5e8ce8def05 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -1743,8 +1743,6 @@ pub type SimpleArcChannelManager = ChannelManager< Arc, Arc, Arc>>, Arc>>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer>>, Arc>, >, >, Arc>>, Arc, Arc>>, @@ -1775,8 +1773,6 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, M, T, F, L> &'g L, &'c KeysManager, &'h RwLock, &'g L>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>, >, &'i DefaultMessageRouter<&'f NetworkGraph<&'g L>, &'g L, &'c KeysManager>, &'g L, @@ -1961,7 +1957,7 @@ where /// # fee_estimator: &dyn lightning::chain::chaininterface::FeeEstimator, /// # chain_monitor: &dyn lightning::chain::Watch, /// # tx_broadcaster: &dyn lightning::chain::chaininterface::BroadcasterInterface, -/// # router: &lightning::routing::router::DefaultRouter<&NetworkGraph<&'a L>, &'a L, &ES, &S, SP, SL>, +/// # router: &lightning::routing::router::DefaultRouter<&NetworkGraph<&'a L>, &'a L, &ES, &S>, /// # message_router: &lightning::onion_message::messenger::DefaultMessageRouter<&NetworkGraph<&'a L>, &'a L, &ES>, /// # logger: &L, /// # entropy_source: &ES, diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 8ea3ea068b3..8e7abd2a6f8 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -60,18 +60,16 @@ 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>, + 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< @@ -79,17 +77,15 @@ impl< L: Deref, ES: Deref, S: Deref, - SP: Sized, - Sc: ScoreLookUp, - > DefaultRouter + > 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, + 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 } } @@ -100,12 +96,10 @@ impl< L: Deref, ES: Deref, S: Deref, - SP: Sized, - Sc: ScoreLookUp, - > Router for DefaultRouter + > Router for DefaultRouter where L::Target: Logger, - S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for<'a> LockableScore<'a>, ES::Target: EntropySource, { #[rustfmt::skip] @@ -320,9 +314,10 @@ impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp, { + #[cfg(not(c_bindings))] type ScoreParams = ::ScoreParams; #[rustfmt::skip] - 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), @@ -2420,7 +2415,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(); @@ -2433,7 +2428,7 @@ where L::Target: Logger, GL::Target: Logger { #[rustfmt::skip] 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 { @@ -3845,9 +3840,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() { @@ -7222,9 +7218,10 @@ mod tests { fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } } impl ScoreLookUp for BadChannelScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); #[rustfmt::skip] - 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 } } } @@ -7240,9 +7237,10 @@ mod tests { } impl ScoreLookUp for BadNodeScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); #[rustfmt::skip] - 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 } } } @@ -9385,7 +9383,7 @@ pub(crate) mod bench_utils { #[rustfmt::skip] 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(); @@ -9528,7 +9526,7 @@ pub mod benches { #[rustfmt::skip] 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, ) { // First, get 100 (source, destination) pairs for which route-getting actually succeeds... diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 6c111ab475b..e59e37ad27f 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,9 +331,10 @@ 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, + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters, ) -> u64 { self.0.channel_penalty_msat(candidate, usage, score_params) } @@ -410,9 +416,10 @@ impl FixedPenaltyScorer { } impl ScoreLookUp for FixedPenaltyScorer { + #[cfg(not(c_bindings))] type ScoreParams = (); fn channel_penalty_msat( - &self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &Self::ScoreParams, + &self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &ProbabilisticScoringFeeParameters, ) -> u64 { self.penalty_msat } @@ -1673,6 +1680,7 @@ impl>, L: Deref> ScoreLookUp for Probabilistic where L::Target: Logger, { + #[cfg(not(c_bindings))] type ScoreParams = ProbabilisticScoringFeeParameters; #[rustfmt::skip] fn channel_penalty_msat( @@ -1882,6 +1890,7 @@ impl>, L: Deref> ScoreLookUp for CombinedScore where L::Target: Logger, { + #[cfg(not(c_bindings))] type ScoreParams = ProbabilisticScoringFeeParameters; fn channel_penalty_msat( diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index c9f9ba2d086..1d1afc14899 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -143,8 +143,6 @@ pub struct TestRouter<'a> { &'a TestLogger, Arc, &'a RwLock, - (), - TestScorer, >, pub network_graph: Arc>, pub next_routes: Mutex>)>>, @@ -2119,10 +2117,11 @@ 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, + _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters, ) -> u64 { let short_channel_id = match candidate.globally_unique_short_channel_id() { Some(scid) => scid, From 51d0ef6e4154d328a8348c85a3180f9928618785 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 19 Jul 2023 20:09:23 +0000 Subject: [PATCH 09/28] Mark several types no-export which should be exported eventually --- lightning-types/src/features.rs | 2 ++ lightning/src/events/bump_transaction/mod.rs | 4 ++++ lightning/src/ln/script.rs | 2 ++ 3 files changed, 8 insertions(+) diff --git a/lightning-types/src/features.rs b/lightning-types/src/features.rs index 54f1d9e44f0..29e3762e93a 100644 --- a/lightning-types/src/features.rs +++ b/lightning-types/src/features.rs @@ -914,6 +914,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()); @@ -924,6 +925,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; diff --git a/lightning/src/events/bump_transaction/mod.rs b/lightning/src/events/bump_transaction/mod.rs index 11f008612a2..d46f7131ca5 100644 --- a/lightning/src/events/bump_transaction/mod.rs +++ b/lightning/src/events/bump_transaction/mod.rs @@ -305,6 +305,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: Amount, pubkey_hash: &WPubkeyHash) -> Self { let script_sig_size = 1 /* script_sig length */ + 1 /* OP_0 */ + @@ -324,6 +326,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: Amount, pubkey_hash: &WPubkeyHash) -> Self { Self { outpoint, diff --git a/lightning/src/ln/script.rs b/lightning/src/ln/script.rs index 6bbbf3bf86e..aa361e4af83 100644 --- a/lightning/src/ln/script.rs +++ b/lightning/src/ln/script.rs @@ -85,6 +85,8 @@ impl ShutdownScript { /// /// This function may return an error if `data` is not [BOLT-2] compliant. /// + /// This is not exported to bindings users as the `PushBytes` isn't currently mapped. + /// /// [BOLT-2]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#closing-negotiation-closing_complete-and-closing_sig pub fn new_op_return>(data: T) -> Result { Self::try_from(ScriptBuf::new_op_return(data)) From 4ae7bdb55a5f4167862e4e2f2fd38add115bb5f7 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 28 Sep 2023 03:03:38 +0000 Subject: [PATCH 10/28] `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 | 9 +++++---- lightning/src/offers/invoice_request.rs | 4 +++- lightning/src/sign/mod.rs | 3 --- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index b4ae407c4c0..a75e3e0f084 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -16,7 +16,7 @@ //! The payment recipient must include a [`PaymentHash`], so as to reveal the preimage upon payment //! receipt, and one or more [`BlindedPaymentPath`]s for the payer to use when sending the payment. //! -//! ``` +//! ```ignore //! extern crate bitcoin; //! extern crate lightning; //! @@ -280,8 +280,7 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { Self::new(&refund.bytes, contents, ExplicitSigningPubkey {}) } - /// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by - /// [`UnsignedBolt12Invoice::sign`]. + /// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. pub fn build($self: $self_type) -> Result { #[cfg(feature = "std")] { @@ -671,7 +670,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 d5d3c4d75a8..8622cf72634 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -528,7 +528,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_signing_pubkey; diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index ac24a4a4040..d23599b4d1c 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -957,9 +957,6 @@ pub trait NodeSigner { /// Signs the [`TaggedHash`] of a BOLT 12 invoice. /// - /// May be called by a function passed to [`UnsignedBolt12Invoice::sign`] where `invoice` is the - /// callee. - /// /// Implementors may check that the `invoice` is expected rather than blindly signing the tagged /// hash. An `Ok` result should sign `invoice.tagged_hash().as_digest()` with the node's signing /// key or an ephemeral key to preserve privacy, whichever is associated with From 05f3a63610459970ad898345a73a5a9adf411710 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 31 Jan 2021 20:12:50 -0500 Subject: [PATCH 11/28] 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 | 5 +---- lightning/src/events/bump_transaction/mod.rs | 2 +- lightning/src/ln/async_signer_tests.rs | 2 +- lightning/src/ln/channel.rs | 2 +- lightning/src/ln/htlc_reserve_unit_tests.rs | 2 +- lightning/src/ln/monitor_tests.rs | 2 +- lightning/src/ln/update_fee_tests.rs | 2 +- lightning/src/sign/ecdsa.rs | 20 +++++++++++++++++++- lightning/src/sign/mod.rs | 12 +++++++----- lightning/src/util/dyn_signer.rs | 10 ++++++---- lightning/src/util/test_channel_signer.rs | 14 ++++++++------ 11 files changed, 47 insertions(+), 26 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 72bfde9e629..d3425843bd5 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -1078,10 +1078,7 @@ pub struct ChannelMonitor { pub(crate) 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/events/bump_transaction/mod.rs b/lightning/src/events/bump_transaction/mod.rs index d46f7131ca5..d653974beab 100644 --- a/lightning/src/events/bump_transaction/mod.rs +++ b/lightning/src/events/bump_transaction/mod.rs @@ -31,7 +31,7 @@ use crate::ln::chan_utils::{ }; use crate::ln::types::ChannelId; use crate::prelude::*; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::BaseEcdsaChannelSigner; use crate::sign::{ ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT, }; diff --git a/lightning/src/ln/async_signer_tests.rs b/lightning/src/ln/async_signer_tests.rs index 03728e28222..4acb5514b49 100644 --- a/lightning/src/ln/async_signer_tests.rs +++ b/lightning/src/ln/async_signer_tests.rs @@ -22,7 +22,7 @@ use crate::ln::channel_state::{ChannelDetails, ChannelShutdownState}; use crate::ln::channelmanager::{PaymentId, RAACommitmentOrder, RecipientOnionFields}; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent}; use crate::ln::{functional_test_utils::*, msgs}; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::BaseEcdsaChannelSigner; use crate::sign::SignerProvider; use crate::util::logger::Logger; use crate::util::test_channel_signer::SignerOp; diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index b18a4a59062..f8add1963c4 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -72,7 +72,7 @@ use crate::ln::types::ChannelId; use crate::ln::LN_MAX_MSG_LEN; use crate::offers::static_invoice::StaticInvoice; use crate::routing::gossip::NodeId; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::{BaseEcdsaChannelSigner, EcdsaChannelSigner}; use crate::sign::tx_builder::{HTLCAmountDirection, NextCommitmentStats, SpecTxBuilder, TxBuilder}; use crate::sign::{ChannelSigner, EntropySource, NodeSigner, Recipient, SignerProvider}; use crate::types::features::{ChannelTypeFeatures, InitFeatures}; diff --git a/lightning/src/ln/htlc_reserve_unit_tests.rs b/lightning/src/ln/htlc_reserve_unit_tests.rs index dc5d07c180e..f3de8951abc 100644 --- a/lightning/src/ln/htlc_reserve_unit_tests.rs +++ b/lightning/src/ln/htlc_reserve_unit_tests.rs @@ -15,7 +15,7 @@ use crate::ln::msgs::{self, BaseMessageHandler, ChannelMessageHandler, MessageSe use crate::ln::onion_utils::{self, AttributionData}; use crate::ln::outbound_payment::RecipientOnionFields; use crate::routing::router::PaymentParameters; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::BaseEcdsaChannelSigner; use crate::sign::tx_builder::{SpecTxBuilder, TxBuilder}; use crate::types::features::ChannelTypeFeatures; use crate::types::payment::PaymentPreimage; diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs index 5a287585680..eeedf9c6fd4 100644 --- a/lightning/src/ln/monitor_tests.rs +++ b/lightning/src/ln/monitor_tests.rs @@ -11,7 +11,7 @@ //! Further functional tests which test blockchain reorganizations. -use crate::sign::{ecdsa::EcdsaChannelSigner, OutputSpender, SignerProvider, SpendableOutputDescriptor}; +use crate::sign::{ecdsa::BaseEcdsaChannelSigner, OutputSpender, SignerProvider, SpendableOutputDescriptor}; use crate::chain::Watch; use crate::chain::channelmonitor::{Balance, BalanceSource, ChannelMonitorUpdateStep, HolderCommitmentTransactionBalance, ANTI_REORG_DELAY, ARCHIVAL_DELAY_BLOCKS, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::chain::transaction::OutPoint; diff --git a/lightning/src/ln/update_fee_tests.rs b/lightning/src/ln/update_fee_tests.rs index acb913294ab..879afb439c4 100644 --- a/lightning/src/ln/update_fee_tests.rs +++ b/lightning/src/ln/update_fee_tests.rs @@ -15,7 +15,7 @@ use crate::ln::msgs::{ self, BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, }; use crate::ln::outbound_payment::RecipientOnionFields; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::BaseEcdsaChannelSigner; use crate::types::features::ChannelTypeFeatures; use crate::util::config::UserConfig; use crate::util::errors::APIError; diff --git a/lightning/src/sign/ecdsa.rs b/lightning/src/sign/ecdsa.rs index e13285722af..0f0c705df84 100644 --- a/lightning/src/sign/ecdsa.rs +++ b/lightning/src/sign/ecdsa.rs @@ -34,7 +34,25 @@ use crate::sign::{ChannelSigner, HTLCDescriptor}; /// /// [`ChannelManager::signer_unblocked`]: crate::ln::channelmanager::ChannelManager::signer_unblocked /// [`ChainMonitor::signer_unblocked`]: crate::chain::chainmonitor::ChainMonitor::signer_unblocked -pub trait EcdsaChannelSigner: ChannelSigner { +pub trait EcdsaChannelSigner: BaseEcdsaChannelSigner + Clone {} + +/// A trait to sign Lightning channel transactions as described in +/// [BOLT 3](https://github.com/lightning/bolts/blob/master/03-transactions.md). +/// +/// Signing services could be implemented on a hardware wallet and should implement signing +/// policies in order to be secure. Please refer to the [VLS Policy +/// Controls](https://gitlab.com/lightning-signer/validating-lightning-signer/-/blob/main/docs/policy-controls.md) +/// for an example of such policies. +/// +/// Like [`ChannelSigner`], many of the methods allow errors to be returned to support async +/// signing. In such cases, the signing operation can be replayed by calling +/// [`ChannelManager::signer_unblocked`] or [`ChainMonitor::signer_unblocked`] (see individual +/// method documentation for which method should be called) once the result is ready, at which +/// point the channel operation will resume. +/// +/// [`ChannelManager::signer_unblocked`]: crate::ln::channelmanager::ChannelManager::signer_unblocked +/// [`ChainMonitor::signer_unblocked`]: crate::chain::chainmonitor::ChainMonitor::signer_unblocked +pub trait BaseEcdsaChannelSigner: ChannelSigner { /// Create a signature for a counterparty's commitment transaction and associated HTLC transactions. /// /// Policy checks should be implemented in this function, including checking the amount diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index d23599b4d1c..02e859cb962 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -64,7 +64,7 @@ use crate::util::transaction_utils; use crate::crypto::chacha20::ChaCha20; use crate::prelude::*; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::{BaseEcdsaChannelSigner, EcdsaChannelSigner}; #[cfg(taproot)] use crate::sign::taproot::TaprootChannelSigner; use crate::util::atomic_counter::AtomicCounter; @@ -1516,7 +1516,9 @@ impl ChannelSigner for InMemorySigner { const MISSING_PARAMS_ERR: &'static str = "ChannelTransactionParameters must be populated before signing operations"; -impl EcdsaChannelSigner for InMemorySigner { +impl EcdsaChannelSigner for InMemorySigner {} + +impl BaseEcdsaChannelSigner for InMemorySigner { fn sign_counterparty_commitment( &self, channel_parameters: &ChannelTransactionParameters, commitment_tx: &CommitmentTransaction, _inbound_htlc_preimages: Vec, @@ -2691,11 +2693,11 @@ impl EntropySource for RandomBytes { } } -// Ensure that EcdsaChannelSigner can have a vtable -#[test] +// Ensure that EcdsaChannelSigner can have a vtable - not required in bindings +/*#[test] pub fn dyn_sign() { let _signer: Box; -} +}*/ #[cfg(ldk_bench)] pub mod benches { diff --git a/lightning/src/util/dyn_signer.rs b/lightning/src/util/dyn_signer.rs index cf1cac37903..b7b80efd027 100644 --- a/lightning/src/util/dyn_signer.rs +++ b/lightning/src/util/dyn_signer.rs @@ -11,7 +11,7 @@ use crate::ln::chan_utils::{ use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage}; use crate::ln::script::ShutdownScript; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::{BaseEcdsaChannelSigner, EcdsaChannelSigner}; #[cfg(taproot)] use crate::sign::taproot::TaprootChannelSigner; use crate::sign::InMemorySigner; @@ -33,11 +33,11 @@ use types::payment::PaymentPreimage; #[cfg(not(taproot))] /// A super-trait for all the traits that a dyn signer backing implements -pub trait DynSignerTrait: EcdsaChannelSigner + Send + Sync {} +pub trait DynSignerTrait: BaseEcdsaChannelSigner + Send + Sync {} #[cfg(taproot)] /// A super-trait for all the traits that a dyn signer backing implements -pub trait DynSignerTrait: EcdsaChannelSigner + TaprootChannelSigner + Send + Sync {} +pub trait DynSignerTrait: BaseEcdsaChannelSigner + TaprootChannelSigner + Send + Sync {} /// Helper to allow DynSigner to clone itself pub trait InnerSign: DynSignerTrait { @@ -127,7 +127,9 @@ impl Clone for DynSigner { } } -delegate!(DynSigner, EcdsaChannelSigner, inner, +impl EcdsaChannelSigner for DynSigner {} + +delegate!(DynSigner, BaseEcdsaChannelSigner, inner, fn sign_holder_commitment(, channel_parameters: &ChannelTransactionParameters, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result, diff --git a/lightning/src/util/test_channel_signer.rs b/lightning/src/util/test_channel_signer.rs index 3bacd76a610..ae51ee2f765 100644 --- a/lightning/src/util/test_channel_signer.rs +++ b/lightning/src/util/test_channel_signer.rs @@ -14,7 +14,7 @@ use crate::ln::chan_utils::{ use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSHIS}; use crate::ln::channel_keys::HtlcKey; use crate::ln::msgs; -use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::ecdsa::{BaseEcdsaChannelSigner, EcdsaChannelSigner}; use crate::sign::ChannelSigner; use crate::types::payment::PaymentPreimage; @@ -264,7 +264,9 @@ impl ChannelSigner for TestChannelSigner { } } -impl EcdsaChannelSigner for TestChannelSigner { +impl EcdsaChannelSigner for TestChannelSigner {} + +impl BaseEcdsaChannelSigner for TestChannelSigner { fn sign_counterparty_commitment( &self, channel_parameters: &ChannelTransactionParameters, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, @@ -358,7 +360,7 @@ impl EcdsaChannelSigner for TestChannelSigner { if !self.is_signer_available(SignerOp::SignJusticeRevokedOutput) { return Err(()); } - Ok(EcdsaChannelSigner::sign_justice_revoked_output( + Ok(BaseEcdsaChannelSigner::sign_justice_revoked_output( &self.inner, channel_parameters, justice_tx, @@ -379,7 +381,7 @@ impl EcdsaChannelSigner for TestChannelSigner { if !self.is_signer_available(SignerOp::SignJusticeRevokedHtlc) { return Err(()); } - Ok(EcdsaChannelSigner::sign_justice_revoked_htlc( + Ok(BaseEcdsaChannelSigner::sign_justice_revoked_htlc( &self.inner, channel_parameters, justice_tx, @@ -447,7 +449,7 @@ impl EcdsaChannelSigner for TestChannelSigner { ) .unwrap(); } - Ok(EcdsaChannelSigner::sign_holder_htlc_transaction( + Ok(BaseEcdsaChannelSigner::sign_holder_htlc_transaction( &self.inner, htlc_tx, input, @@ -466,7 +468,7 @@ impl EcdsaChannelSigner for TestChannelSigner { if !self.is_signer_available(SignerOp::SignCounterpartyHtlcTransaction) { return Err(()); } - Ok(EcdsaChannelSigner::sign_counterparty_htlc_transaction( + Ok(BaseEcdsaChannelSigner::sign_counterparty_htlc_transaction( &self.inner, channel_parameters, htlc_tx, From 93ee7435d293403b0d9a52558dfbd50cac413338 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 24 Sep 2021 18:44:32 +0000 Subject: [PATCH 12/28] Make the custom message traits cloneable as they're deep in nested structs --- fuzz/src/onion_message.rs | 2 +- lightning/src/ln/wire.rs | 14 +++++++------- lightning/src/onion_message/functional_tests.rs | 2 +- lightning/src/onion_message/messenger.rs | 2 +- lightning/src/onion_message/packet.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index 934d748d6a5..a1627df4ff0 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -164,7 +164,7 @@ impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler { fn handle_release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) {} } -#[derive(Debug)] +#[derive(Clone, Debug)] struct TestCustomMessage {} const CUSTOM_MESSAGE_TYPE: u64 = 4242; diff --git a/lightning/src/ln/wire.rs b/lightning/src/ln/wire.rs index bc1d83adb68..abe01be0c8e 100644 --- a/lightning/src/ln/wire.rs +++ b/lightning/src/ln/wire.rs @@ -46,9 +46,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(any(test, feature = "_test_utils"), derive(PartialEq))] -pub(crate) enum Message { +pub(crate) enum Message where T: Clone + core::fmt::Debug + Type + TestEq { Init(msgs::Init), Error(msgs::ErrorMessage), Warning(msgs::WarningMessage), @@ -452,13 +452,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; } @@ -470,14 +470,14 @@ impl Type for () { } #[cfg(test)] -impl Type for T { +impl Type for T { fn type_id(&self) -> u16 { T::TYPE } } #[cfg(not(test))] -impl Type for T { +impl Type for T { fn type_id(&self) -> u16 { T::TYPE } @@ -882,7 +882,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 605a81a4f95..53a68b94fec 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -898,7 +898,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 9a2c06bb72f..fd900500308 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -243,7 +243,7 @@ where /// &custom_message_handler, /// ); /// -/// # #[derive(Debug)] +/// # #[derive(Clone, Debug)] /// # 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 2e0ccaf3a3e..95867d23d7e 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -189,7 +189,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 82347ec9fd7072ded6031259a48c90e906b82a85 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 28 Sep 2023 03:05:09 +0000 Subject: [PATCH 13/28] Avoid slices without inner references As we cannot express slices without inner references in bindings wrappers. --- lightning/src/blinded_path/payment.rs | 8 +++---- lightning/src/ln/blinded_payment_tests.rs | 12 +++++----- lightning/src/ln/channelmanager.rs | 24 +++++++++---------- lightning/src/ln/functional_tests.rs | 6 ++--- .../src/ln/max_payment_path_len_tests.rs | 2 +- lightning/src/ln/onion_route_tests.rs | 4 ++-- lightning/src/routing/gossip.rs | 2 +- lightning/src/routing/router.rs | 4 ++-- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/lightning/src/blinded_path/payment.rs b/lightning/src/blinded_path/payment.rs index 37d7a1dba7d..202f0c615be 100644 --- a/lightning/src/blinded_path/payment.rs +++ b/lightning/src/blinded_path/payment.rs @@ -103,7 +103,7 @@ impl BlindedPaymentPath { // be in relation to a specific channel. let htlc_maximum_msat = u64::max_value(); Self::new( - &[], + Vec::new(), payee_node_id, payee_tlvs, htlc_maximum_msat, @@ -120,7 +120,7 @@ impl BlindedPaymentPath { /// * any unknown features are required in the provided [`ForwardTlvs`] // TODO: make all payloads the same size with padding + add dummy hops pub fn new( - intermediate_nodes: &[PaymentForwardNode], payee_node_id: PublicKey, + intermediate_nodes: Vec, payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs, htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16, entropy_source: ES, secp_ctx: &Secp256k1, ) -> Result @@ -135,7 +135,7 @@ impl BlindedPaymentPath { SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); let blinded_payinfo = compute_payinfo( - intermediate_nodes, + &intermediate_nodes, &payee_tlvs.tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta, @@ -146,7 +146,7 @@ impl BlindedPaymentPath { blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), blinded_hops: blinded_hops( secp_ctx, - intermediate_nodes, + &intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret, diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index 25fa5e71e5d..a750fba9a38 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -92,7 +92,7 @@ pub fn blinded_payment_path( let mut secp_ctx = Secp256k1::new(); BlindedPaymentPath::new( - &intermediate_nodes[..], *node_ids.last().unwrap(), payee_tlvs, + intermediate_nodes, *node_ids.last().unwrap(), payee_tlvs, intro_node_max_htlc_opt.unwrap_or_else(|| channel_upds.last().unwrap().htlc_maximum_msat), TEST_FINAL_CLTV as u16, keys_manager, &secp_ctx ).unwrap() @@ -177,7 +177,7 @@ fn do_one_hop_blinded_path(success: bool) { let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, + vec![], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, &chanmon_cfgs[1].keys_manager, &secp_ctx ).unwrap(); @@ -229,7 +229,7 @@ fn mpp_to_one_hop_blinded_path() { let expanded_key = chanmon_cfgs[3].keys_manager.get_expanded_key(); let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key); let blinded_path = BlindedPaymentPath::new( - &[], nodes[3].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, + vec![], nodes[3].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, &chanmon_cfgs[3].keys_manager, &secp_ctx ).unwrap(); @@ -1340,7 +1340,7 @@ fn custom_tlvs_to_blinded_path() { let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key); let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, + vec![], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, &chanmon_cfgs[1].keys_manager, &secp_ctx ).unwrap(); @@ -1395,7 +1395,7 @@ fn fails_receive_tlvs_authentication() { let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, + vec![], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, &chanmon_cfgs[1].keys_manager, &secp_ctx ).unwrap(); @@ -1426,7 +1426,7 @@ fn fails_receive_tlvs_authentication() { let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, + vec![], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, &chanmon_cfgs[1].keys_manager, &secp_ctx ).unwrap(); diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5e8ce8def05..9b0b9db2a91 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -6598,7 +6598,7 @@ where /// [`APIMisuseError`]: APIError::APIMisuseError #[rustfmt::skip] 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 { @@ -6613,14 +6613,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) = peer_state.channel_by_id.get_mut(channel_id) { let mut config = channel.context().config(); config.apply(config_update); @@ -6677,7 +6677,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> { self.update_partial_channel_config(counterparty_node_id, channel_ids, &(*config).into()) } @@ -19034,7 +19034,7 @@ mod tests { check_unkown_peer_error(nodes[0].node.forward_intercepted_htlc(intercept_id, &channel_id, unkown_public_key, 1_000_000), unkown_public_key); - check_unkown_peer_error(nodes[0].node.update_channel_config(&unkown_public_key, &[channel_id], &ChannelConfig::default()), unkown_public_key); + check_unkown_peer_error(nodes[0].node.update_channel_config(&unkown_public_key, vec![channel_id], &ChannelConfig::default()), unkown_public_key); } #[test] @@ -19064,7 +19064,7 @@ mod tests { check_channel_unavailable_error(nodes[0].node.forward_intercepted_htlc(InterceptId([0; 32]), &channel_id, counterparty_node_id, 1_000_000), channel_id, counterparty_node_id); - check_channel_unavailable_error(nodes[0].node.update_channel_config(&counterparty_node_id, &[channel_id], &ChannelConfig::default()), channel_id, counterparty_node_id); + check_channel_unavailable_error(nodes[0].node.update_channel_config(&counterparty_node_id, vec![channel_id], &ChannelConfig::default()), channel_id, counterparty_node_id); } #[test] @@ -19279,12 +19279,12 @@ mod tests { let _ = create_announced_chan_between_nodes(&nodes, 0, 1); let channel = &nodes[0].node.list_channels()[0]; - nodes[0].node.update_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &user_config.channel_config).unwrap(); + nodes[0].node.update_channel_config(&channel.counterparty.node_id, vec![channel.channel_id], &user_config.channel_config).unwrap(); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 0); user_config.channel_config.forwarding_fee_base_msat += 10; - nodes[0].node.update_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &user_config.channel_config).unwrap(); + nodes[0].node.update_channel_config(&channel.counterparty.node_id, vec![channel.channel_id], &user_config.channel_config).unwrap(); assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_base_msat, user_config.channel_config.forwarding_fee_base_msat); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -19293,12 +19293,12 @@ mod tests { _ => panic!("expected BroadcastChannelUpdate event"), } - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate::default()).unwrap(); + nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, vec![channel.channel_id], &ChannelConfigUpdate::default()).unwrap(); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 0); let new_cltv_expiry_delta = user_config.channel_config.cltv_expiry_delta + 6; - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate { + nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, vec![channel.channel_id], &ChannelConfigUpdate { cltv_expiry_delta: Some(new_cltv_expiry_delta), ..Default::default() }).unwrap(); @@ -19311,7 +19311,7 @@ mod tests { } let new_fee = user_config.channel_config.forwarding_fee_proportional_millionths + 100; - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate { + nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, vec![channel.channel_id], &ChannelConfigUpdate { forwarding_fee_proportional_millionths: Some(new_fee), accept_underpaying_htlcs: Some(true), ..Default::default() @@ -19333,7 +19333,7 @@ mod tests { let new_fee = current_fee + 100; assert!( matches!( - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id, bad_channel_id], &ChannelConfigUpdate { + nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, vec![channel.channel_id, bad_channel_id], &ChannelConfigUpdate { forwarding_fee_proportional_millionths: Some(new_fee), ..Default::default() }), diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index c161a9664c0..a3df77ddd4c 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -9197,7 +9197,7 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) )), ..ChannelConfigUpdate::default() }; - nodes[1].node.update_partial_channel_config(&node_a_id, &[chan_id], &config).unwrap(); + nodes[1].node.update_partial_channel_config(&node_a_id, vec![chan_id], &config).unwrap(); // Check a successful payment send_payment(&nodes[0], &[&nodes[1]], NON_DUST_HTLC_MSAT); @@ -9231,7 +9231,7 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) )), ..ChannelConfigUpdate::default() }; - nodes[1].node.update_partial_channel_config(&node_a_id, &[chan_id], &update).unwrap(); + nodes[1].node.update_partial_channel_config(&node_a_id, vec![chan_id], &update).unwrap(); // Send an additional non-dust htlc from 1 to 0 using the pre-calculated route above, and check the immediate complaint let onion = RecipientOnionFields::secret_only(payment_secret_1_0); @@ -9265,7 +9265,7 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) )), ..ChannelConfigUpdate::default() }; - nodes[1].node.update_partial_channel_config(&node_a_id, &[chan_id], &update).unwrap(); + nodes[1].node.update_partial_channel_config(&node_a_id, vec![chan_id], &update).unwrap(); // Check a successful payment send_payment(&nodes[1], &[&nodes[0]], NON_DUST_HTLC_MSAT); diff --git a/lightning/src/ln/max_payment_path_len_tests.rs b/lightning/src/ln/max_payment_path_len_tests.rs index 8425e1928ad..a96cc884dd8 100644 --- a/lightning/src/ln/max_payment_path_len_tests.rs +++ b/lightning/src/ln/max_payment_path_len_tests.rs @@ -226,7 +226,7 @@ fn one_hop_blinded_path_with_custom_tlv() { let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key); let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], + vec![], nodes[2].node.get_our_node_id(), payee_tlvs, u64::MAX, diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index 32e8601fdc1..6ec00a2d473 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -1654,7 +1654,7 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { -> Option { nodes[1] .node - .update_channel_config(channel_to_update_counterparty, &[channel_to_update.0], config) + .update_channel_config(channel_to_update_counterparty, vec![channel_to_update.0], config) .unwrap(); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expect_new_update as usize); @@ -1714,7 +1714,7 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { invalid_config.cltv_expiry_delta = 0; match nodes[1].node.update_channel_config( channel_to_update_counterparty, - &[channel_to_update.0], + vec![channel_to_update.0], &invalid_config, ) { Err(APIError::APIMisuseError { .. }) => {}, diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index f3f81f812a0..5af264d7f72 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -105,7 +105,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 8e7abd2a6f8..fbfd66b079e 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -191,7 +191,7 @@ where }) .map(|forward_node| { BlindedPaymentPath::new( - &[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 ) }) @@ -203,7 +203,7 @@ where _ => { if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) { BlindedPaymentPath::new( - &[], recipient, tlvs, u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source, + Vec::new(), recipient, tlvs, u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source, secp_ctx ).map(|path| vec![path]) } else { From c065a803232c298954151a4bae2f589ab549d02b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 17 Aug 2024 23:53:16 +0000 Subject: [PATCH 14/28] Avoid options holding references in the public API --- lightning/src/ln/async_payments_tests.rs | 2 +- lightning/src/ln/channelmanager.rs | 4 ++-- lightning/src/ln/offers_tests.rs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lightning/src/ln/async_payments_tests.rs b/lightning/src/ln/async_payments_tests.rs index 0496febc761..3321d03a548 100644 --- a/lightning/src/ln/async_payments_tests.rs +++ b/lightning/src/ln/async_payments_tests.rs @@ -996,7 +996,7 @@ fn ignore_duplicate_invoice() { match sender.onion_messenger.peel_onion_message(&invoice_om) { Ok(PeeledOnion::Offers(OffersMessage::Invoice(invoice), context, _)) => { assert!(matches!( - sender.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + sender.node.send_payment_for_bolt12_invoice(&invoice, context), Err(Bolt12PaymentError::DuplicateInvoice) )) }, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 9b0b9db2a91..e626202bce5 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -5568,9 +5568,9 @@ where /// /// [timer tick]: Self::timer_tick_occurred pub fn send_payment_for_bolt12_invoice( - &self, invoice: &Bolt12Invoice, context: Option<&OffersContext>, + &self, invoice: &Bolt12Invoice, context: Option, ) -> Result<(), Bolt12PaymentError> { - match self.verify_bolt12_invoice(invoice, context) { + match self.verify_bolt12_invoice(invoice, context.as_ref()) { Ok(payment_id) => self.send_payment_for_verified_bolt12_invoice(invoice, payment_id), Err(()) => Err(Bolt12PaymentError::UnexpectedInvoice), } diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 8735c628630..8d15e90abc4 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -1321,9 +1321,9 @@ fn pays_bolt12_invoice_asynchronously() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } - assert!(bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()).is_ok()); + assert!(bob.node.send_payment_for_bolt12_invoice(&invoice, context.clone()).is_ok()); assert_eq!( - bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + bob.node.send_payment_for_bolt12_invoice(&invoice, context.clone()), Err(Bolt12PaymentError::DuplicateInvoice), ); @@ -1334,7 +1334,7 @@ fn pays_bolt12_invoice_asynchronously() { expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id); assert_eq!( - bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + bob.node.send_payment_for_bolt12_invoice(&invoice, context.clone()), Err(Bolt12PaymentError::DuplicateInvoice), ); @@ -1343,7 +1343,7 @@ fn pays_bolt12_invoice_asynchronously() { } assert_eq!( - bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + bob.node.send_payment_for_bolt12_invoice(&invoice, context), Err(Bolt12PaymentError::UnexpectedInvoice), ); } From 92eefae142e30068231c17eedb6a96e29f4db479 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:12:39 +0000 Subject: [PATCH 15/28] 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 2f9b1b9a411..b72e61ad3eb 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -183,7 +183,7 @@ impl_writeable!(BlindedHop, { impl Direction { /// Returns the [`NodeId`] from the inputs corresponding to the direction. - pub fn select_node_id(&self, node_a: NodeId, node_b: NodeId) -> NodeId { + pub(crate) fn select_node_id(&self, node_a: NodeId, node_b: NodeId) -> NodeId { match self { Direction::NodeOne => core::cmp::min(node_a, node_b), Direction::NodeTwo => core::cmp::max(node_a, node_b), @@ -191,7 +191,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 f65de4cc05a5a516c06dc8f05d43bb44dd17b12d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 11 May 2024 16:13:02 +0000 Subject: [PATCH 16/28] Drop `SerialId` type as bindings don't support primitive aliasing --- lightning/src/ln/interactivetxs.rs | 3 ++- lightning/src/ln/msgs.rs | 14 +++++--------- lightning/src/util/ser.rs | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/lightning/src/ln/interactivetxs.rs b/lightning/src/ln/interactivetxs.rs index badd8428db3..1496d11e845 100644 --- a/lightning/src/ln/interactivetxs.rs +++ b/lightning/src/ln/interactivetxs.rs @@ -34,8 +34,9 @@ use crate::ln::chan_utils::{ use crate::ln::channel::{FundingNegotiationContext, TOTAL_BITCOIN_SUPPLY_SATOSHIS}; use crate::ln::funding::FundingTxInput; use crate::ln::msgs; -use crate::ln::msgs::{MessageSendEvent, SerialId, TxSignatures}; +use crate::ln::msgs::{MessageSendEvent, TxSignatures}; use crate::ln::types::ChannelId; +type SerialId = u64; use crate::sign::{EntropySource, P2TR_KEY_PATH_WITNESS_WEIGHT, P2WPKH_WITNESS_WEIGHT}; use core::fmt::Display; diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 75577ae0e32..7b68c43319a 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -450,10 +450,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/1160 @@ -521,7 +517,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. Omitted for shared input. pub prevtx: Option, @@ -542,7 +538,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 @@ -557,7 +553,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. @@ -568,7 +564,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 @@ -2848,7 +2844,7 @@ impl Writeable for TxAddInput { impl LengthReadable for TxAddInput { fn read_from_fixed_length_buffer(r: &mut R) -> Result { let channel_id: ChannelId = Readable::read(r)?; - let serial_id: SerialId = Readable::read(r)?; + let serial_id: u64 = Readable::read(r)?; let prevtx_len: u16 = Readable::read(r)?; let prevtx = if prevtx_len > 0 { diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index f821aa5afc0..ec7d9fa2de6 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -48,7 +48,7 @@ use dnssec_prover::rr::Name; use crate::chain::ClaimId; #[cfg(taproot)] use crate::ln::msgs::PartialSignatureWithNonce; -use crate::ln::msgs::{DecodeError, SerialId}; +use crate::ln::msgs::DecodeError; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::types::string::UntrustedString; use crate::util::byte_utils::{be48_to_array, slice_to_be48}; @@ -1089,7 +1089,7 @@ impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction); impl_for_vec!(crate::ln::channelmanager::PaymentClaimDetails); impl_for_vec!(crate::ln::msgs::SocketAddress); impl_for_vec!((A, B), A, B); -impl_for_vec!(SerialId); +impl_for_vec!(u64); impl_for_vec!(TxInMetadata); impl_for_vec!(TxOutMetadata); impl_for_vec!(crate::ln::our_peer_storage::PeerStorageMonitorHolder); From 6719ef18094d9de9a3a31d112ad93430fc4d31a9 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 5 Jun 2024 14:41:03 +0000 Subject: [PATCH 17/28] Minimal updates to `lightning-transaction-sync` for bindings Bindings don't accept dyn traits, but instead map any traits to a single dynamic struct. Thus, we can always take a specific trait to accept any implementation, which we do here. --- lightning-transaction-sync/src/electrum.rs | 2 ++ lightning-transaction-sync/src/error.rs | 2 ++ lightning-transaction-sync/src/esplora.rs | 2 ++ lightning-transaction-sync/src/lib.rs | 6 +++--- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lightning-transaction-sync/src/electrum.rs b/lightning-transaction-sync/src/electrum.rs index 47489df69bb..9691a68d3d2 100644 --- a/lightning-transaction-sync/src/electrum.rs +++ b/lightning-transaction-sync/src/electrum.rs @@ -5,6 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. You may not use this file except in // accordance with one or both of these licenses. +//! Chain sync using the electrum protocol + use crate::common::{ConfirmedTx, FilterQueue, SyncState}; use crate::error::{InternalError, TxSyncError}; diff --git a/lightning-transaction-sync/src/error.rs b/lightning-transaction-sync/src/error.rs index 2fafe50fc16..daf57c6494d 100644 --- a/lightning-transaction-sync/src/error.rs +++ b/lightning-transaction-sync/src/error.rs @@ -5,6 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. You may not use this file except in // accordance with one or both of these licenses. +//! Common error types + use std::fmt; #[derive(Debug)] diff --git a/lightning-transaction-sync/src/esplora.rs b/lightning-transaction-sync/src/esplora.rs index a191260bc01..835a1619e92 100644 --- a/lightning-transaction-sync/src/esplora.rs +++ b/lightning-transaction-sync/src/esplora.rs @@ -5,6 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. You may not use this file except in // accordance with one or both of these licenses. +//! Chain sync using the Esplora API + use crate::common::{ConfirmedTx, FilterQueue, SyncState}; use crate::error::{InternalError, TxSyncError}; diff --git a/lightning-transaction-sync/src/lib.rs b/lightning-transaction-sync/src/lib.rs index baf074a7bca..2e80cf6d3a8 100644 --- a/lightning-transaction-sync/src/lib.rs +++ b/lightning-transaction-sync/src/lib.rs @@ -72,15 +72,15 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] -mod esplora; +pub mod esplora; #[cfg(any(feature = "_electrum"))] -mod electrum; +pub mod electrum; #[cfg(any(feature = "esplora-blocking", feature = "esplora-async", feature = "_electrum"))] mod common; #[cfg(any(feature = "esplora-blocking", feature = "esplora-async", feature = "_electrum"))] -mod error; +pub mod error; #[cfg(any(feature = "esplora-blocking", feature = "esplora-async", feature = "_electrum"))] pub use error::TxSyncError; From 688e310c1a214cfbe20663c4b1a6ff5e2b065243 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 20 Aug 2024 14:32:44 +0000 Subject: [PATCH 18/28] Require an OM in BP as this should generally be true and its easier to map --- lightning-background-processor/src/lib.rs | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 6ec3bf5c046..cc43ca7d54e 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -1487,7 +1487,7 @@ impl BackgroundProcessor { OS: 'static + Deref> + Send, >( kv_store: K, event_handler: EH, chain_monitor: M, channel_manager: CM, - onion_messenger: Option, gossip_sync: GossipSync, peer_manager: PM, + onion_messenger: OM, gossip_sync: GossipSync, peer_manager: PM, liquidity_manager: Option, sweeper: Option, logger: L, scorer: Option, ) -> Self where @@ -1556,7 +1556,7 @@ impl BackgroundProcessor { loop { channel_manager.get_cm().process_pending_events(&event_handler); chain_monitor.process_pending_events(&event_handler); - if let Some(om) = &onion_messenger { + if let Some(om) = Some(&onion_messenger) { om.get_om().process_pending_events(&event_handler) }; @@ -1581,7 +1581,7 @@ impl BackgroundProcessor { log_trace!(logger, "Terminating background processor."); break; } - let sleeper = match (onion_messenger.as_ref(), liquidity_manager.as_ref()) { + let sleeper = match (Some(&onion_messenger), liquidity_manager.as_ref()) { (Some(om), Some(lm)) => Sleeper::from_four_futures( &channel_manager.get_cm().get_event_or_persistence_needed_future(), &chain_monitor.get_update_future(), @@ -1708,7 +1708,7 @@ impl BackgroundProcessor { last_sweeper_call = Instant::now(); } if last_onion_message_handler_call.elapsed() > ONION_MESSAGE_HANDLER_TIMER { - if let Some(om) = &onion_messenger { + if let Some(om) = Some(&onion_messenger) { log_trace!(logger, "Calling OnionMessageHandler's timer_tick_occurred"); om.get_om().timer_tick_occurred(); } @@ -2619,7 +2619,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].p2p_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -2714,7 +2714,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -2758,7 +2758,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -2841,7 +2841,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].p2p_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -2872,7 +2872,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -2920,7 +2920,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -2984,7 +2984,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -3148,7 +3148,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -3179,7 +3179,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -3277,7 +3277,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].rapid_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -3489,7 +3489,7 @@ mod tests { event_handler, Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - Some(Arc::clone(&nodes[0].messenger)), + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), Some(Arc::clone(&nodes[0].liquidity_manager)), @@ -3596,7 +3596,7 @@ mod tests { move |_: Event| Ok(()), Arc::clone(&nodes[0].chain_monitor), Arc::clone(&nodes[0].node), - crate::NO_ONION_MESSENGER, + Arc::clone(&nodes[0].messenger), nodes[0].no_gossip_sync(), Arc::clone(&nodes[0].peer_manager), crate::NO_LIQUIDITY_MANAGER_SYNC, From b600c6241f23a8539046221986086b5ce8149b5e Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 24 Aug 2024 20:37:31 +0000 Subject: [PATCH 19/28] Avoid returning references in `NodeAnnouncementInfo` accessors --- lightning/src/routing/gossip.rs | 16 +++++++++------- lightning/src/routing/router.rs | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index 5af264d7f72..b73823be1a1 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -1388,7 +1388,9 @@ pub enum NodeAnnouncementInfo { impl NodeAnnouncementInfo { /// Protocol features the node announced support for - pub fn features(&self) -> &NodeFeatures { + pub fn features(&self) -> NodeFeatures { self.features_ref().clone() } + + pub(crate) fn features_ref(&self) -> &NodeFeatures { match self { NodeAnnouncementInfo::Relayed(relayed) => &relayed.contents.features, NodeAnnouncementInfo::Local(local) => &local.features, @@ -1416,29 +1418,29 @@ impl NodeAnnouncementInfo { /// Moniker assigned to the node. /// /// May be invalid or malicious (eg control chars), should not be exposed to the user. - pub fn alias(&self) -> &NodeAlias { + pub fn alias(&self) -> NodeAlias { match self { NodeAnnouncementInfo::Relayed(relayed) => &relayed.contents.alias, NodeAnnouncementInfo::Local(local) => &local.alias, - } + }.clone() } /// Internet-level addresses via which one can connect to the node - pub fn addresses(&self) -> &[SocketAddress] { + pub fn addresses(&self) -> Vec { match self { NodeAnnouncementInfo::Relayed(relayed) => &relayed.contents.addresses, NodeAnnouncementInfo::Local(local) => &local.addresses, - } + }.to_vec() } /// An initial announcement of the node /// /// Not stored if contains excess data to prevent DoS. - pub fn announcement_message(&self) -> Option<&NodeAnnouncement> { + pub fn announcement_message(&self) -> Option { match self { NodeAnnouncementInfo::Relayed(announcement) => Some(announcement), NodeAnnouncementInfo::Local(_) => None, - } + }.cloned() } } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index fbfd66b079e..c7487746f79 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -3167,7 +3167,7 @@ where L::Target: Logger { if let Some(node) = network_nodes.get(&$node_id) { let features = if let Some(node_info) = node.announcement_info.as_ref() { - &node_info.features() + node_info.features_ref() } else { &default_node_features }; From d7e4a44bb96b72fbd4f771d60c80009891cf00d7 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 16 Oct 2025 19:28:03 +0000 Subject: [PATCH 20/28] Use `[u8; 32]` rather than `Hmac` for simplicity Mapping an `Hmac` would require somewhat custom logic as we'd have to behave differently based on generic parameters, so its simplest to just swap it to a `[u8; 32]` instead. --- lightning/src/blinded_path/payment.rs | 2 +- lightning/src/ln/channelmanager.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lightning/src/blinded_path/payment.rs b/lightning/src/blinded_path/payment.rs index 202f0c615be..30701fc25f1 100644 --- a/lightning/src/blinded_path/payment.rs +++ b/lightning/src/blinded_path/payment.rs @@ -332,7 +332,7 @@ pub struct ReceiveTlvs { /// The TLVs for which the HMAC in `authentication` is derived. pub(crate) tlvs: UnauthenticatedReceiveTlvs, /// An HMAC of `tlvs` along with a nonce used to construct it. - pub(crate) authentication: (Hmac, Nonce), + pub(crate) authentication: ([u8; 32], Nonce), } impl ReceiveTlvs { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index e626202bce5..4ef1c1d118e 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -570,24 +570,25 @@ pub trait Verification { /// [`Nonce`]. fn hmac_for_offer_payment( &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, - ) -> Hmac; + ) -> [u8; 32]; /// Authenticates the data using an HMAC and a [`Nonce`] taken from an [`OffersContext`]. fn verify_for_offer_payment( - &self, hmac: Hmac, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, + &self, hmac: [u8; 32], nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Result<(), ()>; } impl Verification for UnauthenticatedReceiveTlvs { fn hmac_for_offer_payment( &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, - ) -> Hmac { - signer::hmac_for_payment_tlvs(self, nonce, expanded_key) + ) -> [u8; 32] { + signer::hmac_for_payment_tlvs(self, nonce, expanded_key).to_byte_array() } fn verify_for_offer_payment( - &self, hmac: Hmac, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, + &self, hmac: [u8; 32], nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Result<(), ()> { + let hmac = bitcoin::hashes::hmac::Hmac::from_byte_array(hmac); signer::verify_payment_tlvs(self, hmac, nonce, expanded_key) } } From 53934a289f88d41d16afa99c55ae884259b51e01 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 26 Aug 2024 18:31:24 +0000 Subject: [PATCH 21/28] Use inline bounds for secp contexts, rather than `where` clauses The bindings really should support this, but currently they don't and its late enough in the release cycle I don't want to try to fix that. --- lightning/src/blinded_path/message.rs | 3 +-- lightning/src/blinded_path/payment.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index ed55ca5dc9b..1f3e048b6b3 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -176,13 +176,12 @@ impl BlindedMessagePath { /// introduction node. /// /// Will only modify `self` when returning `Ok`. - pub fn advance_path_by_one( + pub fn advance_path_by_one( &mut self, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1, ) -> Result<(), ()> where NS::Target: NodeSigner, NL::Target: NodeIdLookUp, - T: secp256k1::Signing + secp256k1::Verification, { let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &self.0.blinding_point, None)?; let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes()); diff --git a/lightning/src/blinded_path/payment.rs b/lightning/src/blinded_path/payment.rs index 30701fc25f1..da02056d8c7 100644 --- a/lightning/src/blinded_path/payment.rs +++ b/lightning/src/blinded_path/payment.rs @@ -185,13 +185,12 @@ impl BlindedPaymentPath { /// introduction node. /// /// Will only modify `self` when returning `Ok`. - pub fn advance_path_by_one( + pub fn advance_path_by_one( &mut self, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1, ) -> Result<(), ()> where NS::Target: NodeSigner, NL::Target: NodeIdLookUp, - T: secp256k1::Signing + secp256k1::Verification, { match self.decrypt_intro_payload::(node_signer) { Ok(( From 4560d7196f5c36083d26e94e2325fcf681155d6e Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 29 Jan 2025 01:40:19 +0000 Subject: [PATCH 22/28] Mark `RawBolt11Invoice`'s de/ser methods as no-export --- lightning-invoice/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 47f929377de..1d7e11d5773 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -1220,12 +1220,16 @@ impl RawBolt11Invoice { /// Convert to HRP prefix and Fe32 encoded data part. /// Can be used to transmit unsigned invoices for remote signing. + /// + /// This is not exported to bindings users as we don't currently support Fe32s pub fn to_raw(&self) -> (String, Vec) { (self.hrp.to_string(), self.data.fe_iter().collect()) } /// Convert from HRP prefix and Fe32 encoded data part. /// Can be used to receive unsigned invoices for remote signing. + /// + /// This is not exported to bindings users as we don't currently support Fe32s pub fn from_raw(hrp: &str, data: &[Fe32]) -> Result { let raw_hrp: RawHrp = RawHrp::from_str(hrp)?; let data_part = RawDataPart::from_base32(data)?; From 601774294c3c3499f0e3132cc699b5c31361180a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 2 Apr 2025 22:38:24 +0000 Subject: [PATCH 23/28] Mark `Bolt11Bech32` as bindings-no-export as its unconstructable We don't expect anyone to access `Bolt11Bech32` directly in most use-cases, and the bindings don't support mapping an enum that cannot be constructed (not to mention there would be no point), so we mark it as no-export in bindings builds. --- lightning-invoice/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 1d7e11d5773..68341da00aa 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -162,6 +162,9 @@ pub const MAX_LENGTH: usize = 7089; /// The [`bech32::Bech32`] checksum algorithm, with extended max length suitable /// for BOLT11 invoices. +/// +/// This is not exported to bindings users as it generally shouldn't be used directly publicly +/// anyway. pub enum Bolt11Bech32 {} impl Checksum for Bolt11Bech32 { From f90f29945d4eac9af94baec8d0672fbd2d8403c3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 2 Nov 2025 19:30:51 +0000 Subject: [PATCH 24/28] Require several additional traits to be `Clone` In 0.2 we added some places where `Clone` bounds on traits provided additional features. The bindings, of course, cannot capture such optionality as traits have to be concretized first. Thus, we add the `Clone` bounds explicitly on the traits themselves. --- lightning-persister/src/fs_store.rs | 5 +++-- lightning/src/chain/chaininterface.rs | 2 +- lightning/src/chain/channelmonitor.rs | 11 +++++++++++ lightning/src/ln/channel.rs | 11 +++++++++++ lightning/src/ln/channelmanager.rs | 19 ++++++++----------- lightning/src/ln/invoice_utils.rs | 9 +++++++++ lightning/src/util/logger.rs | 13 ++++++++++++- lightning/src/util/persist.rs | 4 ++-- 8 files changed, 57 insertions(+), 17 deletions(-) diff --git a/lightning-persister/src/fs_store.rs b/lightning-persister/src/fs_store.rs index 9b15398d4d1..d718831c2fc 100644 --- a/lightning-persister/src/fs_store.rs +++ b/lightning-persister/src/fs_store.rs @@ -53,12 +53,13 @@ struct FilesystemStoreInner { /// A [`KVStore`] and [`KVStoreSync`] implementation that writes to and reads from the file system. /// /// [`KVStore`]: lightning::util::persist::KVStore +#[derive(Clone)] pub struct FilesystemStore { inner: Arc, // Version counter to ensure that writes are applied in the correct order. It is assumed that read and list // operations aren't sensitive to the order of execution. - next_version: AtomicU64, + next_version: Arc, } impl FilesystemStore { @@ -68,7 +69,7 @@ impl FilesystemStore { let tmp_file_counter = AtomicUsize::new(0); Self { inner: Arc::new(FilesystemStoreInner { data_dir, tmp_file_counter, locks }), - next_version: AtomicU64::new(1), + next_version: Arc::new(AtomicU64::new(1)), } } diff --git a/lightning/src/chain/chaininterface.rs b/lightning/src/chain/chaininterface.rs index 5dc46d5a055..443687a8ede 100644 --- a/lightning/src/chain/chaininterface.rs +++ b/lightning/src/chain/chaininterface.rs @@ -28,7 +28,7 @@ pub(crate) const fn fee_for_weight(feerate_sat_per_1000_weight: u32, weight: u64 } /// An interface to send a transaction to the Bitcoin network. -pub trait BroadcasterInterface { +pub trait BroadcasterInterface : Clone { /// Sends a list of transactions out to (hopefully) be mined. /// This only needs to handle the actual broadcasting of transactions, LDK will automatically /// rebroadcast transactions that haven't made it into a block. diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index d3425843bd5..79e41bbf49b 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -1832,6 +1832,17 @@ where payment_hash: Option, } +impl<'a, L: Deref> Clone for WithChannelMonitor<'a, L> where L::Target: Logger { + fn clone(&self) -> Self { + Self { + logger: self.logger, + peer_id: self.peer_id, + channel_id: self.channel_id, + payment_hash: self.payment_hash, + } + } +} + impl<'a, L: Deref> Logger for WithChannelMonitor<'a, L> where L::Target: Logger, diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index f8add1963c4..3a054e25ca0 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -968,6 +968,17 @@ where pub payment_hash: Option, } +impl<'a, L: Deref> Clone for WithChannelContext<'a, L> where L::Target: Logger { + fn clone(&self) -> Self { + Self { + logger: self.logger, + peer_id: self.peer_id, + channel_id: self.channel_id, + payment_hash: self.payment_hash, + } + } +} + impl<'a, L: Deref> Logger for WithChannelContext<'a, L> where L::Target: Logger, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 4ef1c1d118e..3e2e296e88d 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2694,9 +2694,9 @@ pub struct ChannelManager< router: R, #[cfg(test)] - pub(super) flow: OffersMessageFlow, + pub(super) flow: OffersMessageFlow>, #[cfg(not(test))] - flow: OffersMessageFlow, + flow: OffersMessageFlow>, /// See `ChannelManager` struct-level documentation for lock order requirements. #[cfg(any(test, feature = "_test_utils"))] @@ -2718,7 +2718,7 @@ pub struct ChannelManager< /// See `PendingOutboundPayment` documentation for more info. /// /// See `ChannelManager` struct-level documentation for lock order requirements. - pending_outbound_payments: OutboundPayments, + pending_outbound_payments: OutboundPayments>, /// SCID/SCID Alias -> forward infos. Key of 0 means payments received. /// @@ -3948,10 +3948,7 @@ where fee_est: F, chain_monitor: M, tx_broadcaster: T, router: R, message_router: MR, logger: L, entropy_source: ES, node_signer: NS, signer_provider: SP, config: UserConfig, params: ChainParameters, current_timestamp: u32, - ) -> Self - where - L: Clone, - { + ) -> Self { let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes()); @@ -3961,7 +3958,7 @@ where let flow = OffersMessageFlow::new( ChainHash::using_genesis_block(params.network), params.best_block, our_network_pubkey, current_timestamp, expanded_inbound_key, - node_signer.get_receive_auth_key(), message_router, logger.clone(), + node_signer.get_receive_auth_key(), message_router, Box::new((*logger).clone()), ); ChannelManager { @@ -3976,7 +3973,7 @@ where best_block: RwLock::new(params.best_block), outbound_scid_aliases: Mutex::new(new_hash_set()), - pending_outbound_payments: OutboundPayments::new(new_hash_map(), logger.clone()), + pending_outbound_payments: OutboundPayments::new(new_hash_map(), Box::new((*logger).clone())), forward_htlcs: Mutex::new(new_hash_map()), decode_update_add_htlcs: Mutex::new(new_hash_map()), claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: new_hash_map(), pending_claiming_payments: new_hash_map() }), @@ -17151,7 +17148,7 @@ where pending_outbound_payments = Some(outbounds); } let pending_outbounds = - OutboundPayments::new(pending_outbound_payments.unwrap(), args.logger.clone()); + OutboundPayments::new(pending_outbound_payments.unwrap(), Box::new((*args.logger).clone())); for (peer_pubkey, peer_storage) in peer_storage_dir { if let Some(peer_state) = per_peer_state.get_mut(&peer_pubkey) { @@ -17997,7 +17994,7 @@ where expanded_inbound_key, args.node_signer.get_receive_auth_key(), args.message_router, - args.logger.clone(), + Box::new((*args.logger).clone()), ) .with_async_payments_offers_cache(async_receive_offer_cache); diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index cfa05f56482..b1716f934d7 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -600,6 +600,15 @@ where details: &'b ChannelDetails, } +impl<'a, 'b, L: Deref> Clone for WithChannelDetails<'a, 'b, L> where L::Target: Logger { + fn clone(&self) -> Self { + Self { + logger: self.logger, + details: self.details, + } + } +} + impl<'a, 'b, L: Deref> Logger for WithChannelDetails<'a, 'b, L> where L::Target: Logger, diff --git a/lightning/src/util/logger.rs b/lightning/src/util/logger.rs index 283d3158144..216e97e84f7 100644 --- a/lightning/src/util/logger.rs +++ b/lightning/src/util/logger.rs @@ -159,7 +159,7 @@ impl_record!('a, ); impl_record!(, 'a); /// A trait encapsulating the operations required of a logger. -pub trait Logger { +pub trait Logger: Clone { /// Logs the [`Record`]. fn log(&self, record: Record); } @@ -182,6 +182,17 @@ where payment_hash: Option, } +impl<'a, L: Deref> Clone for WithContext<'a, L> where L::Target: Logger { + fn clone(&self) -> Self { + WithContext { + logger: self.logger, + peer_id: self.peer_id, + channel_id: self.channel_id, + payment_hash: self.payment_hash, + } + } +} + impl<'a, L: Deref> Logger for WithContext<'a, L> where L::Target: Logger, diff --git a/lightning/src/util/persist.rs b/lightning/src/util/persist.rs index d00e29e686a..121ce99bfea 100644 --- a/lightning/src/util/persist.rs +++ b/lightning/src/util/persist.rs @@ -142,7 +142,7 @@ pub const MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL: &[u8] = &[0xFF; 2]; /// /// For an asynchronous version of this trait, see [`KVStore`]. // Note that updates to documentation on this trait should be copied to the asynchronous version. -pub trait KVStoreSync { +pub trait KVStoreSync : Clone { /// Returns the data stored for the given `primary_namespace`, `secondary_namespace`, and /// `key`. /// @@ -339,7 +339,7 @@ pub trait KVStore { /// Provides additional interface methods that are required for [`KVStore`]-to-[`KVStore`] /// data migration. -pub trait MigratableKVStore: KVStoreSync { +pub trait MigratableKVStore: KVStoreSync + Clone { /// Returns *all* known keys as a list of `primary_namespace`, `secondary_namespace`, `key` tuples. /// /// This is useful for migrating data from [`KVStoreSync`] implementation to [`KVStoreSync`] From b06ba922988a4a7a159a930276796e6f2ce57a6a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 3 Nov 2025 00:13:26 +0000 Subject: [PATCH 25/28] Use explicit `Send`/`Sync` rather than `MaybeSend`/`MaybeSync` We use `MaybeSend` + `MaybeSync` in rust to only enable `Send`+`Sync` bounds if built with `std`, but there's no reason to bother with this in bindings, even for `no_std` builds. As the bindings generator doesn't currently have logic to identify traits like these as "synonyms" for `Send`+`Sync`, we just use `Send`+`Sync` explicitly. --- lightning/src/events/bump_transaction/sync.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lightning/src/events/bump_transaction/sync.rs b/lightning/src/events/bump_transaction/sync.rs index 653710a3358..f14fc31f9f1 100644 --- a/lightning/src/events/bump_transaction/sync.rs +++ b/lightning/src/events/bump_transaction/sync.rs @@ -17,7 +17,7 @@ use crate::chain::chaininterface::BroadcasterInterface; use crate::chain::ClaimId; use crate::prelude::*; use crate::sign::SignerProvider; -use crate::util::async_poll::{dummy_waker, AsyncResult, MaybeSend, MaybeSync}; +use crate::util::async_poll::{dummy_waker, AsyncResult}; use crate::util::logger::Logger; use bitcoin::{Psbt, ScriptBuf, Transaction, TxOut}; @@ -93,18 +93,18 @@ where /// /// For an asynchronous version of this wrapper, see [`Wallet`]. // Note that updates to documentation on this struct should be copied to the asynchronous version. -pub struct WalletSync +pub struct WalletSync where - W::Target: WalletSourceSync + MaybeSend, - L::Target: Logger + MaybeSend, + W::Target: WalletSourceSync + Send, + L::Target: Logger + Send, { wallet: Wallet, L>, } -impl WalletSync +impl WalletSync where - W::Target: WalletSourceSync + MaybeSend, - L::Target: Logger + MaybeSend, + W::Target: WalletSourceSync + Send, + L::Target: Logger + Send, { /// Constructs a new [`WalletSync`] instance. pub fn new(source: W, logger: L) -> Self { @@ -112,11 +112,11 @@ where } } -impl CoinSelectionSourceSync +impl CoinSelectionSourceSync for WalletSync where - W::Target: WalletSourceSync + MaybeSend + MaybeSync, - L::Target: Logger + MaybeSend + MaybeSync, + W::Target: WalletSourceSync + Send + Sync, + L::Target: Logger + Send + Sync, { fn select_confirmed_utxos( &self, claim_id: ClaimId, must_spend: Vec, must_pay_to: &[TxOut], From 030740d5b6f89a090c20ed6f891eb816c435c0d0 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 3 Nov 2025 01:48:41 +0000 Subject: [PATCH 26/28] Make `onion_utils` public rather than re-exporting --- lightning/src/events/mod.rs | 3 ++- lightning/src/ln/mod.rs | 3 +-- lightning/src/ln/onion_utils.rs | 16 +++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index b9c4b1ca1ef..59916392a00 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -26,7 +26,8 @@ use crate::chain::transaction; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::types::ChannelId; -use crate::ln::{msgs, LocalHTLCFailureReason}; +use crate::ln::onion_utils::LocalHTLCFailureReason; +use crate::ln::msgs; use crate::offers::invoice::Bolt12Invoice; use crate::offers::invoice_request::InvoiceRequest; use crate::offers::static_invoice::StaticInvoice; diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index 333ae451aca..c83239ffc32 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -41,14 +41,13 @@ pub mod channel; #[cfg(not(fuzzing))] pub(crate) mod channel; -pub(crate) mod onion_utils; +pub mod onion_utils; pub mod outbound_payment; pub mod wire; #[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled. pub(crate) mod interactivetxs; -pub use onion_utils::{create_payment_onion, LocalHTLCFailureReason}; // Older rustc (which we support) refuses to let us call the get_payment_preimage_hash!() macro // without the node parameter being mut. This is incorrect, and thus newer rustcs will complain // about an unnecessary mut. Thus, we silence the unused_mut warning in two test modules below. diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 6bba2b59e10..f7aaee19f0d 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -7,6 +7,8 @@ // You may not use this file except in accordance with one or both of these // licenses. +//! Utilities for handling and manipulating onions + use super::msgs::OnionErrorPacket; use crate::blinded_path::BlindedHop; use crate::crypto::chacha20::ChaCha20; @@ -985,7 +987,7 @@ pub use self::fuzzy_onion_utils::*; #[cfg(not(fuzzing))] pub(crate) use self::fuzzy_onion_utils::*; -pub fn process_onion_failure( +pub(crate) fn process_onion_failure( secp_ctx: &Secp256k1, logger: &L, htlc_source: &HTLCSource, encrypted_packet: OnionErrorPacket, ) -> DecodedOnionFailure @@ -1467,7 +1469,7 @@ where } /// Decodes the attribution data that we got back from upstream on a payment we sent. -pub fn decode_fulfill_attribution_data( +pub(crate) fn decode_fulfill_attribution_data( secp_ctx: &Secp256k1, logger: &L, path: &Path, outer_session_priv: &SecretKey, mut attribution_data: AttributionData, ) -> Vec @@ -2708,16 +2710,16 @@ fn decode_next_hop, N: NextPacketBytes>( } } -pub const HOLD_TIME_LEN: usize = 4; -pub const MAX_HOPS: usize = 20; -pub const HMAC_LEN: usize = 4; +pub(crate) const HOLD_TIME_LEN: usize = 4; +pub(crate) const MAX_HOPS: usize = 20; +pub(crate) const HMAC_LEN: usize = 4; // Define the number of HMACs in the attributable data block. For the first node, there are 20 HMACs, and then for every // subsequent node, the number of HMACs decreases by 1. 20 + 19 + 18 + ... + 1 = 20 * 21 / 2 = 210. -pub const HMAC_COUNT: usize = MAX_HOPS * (MAX_HOPS + 1) / 2; +pub(crate) const HMAC_COUNT: usize = MAX_HOPS * (MAX_HOPS + 1) / 2; #[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct AttributionData { +pub(crate) struct AttributionData { pub hold_times: [u8; MAX_HOPS * HOLD_TIME_LEN], pub hmacs: [u8; HMAC_LEN * HMAC_COUNT], } From 5ced7632f2c36b0f16e17c76e3116ef4134228e4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 5 Dec 2025 20:15:06 +0000 Subject: [PATCH 27/28] Remove `lightning-liquidity` from bindings Sadly its not currently possible to map `lightning-liquidity` to bindings as it requires additional (`Clone`) bounds on various trait objects passed in to the top-level manager constructor. Because we don't anticipate bindings users using it immediately, we simply drop it here. --- lightning-background-processor/src/lib.rs | 28 ++++------------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index cc43ca7d54e..a5bb72c180a 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -1478,7 +1478,6 @@ impl BackgroundProcessor { PGS: 'static + Deref> + Send, RGS: 'static + Deref> + Send, PM: 'static + Deref + Send, - LM: 'static + Deref + Send, S: 'static + Deref + Send + Sync, SC: for<'b> WriteableScore<'b>, D: 'static + Deref, @@ -1488,7 +1487,7 @@ impl BackgroundProcessor { >( kv_store: K, event_handler: EH, chain_monitor: M, channel_manager: CM, onion_messenger: OM, gossip_sync: GossipSync, peer_manager: PM, - liquidity_manager: Option, sweeper: Option, logger: L, scorer: Option, + sweeper: Option, logger: L, scorer: Option, ) -> Self where UL::Target: 'static + UtxoLookup, @@ -1501,7 +1500,6 @@ impl BackgroundProcessor { CM::Target: AChannelManager, OM::Target: AOnionMessenger, PM::Target: APeerManager, - LM::Target: ALiquidityManagerSync, D::Target: ChangeDestinationSourceSync, O::Target: 'static + OutputSpender, K::Target: 'static + KVStoreSync, @@ -1581,24 +1579,13 @@ impl BackgroundProcessor { log_trace!(logger, "Terminating background processor."); break; } - let sleeper = match (Some(&onion_messenger), liquidity_manager.as_ref()) { - (Some(om), Some(lm)) => Sleeper::from_four_futures( + let sleeper = match Some(&onion_messenger) { + Some(om) => Sleeper::from_three_futures( &channel_manager.get_cm().get_event_or_persistence_needed_future(), &chain_monitor.get_update_future(), &om.get_om().get_update_future(), - &lm.get_lm().get_pending_msgs_or_needs_persist_future(), ), - (Some(om), None) => Sleeper::from_three_futures( - &channel_manager.get_cm().get_event_or_persistence_needed_future(), - &chain_monitor.get_update_future(), - &om.get_om().get_update_future(), - ), - (None, Some(lm)) => Sleeper::from_three_futures( - &channel_manager.get_cm().get_event_or_persistence_needed_future(), - &chain_monitor.get_update_future(), - &lm.get_lm().get_pending_msgs_or_needs_persist_future(), - ), - (None, None) => Sleeper::from_two_futures( + None => Sleeper::from_two_futures( &channel_manager.get_cm().get_event_or_persistence_needed_future(), &chain_monitor.get_update_future(), ), @@ -1630,13 +1617,6 @@ impl BackgroundProcessor { log_trace!(logger, "Done persisting ChannelManager."); } - if let Some(liquidity_manager) = liquidity_manager.as_ref() { - log_trace!(logger, "Persisting LiquidityManager..."); - let _ = liquidity_manager.get_lm().persist().map_err(|e| { - log_error!(logger, "Persisting LiquidityManager failed: {}", e); - }); - } - // Note that we want to run a graph prune once not long after startup before // falling back to our usual hourly prunes. This avoids short-lived clients never // pruning their network graph. We run once 60 seconds after startup before From 464a8db09487faea7f734dd4f256d0640c875b76 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 5 Dec 2025 20:19:30 +0000 Subject: [PATCH 28/28] Ensure `Option
` gets derived This is used in bindings for the `Address` constructor, and needs to exist in the (public) source tree to ensure bindings derives it. --- lightning-invoice/src/lib.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 68341da00aa..ddd0a2928fb 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -1609,6 +1609,29 @@ impl Bolt11Invoice { self.fallbacks().iter().filter_map(filter_fn).collect() } + /// Returns the first fallback address as an [`Address`]. + /// + /// See [`Self::fallback_addresses`] to fetch all addresses of known type. + pub fn first_fallback_address(&self) -> Option
{ + let filter_fn = |fallback: &&Fallback| { + let address = match fallback { + Fallback::SegWitProgram { version, program } => { + match WitnessProgram::new(*version, &program) { + Ok(witness_program) => { + Address::from_witness_program(witness_program, self.network()) + }, + Err(_) => return None, + } + }, + Fallback::PubKeyHash(pkh) => Address::p2pkh(*pkh, self.network()), + Fallback::ScriptHash(sh) => Address::p2sh_from_hash(*sh, self.network()), + }; + + Some(address) + }; + self.fallbacks().iter().filter_map(filter_fn).next() + } + /// Returns a list of all routes included in the invoice pub fn private_routes(&self) -> Vec<&PrivateRoute> { self.signed_invoice.private_routes()