Skip to content

Commit c09104f

Browse files
committed
Simplify call graph of get_update_fulfill_htlc since it can't Err.
1 parent 7e78fa6 commit c09104f

File tree

2 files changed

+83
-66
lines changed

2 files changed

+83
-66
lines changed

lightning/src/ln/channel.rs

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,33 @@ pub struct CounterpartyForwardingInfo {
301301
pub cltv_expiry_delta: u16,
302302
}
303303

304+
/// A return value enum for get_update_fulfill_htlc. See UpdateFulfillCommitFetch variants for
305+
/// description
306+
enum UpdateFulfillFetch {
307+
NewClaim {
308+
monitor_update: ChannelMonitorUpdate,
309+
msg: Option<msgs::UpdateFulfillHTLC>,
310+
},
311+
DuplicateClaim {},
312+
}
313+
314+
/// The return type of get_update_fulfill_htlc_and_commit.
315+
pub enum UpdateFulfillCommitFetch {
316+
/// Indicates the HTLC fulfill is new, and either generated an update_fulfill message, placed
317+
/// it in the holding cell, or re-generated the update_fulfill message after the same claim was
318+
/// previously placed in the holding cell (and has since been removed).
319+
NewClaim {
320+
/// The ChannelMonitorUpdate which places the new payment preimage in the channel monitor
321+
monitor_update: ChannelMonitorUpdate,
322+
/// The update_fulfill message and commitment_signed message (if the claim was not placed
323+
/// in the holding cell).
324+
msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>,
325+
},
326+
/// Indicates the HTLC fulfill is duplicative and already existed either in the holding cell
327+
/// or has been forgotten (presumably previously claimed).
328+
DuplicateClaim {},
329+
}
330+
304331
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
305332
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
306333
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
@@ -1232,13 +1259,7 @@ impl<Signer: Sign> Channel<Signer> {
12321259
make_funding_redeemscript(&self.get_holder_pubkeys().funding_pubkey, self.counterparty_funding_pubkey())
12331260
}
12341261

1235-
/// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made.
1236-
/// In such cases we debug_assert!(false) and return a ChannelError::Ignore. Thus, will always
1237-
/// return Ok(_) if debug assertions are turned on or preconditions are met.
1238-
///
1239-
/// Note that it is still possible to hit these assertions in case we find a preimage on-chain
1240-
/// but then have a reorg which settles on an HTLC-failure on chain.
1241-
fn get_update_fulfill_htlc<L: Deref>(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) -> Result<(Option<msgs::UpdateFulfillHTLC>, Option<ChannelMonitorUpdate>), ChannelError> where L::Target: Logger {
1262+
fn get_update_fulfill_htlc<L: Deref>(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) -> UpdateFulfillFetch where L::Target: Logger {
12421263
// Either ChannelFunded got set (which means it won't be unset) or there is no way any
12431264
// caller thought we could have something claimed (cause we wouldn't have accepted in an
12441265
// incoming HTLC anyway). If we got to ShutdownComplete, callers aren't allowed to call us,
@@ -1266,7 +1287,7 @@ impl<Signer: Sign> Channel<Signer> {
12661287
log_warn!(logger, "Have preimage and want to fulfill HTLC with payment hash {} we already failed against channel {}", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id()));
12671288
debug_assert!(false, "Tried to fulfill an HTLC that was already failed");
12681289
}
1269-
return Ok((None, None));
1290+
return UpdateFulfillFetch::DuplicateClaim {};
12701291
},
12711292
_ => {
12721293
debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
@@ -1282,7 +1303,7 @@ impl<Signer: Sign> Channel<Signer> {
12821303
// If we failed to find an HTLC to fulfill, make sure it was previously fulfilled and
12831304
// this is simply a duplicate claim, not previously failed and we lost funds.
12841305
debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg));
1285-
return Ok((None, None));
1306+
return UpdateFulfillFetch::DuplicateClaim {};
12861307
}
12871308

12881309
// Now update local state:
@@ -1306,7 +1327,7 @@ impl<Signer: Sign> Channel<Signer> {
13061327
self.latest_monitor_update_id -= 1;
13071328
#[cfg(any(test, feature = "fuzztarget"))]
13081329
debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg));
1309-
return Ok((None, None));
1330+
return UpdateFulfillFetch::DuplicateClaim {};
13101331
}
13111332
},
13121333
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
@@ -1315,7 +1336,7 @@ impl<Signer: Sign> Channel<Signer> {
13151336
// TODO: We may actually be able to switch to a fulfill here, though its
13161337
// rare enough it may not be worth the complexity burden.
13171338
debug_assert!(false, "Tried to fulfill an HTLC that was already failed");
1318-
return Ok((None, Some(monitor_update)));
1339+
return UpdateFulfillFetch::NewClaim { monitor_update, msg: None };
13191340
}
13201341
},
13211342
_ => {}
@@ -1327,7 +1348,7 @@ impl<Signer: Sign> Channel<Signer> {
13271348
});
13281349
#[cfg(any(test, feature = "fuzztarget"))]
13291350
self.historical_inbound_htlc_fulfills.insert(htlc_id_arg);
1330-
return Ok((None, Some(monitor_update)));
1351+
return UpdateFulfillFetch::NewClaim { monitor_update, msg: None };
13311352
}
13321353
#[cfg(any(test, feature = "fuzztarget"))]
13331354
self.historical_inbound_htlc_fulfills.insert(htlc_id_arg);
@@ -1337,44 +1358,43 @@ impl<Signer: Sign> Channel<Signer> {
13371358
if let InboundHTLCState::Committed = htlc.state {
13381359
} else {
13391360
debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
1340-
return Ok((None, Some(monitor_update)));
1361+
return UpdateFulfillFetch::NewClaim { monitor_update, msg: None };
13411362
}
13421363
log_trace!(logger, "Upgrading HTLC {} to LocalRemoved with a Fulfill in channel {}!", log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id));
13431364
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone()));
13441365
}
13451366

1346-
Ok((Some(msgs::UpdateFulfillHTLC {
1347-
channel_id: self.channel_id(),
1348-
htlc_id: htlc_id_arg,
1349-
payment_preimage: payment_preimage_arg,
1350-
}), Some(monitor_update)))
1367+
UpdateFulfillFetch::NewClaim {
1368+
monitor_update,
1369+
msg: Some(msgs::UpdateFulfillHTLC {
1370+
channel_id: self.channel_id(),
1371+
htlc_id: htlc_id_arg,
1372+
payment_preimage: payment_preimage_arg,
1373+
}),
1374+
}
13511375
}
13521376

1353-
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> where L::Target: Logger {
1354-
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger)? {
1355-
(Some(update_fulfill_htlc), Some(mut monitor_update)) => {
1377+
pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> Result<UpdateFulfillCommitFetch, ChannelError> where L::Target: Logger {
1378+
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
1379+
UpdateFulfillFetch::NewClaim { mut monitor_update, msg: Some(update_fulfill_htlc) } => {
13561380
let (commitment, mut additional_update) = self.send_commitment_no_status_check(logger)?;
13571381
// send_commitment_no_status_check may bump latest_monitor_id but we want them to be
13581382
// strictly increasing by one, so decrement it here.
13591383
self.latest_monitor_update_id = monitor_update.update_id;
13601384
monitor_update.updates.append(&mut additional_update.updates);
1361-
Ok((Some((update_fulfill_htlc, commitment)), Some(monitor_update)))
1362-
},
1363-
(Some(update_fulfill_htlc), None) => {
1364-
let (commitment, monitor_update) = self.send_commitment_no_status_check(logger)?;
1365-
Ok((Some((update_fulfill_htlc, commitment)), Some(monitor_update)))
1385+
Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, msgs: Some((update_fulfill_htlc, commitment)) })
13661386
},
1367-
(None, Some(monitor_update)) => Ok((None, Some(monitor_update))),
1368-
(None, None) => Ok((None, None))
1387+
UpdateFulfillFetch::NewClaim { monitor_update, msg: None } => Ok(UpdateFulfillCommitFetch::NewClaim { monitor_update, msgs: None }),
1388+
UpdateFulfillFetch::DuplicateClaim {} => Ok(UpdateFulfillCommitFetch::DuplicateClaim {}),
13691389
}
13701390
}
13711391

1372-
/// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made.
1373-
/// In such cases we debug_assert!(false) and return a ChannelError::Ignore. Thus, will always
1374-
/// return Ok(_) if debug assertions are turned on or preconditions are met.
1375-
///
1376-
/// Note that it is still possible to hit these assertions in case we find a preimage on-chain
1377-
/// but then have a reorg which settles on an HTLC-failure on chain.
1392+
/// We can only have one resolution per HTLC. In some cases around reconnect, we may fulfill
1393+
/// an HTLC more than once or fulfill once and then attempt to fail after reconnect. We cannot,
1394+
/// however, fail more than once as we wait for an upstream failure to be irrevocably committed
1395+
/// before we fail backwards.
1396+
/// If we do fail twice, we debug_assert!(false) and return Ok(None). Thus, will always return
1397+
/// Ok(_) if debug assertions are turned on or preconditions are met.
13781398
pub fn get_update_fail_htlc<L: Deref>(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, logger: &L) -> Result<Option<msgs::UpdateFailHTLC>, ChannelError> where L::Target: Logger {
13791399
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
13801400
panic!("Was asked to fail an HTLC when channel was not in an operational state");
@@ -2468,20 +2488,17 @@ impl<Signer: Sign> Channel<Signer> {
24682488
}
24692489
},
24702490
&HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, htlc_id, .. } => {
2471-
match self.get_update_fulfill_htlc(htlc_id, *payment_preimage, logger) {
2472-
Ok((update_fulfill_msg_option, additional_monitor_update_opt)) => {
2473-
update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap());
2474-
if let Some(mut additional_monitor_update) = additional_monitor_update_opt {
2475-
monitor_update.updates.append(&mut additional_monitor_update.updates);
2476-
}
2477-
},
2478-
Err(e) => {
2479-
if let ChannelError::Ignore(_) = e {}
2480-
else {
2481-
panic!("Got a non-IgnoreError action trying to fulfill holding cell HTLC");
2482-
}
2483-
}
2484-
}
2491+
// If an HTLC claim was previously added to the holding cell (via
2492+
// `get_update_fulfill_htlc`, then generating the claim message itself must
2493+
// not fail - any in between attempts to claim the HTLC will have resulted
2494+
// in it hitting the holding cell again and we cannot change the state of a
2495+
// holding cell HTLC from fulfill to anything else.
2496+
let (update_fulfill_msg_option, mut additional_monitor_update) =
2497+
if let UpdateFulfillFetch::NewClaim { msg, monitor_update } = self.get_update_fulfill_htlc(htlc_id, *payment_preimage, logger) {
2498+
(msg, monitor_update)
2499+
} else { unreachable!() };
2500+
update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap());
2501+
monitor_update.updates.append(&mut additional_monitor_update.updates);
24852502
},
24862503
&HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet } => {
24872504
match self.get_update_fail_htlc(htlc_id, err_packet.clone(), logger) {

lightning/src/ln/channelmanager.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use chain::transaction::{OutPoint, TransactionData};
4444
// construct one themselves.
4545
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
4646
pub use ln::channel::CounterpartyForwardingInfo;
47-
use ln::channel::{Channel, ChannelError, ChannelUpdateStatus};
47+
use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
4848
use ln::features::{InitFeatures, NodeFeatures};
4949
use routing::router::{Route, RouteHop};
5050
use ln::msgs;
@@ -2681,30 +2681,30 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
26812681
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(chan_id) {
26822682
let was_frozen_for_monitor = chan.get().is_awaiting_monitor_update();
26832683
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
2684-
Ok((msgs, monitor_option)) => {
2685-
if let Some(monitor_update) = monitor_option {
2684+
Ok(msgs_monitor_option) => {
2685+
if let UpdateFulfillCommitFetch::NewClaim { msgs, monitor_update } = msgs_monitor_option {
26862686
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
26872687
if was_frozen_for_monitor {
26882688
assert!(msgs.is_none());
26892689
} else {
26902690
return Err(Some((chan.get().get_counterparty_node_id(), handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, msgs.is_some()).unwrap_err())));
26912691
}
26922692
}
2693-
}
2694-
if let Some((msg, commitment_signed)) = msgs {
2695-
log_debug!(self.logger, "Claiming funds for HTLC with preimage {} resulted in a commitment_signed for channel {}",
2696-
log_bytes!(payment_preimage.0), log_bytes!(chan.get().channel_id()));
2697-
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
2698-
node_id: chan.get().get_counterparty_node_id(),
2699-
updates: msgs::CommitmentUpdate {
2700-
update_add_htlcs: Vec::new(),
2701-
update_fulfill_htlcs: vec![msg],
2702-
update_fail_htlcs: Vec::new(),
2703-
update_fail_malformed_htlcs: Vec::new(),
2704-
update_fee: None,
2705-
commitment_signed,
2706-
}
2707-
});
2693+
if let Some((msg, commitment_signed)) = msgs {
2694+
log_debug!(self.logger, "Claiming funds for HTLC with preimage {} resulted in a commitment_signed for channel {}",
2695+
log_bytes!(payment_preimage.0), log_bytes!(chan.get().channel_id()));
2696+
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
2697+
node_id: chan.get().get_counterparty_node_id(),
2698+
updates: msgs::CommitmentUpdate {
2699+
update_add_htlcs: Vec::new(),
2700+
update_fulfill_htlcs: vec![msg],
2701+
update_fail_htlcs: Vec::new(),
2702+
update_fail_malformed_htlcs: Vec::new(),
2703+
update_fee: None,
2704+
commitment_signed,
2705+
}
2706+
});
2707+
}
27082708
}
27092709
return Ok(())
27102710
},

0 commit comments

Comments
 (0)