Skip to content

Commit

Permalink
Introduce PaymentKind to payment store, track by PaymentId
Browse files Browse the repository at this point in the history
  • Loading branch information
tnull committed May 15, 2024
1 parent a78ed43 commit 7cd8a72
Show file tree
Hide file tree
Showing 10 changed files with 400 additions and 209 deletions.
28 changes: 19 additions & 9 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ interface Node {
void update_channel_config([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id, ChannelConfig channel_config);
[Throws=NodeError]
void sync_wallets();
PaymentDetails? payment([ByRef]PaymentHash payment_hash);
PaymentDetails? payment([ByRef]PaymentId payment_id);
[Throws=NodeError]
void remove_payment([ByRef]PaymentHash payment_hash);
void remove_payment([ByRef]PaymentId payment_id);
BalanceDetails list_balances();
sequence<PaymentDetails> list_payments();
sequence<PeerDetails> list_peers();
Expand All @@ -82,9 +82,9 @@ interface Node {

interface Bolt11Payment {
[Throws=NodeError]
PaymentHash send([ByRef]Bolt11Invoice invoice);
PaymentId send([ByRef]Bolt11Invoice invoice);
[Throws=NodeError]
PaymentHash send_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
PaymentId send_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
[Throws=NodeError]
void send_probes([ByRef]Bolt11Invoice invoice);
[Throws=NodeError]
Expand All @@ -101,7 +101,7 @@ interface Bolt11Payment {

interface SpontaneousPayment {
[Throws=NodeError]
PaymentHash send(u64 amount_msat, PublicKey node_id);
PaymentId send(u64 amount_msat, PublicKey node_id);
[Throws=NodeError]
void send_probes(u64 amount_msat, PublicKey node_id);
};
Expand Down Expand Up @@ -139,6 +139,7 @@ enum NodeError {
"InvalidSocketAddress",
"InvalidPublicKey",
"InvalidSecretKey",
"InvalidPaymentId",
"InvalidPaymentHash",
"InvalidPaymentPreimage",
"InvalidPaymentSecret",
Expand Down Expand Up @@ -219,6 +220,14 @@ interface ClosureReason {
HTLCsTimedOut();
};

[Enum]
interface PaymentKind {
Onchain();
Bolt11(PaymentHash hash, PaymentPreimage? preimage, PaymentSecret? secret);
Bolt11Jit(PaymentHash hash, PaymentPreimage? preimage, PaymentSecret? secret, LSPFeeLimits lsp_fee_limits);
Spontaneous(PaymentHash hash, PaymentPreimage? preimage);
};

enum PaymentDirection {
"Inbound",
"Outbound",
Expand All @@ -236,13 +245,11 @@ dictionary LSPFeeLimits {
};

dictionary PaymentDetails {
PaymentHash hash;
PaymentPreimage? preimage;
PaymentSecret? secret;
PaymentId id;
PaymentKind kind;
u64? amount_msat;
PaymentDirection direction;
PaymentStatus status;
LSPFeeLimits? lsp_fee_limits;
};

[NonExhaustive]
Expand Down Expand Up @@ -364,6 +371,9 @@ typedef string Address;
[Custom]
typedef string Bolt11Invoice;

[Custom]
typedef string PaymentId;

[Custom]
typedef string PaymentHash;

Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ pub enum Error {
InvalidPublicKey,
/// The given secret key is invalid.
InvalidSecretKey,
/// The given payment id is invalid.
InvalidPaymentId,
/// The given payment hash is invalid.
InvalidPaymentHash,
/// The given payment pre-image is invalid.
Expand Down Expand Up @@ -100,6 +102,7 @@ impl fmt::Display for Error {
Self::InvalidSocketAddress => write!(f, "The given network address is invalid."),
Self::InvalidPublicKey => write!(f, "The given public key is invalid."),
Self::InvalidSecretKey => write!(f, "The given secret key is invalid."),
Self::InvalidPaymentId => write!(f, "The given payment id is invalid."),
Self::InvalidPaymentHash => write!(f, "The given payment hash is invalid."),
Self::InvalidPaymentPreimage => write!(f, "The given payment preimage is invalid."),
Self::InvalidPaymentSecret => write!(f, "The given payment secret is invalid."),
Expand Down
91 changes: 60 additions & 31 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::{
};

use crate::payment::store::{
PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentStatus, PaymentStore,
PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentKind, PaymentStatus,
PaymentStore,
};

use crate::io::{
Expand All @@ -17,6 +18,7 @@ use lightning::chain::chaininterface::ConfirmationTarget;
use lightning::events::{ClosureReason, PaymentPurpose};
use lightning::events::{Event as LdkEvent, PaymentFailureReason};
use lightning::impl_writeable_tlv_based_enum;
use lightning::ln::channelmanager::PaymentId;
use lightning::ln::{ChannelId, PaymentHash};
use lightning::routing::gossip::NodeId;
use lightning::util::errors::APIError;
Expand Down Expand Up @@ -410,7 +412,8 @@ where
onion_fields: _,
counterparty_skimmed_fee_msat,
} => {
if let Some(info) = self.payment_store.get(&payment_hash) {
let payment_id = PaymentId(payment_hash.0);
if let Some(info) = self.payment_store.get(&payment_id) {
if info.status == PaymentStatus::Succeeded {
log_info!(
self.logger,
Expand All @@ -422,7 +425,7 @@ where

let update = PaymentDetailsUpdate {
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_hash)
..PaymentDetailsUpdate::new(payment_id)
};
self.payment_store.update(&update).unwrap_or_else(|e| {
log_error!(self.logger, "Failed to access payment store: {}", e);
Expand All @@ -431,17 +434,22 @@ where
return;
}

let max_total_opening_fee_msat = info
.lsp_fee_limits
.and_then(|l| {
l.max_total_opening_fee_msat.or_else(|| {
l.max_proportional_opening_fee_ppm_msat.and_then(|max_prop_fee| {
// If it's a variable amount payment, compute the actual fee.
compute_opening_fee(amount_msat, 0, max_prop_fee)
let max_total_opening_fee_msat = match info.kind {
PaymentKind::Bolt11Jit { lsp_fee_limits, .. } => {
lsp_fee_limits
.max_total_opening_fee_msat
.or_else(|| {
lsp_fee_limits.max_proportional_opening_fee_ppm_msat.and_then(
|max_prop_fee| {
// If it's a variable amount payment, compute the actual fee.
compute_opening_fee(amount_msat, 0, max_prop_fee)
},
)
})
})
})
.unwrap_or(0);
.unwrap_or(0)
},
_ => 0,
};

if counterparty_skimmed_fee_msat > max_total_opening_fee_msat {
log_info!(
Expand All @@ -455,7 +463,7 @@ where

let update = PaymentDetailsUpdate {
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_hash)
..PaymentDetailsUpdate::new(payment_id)
};
self.payment_store.update(&update).unwrap_or_else(|e| {
log_error!(self.logger, "Failed to access payment store: {}", e);
Expand Down Expand Up @@ -516,7 +524,7 @@ where

let update = PaymentDetailsUpdate {
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_hash)
..PaymentDetailsUpdate::new(payment_id)
};
self.payment_store.update(&update).unwrap_or_else(|e| {
log_error!(self.logger, "Failed to access payment store: {}", e);
Expand All @@ -538,6 +546,7 @@ where
hex_utils::to_string(&payment_hash.0),
amount_msat,
);
let payment_id = PaymentId(payment_hash.0);
match purpose {
PaymentPurpose::Bolt11InvoicePayment {
payment_preimage,
Expand All @@ -549,7 +558,7 @@ where
secret: Some(Some(payment_secret)),
amount_msat: Some(Some(amount_msat)),
status: Some(PaymentStatus::Succeeded),
..PaymentDetailsUpdate::new(payment_hash)
..PaymentDetailsUpdate::new(payment_id)
};
match self.payment_store.update(&update) {
Ok(true) => (),
Expand Down Expand Up @@ -592,13 +601,14 @@ where
},
PaymentPurpose::SpontaneousPayment(preimage) => {
let payment = PaymentDetails {
preimage: Some(preimage),
hash: payment_hash,
secret: None,
id: payment_id,
kind: PaymentKind::Spontaneous {
hash: payment_hash,
preimage: Some(preimage),
},
amount_msat: Some(amount_msat),
direction: PaymentDirection::Inbound,
status: PaymentStatus::Succeeded,
lsp_fee_limits: None,
};

match self.payment_store.insert(payment) {
Expand Down Expand Up @@ -631,14 +641,32 @@ where
panic!("Failed to push to event queue");
});
},
LdkEvent::PaymentSent { payment_preimage, payment_hash, fee_paid_msat, .. } => {
if let Some(mut payment) = self.payment_store.get(&payment_hash) {
payment.preimage = Some(payment_preimage);
payment.status = PaymentStatus::Succeeded;
self.payment_store.insert(payment.clone()).unwrap_or_else(|e| {
log_error!(self.logger, "Failed to access payment store: {}", e);
panic!("Failed to access payment store");
});
LdkEvent::PaymentSent {
payment_id,
payment_preimage,
payment_hash,
fee_paid_msat,
..
} => {
let payment_id = if let Some(id) = payment_id {
id
} else {
debug_assert!(false, "payment_id should always be set.");
return;
};

let update = PaymentDetailsUpdate {
preimage: Some(Some(payment_preimage)),
status: Some(PaymentStatus::Succeeded),
..PaymentDetailsUpdate::new(payment_id)
};

self.payment_store.update(&update).unwrap_or_else(|e| {
log_error!(self.logger, "Failed to access payment store: {}", e);
panic!("Failed to access payment store");
});

self.payment_store.get(&payment_id).map(|payment| {
log_info!(
self.logger,
"Successfully sent payment of {}msat{} from \
Expand All @@ -652,15 +680,16 @@ where
hex_utils::to_string(&payment_hash.0),
hex_utils::to_string(&payment_preimage.0)
);
}
});

self.event_queue
.add_event(Event::PaymentSuccessful { payment_hash, fee_paid_msat })
.unwrap_or_else(|e| {
log_error!(self.logger, "Failed to push to event queue: {}", e);
panic!("Failed to push to event queue");
});
},
LdkEvent::PaymentFailed { payment_hash, reason, .. } => {
LdkEvent::PaymentFailed { payment_id, payment_hash, reason, .. } => {
log_info!(
self.logger,
"Failed to send payment to payment hash {:?} due to {:?}.",
Expand All @@ -670,7 +699,7 @@ where

let update = PaymentDetailsUpdate {
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_hash)
..PaymentDetailsUpdate::new(payment_id)
};
self.payment_store.update(&update).unwrap_or_else(|e| {
log_error!(self.logger, "Failed to access payment store: {}", e);
Expand Down
14 changes: 7 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ pub use types::{ChannelDetails, PeerDetails, UserChannelId};
use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};

use lightning::chain::{BestBlock, Confirm};
use lightning::ln::channelmanager::PaymentId;
use lightning::ln::msgs::SocketAddress;
use lightning::ln::PaymentHash;

use lightning::util::config::{ChannelHandshakeConfig, UserConfig};
pub use lightning::util::logger::Level as LogLevel;
Expand Down Expand Up @@ -1143,16 +1143,16 @@ impl Node {
}
}

/// Retrieve the details of a specific payment with the given hash.
/// Retrieve the details of a specific payment with the given id.
///
/// Returns `Some` if the payment was known and `None` otherwise.
pub fn payment(&self, payment_hash: &PaymentHash) -> Option<PaymentDetails> {
self.payment_store.get(payment_hash)
pub fn payment(&self, payment_id: &PaymentId) -> Option<PaymentDetails> {
self.payment_store.get(payment_id)
}

/// Remove the payment with the given hash from the store.
pub fn remove_payment(&self, payment_hash: &PaymentHash) -> Result<(), Error> {
self.payment_store.remove(&payment_hash)
/// Remove the payment with the given id from the store.
pub fn remove_payment(&self, payment_id: &PaymentId) -> Result<(), Error> {
self.payment_store.remove(&payment_id)
}

/// Retrieves an overview of all known balances.
Expand Down
Loading

0 comments on commit 7cd8a72

Please sign in to comment.