Skip to content

Commit 9f9d532

Browse files
Expand HTLCDestination
1 parent f10b854 commit 9f9d532

File tree

4 files changed

+149
-124
lines changed

4 files changed

+149
-124
lines changed

lightning/src/events/mod.rs

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,39 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
466466
);
467467

468468
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].
469-
#[derive(Clone, Debug, PartialEq, Eq)]
469+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
470470
pub enum HTLCDestination {
471+
DustLimitReached { holder_commitment: bool },
472+
FeeSpikeBuffer,
473+
ShutdownSent,
474+
PrivateChannelForward,
475+
RealSCIDForward,
476+
ChannelNotReady,
477+
FeeInsufficient,
478+
IncorrectCLTVDelta,
479+
ChannelDisabled,
480+
HTLCBelowMinimum,
481+
InvalidKeysendPreimage,
482+
MissingPaymentSecret,
483+
IncorrectHTLCAmount,
484+
CLTVExpiryTooClose,
485+
CLTVExpiryTooFar,
486+
OutgoingCLTVTooClose,
487+
NodeIDForward,
488+
DownstreamHopFailed { node_id: Option<PublicKey>, channel_id: ChannelId },
489+
NextHopChannelClosed { node_id: Option<PublicKey>, channel_id: ChannelId },
490+
FailedPhantomPayment { payment_hash: PaymentHash },
491+
AmountExceedsChannelValue {
492+
amount_msat: u64,
493+
channel_value_msat: u64,
494+
},
495+
InvalidPaymentAmount {
496+
amount_msat: u64,
497+
next_outbound_min_msat: u64,
498+
next_outbound_max_msat: u64,
499+
},
500+
BlindedConstraintsViolated,
501+
IncorrectFinalCltvExpiry,
471502
/// We tried forwarding to a channel but failed to do so. An example of such an instance is when
472503
/// there is insufficient capacity in our outbound channel.
473504
NextHopChannel {
@@ -507,22 +538,22 @@ pub enum HTLCDestination {
507538
},
508539
}
509540

510-
impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
511-
(0, NextHopChannel) => {
512-
(0, node_id, required),
513-
(2, channel_id, required),
514-
},
515-
(1, InvalidForward) => {
516-
(0, requested_forward_scid, required),
517-
},
518-
(2, UnknownNextHop) => {
519-
(0, requested_forward_scid, required),
520-
},
521-
(3, InvalidOnion) => {},
522-
(4, FailedPayment) => {
523-
(0, payment_hash, required),
524-
},
525-
);
541+
// impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
542+
// (0, NextHopChannel) => {
543+
// (0, node_id, required),
544+
// (2, channel_id, required),
545+
// },
546+
// (1, InvalidForward) => {
547+
// (0, requested_forward_scid, required),
548+
// },
549+
// (2, UnknownNextHop) => {
550+
// (0, requested_forward_scid, required),
551+
// },
552+
// (3, InvalidOnion) => {},
553+
// (4, FailedPayment) => {
554+
// (0, payment_hash, required),
555+
// },
556+
// );
526557

527558
/// Will be used in [`Event::HTLCIntercepted`] to identify the next hop in the HTLC's path.
528559
/// Currently only used in serialization for the sake of maintaining compatibility. More variants

lightning/src/ln/channel.rs

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Channel
5757
use crate::chain::transaction::{OutPoint, TransactionData};
5858
use crate::sign::ecdsa::EcdsaChannelSigner;
5959
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
60-
use crate::events::{ClosureReason, Event};
60+
use crate::events::{ClosureReason, Event, HTLCDestination};
6161
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
6262
use crate::routing::gossip::NodeId;
6363
use crate::util::ser::{Readable, ReadableArgs, TransactionU16LenLimited, Writeable, Writer};
@@ -5888,21 +5888,14 @@ impl<SP: Deref> FundedChannel<SP> where
58885888
update_add_count += 1;
58895889
},
58905890
Err(e) => {
5891-
match e {
5892-
ChannelError::Ignore(ref msg) => {
5893-
log_info!(logger, "Failed to send HTLC with payment_hash {} due to {} in channel {}", &payment_hash, msg, &self.context.channel_id());
5894-
// If we fail to send here, then this HTLC should
5895-
// be failed backwards. Failing to send here
5896-
// indicates that this HTLC may keep being put back
5897-
// into the holding cell without ever being
5898-
// successfully forwarded/failed/fulfilled, causing
5899-
// our counterparty to eventually close on us.
5900-
htlcs_to_fail.push((source.clone(), *payment_hash));
5901-
},
5902-
_ => {
5903-
panic!("Got a non-IgnoreError action trying to send holding cell HTLC");
5904-
},
5905-
}
5891+
log_info!(logger, "Failed to send HTLC with payment_hash {} due to {:?} in channel {}", &payment_hash, e, &self.context.channel_id());
5892+
// If we fail to send here, then this HTLC should
5893+
// be failed backwards. Failing to send here
5894+
// indicates that this HTLC may keep being put back
5895+
// into the holding cell without ever being
5896+
// successfully forwarded/failed/fulfilled, causing
5897+
// our counterparty to eventually close on us.
5898+
htlcs_to_fail.push((source.clone(), *payment_hash));
59065899
}
59075900
}
59085901
None
@@ -7580,18 +7573,20 @@ impl<SP: Deref> FundedChannel<SP> where
75807573

75817574
fn internal_htlc_satisfies_config(
75827575
&self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, config: &ChannelConfig,
7583-
) -> Result<(), (&'static str, u16)> {
7576+
) -> Result<(), (HTLCDestination, &'static str, u16)> {
75847577
let fee = amt_to_forward.checked_mul(config.forwarding_fee_proportional_millionths as u64)
75857578
.and_then(|prop_fee| (prop_fee / 1000000).checked_add(config.forwarding_fee_base_msat as u64));
75867579
if fee.is_none() || htlc.amount_msat < fee.unwrap() ||
75877580
(htlc.amount_msat - fee.unwrap()) < amt_to_forward {
75887581
return Err((
7582+
HTLCDestination::FeeInsufficient,
75897583
"Prior hop has deviated from specified fees parameters or origin node has obsolete ones",
75907584
0x1000 | 12, // fee_insufficient
75917585
));
75927586
}
75937587
if (htlc.cltv_expiry as u64) < outgoing_cltv_value as u64 + config.cltv_expiry_delta as u64 {
75947588
return Err((
7589+
HTLCDestination::OutgoingCLTVTooClose,
75957590
"Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
75967591
0x1000 | 13, // incorrect_cltv_expiry
75977592
));
@@ -7604,7 +7599,7 @@ impl<SP: Deref> FundedChannel<SP> where
76047599
/// unsuccessful, falls back to the previous one if one exists.
76057600
pub fn htlc_satisfies_config(
76067601
&self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32,
7607-
) -> Result<(), (&'static str, u16)> {
7602+
) -> Result<(), (HTLCDestination, &'static str, u16)> {
76087603
self.internal_htlc_satisfies_config(&htlc, amt_to_forward, outgoing_cltv_value, &self.context.config())
76097604
.or_else(|err| {
76107605
if let Some(prev_config) = self.context.prev_config() {
@@ -7619,13 +7614,13 @@ impl<SP: Deref> FundedChannel<SP> where
76197614
/// this function determines whether to fail the HTLC, or forward / claim it.
76207615
pub fn can_accept_incoming_htlc<F: Deref, L: Deref>(
76217616
&self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
7622-
) -> Result<(), (&'static str, u16)>
7617+
) -> Result<(), (HTLCDestination, u16)>
76237618
where
76247619
F::Target: FeeEstimator,
76257620
L::Target: Logger
76267621
{
76277622
if self.context.channel_state.is_local_shutdown_sent() {
7628-
return Err(("Shutdown was already sent", 0x4000|8))
7623+
return Err((HTLCDestination::ShutdownSent, 0x4000|8))
76297624
}
76307625

76317626
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
@@ -7636,7 +7631,7 @@ impl<SP: Deref> FundedChannel<SP> where
76367631
// Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
76377632
log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
76387633
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7639-
return Err(("Exceeded our total dust exposure limit on counterparty commitment tx", 0x1000|7))
7634+
return Err((HTLCDestination::DustLimitReached { holder_commitment: false }, 0x1000|7))
76407635
}
76417636
let htlc_success_dust_limit = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
76427637
0
@@ -7650,7 +7645,7 @@ impl<SP: Deref> FundedChannel<SP> where
76507645
if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
76517646
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
76527647
on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7653-
return Err(("Exceeded our dust exposure limit on holder commitment tx", 0x1000|7))
7648+
return Err((HTLCDestination::DustLimitReached { holder_commitment: true }, 0x1000|7))
76547649
}
76557650
}
76567651

@@ -7688,7 +7683,7 @@ impl<SP: Deref> FundedChannel<SP> where
76887683
}
76897684
if pending_remote_value_msat.saturating_sub(self.funding.holder_selected_channel_reserve_satoshis * 1000).saturating_sub(anchor_outputs_value_msat) < remote_fee_cost_incl_stuck_buffer_msat {
76907685
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.context.channel_id());
7691-
return Err(("Fee spike buffer violation", 0x1000|7));
7686+
return Err((HTLCDestination::FeeSpikeBuffer, 0x1000|7));
76927687
}
76937688
}
76947689

@@ -8564,18 +8559,13 @@ impl<SP: Deref> FundedChannel<SP> where
85648559
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource,
85658560
onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>,
85668561
blinding_point: Option<PublicKey>, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L
8567-
) -> Result<(), ChannelError>
8562+
) -> Result<(), HTLCDestination>
85688563
where F::Target: FeeEstimator, L::Target: Logger
85698564
{
85708565
self
85718566
.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, true,
85728567
skimmed_fee_msat, blinding_point, fee_estimator, logger)
85738568
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
8574-
.map_err(|err| {
8575-
if let ChannelError::Ignore(_) = err { /* fine */ }
8576-
else { debug_assert!(false, "Queueing cannot trigger channel failure"); }
8577-
err
8578-
})
85798569
}
85808570

85818571
/// Adds a pending outbound HTLC to this channel, note that you probably want
@@ -8599,33 +8589,42 @@ impl<SP: Deref> FundedChannel<SP> where
85998589
onion_routing_packet: msgs::OnionPacket, mut force_holding_cell: bool,
86008590
skimmed_fee_msat: Option<u64>, blinding_point: Option<PublicKey>,
86018591
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L
8602-
) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError>
8592+
) -> Result<Option<msgs::UpdateAddHTLC>, HTLCDestination>
86038593
where F::Target: FeeEstimator, L::Target: Logger
86048594
{
86058595
if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) ||
86068596
self.context.channel_state.is_local_shutdown_sent() ||
86078597
self.context.channel_state.is_remote_shutdown_sent()
86088598
{
8609-
return Err(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned()));
8599+
return Err(HTLCDestination::ChannelNotReady);
86108600
}
86118601
let channel_total_msat = self.funding.get_value_satoshis() * 1000;
86128602
if amount_msat > channel_total_msat {
8613-
return Err(ChannelError::Ignore(format!("Cannot send amount {}, because it is more than the total value of the channel {}", amount_msat, channel_total_msat)));
8603+
return Err(HTLCDestination::AmountExceedsChannelValue {
8604+
amount_msat,
8605+
channel_value_msat: channel_total_msat,
8606+
})
86148607
}
86158608

86168609
if amount_msat == 0 {
8617-
return Err(ChannelError::Ignore("Cannot send 0-msat HTLC".to_owned()));
8610+
return Err(HTLCDestination::HTLCBelowMinimum)
86188611
}
86198612

86208613
let available_balances = self.context.get_available_balances(&self.funding, fee_estimator);
86218614
if amount_msat < available_balances.next_outbound_htlc_minimum_msat {
8622-
return Err(ChannelError::Ignore(format!("Cannot send less than our next-HTLC minimum - {} msat",
8623-
available_balances.next_outbound_htlc_minimum_msat)));
8615+
return Err(HTLCDestination::InvalidPaymentAmount {
8616+
amount_msat,
8617+
next_outbound_min_msat: available_balances.next_outbound_htlc_minimum_msat,
8618+
next_outbound_max_msat: available_balances.next_outbound_htlc_limit_msat,
8619+
});
86248620
}
86258621

86268622
if amount_msat > available_balances.next_outbound_htlc_limit_msat {
8627-
return Err(ChannelError::Ignore(format!("Cannot send more than our next-HTLC maximum - {} msat",
8628-
available_balances.next_outbound_htlc_limit_msat)));
8623+
return Err(HTLCDestination::InvalidPaymentAmount {
8624+
amount_msat,
8625+
next_outbound_min_msat: available_balances.next_outbound_htlc_minimum_msat,
8626+
next_outbound_max_msat: available_balances.next_outbound_htlc_limit_msat,
8627+
});
86298628
}
86308629

86318630
if self.context.channel_state.is_peer_disconnected() {
@@ -8635,7 +8634,7 @@ impl<SP: Deref> FundedChannel<SP> where
86358634
// disconnected during the time the previous hop was doing the commitment dance we may
86368635
// end up getting here after the forwarding delay. In any case, returning an
86378636
// IgnoreError will get ChannelManager to do the right thing and fail backwards now.
8638-
return Err(ChannelError::Ignore("Cannot send an HTLC while disconnected from channel counterparty".to_owned()));
8637+
return Err(HTLCDestination::ChannelDisabled)
86398638
}
86408639

86418640
let need_holding_cell = !self.context.channel_state.can_generate_new_commitment();
@@ -8850,12 +8849,11 @@ impl<SP: Deref> FundedChannel<SP> where
88508849
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32,
88518850
source: HTLCSource, onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>,
88528851
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L
8853-
) -> Result<Option<ChannelMonitorUpdate>, ChannelError>
8852+
) -> Result<Option<ChannelMonitorUpdate>, HTLCDestination>
88548853
where F::Target: FeeEstimator, L::Target: Logger
88558854
{
88568855
let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source,
88578856
onion_routing_packet, false, skimmed_fee_msat, None, fee_estimator, logger);
8858-
if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } }
88598857
match send_res? {
88608858
Some(_) => {
88618859
let monitor_update = self.build_commitment_no_status_check(logger);

0 commit comments

Comments
 (0)