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, PaymentSendFailure, ChannelManagerReadArgs, PaymentId};
+use lightning::ln::outbound_payment::RecipientOnionFields;
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::util::enforcing_trait_impls::EnforcingSigner;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, Writeable, Writer};
-use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OnionMessenger};
+use lightning::onion_message::packet::CustomOnionMessageContents;
+use lightning::onion_message::messenger::{OnionMessenger, CustomOnionMessageHandler};
use crate::utils::test_logger;
pub struct Sha256(/// This is not exported to bindings users as the native hash types are not currently mapped
pub sha256::Hash);
+impl Sha256 {
+ /// Constructs a new [`Sha256`] from the given bytes, which are assumed to be the output of a
+ /// single sha256 hash.
+ #[cfg(c_bindings)]
+ pub fn from_bytes(bytes: &[u8; 32]) -> Self {
+ Self(sha256::Hash::from_slice(bytes).expect("from_slice only fails if len is not 32"))
+ }
+}
+
/// Description string
///
/// # Invariants
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use lightning::chain::keysinterface::{NodeSigner, SignerProvider, EntropySource};
use lightning::ln::PaymentHash;
-use lightning::ln::channelmanager::{ChannelManager, PaymentId, Retry, RetryableSendFailure, RecipientOnionFields};
+use lightning::ln::channelmanager::{ChannelManager, PaymentId};
+use lightning::ln::outbound_payment::{RecipientOnionFields, RetryableSendFailure, Retry};
use lightning::routing::router::{PaymentParameters, RouteParameters, Router};
use lightning::util::logger::Logger;
use lightning::chain::keysinterface::PhantomKeysManager;
use lightning::events::{MessageSendEvent, MessageSendEventsProvider, Event};
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 bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::hashes::hex::FromHex;
use lightning::chain::channelmonitor::ChannelMonitor;
-use lightning::chain::keysinterface::{EntropySource, SignerProvider};
+use lightning::chain::keysinterface::{EntropySource, SignerProvider, WriteableEcdsaChannelSigner};
use lightning::util::ser::{ReadableArgs, Writeable};
use lightning::util::persist::KVStorePersister;
use std::fs;
}
/// Read `ChannelMonitor`s from disk.
- pub fn read_channelmonitors<ES: Deref, SP: Deref> (
- &self, entropy_source: ES, signer_provider: SP
- ) -> std::io::Result<Vec<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::Signer>)>>
+ pub fn read_channelmonitors<ES: Deref, WES: WriteableEcdsaChannelSigner, SP: SignerProvider<Signer = WES> + Sized, SPD: Deref<Target=SP>> (
+ &self, entropy_source: ES, signer_provider: SPD
+ ) -> Result<Vec<(BlockHash, ChannelMonitor<WES>)>, std::io::Error>
where
ES::Target: EntropySource + Sized,
- SP::Target: SignerProvider + Sized
{
let mut path = PathBuf::from(&self.path_to_channel_data);
path.push("monitors");
let contents = fs::read(&file.path())?;
let mut buffer = Cursor::new(&contents);
- match <(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::Signer>)>::read(&mut buffer, (&*entropy_source, &*signer_provider)) {
+ match <(BlockHash, ChannelMonitor<WES>)>::read(&mut buffer, (&*entropy_source, &*signer_provider)) {
Ok((blockhash, channel_monitor)) => {
if channel_monitor.get_funding_txo().0.txid != txid || channel_monitor.get_funding_txo().0.index != index {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData,
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;
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) => {
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()))?;
let our_bitcoin_sig = self.holder_signer.sign_channel_announcement_with_funding_key(&announcement, &self.secp_ctx)
.map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?;
use core::ops::Deref;
// Re-export this for use in the public API.
-pub use crate::ln::outbound_payment::{PaymentSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
+pub(crate) use crate::ln::outbound_payment::{PaymentSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
//
// 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,
pub(crate) mod channel;
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::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
use crate::ln::wire;
use crate::ln::wire::Encode;
-use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+use crate::onion_message::messenger::{CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+use crate::onion_message::packet::CustomOnionMessageContents;
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias};
use crate::util::atomic_counter::AtomicCounter;
use crate::util::logger::Logger;
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();
///
/// See [module-level documentation] for usage.
///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+///
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
/// [`Refund`]: crate::offers::refund::Refund
/// [module-level documentation]: self
}
/// Indicates how [`Invoice::signing_pubkey`] was set.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub trait SigningPubkeyStrategy {}
/// [`Invoice::signing_pubkey`] was explicitly set.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct ExplicitSigningPubkey {}
/// [`Invoice::signing_pubkey`] was derived.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct DerivedSigningPubkey {}
impl SigningPubkeyStrategy for ExplicitSigningPubkey {}
///
/// 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(),
}
/// Signs the invoice using the given function.
+ ///
+ /// This is not exported to bindings users as functions aren't currently mapped.
pub fn sign<F, E>(self, sign: F) -> Result<Invoice, SignError<E>>
where
F: FnOnce(&Message) -> Result<Signature, E>
/// An invoice may be sent in response to an [`InvoiceRequest`] in the case of an offer or sent
/// directly after scanning a refund. It includes all the information needed to pay a recipient.
///
+/// This is not exported to bindings users as its name conflicts with the BOLT 11 Invoice type.
+///
/// [`Offer`]: crate::offers::offer::Offer
/// [`Refund`]: crate::offers::refund::Refund
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
///
/// Blinded paths provide recipient privacy by obfuscating its node id. Note, however, that this
/// privacy is lost if a public node id is used for [`Invoice::signing_pubkey`].
+ ///
+ /// This is not exported to bindings users as a slice of tuples isn't exportable.
pub fn payment_paths(&self) -> &[(BlindedPath, BlindedPayInfo)] {
&self.contents.fields().payment_paths[..]
}
/// 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> {
let network = match self.network() {
None => return Vec::new(),
}
/// Signature of the invoice verified using [`Invoice::signing_pubkey`].
+ ///
+ /// This is not exported to bindings users as SIgnature is not yet mapped.
pub fn signature(&self) -> Signature {
self.signature
}
///
/// See [module-level documentation] for usage.
///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+///
/// [module-level documentation]: self
pub struct InvoiceRequestBuilder<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> {
offer: &'a Offer,
}
/// Indicates how [`InvoiceRequest::payer_id`] will be set.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub trait PayerIdStrategy {}
/// [`InvoiceRequest::payer_id`] will be explicitly set.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct ExplicitPayerId {}
/// [`InvoiceRequest::payer_id`] will be derived.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct DerivedPayerId {}
impl PayerIdStrategy for ExplicitPayerId {}
impl<'a> UnsignedInvoiceRequest<'a> {
/// Signs the invoice request using the given function.
+ ///
+ /// This is not exported to bindings users as functions are not yet mapped.
pub fn sign<F, E>(self, sign: F) -> Result<InvoiceRequest, SignError<E>>
where
F: FnOnce(&Message) -> Result<Signature, E>
/// Signature of the invoice request using [`payer_id`].
///
+ /// This is not exported to bindings users as Signature is not yet mapped.
+ ///
/// [`payer_id`]: Self::payer_id
pub fn signature(&self) -> Signature {
self.signature
/// See [`InvoiceRequest::respond_with_no_std`] for further details where the aforementioned
/// creation time is used for the `created_at` parameter.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Duration`]: core::time::Duration
#[cfg(feature = "std")]
pub fn respond_with(
///
/// Errors if the request contains unknown required features.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Invoice::created_at`]: crate::offers::invoice::Invoice::created_at
pub fn respond_with_no_std(
&self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
///
/// See [`InvoiceRequest::respond_with`] for further details.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Invoice`]: crate::offers::invoice::Invoice
#[cfg(feature = "std")]
pub fn verify_and_respond_using_derived_keys<T: secp256k1::Signing>(
///
/// See [`InvoiceRequest::respond_with_no_std`] for further details.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Invoice`]: crate::offers::invoice::Invoice
pub fn verify_and_respond_using_derived_keys_no_std<T: secp256k1::Signing>(
&self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
/// keys need to sign an [`Invoice`] for the request if they could be extracted from the
/// metadata.
///
+ /// This is not exported to bindings users as KeyPair is not yet mapped.
+ ///
/// [`Invoice`]: crate::offers::invoice::Invoice
pub fn verify<T: secp256k1::Signing>(
&self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
///
/// See [module-level documentation] for usage.
///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+///
/// [module-level documentation]: self
pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> {
offer: OfferContents,
}
/// Indicates how [`Offer::metadata`] may be set.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub trait MetadataStrategy {}
/// [`Offer::metadata`] may be explicitly set or left empty.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct ExplicitMetadata {}
/// [`Offer::metadata`] will be derived.
+///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
pub struct DerivedMetadata {}
impl MetadataStrategy for ExplicitMetadata {}
///
/// Useful to protect the sender's privacy.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
/// [`InvoiceRequest::metadata`]: crate::offers::invoice_request::InvoiceRequest::metadata
/// [`Invoice::verify`]: crate::offers::invoice::Invoice::verify
///
/// Useful for recurring payments using the same `payer_id` with different invoices.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
pub fn request_invoice_deriving_metadata<ES: Deref>(
&self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES
///
/// Errors if the offer contains unknown required features.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
pub fn request_invoice(
&self, metadata: Vec<u8>, payer_id: PublicKey
/// 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.
}
/// Error when parsing a bech32 encoded message using [`str::parse`].
+///
+/// This is not exported to bindings users as its name conflicts with the BOLT 11 ParseError type.
#[derive(Debug, PartialEq)]
pub enum ParseError {
/// The bech32 encoding does not conform to the BOLT 12 requirements for continuing messages
/// 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.
}
/// Error when interpreting a TLV stream as a specific type.
+///
+/// This is not exported to bindings users as its name conflicts with the BOLT 11 SemanticError type.
#[derive(Debug, PartialEq)]
pub enum SemanticError {
/// The current [`std::time::SystemTime`] is past the offer or invoice's expiration.
///
/// See [module-level documentation] for usage.
///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+///
/// [module-level documentation]: self
pub struct RefundBuilder<'a, T: secp256k1::Signing> {
refund: RefundContents,
/// See [`Refund::respond_with_no_std`] for further details where the aforementioned creation
/// time is used for the `created_at` parameter.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Duration`]: core::time::Duration
#[cfg(feature = "std")]
pub fn respond_with(
///
/// Errors if the request contains unknown required features.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Invoice::created_at`]: crate::offers::invoice::Invoice::created_at
pub fn respond_with_no_std(
&self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
///
/// See [`Refund::respond_with`] for further details.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Invoice`]: crate::offers::invoice::Invoice
#[cfg(feature = "std")]
pub fn respond_using_derived_keys<ES: Deref>(
///
/// See [`Refund::respond_with_no_std`] for further details.
///
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+ ///
/// [`Invoice`]: crate::offers::invoice::Invoice
pub fn respond_using_derived_keys_no_std<ES: Deref>(
&self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
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::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
use crate::util::logger::Logger;
use crate::util::ser::Writeable;
/// # use lightning::blinded_path::BlindedPath;
/// # use lightning::chain::keysinterface::KeysManager;
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
-/// # use lightning::onion_message::{CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
+/// # use lightning::onion_message::messenger::{Destination, OnionMessenger};
+/// # use lightning::onion_message::packet::{CustomOnionMessageContents, OnionMessageContents};
/// # use lightning::util::logger::{Logger, Record};
/// # use lightning::util::ser::{Writeable, Writer};
/// # use lightning::io;
//! [offers]: <https://github.com/lightning/bolts/pull/798>
//! [blinded paths]: crate::blinded_path::BlindedPath
-mod messenger;
-mod packet;
+pub mod messenger;
+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, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+pub(crate) use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
pub(crate) use self::packet::{ControlTlvs, Packet};
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)
}
#[cfg(not(feature = "no-std"))]
-type ConfiguredTime = std::time::Instant;
-#[cfg(feature = "no-std")]
-use crate::util::time::Eternity;
+/// [`Score`] 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)`).
+///
+/// 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`]: ProbabilisticScoringParameters::liquidity_penalty_multiplier_msat
+/// [`liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::liquidity_penalty_amount_multiplier_msat
+/// [`liquidity_offset_half_life`]: ProbabilisticScoringParameters::liquidity_offset_half_life
+/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_multiplier_msat
+/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_amount_multiplier_msat
+pub type ProbabilisticScorer<G, L> = ProbabilisticScorerUsingTime::<G, L, std::time::Instant>;
#[cfg(feature = "no-std")]
-type ConfiguredTime = Eternity;
-
/// [`Score`] 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`]: ProbabilisticScoringParameters::liquidity_offset_half_life
/// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringParameters::historical_liquidity_penalty_multiplier_msat
/// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringParameters::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 [`Score`] implementation.
///
/// Implementing `KVStorePersister` provides auto-implementations for [`Persister`]
/// and [`Persist`] traits. It uses "manager", "network_graph",
/// and "monitors/{funding_txo_id}_{funding_txo_index}" for keys.
+/// (C-not exported)
pub trait KVStorePersister {
/// Persist the given writeable using the provided key
fn persist<W: Writeable>(&self, key: &str, object: &W) -> io::Result<()>;
pub(crate) fn notify(&self) {
let mut lock = self.notify_pending.lock().unwrap();
if let Some(future_state) = &lock.1 {
- if future_state.lock().unwrap().complete() {
+ if complete_future(future_state) {
lock.1 = None;
return;
}
} else {
let state = Arc::new(Mutex::new(FutureState {
callbacks: Vec::new(),
+ callbacks_with_state: Vec::new(),
complete: lock.0,
callbacks_made: false,
}));
// first bool - set to false if we're just calling a Waker, and true if we're calling an actual
// user-provided function.
callbacks: Vec<(bool, Box<dyn FutureCallback>)>,
+ callbacks_with_state: Vec<(bool, Box<dyn Fn(&Arc<Mutex<FutureState>>) -> () + Send>)>,
complete: bool,
callbacks_made: bool,
}
-impl FutureState {
- fn complete(&mut self) -> bool {
- for (counts_as_call, callback) in self.callbacks.drain(..) {
- callback.call();
- self.callbacks_made |= counts_as_call;
- }
- self.complete = true;
- self.callbacks_made
+fn complete_future(this: &Arc<Mutex<FutureState>>) -> bool {
+ let mut state_lock = this.lock().unwrap();
+ let state = &mut *state_lock;
+ for (counts_as_call, callback) in state.callbacks.drain(..) {
+ callback.call();
+ state.callbacks_made |= counts_as_call;
+ }
+ for (counts_as_call, callback) in state.callbacks_with_state.drain(..) {
+ (callback)(this);
+ state.callbacks_made |= counts_as_call;
}
+ state.complete = true;
+ state.callbacks_made
}
/// A simple future which can complete once, and calls some callback(s) when it does so.
for notifier_mtx in self.notifiers.iter() {
let cv_ref = Arc::clone(&cv);
let notified_fut_ref = Arc::clone(¬ified_fut_mtx);
- let notifier_ref = Arc::clone(¬ifier_mtx);
let mut notifier = notifier_mtx.lock().unwrap();
if notifier.complete {
- *notified_fut_mtx.lock().unwrap() = Some(notifier_ref);
+ *notified_fut_mtx.lock().unwrap() = Some(Arc::clone(¬ifier_mtx));
break;
}
- notifier.callbacks.push((false, Box::new(move || {
- *notified_fut_ref.lock().unwrap() = Some(Arc::clone(¬ifier_ref));
+ notifier.callbacks_with_state.push((false, Box::new(move |notifier_ref| {
+ *notified_fut_ref.lock().unwrap() = Some(Arc::clone(notifier_ref));
cv_ref.notify_all();
})));
}
}
}
+ #[cfg(feature = "std")]
+ #[test]
+ fn test_state_drops() {
+ // Previously, there was a leak if a `Notifier` was `drop`ed without ever being notified
+ // but after having been slept-on. This tests for that leak.
+ use crate::sync::Arc;
+ use std::thread;
+
+ let notifier_a = Arc::new(Notifier::new());
+ let notifier_b = Arc::new(Notifier::new());
+
+ let thread_notifier_a = Arc::clone(¬ifier_a);
+
+ let future_a = notifier_a.get_future();
+ let future_state_a = Arc::downgrade(&future_a.state);
+
+ let future_b = notifier_b.get_future();
+ let future_state_b = Arc::downgrade(&future_b.state);
+
+ let join_handle = thread::spawn(move || {
+ // Let the other thread get to the wait point, then notify it.
+ std::thread::sleep(Duration::from_millis(50));
+ thread_notifier_a.notify();
+ });
+
+ // Wait on the other thread to finish its sleep, note that the leak only happened if we
+ // actually have to sleep here, not if we immediately return.
+ Sleeper::from_two_futures(future_a, future_b).wait();
+
+ join_handle.join().unwrap();
+
+ // then drop the notifiers and make sure the future states are gone.
+ mem::drop(notifier_a);
+ mem::drop(notifier_b);
+
+ assert!(future_state_a.upgrade().is_none() && future_state_b.upgrade().is_none());
+ }
+
#[test]
fn test_future_callbacks() {
let future = Future {
state: Arc::new(Mutex::new(FutureState {
callbacks: Vec::new(),
+ callbacks_with_state: Vec::new(),
complete: false,
callbacks_made: false,
}))
future.register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst))));
assert!(!callback.load(Ordering::SeqCst));
- future.state.lock().unwrap().complete();
+ complete_future(&future.state);
assert!(callback.load(Ordering::SeqCst));
- future.state.lock().unwrap().complete();
+ complete_future(&future.state);
}
#[test]
let future = Future {
state: Arc::new(Mutex::new(FutureState {
callbacks: Vec::new(),
+ callbacks_with_state: Vec::new(),
complete: false,
callbacks_made: false,
}))
};
- future.state.lock().unwrap().complete();
+ complete_future(&future.state);
let callback = Arc::new(AtomicBool::new(false));
let callback_ref = Arc::clone(&callback);
let mut future = Future {
state: Arc::new(Mutex::new(FutureState {
callbacks: Vec::new(),
+ callbacks_with_state: Vec::new(),
complete: false,
callbacks_made: false,
}))
assert_eq!(Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), Poll::Pending);
assert!(!second_woken.load(Ordering::SeqCst));
- future.state.lock().unwrap().complete();
+ complete_future(&future.state);
assert!(woken.load(Ordering::SeqCst));
assert!(second_woken.load(Ordering::SeqCst));
assert_eq!(Pin::new(&mut future).poll(&mut Context::from_waker(&waker)), Poll::Ready(()));