use lightning::events;
use lightning::events::MessageSendEventsProvider;
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs, PaymentId, RecipientOnionFields};
+use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, ChannelManagerReadArgs, PaymentId};
+use lightning::ln::outbound_payment::{RecipientOnionFields, PaymentSendFailure};
use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
use lightning::ln::msgs::{self, CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
use lightning::ln::script::ShutdownScript;
use lightning::sign::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
use lightning::events::Event;
use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId, RecipientOnionFields, Retry};
+use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId};
+use lightning::ln::outbound_payment::{RecipientOnionFields, Retry};
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler};
use lightning::ln::msgs::{self, DecodeError};
use lightning::ln::script::ShutdownScript;
persister, chain_monitor,
chain_monitor.process_pending_events_async(async_event_handler).await,
channel_manager, channel_manager.process_pending_events_async(async_event_handler).await,
- peer_manager, process_onion_message_handler_events_async(&peer_manager, async_event_handler).await,
+ peer_manager,
+ for event in onion_message_handler_events(peer_manager) {
+ handler(event).await
+ },
gossip_sync, logger, scorer, should_break, {
let fut = Selector {
a: channel_manager.get_event_or_persistence_needed_future(),
)
}
-#[cfg(feature = "futures")]
-async fn process_onion_message_handler_events_async<
- EventHandlerFuture: core::future::Future<Output = ()>,
- EventHandler: Fn(Event) -> EventHandlerFuture,
- PM: 'static + Deref + Send + Sync,
->(
- peer_manager: &PM, handler: EventHandler
-)
-where
- PM::Target: APeerManager + Send + Sync,
-{
- let events = core::cell::RefCell::new(Vec::new());
- peer_manager.onion_message_handler().process_pending_events(&|e| events.borrow_mut().push(e));
-
- for event in events.into_inner() {
- handler(event).await
- }
+fn onion_message_handler_events<PM: 'static + Deref + Send + Sync>(
+ peer_manager: &PM
+) -> impl Iterator<Item=Event> where PM::Target: APeerManager + Send + Sync {
+ peer_manager.onion_message_handler().get_and_clear_connections_needed()
+ .into_iter().map(|(node_id, addresses)| Event::ConnectionNeeded { node_id, addresses })
}
#[cfg(feature = "std")]
persister, chain_monitor, chain_monitor.process_pending_events(&event_handler),
channel_manager, channel_manager.process_pending_events(&event_handler),
peer_manager,
- peer_manager.onion_message_handler().process_pending_events(&event_handler),
+ for event in onion_message_handler_events(&peer_manager) {
+ event_handler.handle_event(event);
+ },
gossip_sync, logger, scorer, stop_thread.load(Ordering::Acquire),
{ Sleeper::from_two_futures(
channel_manager.get_event_or_persistence_needed_future(),
Arc<DefaultRouter<
Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
Arc<test_utils::TestLogger>,
- Arc<LockingWrapper<TestScorer>>,
- (),
- TestScorer>
+ Arc<KeysManager>,
+ Arc<LockingWrapper<TestScorer>>>
>,
Arc<test_utils::TestLogger>>;
}
impl ScoreLookUp for TestScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
fn channel_penalty_msat(
- &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &Self::ScoreParams
+ &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &lightning::routing::scoring::ProbabilisticScoringFeeParameters
) -> u64 { unimplemented!(); }
}
let genesis_block = genesis_block(network);
let network_graph = Arc::new(NetworkGraph::new(network, logger.clone()));
let scorer = Arc::new(LockingWrapper::new(TestScorer::new()));
+ let now = Duration::from_secs(genesis_block.header.time as u64);
let seed = [i as u8; 32];
- let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), seed, scorer.clone(), Default::default()));
+ let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos()));
+ let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), Arc::clone(&keys_manager), scorer.clone(), Default::default()));
let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Bitcoin));
let kv_store = Arc::new(FilesystemStore::new(format!("{}_persister_{}", &persist_dir, i).into()));
- let now = Duration::from_secs(genesis_block.header.time as u64);
- let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos()));
let chain_monitor = Arc::new(chainmonitor::ChainMonitor::new(Some(chain_source.clone()), tx_broadcaster.clone(), logger.clone(), fee_estimator.clone(), kv_store.clone()));
let best_block = BestBlock::from_network(network);
let params = ChainParameters { network, best_block };
use bitcoin::hashes::Hash;
use lightning::ln::PaymentHash;
-use lightning::ln::channelmanager::RecipientOnionFields;
+use lightning::ln::outbound_payment::RecipientOnionFields;
use lightning::routing::router::{PaymentParameters, RouteParameters};
/// Builds the necessary parameters to pay or pre-flight probe the given zero-amount
#[cfg(feature = "std")]
fn payment_metadata_end_to_end() {
use lightning::events::Event;
- use lightning::ln::channelmanager::{Retry, PaymentId};
+ use lightning::ln::channelmanager::PaymentId;
+ use lightning::ln::outbound_payment::Retry;
use lightning::ln::msgs::ChannelMessageHandler;
use lightning::ln::functional_test_utils::*;
// Test that a payment metadata read from an invoice passed to `pay_invoice` makes it all
use lightning::ln::PaymentHash;
#[cfg(feature = "std")]
use lightning::ln::PaymentPreimage;
- use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields, Retry};
+ use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId};
+ use lightning::ln::outbound_payment::{RecipientOnionFields, Retry};
use lightning::ln::functional_test_utils::*;
use lightning::ln::msgs::ChannelMessageHandler;
use lightning::routing::router::{PaymentParameters, RouteParameters};
+++ /dev/null
-use core::fmt::Debug;
-use core::fmt::Formatter;
-use lightning::ln::msgs::{DecodeError, LightningError};
-
-/// All-encompassing standard error type that processing can return
-pub enum GraphSyncError {
- /// Error trying to read the update data, typically due to an erroneous data length indication
- /// that is greater than the actual amount of data provided
- DecodeError(DecodeError),
- /// Error applying the patch to the network graph, usually the result of updates that are too
- /// old or missing prerequisite data to the application of updates out of order
- LightningError(LightningError),
-}
-
-impl From<lightning::io::Error> for GraphSyncError {
- fn from(error: lightning::io::Error) -> Self {
- Self::DecodeError(DecodeError::Io(error.kind()))
- }
-}
-
-impl From<DecodeError> for GraphSyncError {
- fn from(error: DecodeError) -> Self {
- Self::DecodeError(error)
- }
-}
-
-impl From<LightningError> for GraphSyncError {
- fn from(error: LightningError) -> Self {
- Self::LightningError(error)
- }
-}
-
-impl Debug for GraphSyncError {
- fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
- match self {
- GraphSyncError::DecodeError(e) => f.write_fmt(format_args!("DecodeError: {:?}", e)),
- GraphSyncError::LightningError(e) => f.write_fmt(format_args!("LightningError: {:?}", e))
- }
- }
-}
use core::sync::atomic::{AtomicBool, Ordering};
use lightning::io;
+use lightning::ln::msgs::{DecodeError, LightningError};
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
-pub use crate::error::GraphSyncError;
-
-/// Error types that these functions can return
-mod error;
-
/// Core functionality of this crate
mod processing;
+/// All-encompassing standard error type that processing can return
+#[derive(Debug)]
+pub enum GraphSyncError {
+ /// Error trying to read the update data, typically due to an erroneous data length indication
+ /// that is greater than the actual amount of data provided
+ DecodeError(DecodeError),
+ /// Error applying the patch to the network graph, usually the result of updates that are too
+ /// old or missing prerequisite data to the application of updates out of order
+ LightningError(LightningError),
+}
+
+impl From<lightning::io::Error> for GraphSyncError {
+ fn from(error: lightning::io::Error) -> Self {
+ Self::DecodeError(DecodeError::Io(error.kind()))
+ }
+}
+
+impl From<DecodeError> for GraphSyncError {
+ fn from(error: DecodeError) -> Self {
+ Self::DecodeError(error)
+ }
+}
+
+impl From<LightningError> for GraphSyncError {
+ fn from(error: LightningError) -> Self {
+ Self::LightningError(error)
+ }
+}
+
/// The main Rapid Gossip Sync object.
///
/// See [crate-level documentation] for usage.
use lightning::ln::msgs::DecodeError;
use lightning::routing::gossip::NetworkGraph;
use lightning::util::test_utils::TestLogger;
- use crate::RapidGossipSync;
+ use crate::{GraphSyncError, RapidGossipSync};
#[test]
fn test_sync_from_file() {
let start = std::time::Instant::now();
let sync_result = rapid_sync
.sync_network_graph_with_file_path("./res/full_graph.lngossip");
- if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
+ if let Err(GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-285cb27df79-2022-07-21.bin\n\n{:?}", io_error);
#[cfg(not(require_route_graph_test))]
{
use lightning::util::ser::{BigSize, Readable};
use lightning::io;
-use crate::error::GraphSyncError;
-use crate::RapidGossipSync;
+use crate::{GraphSyncError, RapidGossipSync};
#[cfg(all(feature = "std", not(test)))]
use std::time::{SystemTime, UNIX_EPOCH};
use lightning::routing::gossip::NetworkGraph;
use lightning::util::test_utils::TestLogger;
- use crate::error::GraphSyncError;
use crate::processing::STALE_RGS_UPDATE_AGE_LIMIT_SECS;
- use crate::RapidGossipSync;
+ use crate::{GraphSyncError, RapidGossipSync};
const VALID_RGS_BINARY: [u8; 300] = [
76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
// be in relation to a specific channel.
let htlc_maximum_msat = u64::max_value();
Self::new_for_payment(
- &[], payee_node_id, payee_tlvs, htlc_maximum_msat, entropy_source, secp_ctx
+ Vec::new(), payee_node_id, payee_tlvs, htlc_maximum_msat, entropy_source, secp_ctx
)
}
/// [`ForwardTlvs`]: crate::blinded_path::payment::ForwardTlvs
// TODO: make all payloads the same size with padding + add dummy hops
pub fn new_for_payment<ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification>(
- intermediate_nodes: &[payment::ForwardNode], payee_node_id: PublicKey,
+ intermediate_nodes: Vec<payment::ForwardNode>, payee_node_id: PublicKey,
payee_tlvs: payment::ReceiveTlvs, htlc_maximum_msat: u64, entropy_source: &ES,
secp_ctx: &Secp256k1<T>
) -> Result<(BlindedPayInfo, Self), ()> {
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
- let blinded_payinfo = payment::compute_payinfo(intermediate_nodes, &payee_tlvs, htlc_maximum_msat)?;
+ let blinded_payinfo = payment::compute_payinfo(&intermediate_nodes, &payee_tlvs, htlc_maximum_msat)?;
Ok((blinded_payinfo, BlindedPath {
introduction_node_id: intermediate_nodes.first().map_or(payee_node_id, |n| n.node_id),
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
blinded_hops: payment::blinded_hops(
- secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret
+ secp_ctx, &intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret
).map_err(|_| ())?,
}))
}
pub(super) inner: Mutex<ChannelMonitorImpl<Signer>>,
}
-impl<Signer: WriteableEcdsaChannelSigner> Clone for ChannelMonitor<Signer> where Signer: Clone {
+impl<Signer: WriteableEcdsaChannelSigner> Clone for ChannelMonitor<Signer> {
fn clone(&self) -> Self {
let inner = self.inner.lock().unwrap().clone();
ChannelMonitor::from_impl(inner)
const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)>
- for (BlockHash, ChannelMonitor<SP::EcdsaSigner>) {
+impl<'a, 'b, ES: EntropySource, Signer: WriteableEcdsaChannelSigner, SP: SignerProvider<EcdsaSigner=Signer>> ReadableArgs<(&'a ES, &'b SP)>
+ for (BlockHash, ChannelMonitor<Signer>) {
fn read<R: io::Read>(reader: &mut R, args: (&'a ES, &'b SP)) -> Result<Self, DecodeError> {
macro_rules! unwrap_obj {
($key: expr) => {
}
/// Returns a `Utxo` with the `satisfaction_weight` estimate for a P2WPKH nested in P2SH output.
+ ///
+ /// This is not exported to bindings users as WPubkeyHash is not yet exported
pub fn new_nested_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self {
let script_sig_size = 1 /* script_sig length */ +
1 /* OP_0 */ +
}
/// Returns a `Utxo` with the `satisfaction_weight` estimate for a SegWit v0 P2WPKH output.
+ ///
+ /// This is not exported to bindings users as WPubkeyHash is not yet exported
pub fn new_v0_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self {
Self {
outpoint,
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;
.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) => {
use core::ops::Deref;
// Re-export this for use in the public API.
-pub use crate::ln::outbound_payment::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
+pub(crate) use crate::ln::outbound_payment::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
use crate::ln::script::ShutdownScript;
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
Arc<DefaultRouter<
Arc<NetworkGraph<Arc<L>>>,
Arc<L>,
+ Arc<KeysManager>,
Arc<RwLock<ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>>>,
- ProbabilisticScoringFeeParameters,
- ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>,
>>,
Arc<L>
>;
&'e DefaultRouter<
&'f NetworkGraph<&'g L>,
&'g L,
+ &'c KeysManager,
&'h RwLock<ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>,
- ProbabilisticScoringFeeParameters,
- ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>
>,
&'g L
>;
// 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,
/// [`ChannelUnavailable`]: APIError::ChannelUnavailable
/// [`APIMisuseError`]: APIError::APIMisuseError
pub fn update_partial_channel_config(
- &self, counterparty_node_id: &PublicKey, channel_ids: &[ChannelId], config_update: &ChannelConfigUpdate,
+ &self, counterparty_node_id: &PublicKey, channel_ids: Vec<ChannelId>, 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 {
.ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
let peer_state = &mut *peer_state_lock;
- for channel_id in channel_ids {
+ for channel_id in channel_ids.iter() {
if !peer_state.has_channel(channel_id) {
return Err(APIError::ChannelUnavailable {
err: format!("Channel with id {} not found for the passed counterparty node_id {}", channel_id, counterparty_node_id),
});
};
}
- for channel_id in channel_ids {
+ for channel_id in channel_ids.iter() {
if let Some(channel_phase) = peer_state.channel_by_id.get_mut(channel_id) {
let mut config = channel_phase.context().config();
config.apply(config_update);
/// [`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<ChannelId>, config: &ChannelConfig,
) -> Result<(), APIError> {
return self.update_partial_channel_config(counterparty_node_id, channel_ids, &(*config).into());
}
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
let recipient = self.get_our_node_id();
- let entropy_source = self.entropy_source.deref();
let secp_ctx = &self.secp_ctx;
let peers = self.per_peer_state.read().unwrap()
.collect::<Vec<_>>();
self.router
- .create_blinded_paths(recipient, peers, entropy_source, secp_ctx)
+ .create_blinded_paths(recipient, peers, secp_ctx)
.and_then(|paths| paths.into_iter().next().ok_or(()))
}
fn create_blinded_payment_paths(
&self, amount_msats: u64, payment_secret: PaymentSecret
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
- let entropy_source = self.entropy_source.deref();
let secp_ctx = &self.secp_ctx;
let first_hops = self.list_usable_channels();
},
};
self.router.create_blinded_payment_paths(
- payee_node_id, first_hops, payee_tlvs, amount_msats, entropy_source, secp_ctx
+ payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx
)
}
mark: PhantomData<T>,
}
+/// This is not exported to bindings users but probably should be.
impl<T: sealed::Context, Rhs: Borrow<Self>> core::ops::BitOrAssign<Rhs> for Features<T> {
fn bitor_assign(&mut self, rhs: Rhs) {
let total_feature_len = cmp::max(self.flags.len(), rhs.borrow().flags.len());
}
}
+/// This is not exported to bindings users but probably should be.
impl<T: sealed::Context> core::ops::BitOr for Features<T> {
type Output = Self;
pub use channel_id::ChannelId;
pub(crate) mod onion_utils;
-mod outbound_payment;
+pub mod outbound_payment;
pub mod wire;
pub use onion_utils::create_payment_onion;
}
/// 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<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
match self {
UnsignedGossipMessage::ChannelAnnouncement(ref msg) => msg.write(writer),
}
/// A handler for received [`OnionMessage`]s and for providing generated ones to send.
-pub trait OnionMessageHandler: EventsProvider {
+pub trait OnionMessageHandler {
+ /// Because much of the lightning network does not yet support forwarding onion messages, we
+ /// may need to directly connect to a node which will forward a message for us. In such a case,
+ /// this method will return the set of nodes which need connection by node_id and the
+ /// corresponding socket addresses where they may accept incoming connections.
+ ///
+ /// Thus, this method should be polled regularly to detect messages await such a direct
+ /// connection.
+ fn get_and_clear_connections_needed(&self) -> Vec<(PublicKey, Vec<SocketAddress>)>;
+
/// Handle an incoming `onion_message` message from the given peer.
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
fn processing_queue_high(&self) -> bool { false }
}
impl OnionMessageHandler for IgnoringMessageHandler {
+ fn get_and_clear_connections_needed(&self) -> Vec<(PublicKey, Vec<SocketAddress>)> { Vec::new() }
fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {}
fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option<msgs::OnionMessage> { None }
fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) }
excess_data: Vec::new(),
};
let node_announce_sig = match self.node_signer.sign_gossip_message(
- msgs::UnsignedGossipMessage::NodeAnnouncement(&announcement)
+ msgs::UnsignedGossipMessage::NodeAnnouncement(announcement.clone())
) {
Ok(sig) => sig,
Err(_) => {
fee_proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths,
excess_data: Vec::new(),
};
- let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&contents)).unwrap();
+ let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(contents.clone())).unwrap();
let msg = msgs::ChannelUpdate { signature, contents };
let mut err_data = Vec::new();
/// A Lightning message returned by [`read`] when decoding bytes received over the wire. Each
/// variant contains a message from [`msgs`] or otherwise the message type if unknown.
#[allow(missing_docs)]
-#[derive(Debug)]
+#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq))]
-pub(crate) enum Message<T> where T: core::fmt::Debug + Type + TestEq {
+pub(crate) enum Message<T> where T: Clone + core::fmt::Debug + Type + TestEq {
Init(msgs::Init),
Error(msgs::ErrorMessage),
Warning(msgs::WarningMessage),
/// 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;
}
}
#[cfg(test)]
-impl<T: core::fmt::Debug + Writeable + PartialEq> Type for T where T: Encode {
+impl<T: core::fmt::Debug + Writeable + Clone + PartialEq> Type for T where T: Encode {
fn type_id(&self) -> u16 { T::TYPE }
}
#[cfg(not(test))]
-impl<T: core::fmt::Debug + Writeable> Type for T where T: Encode {
+impl<T: core::fmt::Debug + Writeable + Clone> Type for T where T: Encode {
fn type_id(&self) -> u16 { T::TYPE }
}
}
}
- #[derive(Eq, PartialEq, Debug)]
+ #[derive(Clone, Eq, PartialEq, Debug)]
struct TestCustomMessage {}
const CUSTOM_MESSAGE_TYPE : u16 = 9000;
///
/// Successive calls to this method will add another address. Caller is responsible for not
/// adding duplicate addresses and only calling if capable of receiving to P2TR addresses.
+ ///
+ /// This is not exported to bindings users as TweakedPublicKey isn't yet mapped.
pub fn fallback_v1_p2tr_tweaked(mut self, output_key: &TweakedPublicKey) -> Self {
let address = FallbackAddress {
version: WitnessVersion::V1.to_num(),
/// Note: The hash computation may have included unknown, odd TLV records.
///
/// This is not exported to bindings users as functions aren't currently mapped.
- pub fn sign<F, E>(mut self, sign: F) -> Result<Bolt12Invoice, SignError<E>>
+ pub(crate) fn sign<F, E>(mut self, sign: F) -> Result<Bolt12Invoice, SignError<E>>
where
F: FnOnce(&Self) -> Result<Signature, E>
{
/// Fallback addresses for paying the invoice on-chain, in order of most-preferred to
/// least-preferred.
+ ///
+ /// This is not exported to bindings users as Address is not yet mapped
pub fn fallbacks(&$self) -> Vec<Address> {
$contents.fallbacks()
}
/// Note: The hash computation may have included unknown, odd TLV records.
///
/// This is not exported to bindings users as functions are not yet mapped.
- pub fn sign<F, E>(mut self, sign: F) -> Result<InvoiceRequest, SignError<E>>
+ pub(crate) fn sign<F, E>(mut self, sign: F) -> Result<InvoiceRequest, SignError<E>>
where
F: FnOnce(&Self) -> Result<Signature, E>
{
/// Error when signing messages.
#[derive(Debug, PartialEq)]
-pub enum SignError<E> {
+pub(crate) enum SignError<E> {
/// User-defined error when signing the message.
Signing(E),
/// Error when verifying the produced signature using the given pubkey.
/// An amount of currency specified using ISO 4712.
Currency {
/// The currency that the amount is denominated in.
+ ///
+ /// This is not exported to bindings users as bindings have troubles with type aliases to
+ /// byte arrays.
iso4217_code: CurrencyCode,
/// The amount in the currency unit adjusted by the ISO 4712 exponent (e.g., USD cents).
amount: u64,
}
/// An ISO 4712 three-letter currency code (e.g., USD).
-pub type CurrencyCode = [u8; 3];
+pub(crate) type CurrencyCode = [u8; 3];
/// Quantity of items supported by an [`Offer`].
#[derive(Clone, Copy, Debug, PartialEq)]
///
/// May be used with `NonZeroU64::new(1)` but prefer to use [`Quantity::One`] if only one item
/// is supported.
- Bounded(NonZeroU64),
+ Bounded(/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ NonZeroU64),
/// One or more items. Use when more than one item can be requested without any limit.
Unbounded,
/// Only one item. Use when only a single item can be requested.
/// being parsed.
InvalidBech32Hrp,
/// The string could not be bech32 decoded.
- Bech32(bech32::Error),
+ Bech32(/// This is not exported to bindings users as the details don't matter much
+ bech32::Error),
/// The bech32 decoded string could not be decoded as the expected message type.
Decode(DecodeError),
/// The parsed message has invalid semantics.
use crate::prelude::*;
+use core::ops::Deref;
+
struct MessengerNode {
node_id: PublicKey,
entropy_source: Arc<test_utils::TestKeysInterface>,
}
fn create_blinded_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ T: secp256k1::Signing + secp256k1::Verification
>(
- &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _entropy_source: &ES,
- _secp_ctx: &Secp256k1<T>
+ &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
unreachable!()
}
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 {
/// # first_node_addresses: None,
/// # })
/// # }
-/// # fn create_blinded_paths<ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification>(
-/// # &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _entropy_source: &ES, _secp_ctx: &Secp256k1<T>
+/// # fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
+/// # &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>
/// # ) -> Result<Vec<BlindedPath>, ()> {
/// # unreachable!()
/// # }
/// &keys_manager, &keys_manager, logger, message_router, &offers_message_handler,
/// &custom_message_handler
/// );
-
-/// # #[derive(Debug)]
+///
+/// # #[derive(Debug, Clone)]
/// # struct YourCustomMessage {}
/// impl Writeable for YourCustomMessage {
/// fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
/// Creates [`BlindedPath`]s to the `recipient` node. The nodes in `peers` are assumed to be
/// direct peers with the `recipient`.
fn create_blinded_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, entropy_source: &ES,
- secp_ctx: &Secp256k1<T>
+ &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()>;
}
/// A [`MessageRouter`] that can only route to a directly connected [`Destination`].
-pub struct DefaultMessageRouter<G: Deref<Target=NetworkGraph<L>>, L: Deref>
+pub struct DefaultMessageRouter<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref>
where
L::Target: Logger,
+ ES::Target: EntropySource,
{
network_graph: G,
+ entropy_source: ES,
}
-impl<G: Deref<Target=NetworkGraph<L>>, L: Deref> DefaultMessageRouter<G, L>
+impl<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref> DefaultMessageRouter<G, L, ES>
where
L::Target: Logger,
+ ES::Target: EntropySource,
{
/// Creates a [`DefaultMessageRouter`] using the given [`NetworkGraph`].
- pub fn new(network_graph: G) -> Self {
- Self { network_graph }
+ pub fn new(network_graph: G, entropy_source: ES) -> Self {
+ Self { network_graph, entropy_source }
}
}
-impl<G: Deref<Target=NetworkGraph<L>>, L: Deref> MessageRouter for DefaultMessageRouter<G, L>
+impl<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref> DefaultMessageRouter<G, L, ES>
where
L::Target: Logger,
+ ES::Target: EntropySource,
{
- fn find_path(
- &self, _sender: PublicKey, peers: Vec<PublicKey>, destination: Destination
+ pub(crate) fn find_path(
+ network_graph: &G, _sender: PublicKey, peers: Vec<PublicKey>, destination: Destination
) -> Result<OnionMessagePath, ()> {
let first_node = destination.first_node();
if peers.contains(&first_node) {
intermediate_nodes: vec![], destination, first_node_addresses: None
})
} else {
- let network_graph = self.network_graph.deref().read_only();
+ let network_graph = network_graph.deref().read_only();
let node_announcement = network_graph
.node(&NodeId::from_pubkey(&first_node))
.and_then(|node_info| node_info.announcement_info.as_ref())
}
}
- fn create_blinded_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ pub(crate) fn create_blinded_paths<
+ T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, entropy_source: &ES,
- secp_ctx: &Secp256k1<T>
+ network_graph: &G, recipient: PublicKey, peers: Vec<PublicKey>, entropy_source: &ES,
+ secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
// Limit the number of blinded paths that are computed.
const MAX_PATHS: usize = 3;
// recipient's node_id.
const MIN_PEER_CHANNELS: usize = 3;
- let network_graph = self.network_graph.deref().read_only();
+ let network_graph = network_graph.deref().read_only();
let paths = peers.iter()
// Limit to peers with announced channels
.filter(|pubkey|
.unwrap_or(false)
)
.map(|pubkey| vec![*pubkey, recipient])
- .map(|node_pks| BlindedPath::new_for_message(&node_pks, entropy_source, secp_ctx))
+ .map(|node_pks| BlindedPath::new_for_message(&node_pks, &**entropy_source, secp_ctx))
.take(MAX_PATHS)
.collect::<Result<Vec<_>, _>>();
Ok(paths) if !paths.is_empty() => Ok(paths),
_ => {
if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) {
- BlindedPath::one_hop_for_message(recipient, entropy_source, secp_ctx)
+ BlindedPath::one_hop_for_message(recipient, &**entropy_source, secp_ctx)
.map(|path| vec![path])
} else {
Err(())
}
}
+impl<G: Deref<Target=NetworkGraph<L>>, L: Deref, ES: Deref> MessageRouter for DefaultMessageRouter<G, L, ES>
+where
+ L::Target: Logger,
+ ES::Target: EntropySource,
+{
+ fn find_path(
+ &self, sender: PublicKey, peers: Vec<PublicKey>, destination: Destination
+ ) -> Result<OnionMessagePath, ()> {
+ Self::find_path(&self.network_graph, sender, peers, destination)
+ }
+
+ fn create_blinded_paths<
+ T: secp256k1::Signing + secp256k1::Verification
+ >(
+ &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+ ) -> Result<Vec<BlindedPath>, ()> {
+ Self::create_blinded_paths(&self.network_graph, recipient, peers, &self.entropy_source, secp_ctx)
+ }
+}
+
/// A path for sending an [`OnionMessage`].
#[derive(Clone)]
pub struct OnionMessagePath {
false
}
-impl<ES: Deref, NS: Deref, L: Deref, MR: Deref, OMH: Deref, CMH: Deref> EventsProvider
+impl<ES: Deref, NS: Deref, L: Deref, MR: Deref, OMH: Deref, CMH: Deref> OnionMessageHandler
for OnionMessenger<ES, NS, L, MR, OMH, CMH>
where
ES::Target: EntropySource,
OMH::Target: OffersMessageHandler,
CMH::Target: CustomOnionMessageHandler,
{
- fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler {
+ fn get_and_clear_connections_needed(&self) -> Vec<(PublicKey, Vec<SocketAddress>)> {
+ let mut res = Vec::new();
for (node_id, recipient) in self.message_recipients.lock().unwrap().iter_mut() {
if let OnionMessageRecipient::PendingConnection(_, addresses, _) = recipient {
if let Some(addresses) = addresses.take() {
- handler.handle_event(Event::ConnectionNeeded { node_id: *node_id, addresses });
+ res.push((*node_id, addresses));
}
}
}
+ res
}
-}
-impl<ES: Deref, NS: Deref, L: Deref, MR: Deref, OMH: Deref, CMH: Deref> OnionMessageHandler
-for OnionMessenger<ES, NS, L, MR, OMH, CMH>
-where
- ES::Target: EntropySource,
- NS::Target: NodeSigner,
- L::Target: Logger,
- MR::Target: MessageRouter,
- OMH::Target: OffersMessageHandler,
- CMH::Target: CustomOnionMessageHandler,
-{
fn handle_onion_message(&self, _peer_node_id: &PublicKey, msg: &OnionMessage) {
match peel_onion_message(
msg, &self.secp_ctx, &*self.node_signer, &*self.logger, &*self.custom_handler
Arc<KeysManager>,
Arc<KeysManager>,
Arc<L>,
- Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<L>>>, Arc<L>>>,
+ Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<L>>>, Arc<L>, Arc<KeysManager>>>,
Arc<SimpleArcChannelManager<M, T, F, L>>,
IgnoringMessageHandler
>;
&'a KeysManager,
&'a KeysManager,
&'b L,
- &'i DefaultMessageRouter<&'g NetworkGraph<&'b L>, &'b L>,
+ &'i DefaultMessageRouter<&'g NetworkGraph<&'b L>, &'b L, &'a KeysManager>,
&'j SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>,
IgnoringMessageHandler
>;
/// The contents of an [`OnionMessage`] as read from the wire.
///
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
-#[derive(Debug)]
+#[derive(Clone, Debug)]
pub enum ParsedOnionMessageContents<T: OnionMessageContents> {
/// A message related to BOLT 12 Offers.
Offers(OffersMessage),
}
/// 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;
}
}
/// 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
}
impl ChannelInfo {
/// Returns a [`DirectedChannelInfo`] for the channel directed to the given `target` from a
/// returned `source`, or `None` if `target` is not one of the channel's counterparties.
- pub fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
+ pub(crate) fn as_directed_to(&self, target: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
let (direction, source, outbound) = {
if target == &self.node_one {
(self.two_to_one.as_ref(), &self.node_two, false)
/// Returns a [`DirectedChannelInfo`] for the channel directed from the given `source` to a
/// returned `target`, or `None` if `source` is not one of the channel's counterparties.
- pub fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
+ pub(crate) fn as_directed_from(&self, source: &NodeId) -> Option<(DirectedChannelInfo, &NodeId)> {
let (direction, target, outbound) = {
if source == &self.node_one {
(self.one_to_two.as_ref(), &self.node_two, true)
//! The router finds paths within a [`NetworkGraph`] for a payment.
use bitcoin::secp256k1::{PublicKey, Secp256k1, self};
-use bitcoin::hashes::Hash;
-use bitcoin::hashes::sha256::Hash as Sha256;
use crate::blinded_path::{BlindedHop, BlindedPath};
use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs};
use crate::io;
use crate::prelude::*;
-use crate::sync::Mutex;
use alloc::collections::BinaryHeap;
use core::{cmp, fmt};
use core::ops::Deref;
/// A [`Router`] implemented using [`find_route`].
-pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> where
+pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref> where
L::Target: Logger,
- S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
+ S::Target: for <'a> LockableScore<'a>,
+ ES::Target: EntropySource,
{
network_graph: G,
logger: L,
- random_seed_bytes: Mutex<[u8; 32]>,
+ entropy_source: ES,
scorer: S,
- score_params: SP,
- message_router: DefaultMessageRouter<G, L>,
+ score_params: crate::routing::scoring::ProbabilisticScoringFeeParameters,
}
-impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> DefaultRouter<G, L, S, SP, Sc> where
+impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref> DefaultRouter<G, L, ES, S> 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, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self {
- let random_seed_bytes = Mutex::new(random_seed_bytes);
- let message_router = DefaultMessageRouter::new(network_graph.clone());
- Self { network_graph, logger, random_seed_bytes, scorer, score_params, message_router }
+ pub fn new(network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: crate::routing::scoring::ProbabilisticScoringFeeParameters) -> Self {
+ Self { network_graph, logger, entropy_source, scorer, score_params }
}
}
-impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> Router for DefaultRouter<G, L, S, SP, Sc> where
+impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref> Router for DefaultRouter<G, L, ES, S> where
L::Target: Logger,
- S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
+ S::Target: for <'a> LockableScore<'a>,
+ ES::Target: EntropySource,
{
fn find_route(
&self,
first_hops: Option<&[&ChannelDetails]>,
inflight_htlcs: InFlightHtlcs
) -> Result<Route, LightningError> {
- let random_seed_bytes = {
- let mut locked_random_seed_bytes = self.random_seed_bytes.lock().unwrap();
- *locked_random_seed_bytes = Sha256::hash(&*locked_random_seed_bytes).to_byte_array();
- *locked_random_seed_bytes
- };
+ let random_seed_bytes = self.entropy_source.get_secure_random_bytes();
find_route(
payer, params, &self.network_graph, first_hops, &*self.logger,
&ScorerAccountingForInFlightHtlcs::new(self.scorer.read_lock(), &inflight_htlcs),
}
fn create_blinded_payment_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
- >(
+ T: secp256k1::Signing + secp256k1::Verification
+ > (
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
- amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1<T>
+ amount_msats: u64, secp_ctx: &Secp256k1<T>
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
// Limit the number of blinded paths that are computed.
const MAX_PAYMENT_PATHS: usize = 3;
})
.map(|forward_node| {
BlindedPath::new_for_payment(
- &[forward_node], recipient, tlvs.clone(), u64::MAX, entropy_source, secp_ctx
+ vec![forward_node], recipient, tlvs.clone(), u64::MAX, &*self.entropy_source, secp_ctx
)
})
.take(MAX_PAYMENT_PATHS)
Ok(paths) if !paths.is_empty() => Ok(paths),
_ => {
if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) {
- BlindedPath::one_hop_for_payment(recipient, tlvs, entropy_source, secp_ctx)
+ BlindedPath::one_hop_for_payment(recipient, tlvs, &*self.entropy_source, secp_ctx)
.map(|path| vec![path])
} else {
Err(())
}
}
-impl< G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> MessageRouter for DefaultRouter<G, L, S, SP, Sc> where
+impl< G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref> MessageRouter for DefaultRouter<G, L, ES, S> where
L::Target: Logger,
- S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
+ S::Target: for <'a> LockableScore<'a>,
+ ES::Target: EntropySource,
{
fn find_path(
&self, sender: PublicKey, peers: Vec<PublicKey>, destination: Destination
) -> Result<OnionMessagePath, ()> {
- self.message_router.find_path(sender, peers, destination)
+ DefaultMessageRouter::<_, _, ES>::find_path(&self.network_graph, sender, peers, destination)
}
fn create_blinded_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
- >(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, entropy_source: &ES,
- secp_ctx: &Secp256k1<T>
+ T: secp256k1::Signing + secp256k1::Verification
+ > (
+ &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.message_router.create_blinded_paths(recipient, peers, entropy_source, secp_ctx)
+ DefaultMessageRouter::create_blinded_paths(&self.network_graph, recipient, peers, &self.entropy_source, secp_ctx)
}
}
/// are assumed to be with the `recipient`'s peers. The payment secret and any constraints are
/// given in `tlvs`.
fn create_blinded_payment_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
- >(
+ T: secp256k1::Signing + secp256k1::Verification
+ > (
&self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
- amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1<T>
+ amount_msats: u64, secp_ctx: &Secp256k1<T>
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()>;
}
}
impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp {
+ #[cfg(not(c_bindings))]
type ScoreParams = <S::Target as ScoreLookUp>::ScoreParams;
- fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 {
let target = match candidate.target() {
Some(target) => target,
None => return self.scorer.channel_penalty_msat(candidate, usage, score_params),
/// has been funded and is able to pay), and accessor methods may panic otherwise.
///
/// [`find_route`] validates this prior to constructing a [`CandidateRouteHop`].
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub details: &'a ChannelDetails,
/// The node id of the payer, which is also the source side of this candidate route hop.
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub payer_node_id: &'a NodeId,
}
pub struct PublicHopCandidate<'a> {
/// Information about the channel, including potentially its capacity and
/// direction-specific information.
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub info: DirectedChannelInfo<'a>,
/// The short channel ID of the channel, i.e. the identifier by which we refer to this
/// channel.
#[derive(Clone, Debug)]
pub struct PrivateHopCandidate<'a> {
/// Information about the private hop communicated via BOLT 11.
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub hint: &'a RouteHintHop,
/// Node id of the next hop in BOLT 11 route hint.
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub target_node_id: &'a NodeId
}
pub struct BlindedPathCandidate<'a> {
/// Information about the blinded path including the fee, HTLC amount limits, and
/// cryptographic material required to build an HTLC through the given path.
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub hint: &'a (BlindedPayInfo, BlindedPath),
/// Index of the hint in the original list of blinded hints.
///
/// cryptographic material required to build an HTLC terminating with the given path.
///
/// Note that the [`BlindedPayInfo`] is ignored here.
+ ///
+ /// This is not exported to bindings users as lifetimes are not expressable in most languages.
pub hint: &'a (BlindedPayInfo, BlindedPath),
/// Index of the hint in the original list of blinded hints.
///
pub fn find_route<L: Deref, GL: Deref, S: ScoreLookUp>(
our_node_pubkey: &PublicKey, route_params: &RouteParameters,
network_graph: &NetworkGraph<GL>, 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<Route, LightningError>
where L::Target: Logger, GL::Target: Logger {
let graph_lock = network_graph.read_only();
pub(crate) fn get_route<L: Deref, S: ScoreLookUp>(
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<Route, LightningError>
where L::Target: Logger {
}
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() {
fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() }
}
impl ScoreLookUp for BadChannelScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
- fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 {
if candidate.short_channel_id() == Some(self.short_channel_id) { u64::max_value() } else { 0 }
}
}
}
impl ScoreLookUp for BadNodeScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
- fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 {
if candidate.target() == Some(self.node_id) { u64::max_value() } else { 0 }
}
}
}
pub(crate) fn generate_test_routes<S: ScoreLookUp + ScoreUpdate>(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();
fn generate_routes<S: ScoreLookUp + ScoreUpdate>(
bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
- score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, starting_amount: u64,
+ score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters, features: Bolt11InvoiceFeatures, starting_amount: u64,
bench_name: &'static str,
) {
let payer = bench_utils::payer_pubkey();
///
/// 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`.
/// [`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;
}
#[cfg(not(c_bindings))]
impl<S: ScoreLookUp, T: Deref<Target=S>> 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)
}
#[cfg(c_bindings)]
impl<'a, T: Score> ScoreLookUp for MultiThreadedScoreLockRead<'a, T> {
+ #[cfg(not(c_bindings))]
type ScoreParams = T::ScoreParams;
- fn channel_penalty_msat(&self, candidate:&CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams
+ fn channel_penalty_msat(&self, candidate:&CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters
) -> u64 {
self.0.channel_penalty_msat(candidate, usage, score_params)
}
}
impl ScoreLookUp for FixedPenaltyScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
- fn channel_penalty_msat(&self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &ProbabilisticScoringFeeParameters) -> u64 {
self.penalty_msat
}
}
}
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref> ScoreLookUp for ProbabilisticScorer<G, L> where L::Target: Logger {
+ #[cfg(not(c_bindings))]
type ScoreParams = ProbabilisticScoringFeeParameters;
fn channel_penalty_msat(
&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters
///
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
/// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
-pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable {}
+pub trait WriteableEcdsaChannelSigner: EcdsaChannelSigner + Writeable + Clone {}
}
}
+macro_rules! impl_record {
+ ($($args: lifetime)?, $($nonstruct_args: lifetime)?) => {
/// A Record, unit of logging output with Metadata to enable filtering
/// Module_path, file, line to inform on log's source
#[derive(Clone, Debug)]
-pub struct Record<'a> {
+pub struct Record<$($args)?> {
/// The verbosity level of the message.
pub level: Level,
/// The node id of the peer pertaining to the logged record.
pub file: &'static str,
/// The line containing the message.
pub line: u32,
-
- #[cfg(c_bindings)]
- /// We don't actually use the lifetime parameter in C bindings (as there is no good way to
- /// communicate a lifetime to a C, or worse, Java user).
- _phantom: core::marker::PhantomData<&'a ()>,
}
-impl<'a> Record<'a> {
+impl<$($args)?> Record<$($args)?> {
/// Returns a new Record.
///
/// This is not exported to bindings users as fmt can't be used in C
#[inline]
- pub fn new(
+ pub fn new<$($nonstruct_args)?>(
level: Level, peer_id: Option<PublicKey>, channel_id: Option<ChannelId>,
args: fmt::Arguments<'a>, module_path: &'static str, file: &'static str, line: u32
- ) -> Record<'a> {
+ ) -> Record<$($args)?> {
Record {
level,
peer_id,
module_path,
file,
line,
- #[cfg(c_bindings)]
- _phantom: core::marker::PhantomData,
}
}
}
+} }
+#[cfg(not(c_bindings))]
+impl_record!('a, );
+#[cfg(c_bindings)]
+impl_record!(, 'a);
/// A trait encapsulating the operations required of a logger.
pub trait Logger {
}
/// Adds relevant context to a [`Record`] before passing it to the wrapped [`Logger`].
+///
+/// This is not exported to bindings users as lifetimes are problematic and there's little reason
+/// for this to be used downstream anyway.
pub struct WithContext<'a, L: Deref> where L::Target: Logger {
/// The logger to delegate to after adding context to the record.
logger: &'a L,
use crate::prelude::*;
use core::cell::RefCell;
use core::time::Duration;
+use core::ops::Deref;
use crate::sync::{Mutex, Arc};
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::mem;
details: first_hops[idx],
payer_node_id: &node_id,
});
- scorer.channel_penalty_msat(&candidate, usage, &());
+ scorer.channel_penalty_msat(&candidate, usage, &Default::default());
continue;
}
}
info: directed,
short_channel_id: hop.short_channel_id,
});
- scorer.channel_penalty_msat(&candidate, usage, &());
+ scorer.channel_penalty_msat(&candidate, usage, &Default::default());
} else {
let target_node_id = NodeId::from_pubkey(&hop.pubkey);
let route_hint = RouteHintHop {
hint: &route_hint,
target_node_id: &target_node_id,
});
- scorer.channel_penalty_msat(&candidate, usage, &());
+ scorer.channel_penalty_msat(&candidate, usage, &Default::default());
}
prev_hop_node = &hop.pubkey;
}
}
fn create_blinded_payment_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ T: secp256k1::Signing + secp256k1::Verification
>(
&self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
- _amount_msats: u64, _entropy_source: &ES, _secp_ctx: &Secp256k1<T>
+ _amount_msats: u64, _secp_ctx: &Secp256k1<T>
) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
unreachable!()
}
}
fn create_blinded_paths<
- ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification
+ T: secp256k1::Signing + secp256k1::Verification
>(
- &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _entropy_source: &ES,
- _secp_ctx: &Secp256k1<T>
+ &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
unreachable!()
}
}
impl ScoreLookUp for TestScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
fn channel_penalty_msat(
- &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &Self::ScoreParams
+ &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters
) -> u64 {
let short_channel_id = match candidate.globally_unique_short_channel_id() {
Some(scid) => scid,