Skip to content

Commit

Permalink
Abort if insufficient liquidity in pay_for_offer
Browse files Browse the repository at this point in the history
This commit introduces a check to abort early if
there's insufficient liquidity when fulfilling
the payment in `pay_for_offer`

The logic gets the available liquidity by summing up the 
`next_outbound_htlc_limit_msat` from all usable channels.
Then, compares the total liquidity amount with the total
payment amount. If the payment amount is > the available
liquidity, the function logs an error and returns a 
Bolt12SemanticError::InsufficientLiquidity error.

I couldn't find an insufficient liquidity error so I added
the error type InsufficientLiquidity to the 
Bolt12SemanticError enum.
  • Loading branch information
slanesuke committed Jul 12, 2024
1 parent a20c87f commit 8a7655d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
22 changes: 21 additions & 1 deletion lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use crate::ln::wire::Encode;
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
use crate::offers::invoice_error::InvoiceError;
use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
use crate::offers::offer::{Offer, OfferBuilder};
use crate::offers::offer::{Offer, OfferBuilder, Amount};
use crate::offers::parse::Bolt12SemanticError;
use crate::offers::refund::{Refund, RefundBuilder};
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
Expand Down Expand Up @@ -8816,6 +8816,26 @@ where
None => builder,
Some(payer_note) => builder.payer_note(payer_note),
};

let total_liquidity: u64 = self.list_usable_channels().iter().map(|channel| channel.next_outbound_htlc_limit_msat).sum();
let total_amount_msats = match amount_msats {
Some(amount_msats) => Some(amount_msats),
None => match offer.amount() {
Some(Amount::Bitcoin {amount_msats}) => Some(amount_msats),
_ => None,
},
};

if let Some(amount) = total_amount_msats {
return if amount > total_liquidity {
log_error!(self.logger, "Insufficient liquidity for payment with payment id: {}", payment_id);
Err(Bolt12SemanticError::InsufficientLiquidity)
} else {
log_error!(self.logger, "Offer amount is missing for payment with id: {}", payment_id);
Err(Bolt12SemanticError::InvalidAmount)
}
}

let invoice_request = builder.build_and_sign()?;

let context = OffersContext::OutboundPayment { payment_id };
Expand Down
2 changes: 2 additions & 0 deletions lightning/src/offers/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ pub enum Bolt12SemanticError {
UnexpectedPaymentHash,
/// A signature was expected but was missing.
MissingSignature,
/// There is insufficient liquidity to complete the payment.
InsufficientLiquidity,
}

impl From<bech32::Error> for Bolt12ParseError {
Expand Down

0 comments on commit 8a7655d

Please sign in to comment.