Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ interface Event {
PaymentFailed(PaymentId? payment_id, PaymentHash? payment_hash, PaymentFailureReason? reason);
PaymentReceived(PaymentId? payment_id, PaymentHash payment_hash, u64 amount_msat);
PaymentClaimable(PaymentId payment_id, PaymentHash payment_hash, u64 claimable_amount_msat, u32? claim_deadline);
PaymentForwarded(ChannelId prev_channel_id, ChannelId next_channel_id, UserChannelId? prev_user_channel_id, UserChannelId? next_user_channel_id, u64? total_fee_earned_msat, u64? skimmed_fee_msat, boolean claim_from_onchain_tx, u64? outbound_amount_forwarded_msat);
ChannelPending(ChannelId channel_id, UserChannelId user_channel_id, ChannelId former_temporary_channel_id, PublicKey counterparty_node_id, OutPoint funding_txo);
ChannelReady(ChannelId channel_id, UserChannelId user_channel_id, PublicKey? counterparty_node_id);
ChannelClosed(ChannelId channel_id, UserChannelId user_channel_id, PublicKey? counterparty_node_id, ClosureReason? reason);
Expand Down
73 changes: 72 additions & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,50 @@ pub enum Event {
/// The value, in thousandths of a satoshi, that has been received.
amount_msat: u64,
},
/// A payment has been forwarded.
PaymentForwarded {
/// The channel id of the incoming channel between the previous node and us.
prev_channel_id: ChannelId,
/// The channel id of the outgoing channel between the next node and us.
next_channel_id: ChannelId,
/// The `user_channel_id` of the incoming channel between the previous node and us.
///
/// Will only be `None` for events serialized with LDK Node v0.3.0 or prior.
prev_user_channel_id: Option<UserChannelId>,
/// The `user_channel_id` of the outgoing channel between the next node and us.
///
/// This will be `None` if the payment was settled via an on-chain transaction. See the
/// caveat described for the `total_fee_earned_msat` field.
next_user_channel_id: Option<UserChannelId>,
/// The total fee, in milli-satoshis, which was earned as a result of the payment.
///
/// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
/// was pending, the amount the next hop claimed will have been rounded down to the nearest
/// whole satoshi. Thus, the fee calculated here may be higher than expected as we still
/// claimed the full value in millisatoshis from the source. In this case,
/// `claim_from_onchain_tx` will be set.
///
/// If the channel which sent us the payment has been force-closed, we will claim the funds
/// via an on-chain transaction. In that case we do not yet know the on-chain transaction
/// fees which we will spend and will instead set this to `None`.
total_fee_earned_msat: Option<u64>,
/// The share of the total fee, in milli-satoshis, which was withheld in addition to the
/// forwarding fee.
///
/// This will only be `Some` if we forwarded an intercepted HTLC with less than the
/// expected amount. This means our counterparty accepted to receive less than the invoice
/// amount.
///
/// The caveat described above the `total_fee_earned_msat` field applies here as well.
skimmed_fee_msat: Option<u64>,
/// If this is `true`, the forwarded HTLC was claimed by our counterparty via an on-chain
/// transaction.
claim_from_onchain_tx: bool,
/// The final amount forwarded, in milli-satoshis, after the fee is deducted.
///
/// The caveat described above the `total_fee_earned_msat` field applies here as well.
outbound_amount_forwarded_msat: Option<u64>,
},
/// A payment for a previously-registered payment hash has been received.
///
/// This needs to be manually claimed by supplying the correct preimage to [`claim_for_hash`].
Expand Down Expand Up @@ -204,6 +248,16 @@ impl_writeable_tlv_based_enum!(Event,
(2, payment_id, required),
(4, claimable_amount_msat, required),
(6, claim_deadline, option),
},
(7, PaymentForwarded) => {
(0, prev_channel_id, required),
(2, next_channel_id, required),
(4, prev_user_channel_id, option),
(6, next_user_channel_id, option),
(8, total_fee_earned_msat, option),
(10, skimmed_fee_msat, option),
(12, claim_from_onchain_tx, required),
(14, outbound_amount_forwarded_msat, option),
}
);

Expand Down Expand Up @@ -1068,11 +1122,28 @@ where
LdkEvent::PaymentForwarded {
prev_channel_id,
next_channel_id,
prev_user_channel_id,
next_user_channel_id,
total_fee_earned_msat,
skimmed_fee_msat,
claim_from_onchain_tx,
outbound_amount_forwarded_msat,
..
} => {
let event = Event::PaymentForwarded {
prev_channel_id: prev_channel_id.expect("prev_channel_id expected for events generated by LDK versions greater than 0.0.107."),
next_channel_id: next_channel_id.expect("next_channel_id expected for events generated by LDK versions greater than 0.0.107."),
prev_user_channel_id: prev_user_channel_id.map(UserChannelId),
next_user_channel_id: next_user_channel_id.map(UserChannelId),
total_fee_earned_msat,
skimmed_fee_msat,
claim_from_onchain_tx,
outbound_amount_forwarded_msat,
};
self.event_queue.add_event(event).map_err(|e| {
log_error!(self.logger, "Failed to push to event queue: {}", e);
ReplayEvent()
})?;

let read_only_network_graph = self.network_graph.read_only();
let nodes = read_only_network_graph.nodes();
let channels = self.channel_manager.list_channels();
Expand Down
3 changes: 3 additions & 0 deletions tests/integration_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ fn multi_hop_sending() {
let invoice = nodes[4].bolt11_payment().receive(2_500_000, &"asdf", 9217).unwrap();
nodes[0].bolt11_payment().send(&invoice, Some(sending_params)).unwrap();

expect_event!(nodes[1], PaymentForwarded);
expect_event!(nodes[2], PaymentForwarded);

let payment_id = expect_payment_received_event!(&nodes[4], 2_500_000);
let fee_paid_msat = Some(2000);
expect_payment_successful_event!(nodes[0], payment_id, Some(fee_paid_msat));
Expand Down
Loading