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;
use lightning::util::test_channel_signer::TestChannelSigner;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, Writeable, Writer};
-use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessagePath, OnionMessenger};
+use lightning::onion_message::messenger::{CustomOnionMessageHandler, MessageRouter, OnionMessenger, Destination, OnionMessagePath};
+use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler};
+use lightning::onion_message::packet::CustomOnionMessageContents;
use crate::utils::test_logger;
fn disconnect_socket(&mut self) {}
}
+ #[cfg(not(c_bindings))]
type ChannelManager =
channelmanager::ChannelManager<
Arc<ChainMonitor>,
Arc<DefaultRouter<
Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
Arc<test_utils::TestLogger>,
- Arc<Mutex<TestScorer>>,
- (),
- TestScorer>
+ Arc<Mutex<TestScorer>>>
+ >,
+ Arc<test_utils::TestLogger>>;
+ #[cfg(c_bindings)]
+ type ChannelManager =
+ channelmanager::ChannelManager<
+ Arc<ChainMonitor>,
+ Arc<test_utils::TestBroadcaster>,
+ Arc<KeysManager>,
+ Arc<KeysManager>,
+ Arc<KeysManager>,
+ Arc<test_utils::TestFeeEstimator>,
+ Arc<DefaultRouter<
+ Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
+ Arc<test_utils::TestLogger>,
+ Arc<Mutex<TestScorer>>>
>,
Arc<test_utils::TestLogger>>;
}
impl ScoreLookUp for TestScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
fn channel_penalty_msat(
- &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage, _score_params: &Self::ScoreParams
+ &self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage, _score_params: &lightning::routing::scoring::ProbabilisticScoringFeeParameters
) -> u64 { unimplemented!(); }
}
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use lightning::sign::{NodeSigner, SignerProvider, EntropySource};
use lightning::ln::PaymentHash;
-use lightning::ln::channelmanager::{AChannelManager, ChannelManager, PaymentId, Retry, RetryableSendFailure, RecipientOnionFields, ProbeSendFailure};
+use lightning::ln::channelmanager::{AChannelManager, ChannelManager, PaymentId};
+use lightning::ln::outbound_payment::{ProbeSendFailure, RecipientOnionFields, RetryableSendFailure, Retry};
use lightning::routing::router::{PaymentParameters, RouteParameters, Router};
use lightning::util::logger::Logger;
use lightning::sign::PhantomKeysManager;
use lightning::events::{MessageSendEvent, MessageSendEventsProvider, Event, EventsProvider};
use lightning::ln::{PaymentPreimage, PaymentHash};
- 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};
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
-pub use crate::error::GraphSyncError;
+use crate::error::GraphSyncError;
/// Error types that these functions can return
-mod error;
+pub mod error;
/// Core functionality of this crate
mod processing;
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::Signer>) {
+impl<'a, 'b, ES: EntropySource, SP: SignerProvider<Signer=Signer>, Signer: WriteableEcdsaChannelSigner> 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:
/// or, respectively, [`Router`] for its router, but this type alias chooses the concrete types
/// of [`KeysManager`] and [`DefaultRouter`].
///
-/// This is not exported to bindings users as Arcs don't make sense in bindings
+/// This is not exported to bindings users as type aliases aren't supported in most languages
+#[cfg(not(c_bindings))]
pub type SimpleArcChannelManager<M, T, F, L> = ChannelManager<
Arc<M>,
Arc<T>,
Arc<NetworkGraph<Arc<L>>>,
Arc<L>,
Arc<RwLock<ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>>>,
- ProbabilisticScoringFeeParameters,
- ProbabilisticScorer<Arc<NetworkGraph<Arc<L>>>, Arc<L>>,
>>,
Arc<L>
>;
/// or, respectively, [`Router`] for its router, but this type alias chooses the concrete types
/// of [`KeysManager`] and [`DefaultRouter`].
///
-/// This is not exported to bindings users as Arcs don't make sense in bindings
+/// This is not exported to bindings users as type aliases aren't supported in most languages
+#[cfg(not(c_bindings))]
pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> =
ChannelManager<
&'a M,
&'f NetworkGraph<&'g L>,
&'g L,
&'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 {} was 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());
}
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;
// Older rustc (which we support) refuses to let us call the get_payment_preimage_hash!() macro
}
/// 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),
use crate::ln::features::{InitFeatures, NodeFeatures};
use crate::ln::msgs;
use crate::ln::msgs::{ChannelMessageHandler, LightningError, SocketAddress, OnionMessageHandler, RoutingMessageHandler};
+#[cfg(not(c_bindings))]
use crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager};
use crate::util::ser::{VecWriter, Writeable, Writer};
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
use crate::ln::wire;
use crate::ln::wire::{Encode, Type};
-use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+use crate::onion_message::packet::CustomOnionMessageContents;
+use crate::onion_message::{CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias};
use crate::util::atomic_counter::AtomicCounter;
use crate::util::logger::Logger;
/// SimpleRefPeerManager is the more appropriate type. Defining these type aliases prevents
/// issues such as overly long function definitions.
///
-/// This is not exported to bindings users as `Arc`s don't make sense in bindings.
+/// This is not exported to bindings users as type aliases aren't supported in most languages.
+#[cfg(not(c_bindings))]
pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<
SD,
Arc<SimpleArcChannelManager<M, T, F, L>>,
/// But if this is not necessary, using a reference is more efficient. Defining these type aliases
/// helps with issues such as long function definitions.
///
-/// This is not exported to bindings users as general type aliases don't make sense in bindings.
+/// This is not exported to bindings users as type aliases aren't supported in most languages.
+#[cfg(not(c_bindings))]
pub type SimpleRefPeerManager<
'a, 'b, 'c, 'd, 'e, 'f, 'logger, 'h, 'i, 'j, 'graph, SD, M, T, F, C, L
> = PeerManager<
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>
{
}
/// Returns the digest to sign.
- pub fn as_digest(&self) -> &Message {
+ pub(crate) fn as_digest(&self) -> &Message {
&self.0
}
}
/// 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.
fn invalid_custom_message_type() {
let nodes = create_nodes(2);
+ #[derive(Clone)]
struct InvalidCustomMessage{}
impl CustomOnionMessageContents for InvalidCustomMessage {
fn tlv_type(&self) -> u64 {
use crate::ln::msgs::{self, OnionMessageHandler};
use crate::ln::onion_utils;
use crate::ln::peer_handler::IgnoringMessageHandler;
-pub use super::packet::{CustomOnionMessageContents, OnionMessageContents};
+pub(crate) use super::packet::{CustomOnionMessageContents, OnionMessageContents};
use super::offers::OffersMessageHandler;
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
use crate::util::logger::Logger;
/// # use lightning::blinded_path::BlindedPath;
/// # use lightning::sign::KeysManager;
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
-/// # use lightning::onion_message::{CustomOnionMessageContents, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger};
+/// # use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessenger, OnionMessagePath};
+/// # use lightning::onion_message::packet::{CustomOnionMessageContents, OnionMessageContents};
/// # use lightning::util::logger::{Logger, Record};
/// # use lightning::util::ser::{Writeable, Writer};
/// # use lightning::io;
/// &custom_message_handler
/// );
///
+/// # #[derive(Clone)]
/// # struct YourCustomMessage {}
/// impl Writeable for YourCustomMessage {
/// fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
//! [offers]: <https://github.com/lightning/bolts/pull/798>
//! [blinded paths]: crate::blinded_path::BlindedPath
-mod messenger;
-mod offers;
-mod packet;
+pub mod messenger;
+pub mod offers;
+pub mod packet;
#[cfg(test)]
mod functional_tests;
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
-pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
-pub use self::offers::{OffersMessage, OffersMessageHandler};
-pub use self::packet::Packet;
-pub(crate) use self::packet::ControlTlvs;
+pub(crate) use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+pub(crate) use self::offers::{OffersMessage, OffersMessageHandler};
+pub(crate) use self::packet::{ControlTlvs, Packet};
}
}
-#[derive(Debug)]
+#[derive(Clone, Debug)]
/// The contents of an onion message. In the context of offers, this would be the invoice, invoice
/// request, or invoice error.
pub enum OnionMessageContents<T: CustomOnionMessageContents> {
}
/// The contents of a custom onion message.
-pub trait CustomOnionMessageContents: Writeable {
+pub trait CustomOnionMessageContents: Writeable + Clone {
/// Returns the TLV type identifying the message contents. MUST be >= 64.
fn tlv_type(&self) -> u64;
}
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) = {
if target == &self.node_one {
(self.two_to_one.as_ref(), &self.node_two)
/// 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) = {
if source == &self.node_one {
(self.one_to_two.as_ref(), &self.node_two)
use core::ops::Deref;
/// A [`Router`] implemented using [`find_route`].
-pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp<ScoreParams = SP>> where
+pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> where
L::Target: Logger,
- S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
+ S::Target: for <'a> LockableScore<'a>,
{
network_graph: G,
logger: L,
random_seed_bytes: Mutex<[u8; 32]>,
scorer: S,
- score_params: SP
+ score_params: crate::routing::scoring::ProbabilisticScoringFeeParameters,
}
-impl<G: Deref<Target = NetworkGraph<L>>, 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, S: Deref> DefaultRouter<G, L, S> where
L::Target: Logger,
- S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
+ S::Target: for <'a> LockableScore<'a>,
{
/// Creates a new router.
- pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self {
+ pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: crate::routing::scoring::ProbabilisticScoringFeeParameters) -> Self {
let random_seed_bytes = Mutex::new(random_seed_bytes);
Self { network_graph, logger, random_seed_bytes, scorer, score_params }
}
}
-impl< G: Deref<Target = NetworkGraph<L>>, 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, S: Deref> Router for DefaultRouter<G, L, S> where
L::Target: Logger,
- S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>,
+ S::Target: for <'a> LockableScore<'a>,
{
fn find_route(
&self,
}
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, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 {
if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat(
source, target, short_channel_id
) {
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, _short_channel_id: u64, source: &NodeId, target: &NodeId,
- _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, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 {
if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 }
}
}
}
impl ScoreLookUp for BadNodeScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
- fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters) -> u64 {
if *target == 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, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams
+ &self, short_channel_id: u64, source: &NodeId, target: &NodeId, 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, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams
+ &self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters
) -> u64 {
self.deref().channel_penalty_msat(short_channel_id, source, target, 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, short_channel_id: u64, source: &NodeId,
- target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams
+ target: &NodeId, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters
) -> u64 {
self.0.channel_penalty_msat(short_channel_id, source, target, usage, score_params)
}
}
impl ScoreLookUp for FixedPenaltyScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
- fn channel_penalty_msat(&self, _: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 {
+ fn channel_penalty_msat(&self, _: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params: &ProbabilisticScoringFeeParameters) -> u64 {
self.penalty_msat
}
}
}
#[cfg(not(feature = "no-std"))]
-type ConfiguredTime = crate::util::time::MonotonicTime;
-#[cfg(feature = "no-std")]
-use crate::util::time::Eternity;
-#[cfg(feature = "no-std")]
-type ConfiguredTime = Eternity;
+/// [`ScoreLookUp`] implementation using channel success probability distributions.
+///
+/// Channels are tracked with upper and lower liquidity bounds - when an HTLC fails at a channel,
+/// we learn that the upper-bound on the available liquidity is lower than the amount of the HTLC.
+/// When a payment is forwarded through a channel (but fails later in the route), we learn the
+/// lower-bound on the channel's available liquidity must be at least the value of the HTLC.
+///
+/// These bounds are then used to determine a success probability using the formula from
+/// *Optimally Reliable & Cheap Payment Flows on the Lightning Network* by Rene Pickhardt
+/// and Stefan Richter [[1]] (i.e. `(upper_bound - payment_amount) / (upper_bound - lower_bound)`).
+///6762, 1070
+/// This probability is combined with the [`liquidity_penalty_multiplier_msat`] and
+/// [`liquidity_penalty_amount_multiplier_msat`] parameters to calculate a concrete penalty in
+/// milli-satoshis. The penalties, when added across all hops, have the property of being linear in
+/// terms of the entire path's success probability. This allows the router to directly compare
+/// penalties for different paths. See the documentation of those parameters for the exact formulas.
+///
+/// The liquidity bounds are decayed by halving them every [`liquidity_offset_half_life`].
+///
+/// Further, we track the history of our upper and lower liquidity bounds for each channel,
+/// allowing us to assign a second penalty (using [`historical_liquidity_penalty_multiplier_msat`]
+/// and [`historical_liquidity_penalty_amount_multiplier_msat`]) based on the same probability
+/// formula, but using the history of a channel rather than our latest estimates for the liquidity
+/// bounds.
+///
+/// # Note
+///
+/// Mixing the `no-std` feature between serialization and deserialization results in undefined
+/// behavior.
+///
+/// [1]: https://arxiv.org/abs/2107.05322
+/// [`liquidity_penalty_multiplier_msat`]: ProbabilisticScoringFeeParameters::liquidity_penalty_multiplier_msat
+/// [`liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringFeeParameters::liquidity_penalty_amount_multiplier_msat
+/// [`liquidity_offset_half_life`]: ProbabilisticScoringDecayParameters::liquidity_offset_half_life
+/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_multiplier_msat
+/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_amount_multiplier_msat
+pub type ProbabilisticScorer<G, L> = ProbabilisticScorerUsingTime::<G, L, crate::util::time::MonotonicTime>;
+#[cfg(feature = "no-std")]
/// [`ScoreLookUp`] implementation using channel success probability distributions.
///
/// Channels are tracked with upper and lower liquidity bounds - when an HTLC fails at a channel,
/// [`liquidity_offset_half_life`]: ProbabilisticScoringDecayParameters::liquidity_offset_half_life
/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_multiplier_msat
/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_amount_multiplier_msat
-pub type ProbabilisticScorer<G, L> = ProbabilisticScorerUsingTime::<G, L, ConfiguredTime>;
+pub type ProbabilisticScorer<G, L> = ProbabilisticScorerUsingTime::<G, L, crate::util::time::Eternity>;
/// Probabilistic [`ScoreLookUp`] implementation.
///
}
impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, T: Time> ScoreLookUp for ProbabilisticScorerUsingTime<G, L, T> where L::Target: Logger {
+ #[cfg(not(c_bindings))]
type ScoreParams = ProbabilisticScoringFeeParameters;
fn channel_penalty_msat(
&self, short_channel_id: u64, source: &NodeId, target: &NodeId, 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 {}
/// Specifies the recipient of an invoice.
///
}
impl ScoreLookUp for TestScorer {
+ #[cfg(not(c_bindings))]
type ScoreParams = ();
fn channel_penalty_msat(
- &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &Self::ScoreParams
+ &self, short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage, _score_params: &crate::routing::scoring::ProbabilisticScoringFeeParameters
) -> u64 {
if let Some(scorer_expectations) = self.scorer_expectations.borrow_mut().as_mut() {
match scorer_expectations.pop_front() {