Skip to content

Commit b12b748

Browse files
committed
Add counterparty_skimmed_fee_msat field to PaymentKind::Bolt11Jit
.. we add a field describing exactly how much the LSP withheld.
1 parent f0338d1 commit b12b748

File tree

4 files changed

+72
-3
lines changed

4 files changed

+72
-3
lines changed

src/event.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,26 @@ where
659659
};
660660
}
661661

662+
// If the LSP skimmed anything, update our stored payment.
663+
if counterparty_skimmed_fee_msat > 0 {
664+
match info.kind {
665+
PaymentKind::Bolt11Jit { .. } => {
666+
let update = PaymentDetailsUpdate {
667+
counterparty_skimmed_fee_msat: Some(Some(counterparty_skimmed_fee_msat)),
668+
..PaymentDetailsUpdate::new(payment_id)
669+
};
670+
match self.payment_store.update(&update) {
671+
Ok(_) => (),
672+
Err(e) => {
673+
log_error!(self.logger, "Failed to access payment store: {}", e);
674+
return Err(ReplayEvent());
675+
},
676+
};
677+
}
678+
_ => debug_assert!(false, "We only expect the counterparty to get away with withholding fees for JIT payments."),
679+
}
680+
}
681+
662682
// If this is known by the store but ChannelManager doesn't know the preimage,
663683
// the payment has been registered via `_for_hash` variants and needs to be manually claimed via
664684
// user interaction.

src/payment/bolt11.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ impl Bolt11Payment {
664664
hash: payment_hash,
665665
preimage,
666666
secret: Some(payment_secret.clone()),
667+
counterparty_skimmed_fee_msat: None,
667668
lsp_fee_limits,
668669
};
669670
let payment = PaymentDetails::new(

src/payment/store.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ impl PaymentDetails {
165165
update_if_necessary!(self.fee_paid_msat, fee_paid_msat_opt);
166166
}
167167

168+
if let Some(skimmed_fee_msat) = update.counterparty_skimmed_fee_msat {
169+
match self.kind {
170+
PaymentKind::Bolt11Jit { ref mut counterparty_skimmed_fee_msat, .. } => {
171+
update_if_necessary!(*counterparty_skimmed_fee_msat, skimmed_fee_msat);
172+
},
173+
_ => {},
174+
}
175+
}
176+
168177
if let Some(status) = update.status {
169178
update_if_necessary!(self.status, status);
170179
}
@@ -257,7 +266,14 @@ impl Readable for PaymentDetails {
257266

258267
if secret.is_some() {
259268
if let Some(lsp_fee_limits) = lsp_fee_limits {
260-
PaymentKind::Bolt11Jit { hash, preimage, secret, lsp_fee_limits }
269+
let counterparty_skimmed_fee_msat = None;
270+
PaymentKind::Bolt11Jit {
271+
hash,
272+
preimage,
273+
secret,
274+
counterparty_skimmed_fee_msat,
275+
lsp_fee_limits,
276+
}
261277
} else {
262278
PaymentKind::Bolt11 { hash, preimage, secret }
263279
}
@@ -346,6 +362,12 @@ pub enum PaymentKind {
346362
preimage: Option<PaymentPreimage>,
347363
/// The secret used by the payment.
348364
secret: Option<PaymentSecret>,
365+
/// The value, in thousands of a satoshi, that was deducted off of this payment as an extra
366+
/// fee taken by our channel counterparty.
367+
///
368+
/// Will only be `Some` once we received the payment. Will always be `None` for LDK Node
369+
/// v0.4 and prior.
370+
counterparty_skimmed_fee_msat: Option<u64>,
349371
/// Limits applying to how much fee we allow an LSP to deduct from the payment amount.
350372
///
351373
/// Allowing them to deduct this fee from the first inbound payment will pay for the LSP's
@@ -423,6 +445,7 @@ impl_writeable_tlv_based_enum!(PaymentKind,
423445
},
424446
(4, Bolt11Jit) => {
425447
(0, hash, required),
448+
(1, counterparty_skimmed_fee_msat, option),
426449
(2, preimage, option),
427450
(4, secret, option),
428451
(6, lsp_fee_limits, required),
@@ -501,6 +524,7 @@ pub(crate) struct PaymentDetailsUpdate {
501524
pub secret: Option<Option<PaymentSecret>>,
502525
pub amount_msat: Option<Option<u64>>,
503526
pub fee_paid_msat: Option<Option<u64>>,
527+
pub counterparty_skimmed_fee_msat: Option<Option<u64>>,
504528
pub direction: Option<PaymentDirection>,
505529
pub status: Option<PaymentStatus>,
506530
pub confirmation_status: Option<ConfirmationStatus>,
@@ -515,6 +539,7 @@ impl PaymentDetailsUpdate {
515539
secret: None,
516540
amount_msat: None,
517541
fee_paid_msat: None,
542+
counterparty_skimmed_fee_msat: None,
518543
direction: None,
519544
status: None,
520545
confirmation_status: None,
@@ -538,13 +563,21 @@ impl From<&PaymentDetails> for PaymentDetailsUpdate {
538563
_ => None,
539564
};
540565

566+
let counterparty_skimmed_fee_msat = match value.kind {
567+
PaymentKind::Bolt11Jit { counterparty_skimmed_fee_msat, .. } => {
568+
Some(counterparty_skimmed_fee_msat)
569+
},
570+
_ => None,
571+
};
572+
541573
Self {
542574
id: value.id,
543575
hash: Some(hash),
544576
preimage: Some(preimage),
545577
secret: Some(secret),
546578
amount_msat: Some(value.amount_msat),
547579
fee_paid_msat: Some(value.fee_paid_msat),
580+
counterparty_skimmed_fee_msat,
548581
direction: Some(value.direction),
549582
status: Some(value.status),
550583
confirmation_status,
@@ -841,10 +874,17 @@ mod tests {
841874
);
842875

843876
match bolt11_jit_decoded.kind {
844-
PaymentKind::Bolt11Jit { hash: h, preimage: p, secret: s, lsp_fee_limits: l } => {
877+
PaymentKind::Bolt11Jit {
878+
hash: h,
879+
preimage: p,
880+
secret: s,
881+
counterparty_skimmed_fee_msat: c,
882+
lsp_fee_limits: l,
883+
} => {
845884
assert_eq!(hash, h);
846885
assert_eq!(preimage, p);
847886
assert_eq!(secret, s);
887+
assert_eq!(None, c);
848888
assert_eq!(lsp_fee_limits, Some(l));
849889
},
850890
_ => {

tests/integration_tests_rust.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,15 @@ fn lsps2_client_service_integration() {
11371137
let service_fee_msat = (jit_amount_msat * channel_opening_fee_ppm as u64) / 1_000_000;
11381138
let expected_received_amount_msat = jit_amount_msat - service_fee_msat;
11391139
expect_payment_successful_event!(payer_node, Some(payment_id), None);
1140-
expect_payment_received_event!(client_node, expected_received_amount_msat);
1140+
let client_payment_id =
1141+
expect_payment_received_event!(client_node, expected_received_amount_msat).unwrap();
1142+
let client_payment = client_node.payment(&client_payment_id).unwrap();
1143+
match client_payment.kind {
1144+
PaymentKind::Bolt11Jit { counterparty_skimmed_fee_msat, .. } => {
1145+
assert_eq!(counterparty_skimmed_fee_msat, Some(service_fee_msat));
1146+
},
1147+
_ => panic!("Unexpected payment kind"),
1148+
}
11411149

11421150
let expected_channel_overprovisioning_msat =
11431151
(expected_received_amount_msat * channel_over_provisioning_ppm as u64) / 1_000_000;

0 commit comments

Comments
 (0)