use lightning::ln::script::ShutdownScript;
use lightning::util::enforcing_trait_impls::EnforcingSigner;
use lightning::util::logger::Logger;
-use lightning::util::ser::{MaybeReadableArgs, Readable, Writeable, Writer};
-use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OnionMessenger};
+use lightning::util::ser::{Readable, Writeable, Writer};
+use lightning::onion_message::packet::CustomOnionMessageContents;
+use lightning::onion_message::messenger::{OnionMessenger, CustomOnionMessageHandler};
use crate::utils::test_logger;
}
}
-impl MaybeReadableArgs<u64> for TestCustomMessage {
- fn read<R: io::Read>(buffer: &mut R, _message_type: u64,) -> Result<Option<Self>, DecodeError> where Self: Sized {
- let mut buf = Vec::new();
- buffer.read_to_end(&mut buf)?;
- return Ok(Some(TestCustomMessage {}))
- }
-}
-
struct TestCustomMessageHandler {}
impl CustomOnionMessageHandler for TestCustomMessageHandler {
type CustomMessage = TestCustomMessage;
fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
+ fn read_custom_message<R: io::Read>(&self, _message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError> {
+ let mut buf = Vec::new();
+ buffer.read_to_end(&mut buf)?;
+ return Ok(Some(TestCustomMessage {}))
+ }
}
pub struct VecWriter(pub Vec<u8>);
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;
}
/// Returns the witness required to satisfy and spend an anchor input.
-pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
+pub(crate) fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key);
let mut funding_sig = funding_sig.serialize_der().to_vec();
funding_sig.push(EcdsaSighashType::All as u8);
pub struct OnionMessage {
/// Used in decrypting the onion packet's payload.
pub blinding_point: PublicKey,
- pub(crate) onion_routing_packet: onion_message::Packet,
+ pub(crate) onion_routing_packet: onion_message::packet::Packet,
}
/// An update_fulfill_htlc message to be sent or received from a peer
let blinding_point: PublicKey = Readable::read(r)?;
let len: u16 = Readable::read(r)?;
let mut packet_reader = FixedLengthReader::new(r, len as u64);
- let onion_routing_packet: onion_message::Packet = <onion_message::Packet as LengthReadable>::read(&mut packet_reader)?;
+ let onion_routing_packet = <onion_message::packet::Packet as LengthReadable>::read(&mut packet_reader)?;
Ok(Self {
blinding_point,
onion_routing_packet,
} else { unreachable!(); }
}
-/// An input used when decoding an onion packet.
-pub(crate) trait DecodeInput {
- type Arg;
- /// If Some, this is the input when checking the hmac of the onion packet.
- fn payment_hash(&self) -> Option<&PaymentHash>;
- /// Read argument when decrypting our hop payload.
- fn read_arg(self) -> Self::Arg;
-}
-
-impl DecodeInput for PaymentHash {
- type Arg = ();
- fn payment_hash(&self) -> Option<&PaymentHash> {
- Some(self)
- }
- fn read_arg(self) -> Self::Arg { () }
-}
-
-impl DecodeInput for SharedSecret {
- type Arg = SharedSecret;
- fn payment_hash(&self) -> Option<&PaymentHash> {
- None
- }
- fn read_arg(self) -> Self::Arg { self }
-}
-
/// Allows `decode_next_hop` to return the next hop packet bytes for either payments or onion
/// message forwards.
pub(crate) trait NextPacketBytes: AsMut<[u8]> {
}
pub(crate) fn decode_next_payment_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash) -> Result<Hop, OnionDecodeErr> {
- match decode_next_hop(shared_secret, hop_data, hmac_bytes, payment_hash) {
+ match decode_next_hop(shared_secret, hop_data, hmac_bytes, Some(payment_hash), ()) {
Ok((next_hop_data, None)) => Ok(Hop::Receive(next_hop_data)),
Ok((next_hop_data, Some((next_hop_hmac, FixedSizeOnionPacket(new_packet_bytes))))) => {
Ok(Hop::Forward {
}
}
-pub(crate) fn decode_next_hop<D: DecodeInput, R: ReadableArgs<D::Arg>, N: NextPacketBytes>(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], decode_input: D) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> {
+pub(crate) fn decode_next_untagged_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], read_args: T) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> {
+ decode_next_hop(shared_secret, hop_data, hmac_bytes, None, read_args)
+}
+
+fn decode_next_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: Option<PaymentHash>, read_args: T) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> {
let (rho, mu) = gen_rho_mu_from_shared_secret(&shared_secret);
let mut hmac = HmacEngine::<Sha256>::new(&mu);
hmac.input(hop_data);
- if let Some(payment_hash) = decode_input.payment_hash() {
- hmac.input(&payment_hash.0[..]);
+ if let Some(tag) = payment_hash {
+ hmac.input(&tag.0[..]);
}
if !fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &hmac_bytes) {
return Err(OnionDecodeErr::Malformed {
let mut chacha = ChaCha20::new(&rho, &[0u8; 8]);
let mut chacha_stream = ChaChaReader { chacha: &mut chacha, read: Cursor::new(&hop_data[..]) };
- match R::read(&mut chacha_stream, decode_input.read_arg()) {
+ match R::read(&mut chacha_stream, read_args) {
Err(err) => {
let error_code = match err {
msgs::DecodeError::UnknownVersion => 0x4000 | 1, // unknown realm byte
use crate::ln::msgs;
use crate::ln::msgs::{ChannelMessageHandler, LightningError, NetAddress, OnionMessageHandler, RoutingMessageHandler};
use crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager};
-use crate::util::ser::{MaybeReadableArgs, VecWriter, Writeable, Writer};
+use crate::util::ser::{VecWriter, Writeable, 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};
use crate::util::atomic_counter::AtomicCounter;
use crate::util::crypto::sign;
}
impl CustomOnionMessageHandler for IgnoringMessageHandler {
type CustomMessage = Infallible;
- fn handle_custom_message(&self, _msg: Self::CustomMessage) {
+ fn handle_custom_message(&self, _msg: Infallible) {
// Since we always return `None` in the read the handle method should never be called.
unreachable!();
}
-}
-impl MaybeReadableArgs<u64> for Infallible {
- fn read<R: io::Read>(_buffer: &mut R, _msg_type: u64) -> Result<Option<Self>, msgs::DecodeError> where Self: Sized {
+ fn read_custom_message<R: io::Read>(&self, _msg_type: u64, _buffer: &mut R) -> Result<Option<Infallible>, msgs::DecodeError> where Self: Sized {
Ok(None)
}
}
use crate::chain::keysinterface::{KeysInterface, Recipient};
use crate::ln::features::InitFeatures;
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
-use super::{BlindedRoute, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError};
+use super::blinded_route::BlindedRoute;
+use super::messenger::{CustomOnionMessageHandler, Destination, OnionMessenger, SendError};
+use super::packet::{CustomOnionMessageContents, OnionMessageContents};
use crate::util::enforcing_trait_impls::EnforcingSigner;
-use crate::util::ser::{MaybeReadableArgs, Writeable, Writer};
+use crate::util::ser::{ Writeable, Writer};
use crate::util::test_utils;
use bitcoin::network::constants::Network;
}
}
-impl MaybeReadableArgs<u64> for TestCustomMessage {
- fn read<R: io::Read>(buffer: &mut R, message_type: u64) -> Result<Option<Self>, DecodeError> where Self: Sized {
+struct TestCustomMessageHandler {}
+
+impl CustomOnionMessageHandler for TestCustomMessageHandler {
+ type CustomMessage = TestCustomMessage;
+ fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
+ fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, DecodeError> where Self: Sized {
if message_type == CUSTOM_MESSAGE_TYPE {
let mut buf = Vec::new();
buffer.read_to_end(&mut buf)?;
}
}
-struct TestCustomMessageHandler {}
-
-impl CustomOnionMessageHandler for TestCustomMessageHandler {
- type CustomMessage = TestCustomMessage;
- fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
-}
-
fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
let mut nodes = Vec::new();
for i in 0..num_messengers {
fn write<W: Writer>(&self, _w: &mut W) -> Result<(), io::Error> { unreachable!() }
}
- impl MaybeReadableArgs<u64> for InvalidCustomMessage {
- fn read<R: io::Read>(_buffer: &mut R, _message_type: u64) -> Result<Option<Self>, DecodeError> where Self: Sized {
- unreachable!()
- }
- }
-
let test_msg = OnionMessageContents::Custom(InvalidCustomMessage {});
let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), test_msg, None).unwrap_err();
assert_eq!(err, SendError::InvalidMessage);
use crate::ln::onion_utils;
use crate::ln::peer_handler::IgnoringMessageHandler;
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
-pub use super::packet::{CustomOnionMessageContents, OnionMessageContents};
+use super::packet::{CustomOnionMessageContents, OnionMessageContents};
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
use super::utils;
use crate::util::events::OnionMessageProvider;
use crate::util::ser::Writeable;
use core::ops::Deref;
+use crate::io;
use crate::sync::{Arc, Mutex};
use crate::prelude::*;
/// # use lightning::chain::keysinterface::{InMemorySigner, KeysManager, KeysInterface};
/// # use lightning::ln::msgs::DecodeError;
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
-/// # use lightning::onion_message::{BlindedRoute, CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
+/// # use lightning::onion_message::messenger::{Destination, OnionMessenger};
+/// # use lightning::onion_message::packet::CustomOnionMessageContents;
+/// # use lightning::onion_message::blinded_route::BlindedRoute;
/// # use lightning::util::logger::{Logger, Record};
-/// # use lightning::util::ser::{MaybeReadableArgs, Writeable, Writer};
+/// # use lightning::util::ser::{Writeable, Writer};
/// # use lightning::io;
/// # use std::sync::Arc;
/// # struct FakeLogger {};
/// your_custom_message_type
/// }
/// }
-/// impl MaybeReadableArgs<u64> for YourCustomMessage {
-/// fn read<R: io::Read>(r: &mut R, message_type: u64) -> Result<Option<Self>, DecodeError> {
-/// # unreachable!()
-/// // Read your custom onion message of type `message_type` from `r`, or return `None`
-/// // if the message type is unknown
-/// }
-/// }
/// // Send a custom onion message to a node id.
/// let intermediate_hops = [hop_node_id1, hop_node_id2];
/// let reply_path = None;
/// # let your_custom_message = YourCustomMessage {};
-/// let message = OnionMessageContents::Custom(your_custom_message);
-/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), message, reply_path);
+/// onion_messenger.send_custom_onion_message(&intermediate_hops, Destination::Node(destination_node_id), your_custom_message, reply_path);
///
/// // Create a blinded route to yourself, for someone to send an onion message to.
/// # let your_node_id = hop_node_id1;
/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
/// let reply_path = None;
/// # let your_custom_message = YourCustomMessage {};
-/// let message = OnionMessageContents::Custom(your_custom_message);
-/// onion_messenger.send_onion_message(&intermediate_hops, Destination::BlindedRoute(blinded_route), message, reply_path);
+/// onion_messenger.send_custom_onion_message(&intermediate_hops, Destination::BlindedRoute(blinded_route), your_custom_message, reply_path);
/// ```
///
/// [offers]: <https://github.com/lightning/bolts/pull/798>
/// Errors that may occur when [sending an onion message].
///
-/// [sending an onion message]: OnionMessenger::send_onion_message
+/// [sending an onion message]: OnionMessenger::send_custom_onion_message
#[derive(Debug, PartialEq, Eq)]
pub enum SendError {
/// Errored computing onion message packet keys.
type CustomMessage: CustomOnionMessageContents;
/// Called with the custom message that was received.
fn handle_custom_message(&self, msg: Self::CustomMessage);
+ /// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
+ /// message type is unknown.
+ fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError>;
}
impl<Signer: Sign, K: Deref, L: Deref, CMH: Deref> OnionMessenger<Signer, K, L, CMH>
/// Send an onion message with contents `message` to `destination`, routing it through `intermediate_nodes`.
/// See [`OnionMessenger`] for example usage.
- pub fn send_onion_message<T: CustomOnionMessageContents>(&self, intermediate_nodes: &[PublicKey], destination: Destination, message: OnionMessageContents<T>, reply_path: Option<BlindedRoute>) -> Result<(), SendError> {
+ pub(crate) fn send_onion_message<T: CustomOnionMessageContents>(&self, intermediate_nodes: &[PublicKey], destination: Destination, msg: OnionMessageContents<T>, reply_path: Option<BlindedRoute>) -> Result<(), SendError> {
+ let OnionMessageContents::Custom(message) = msg;
+ self.send_custom_onion_message(intermediate_nodes, destination, message, reply_path)
+ }
+
+ /// Send an onion message with contents `message` to `destination`, routing it through `intermediate_nodes`.
+ /// See [`OnionMessenger`] for example usage.
+ pub fn send_custom_onion_message<T: CustomOnionMessageContents>(&self, intermediate_nodes: &[PublicKey], destination: Destination, msg: T, reply_path: Option<BlindedRoute>) -> Result<(), SendError> {
if let Destination::BlindedRoute(BlindedRoute { ref blinded_hops, .. }) = destination {
if blinded_hops.len() < 2 {
return Err(SendError::TooFewBlindedHops);
}
}
- let OnionMessageContents::Custom(ref msg) = message;
if msg.tlv_type() < 64 { return Err(SendError::InvalidMessage) }
let blinding_secret_bytes = self.keys_manager.get_secure_random_bytes();
}
};
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
- &self.secp_ctx, intermediate_nodes, destination, message, reply_path, &blinding_secret)
+ &self.secp_ctx, intermediate_nodes, destination, OnionMessageContents::Custom(msg), reply_path, &blinding_secret)
.map_err(|e| SendError::Secp256k1(e))?;
let prng_seed = self.keys_manager.get_secure_random_bytes();
impl<Signer: Sign, K: Deref, L: Deref, CMH: Deref> OnionMessageHandler for OnionMessenger<Signer, K, L, CMH>
where K::Target: KeysInterface<Signer = Signer>,
L::Target: Logger,
- CMH::Target: CustomOnionMessageHandler,
+ CMH::Target: CustomOnionMessageHandler + Sized,
{
/// Handle an incoming onion message. Currently, if a message was destined for us we will log, but
/// soon we'll delegate the onion message to a handler that can generate invoices or send
}
}
};
- match onion_utils::decode_next_hop(onion_decode_ss, &msg.onion_routing_packet.hop_data[..],
- msg.onion_routing_packet.hmac, control_tlvs_ss)
+ match onion_utils::decode_next_untagged_hop(onion_decode_ss, &msg.onion_routing_packet.hop_data[..],
+ msg.onion_routing_packet.hmac, (control_tlvs_ss, &*self.custom_handler))
{
Ok((Payload::Receive::<<<CMH as Deref>::Target as CustomOnionMessageHandler>::CustomMessage> {
message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path,
//! information on its usage.
//!
//! [offers]: <https://github.com/lightning/bolts/pull/798>
-//! [blinded routes]: crate::onion_message::BlindedRoute
+//! [blinded routes]: crate::onion_message::blinded_route::BlindedRoute
+//! [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
-mod blinded_route;
-mod messenger;
-mod packet;
+pub mod blinded_route;
+pub mod messenger;
+pub mod packet;
mod utils;
#[cfg(test)]
mod functional_tests;
-
-// Re-export structs so they can be imported with just the `onion_message::` module prefix.
-pub use self::blinded_route::{BlindedRoute, BlindedHop};
-pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
-pub(crate) use self::packet::Packet;
use crate::ln::msgs::DecodeError;
use crate::ln::onion_utils;
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
+use super::messenger::CustomOnionMessageHandler;
use crate::util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
-use crate::util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, MaybeReadableArgs, Readable, ReadableArgs, Writeable, Writer};
+use crate::util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer};
use core::cmp;
use crate::io::{self, Read};
#[derive(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> where T: CustomOnionMessageContents {
+pub(crate) enum OnionMessageContents<T: CustomOnionMessageContents> {
// Coming soon:
// Invoice,
// InvoiceRequest,
Custom(T),
}
-impl<T> OnionMessageContents<T> where T: CustomOnionMessageContents {
+impl<T: CustomOnionMessageContents> OnionMessageContents<T> {
/// Returns the type that was used to decode the message payload.
pub fn tlv_type(&self) -> u64 {
match self {
}
}
-/// The contents of a custom onion message. Must implement `MaybeReadableArgs<u64>` where the `u64`
-/// is the custom TLV type attempting to be read, and return `Ok(None)` if the TLV type is unknown.
-pub trait CustomOnionMessageContents: Writeable + MaybeReadableArgs<u64> {
+/// The contents of a custom onion message.
+pub trait CustomOnionMessageContents: Writeable {
/// Returns the TLV type identifying the message contents. MUST be >= 64.
fn tlv_type(&self) -> u64;
}
}
// Uses the provided secret to simultaneously decode and decrypt the control TLVs and data TLV.
-impl<T: CustomOnionMessageContents> ReadableArgs<SharedSecret> for Payload<T> {
- fn read<R: Read>(r: &mut R, encrypted_tlvs_ss: SharedSecret) -> Result<Self, DecodeError> {
+impl<H: CustomOnionMessageHandler> ReadableArgs<(SharedSecret, &H)> for Payload<<H as CustomOnionMessageHandler>::CustomMessage> {
+ fn read<R: Read>(r: &mut R, args: (SharedSecret, &H)) -> Result<Self, DecodeError> {
+ let (encrypted_tlvs_ss, handler) = args;
+
let v: BigSize = Readable::read(r)?;
let mut rd = FixedLengthReader::new(r, v.0);
let mut reply_path: Option<BlindedRoute> = None;
if message_type.is_some() { return Err(DecodeError::InvalidValue) }
message_type = Some(msg_type);
- match T::read(msg_reader, msg_type) {
+ match handler.read_custom_message(msg_type, msg_reader) {
Ok(Some(msg)) => {
message = Some(msg);
Ok(true)
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<()>;
}
}
-/// A trait that various rust-lightning types implement allowing them to (maybe) be read in from a
-/// Read, given some additional set of arguments which is required to deserialize.
-///
-/// (C-not exported) as we only export serialization to/from byte arrays instead
-pub trait MaybeReadableArgs<P> {
- /// Reads a Self in from the given Read
- fn read<R: Read>(reader: &mut R, params: P) -> Result<Option<Self>, DecodeError> where Self: Sized;
-}
-
pub(crate) struct OptionDeserWrapper<T: Readable>(pub Option<T>);
impl<T: Readable> Readable for OptionDeserWrapper<T> {
#[inline]