Skip to content

Commit

Permalink
sim_node: add display and is_critical for forwarding error
Browse files Browse the repository at this point in the history
We want to be able to distinguish between expected and critical payment
errors in our simulated payments. An expected error occurs due to a
lightning-related failure (such as running out of liquidity), and a
critical one happens because something has gone wrong with our
simulator (for example, an assertion failure about balances).

This commit adds an some utilities to ForwardingError to make this
distinction and display errors properly.
  • Loading branch information
carlaKC committed Feb 13, 2024
1 parent 56b6eb0 commit d2ea936
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions sim-lib/src/sim_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use lightning::routing::scoring::{
use lightning::util::logger::{Level, Logger, Record};
use std::collections::HashMap;
use std::sync::Arc;
use thiserror::Error;
use tokio::select;
use tokio::sync::oneshot::{channel, Receiver, Sender};
use tokio::sync::Mutex;
Expand All @@ -24,40 +25,69 @@ use triggered::Listener;
/// ForwardingError represents the various errors that we can run into when forwarding payments in a simulated network.
/// Since we're not using real lightning nodes, these errors are not obfuscated and can be propagated to the sending
/// node and used for analysis.
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum ForwardingError {
/// Zero amount htlcs are in valid in the protocol.
#[error("ZeroAmountHtlc")]
ZeroAmountHtlc,
/// The outgoing channel id was not found in the network graph.
#[error("ChannelNotFound: {0}")]
ChannelNotFound(u64),
/// The node pubkey provided was not associated with the channel in the network graph.
#[error("NodeNotFound: {0:?}")]
NodeNotFound(PublicKey),
/// The channel has already forwarded a HTLC with the payment hash provided (to be removed when MPP support is
/// added).
#[error("PaymentHashExists: {0:?}")]
PaymentHashExists(PaymentHash),
/// A htlc with the payment hash provided could not be found to resolve.
#[error("PaymentHashNotFound: {0:?}")]
PaymentHashNotFound(PaymentHash),
/// The forwarding node did not have sufficient outgoing balance to forward the htlc (htlc amount / balance).
#[error("InsufficientBalance: amount: {0} > balance: {1}")]
InsufficientBalance(u64, u64),
/// The htlc forwarded is less than the channel's advertised minimum htlc amount (htlc amount / minimum).
#[error("LessThanMinimum: amount: {0} < minimum: {1}")]
LessThanMinimum(u64, u64),
/// The htlc forwarded is more than the chanenl's advertised maximum htlc amount (htlc amount / maximum).
/// The htlc forwarded is more than the channel's advertised maximum htlc amount (htlc amount / maximum).
#[error("MoreThanMaximum: amount: {0} > maximum: {1}")]
MoreThanMaximum(u64, u64),
/// The channel has reached its maximum allowable number of htlcs in flight (total in flight / maximim).
#[error("ExceedsInFlightCount: total in flight: {0} > maximum count: {1}")]
ExceedsInFlightCount(u64, u64),
/// The forwarded htlc's amount would push the channel over its maximum allowable in flight total
/// (total in flight / maximum).
#[error("ExceedsInFlightTotal: total in flight amount: {0} > maximum amount: {0}")]
ExceedsInFlightTotal(u64, u64),
/// The forwarded htlc's cltv expiry exceeds the maximum value used to express block heights in bitcoin.
#[error("ExpiryInSeconds: cltv expressed in seconds: {0}")]
ExpiryInSeconds(u32),
/// The forwarded htlc has insufficient cltv delta for the channel's minimum delta (cltv delta / minimum).
#[error("InsufficientCltvDelta: cltv delta: {0} < required: {1}")]
InsufficientCltvDelta(u32, u32),
/// The forwarded htlc has insufficient fee for the channel's policy (fee / base fee / prop fee / expected fee).
#[error("InsufficientFee: offered fee: {0} (base: {1}, prop: {2}) < expected: {3}")]
InsufficientFee(u64, u64, u64, u64),
#[error("SanityCheckFailed: capacity: {0} != node_1: {1} + node_2: {2}")]
/// Sanity check on channel balances failed (capacity / node_1 balance / node_2 balance).
SanityCheckFailed(u64, u64, u64),
}

impl ForwardingError {
/// Returns a boolean indicating whether failure to forward a htlc is a critical error that warrants shutdown.
fn is_critical(&self) -> bool {
matches!(
self,
ForwardingError::ZeroAmountHtlc
| ForwardingError::ChannelNotFound(_)
| ForwardingError::NodeNotFound(_)
| ForwardingError::PaymentHashExists(_)
| ForwardingError::PaymentHashNotFound(_)
| ForwardingError::SanityCheckFailed(_, _, _)
)
}
}

/// Represents an in-flight htlc that has been forwarded over a channel that is awaiting resolution.
#[derive(Copy, Clone)]
struct Htlc {
Expand Down

0 comments on commit d2ea936

Please sign in to comment.