Skip to content

Commit 7cd334a

Browse files
committed
Generate a PaymentForwarded event when a forwarded HTLC is claimed
It is useful for accounting and informational reasons for users to be informed when a payment has been successfully forwarded. Thus, when an HTLC which represents a forwarded leg is claimed, we generate a new `PaymentForwarded` event. This requires some additional plumbing to return HTLC values from `OnchainEvent`s. Further, when we have to go on-chain to claim the inbound side of the payment, we do not inform the user of the fee reward, as we cannot calculate it until we see what is confirmed on-chain.
1 parent d4984bf commit 7cd334a

11 files changed

+177
-51
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# 0.0.100 - WIP
2+
3+
## Serialization Compatibility
4+
* HTLCs which were in the process of being claimed on-chain when a pre-0.0.100
5+
`ChannelMonitor` was serialized may generate `PaymentForwarded` events with
6+
spurious `fee_earned_msat` values. This only applies to payments which were
7+
unresolved at the time of the upgrade.
8+
* 0.0.100 clients with pending PaymentForwarded events at serialization-time
9+
will generate serialized `ChannelManager` objects which 0.0.99 and earlier
10+
clients cannot read. The likelihood of this can be reduced by ensuring you
11+
process all pending events immediately before serialization.
12+
13+
114
# 0.0.99 - 2021-07-09
215

316
## API Updates

fuzz/src/chanmon_consistency.rs

+1
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
804804
},
805805
events::Event::PaymentSent { .. } => {},
806806
events::Event::PaymentFailed { .. } => {},
807+
events::Event::PaymentForwarded if $node == 1 { .. } => {},
807808
events::Event::PendingHTLCsForwardable { .. } => {
808809
nodes[$node].process_pending_htlc_forwards();
809810
},

fuzz/src/full_stack.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -596,12 +596,10 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
596596
//TODO: enhance by fetching random amounts from fuzz input?
597597
payments_received.push(payment_hash);
598598
},
599-
Event::PaymentSent {..} => {},
600-
Event::PaymentFailed {..} => {},
601599
Event::PendingHTLCsForwardable {..} => {
602600
should_forward = true;
603601
},
604-
Event::SpendableOutputs {..} => {},
602+
_ => {},
605603
}
606604
}
607605
}

lightning/src/chain/channelmonitor.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,12 @@ pub enum MonitorEvent {
199199
pub struct HTLCUpdate {
200200
pub(crate) payment_hash: PaymentHash,
201201
pub(crate) payment_preimage: Option<PaymentPreimage>,
202-
pub(crate) source: HTLCSource
202+
pub(crate) source: HTLCSource,
203+
pub(crate) onchain_value_satoshis: Option<u64>,
203204
}
204205
impl_writeable_tlv_based!(HTLCUpdate, {
205206
(0, payment_hash, required),
207+
(1, onchain_value_satoshis, option),
206208
(2, source, required),
207209
(4, payment_preimage, option),
208210
});
@@ -385,6 +387,7 @@ enum OnchainEvent {
385387
HTLCUpdate {
386388
source: HTLCSource,
387389
payment_hash: PaymentHash,
390+
onchain_value_satoshis: Option<u64>,
388391
},
389392
MaturingOutput {
390393
descriptor: SpendableOutputDescriptor,
@@ -400,6 +403,7 @@ impl_writeable_tlv_based!(OnchainEventEntry, {
400403
impl_writeable_tlv_based_enum!(OnchainEvent,
401404
(0, HTLCUpdate) => {
402405
(0, source, required),
406+
(1, onchain_value_satoshis, option),
403407
(2, payment_hash, required),
404408
},
405409
(1, MaturingOutput) => {
@@ -1574,6 +1578,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
15741578
event: OnchainEvent::HTLCUpdate {
15751579
source: (**source).clone(),
15761580
payment_hash: htlc.payment_hash.clone(),
1581+
onchain_value_satoshis: Some(htlc.amount_msat / 1000),
15771582
},
15781583
};
15791584
log_info!(logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of revoked counterparty commitment transaction, waiting for confirmation (at height {})", log_bytes!(htlc.payment_hash.0), $commitment_tx, entry.confirmation_threshold());
@@ -1641,6 +1646,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
16411646
event: OnchainEvent::HTLCUpdate {
16421647
source: (**source).clone(),
16431648
payment_hash: htlc.payment_hash.clone(),
1649+
onchain_value_satoshis: Some(htlc.amount_msat / 1000),
16441650
},
16451651
});
16461652
}
@@ -1825,6 +1831,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18251831
height,
18261832
event: OnchainEvent::HTLCUpdate {
18271833
source: source.clone(), payment_hash: htlc.payment_hash,
1834+
onchain_value_satoshis: Some(htlc.amount_msat / 1000)
18281835
},
18291836
};
18301837
log_trace!(logger, "Failing HTLC with payment_hash {} from {} holder commitment tx due to broadcast of transaction, waiting confirmation (at height{})",
@@ -2087,7 +2094,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20872094
// Produce actionable events from on-chain events having reached their threshold.
20882095
for entry in onchain_events_reaching_threshold_conf.drain(..) {
20892096
match entry.event {
2090-
OnchainEvent::HTLCUpdate { ref source, payment_hash } => {
2097+
OnchainEvent::HTLCUpdate { ref source, payment_hash, onchain_value_satoshis } => {
20912098
// Check for duplicate HTLC resolutions.
20922099
#[cfg(debug_assertions)]
20932100
{
@@ -2106,9 +2113,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21062113

21072114
log_debug!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!(payment_hash.0));
21082115
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
2109-
payment_hash: payment_hash,
2116+
payment_hash,
21102117
payment_preimage: None,
21112118
source: source.clone(),
2119+
onchain_value_satoshis,
21122120
}));
21132121
},
21142122
OnchainEvent::MaturingOutput { descriptor } => {
@@ -2325,7 +2333,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
23252333
if pending_htlc.payment_hash == $htlc_output.payment_hash && pending_htlc.amount_msat == $htlc_output.amount_msat {
23262334
if let &Some(ref source) = pending_source {
23272335
log_claim!("revoked counterparty commitment tx", false, pending_htlc, true);
2328-
payment_data = Some(((**source).clone(), $htlc_output.payment_hash));
2336+
payment_data = Some(((**source).clone(), $htlc_output.payment_hash, $htlc_output.amount_msat));
23292337
break;
23302338
}
23312339
}
@@ -2345,7 +2353,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
23452353
// transaction. This implies we either learned a preimage, the HTLC
23462354
// has timed out, or we screwed up. In any case, we should now
23472355
// resolve the source HTLC with the original sender.
2348-
payment_data = Some(((*source).clone(), htlc_output.payment_hash));
2356+
payment_data = Some(((*source).clone(), htlc_output.payment_hash, htlc_output.amount_msat));
23492357
} else if !$holder_tx {
23502358
check_htlc_valid_counterparty!(self.current_counterparty_commitment_txid, htlc_output);
23512359
if payment_data.is_none() {
@@ -2378,7 +2386,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
23782386

23792387
// Check that scan_commitment, above, decided there is some source worth relaying an
23802388
// HTLC resolution backwards to and figure out whether we learned a preimage from it.
2381-
if let Some((source, payment_hash)) = payment_data {
2389+
if let Some((source, payment_hash, amount_msat)) = payment_data {
23822390
let mut payment_preimage = PaymentPreimage([0; 32]);
23832391
if accepted_preimage_claim {
23842392
if !self.pending_monitor_events.iter().any(
@@ -2387,7 +2395,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
23872395
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
23882396
source,
23892397
payment_preimage: Some(payment_preimage),
2390-
payment_hash
2398+
payment_hash,
2399+
onchain_value_satoshis: Some(amount_msat / 1000),
23912400
}));
23922401
}
23932402
} else if offered_preimage_claim {
@@ -2399,7 +2408,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
23992408
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
24002409
source,
24012410
payment_preimage: Some(payment_preimage),
2402-
payment_hash
2411+
payment_hash,
2412+
onchain_value_satoshis: Some(amount_msat / 1000),
24032413
}));
24042414
}
24052415
} else {
@@ -2415,7 +2425,10 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
24152425
let entry = OnchainEventEntry {
24162426
txid: tx.txid(),
24172427
height,
2418-
event: OnchainEvent::HTLCUpdate { source: source, payment_hash: payment_hash },
2428+
event: OnchainEvent::HTLCUpdate {
2429+
source, payment_hash,
2430+
onchain_value_satoshis: Some(amount_msat / 1000),
2431+
},
24192432
};
24202433
log_info!(logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height {})", log_bytes!(payment_hash.0), entry.confirmation_threshold());
24212434
self.onchain_events_awaiting_threshold_conf.push(entry);

lightning/src/ln/chanmon_update_fail_tests.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,7 @@ fn test_monitor_update_fail_reestablish() {
11441144
assert!(updates.update_fee.is_none());
11451145
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
11461146
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
1147+
expect_payment_forwarded!(nodes[1], Some(1000), false);
11471148
check_added_monitors!(nodes[1], 1);
11481149
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
11491150
commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
@@ -2292,6 +2293,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
22922293
assert_eq!(fulfill_msg, cs_updates.update_fulfill_htlcs[0]);
22932294
}
22942295
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &fulfill_msg);
2296+
expect_payment_forwarded!(nodes[1], Some(1000), false);
22952297
check_added_monitors!(nodes[1], 1);
22962298

22972299
let mut bs_updates = None;

lightning/src/ln/channel.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ pub struct CounterpartyForwardingInfo {
309309
// Holder designates channel data owned for the benefice of the user client.
310310
// Counterparty designates channel data owned by the another channel participant entity.
311311
pub(super) struct Channel<Signer: Sign> {
312+
#[cfg(any(test, feature = "_test_utils"))]
313+
pub(crate) config: ChannelConfig,
314+
#[cfg(not(any(test, feature = "_test_utils")))]
312315
config: ChannelConfig,
313316

314317
user_id: u64,
@@ -1231,7 +1234,7 @@ impl<Signer: Sign> Channel<Signer> {
12311234
make_funding_redeemscript(&self.get_holder_pubkeys().funding_pubkey, self.counterparty_funding_pubkey())
12321235
}
12331236

1234-
fn get_update_fulfill_htlc<L: Deref>(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) -> (Option<msgs::UpdateFulfillHTLC>, Option<ChannelMonitorUpdate>) where L::Target: Logger {
1237+
fn get_update_fulfill_htlc<L: Deref>(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) -> (Option<msgs::UpdateFulfillHTLC>, Option<(ChannelMonitorUpdate, u64)>) where L::Target: Logger {
12351238
// Either ChannelFunded got set (which means it won't be unset) or there is no way any
12361239
// caller thought we could have something claimed (cause we wouldn't have accepted in an
12371240
// incoming HTLC anyway). If we got to ShutdownComplete, callers aren't allowed to call us,
@@ -1248,6 +1251,7 @@ impl<Signer: Sign> Channel<Signer> {
12481251
// these, but for now we just have to treat them as normal.
12491252

12501253
let mut pending_idx = core::usize::MAX;
1254+
let mut htlc_value_msat = 0;
12511255
for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() {
12521256
if htlc.htlc_id == htlc_id_arg {
12531257
assert_eq!(htlc.payment_hash, payment_hash_calc);
@@ -1267,6 +1271,7 @@ impl<Signer: Sign> Channel<Signer> {
12671271
}
12681272
}
12691273
pending_idx = idx;
1274+
htlc_value_msat = htlc.amount_msat;
12701275
break;
12711276
}
12721277
}
@@ -1308,7 +1313,7 @@ impl<Signer: Sign> Channel<Signer> {
13081313
// TODO: We may actually be able to switch to a fulfill here, though its
13091314
// rare enough it may not be worth the complexity burden.
13101315
debug_assert!(false, "Tried to fulfill an HTLC that was already failed");
1311-
return (None, Some(monitor_update));
1316+
return (None, Some((monitor_update, htlc_value_msat)));
13121317
}
13131318
},
13141319
_ => {}
@@ -1320,7 +1325,7 @@ impl<Signer: Sign> Channel<Signer> {
13201325
});
13211326
#[cfg(any(test, feature = "fuzztarget"))]
13221327
self.historical_inbound_htlc_fulfills.insert(htlc_id_arg);
1323-
return (None, Some(monitor_update));
1328+
return (None, Some((monitor_update, htlc_value_msat)));
13241329
}
13251330
#[cfg(any(test, feature = "fuzztarget"))]
13261331
self.historical_inbound_htlc_fulfills.insert(htlc_id_arg);
@@ -1330,7 +1335,7 @@ impl<Signer: Sign> Channel<Signer> {
13301335
if let InboundHTLCState::Committed = htlc.state {
13311336
} else {
13321337
debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
1333-
return (None, Some(monitor_update));
1338+
return (None, Some((monitor_update, htlc_value_msat)));
13341339
}
13351340
log_trace!(logger, "Upgrading HTLC {} to LocalRemoved with a Fulfill in channel {}!", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id));
13361341
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone()));
@@ -1340,12 +1345,14 @@ impl<Signer: Sign> Channel<Signer> {
13401345
channel_id: self.channel_id(),
13411346
htlc_id: htlc_id_arg,
13421347
payment_preimage: payment_preimage_arg,
1343-
}), Some(monitor_update))
1348+
}), Some((monitor_update, htlc_value_msat)))
13441349
}
13451350

1346-
pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> Result<(Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>, Option<ChannelMonitorUpdate>), (ChannelError, ChannelMonitorUpdate)> where L::Target: Logger {
1351+
pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L)
1352+
-> Result<(Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>, Option<(ChannelMonitorUpdate, u64)>),
1353+
(ChannelError, ChannelMonitorUpdate)> where L::Target: Logger {
13471354
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
1348-
(Some(update_fulfill_htlc), Some(mut monitor_update)) => {
1355+
(Some(update_fulfill_htlc), Some((mut monitor_update, htlc_value_msat))) => {
13491356
let (commitment, mut additional_update) = match self.send_commitment_no_status_check(logger) {
13501357
Err(e) => return Err((e, monitor_update)),
13511358
Ok(res) => res
@@ -1354,14 +1361,14 @@ impl<Signer: Sign> Channel<Signer> {
13541361
// strictly increasing by one, so decrement it here.
13551362
self.latest_monitor_update_id = monitor_update.update_id;
13561363
monitor_update.updates.append(&mut additional_update.updates);
1357-
Ok((Some((update_fulfill_htlc, commitment)), Some(monitor_update)))
1364+
Ok((Some((update_fulfill_htlc, commitment)), Some((monitor_update, htlc_value_msat))))
13581365
},
13591366
(Some(_), None) => {
13601367
// If we generated a claim message, we absolutely should have generated a
13611368
// ChannelMonitorUpdate, otherwise we are going to probably lose funds.
13621369
unreachable!();
13631370
},
1364-
(None, Some(monitor_update)) => Ok((None, Some(monitor_update))),
1371+
(None, Some(monitor_and_value)) => Ok((None, Some(monitor_and_value))),
13651372
(None, None) => Ok((None, None))
13661373
}
13671374
}
@@ -2138,7 +2145,7 @@ impl<Signer: Sign> Channel<Signer> {
21382145

21392146
/// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
21402147
#[inline]
2141-
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentHash>, fail_reason: Option<HTLCFailReason>) -> Result<&HTLCSource, ChannelError> {
2148+
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentHash>, fail_reason: Option<HTLCFailReason>) -> Result<&OutboundHTLCOutput, ChannelError> {
21422149
for htlc in self.pending_outbound_htlcs.iter_mut() {
21432150
if htlc.htlc_id == htlc_id {
21442151
match check_preimage {
@@ -2157,13 +2164,13 @@ impl<Signer: Sign> Channel<Signer> {
21572164
OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) | OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) | OutboundHTLCState::RemoteRemoved(_) =>
21582165
return Err(ChannelError::Close(format!("Remote tried to fulfill/fail HTLC ({}) that they'd already fulfilled/failed", htlc_id))),
21592166
}
2160-
return Ok(&htlc.source);
2167+
return Ok(htlc);
21612168
}
21622169
}
21632170
Err(ChannelError::Close("Remote tried to fulfill/fail an HTLC we couldn't find".to_owned()))
21642171
}
21652172

2166-
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<HTLCSource, ChannelError> {
2173+
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(HTLCSource, u64), ChannelError> {
21672174
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
21682175
return Err(ChannelError::Close("Got fulfill HTLC message when channel was not in an operational state".to_owned()));
21692176
}
@@ -2172,7 +2179,7 @@ impl<Signer: Sign> Channel<Signer> {
21722179
}
21732180

21742181
let payment_hash = PaymentHash(Sha256::hash(&msg.payment_preimage.0[..]).into_inner());
2175-
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|source| source.clone())
2182+
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|htlc| (htlc.source.clone(), htlc.amount_msat))
21762183
}
21772184

21782185
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> {
@@ -2467,7 +2474,7 @@ impl<Signer: Sign> Channel<Signer> {
24672474
&HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, htlc_id, .. } => {
24682475
let (update_fulfill_msg_option, additional_monitor_update_opt) = self.get_update_fulfill_htlc(htlc_id, *payment_preimage, logger);
24692476
update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap());
2470-
if let Some(mut additional_monitor_update) = additional_monitor_update_opt {
2477+
if let Some((mut additional_monitor_update, _)) = additional_monitor_update_opt {
24712478
monitor_update.updates.append(&mut additional_monitor_update.updates);
24722479
}
24732480
},

0 commit comments

Comments
 (0)