Skip to content

Commit a0131e4

Browse files
committed
ln/refactor: introduce enum for bolt 04 failure codes
1 parent f58c320 commit a0131e4

13 files changed

+647
-365
lines changed

lightning/src/ln/async_payments_tests.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::ln::msgs::{
2020
BaseMessageHandler, ChannelMessageHandler, MessageSendEvent, OnionMessageHandler,
2121
};
2222
use crate::ln::offers_tests;
23-
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
23+
use crate::ln::onion_utils::LocalHTLCFailureReason;
2424
use crate::ln::outbound_payment::PendingOutboundPayment;
2525
use crate::ln::outbound_payment::Retry;
2626
use crate::offers::invoice_request::InvoiceRequest;
@@ -179,7 +179,7 @@ fn invalid_keysend_payment_secret() {
179179
assert_eq!(updates_2_1.update_fail_malformed_htlcs.len(), 1);
180180
let update_malformed = &updates_2_1.update_fail_malformed_htlcs[0];
181181
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
182-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
182+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding);
183183
nodes[1]
184184
.node
185185
.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
@@ -196,7 +196,8 @@ fn invalid_keysend_payment_secret() {
196196
&nodes[0],
197197
payment_hash,
198198
false,
199-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]),
199+
PaymentFailedConditions::new()
200+
.expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]),
200201
);
201202
}
202203

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ use crate::ln::inbound_payment::ExpandedKey;
2626
use crate::ln::msgs;
2727
use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, UnsignedGossipMessage, MessageSendEvent};
2828
use crate::ln::onion_payment;
29-
use crate::ln::onion_utils;
30-
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
29+
use crate::ln::onion_utils::{self, LocalHTLCFailureReason};
3130
use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS};
3231
use crate::offers::invoice::UnsignedBolt12Invoice;
3332
use crate::offers::nonce::Nonce;
@@ -117,7 +116,7 @@ pub fn fail_blinded_htlc_backwards(
117116
match i {
118117
0 => {
119118
let mut payment_failed_conditions = PaymentFailedConditions::new()
120-
.expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]);
119+
.expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]);
121120
if retry_expected {
122121
payment_failed_conditions = payment_failed_conditions.retry_expected();
123122
}
@@ -136,7 +135,7 @@ pub fn fail_blinded_htlc_backwards(
136135
assert_eq!(blinded_node_updates.update_fail_malformed_htlcs.len(), 1);
137136
let update_malformed = &blinded_node_updates.update_fail_malformed_htlcs[0];
138137
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
139-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
138+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
140139
nodes[i-1].node.handle_update_fail_malformed_htlc(nodes[i].node.get_our_node_id(), update_malformed);
141140
do_commitment_signed_dance(&nodes[i-1], &nodes[i], &blinded_node_updates.commitment_signed, true, false);
142141
}
@@ -436,11 +435,11 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
436435
match check {
437436
ForwardCheckFail::ForwardPayloadEncodedAsReceive => {
438437
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
439-
PaymentFailedConditions::new().expected_htlc_error_data(0x4000 | 22, &[0; 0]));
438+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[0; 0]));
440439
}
441440
_ => {
442441
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
443-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
442+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
444443
}
445444
};
446445
return
@@ -468,20 +467,20 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
468467

469468
let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
470469
let update_malformed = &mut updates.update_fail_malformed_htlcs[0];
471-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
470+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
472471
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
473472

474473
// Ensure the intro node will properly blind the error if its downstream node failed to do so.
475474
update_malformed.sha256_of_onion = [1; 32];
476-
update_malformed.failure_code = INVALID_ONION_BLINDING ^ 1;
475+
update_malformed.failure_code = LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() ^ 1;
477476
nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
478477
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, true, false);
479478

480479
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
481480
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
482481
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
483482
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
484-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
483+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
485484
}
486485

487486
#[test]
@@ -533,7 +532,7 @@ fn failed_backwards_to_intro_node() {
533532
let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
534533
let mut update_malformed = &mut updates.update_fail_malformed_htlcs[0];
535534
// Check that the final node encodes its failure correctly.
536-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
535+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
537536
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
538537

539538
// Modify such the final hop does not correctly blind their error so we can ensure the intro node
@@ -546,7 +545,7 @@ fn failed_backwards_to_intro_node() {
546545
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
547546
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
548547
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
549-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
548+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
550549
}
551550

552551
enum ProcessPendingHTLCsCheck {
@@ -654,20 +653,20 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
654653

655654
let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
656655
let update_malformed = &mut updates.update_fail_malformed_htlcs[0];
657-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
656+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
658657
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
659658

660659
// Ensure the intro node will properly blind the error if its downstream node failed to do so.
661660
update_malformed.sha256_of_onion = [1; 32];
662-
update_malformed.failure_code = INVALID_ONION_BLINDING ^ 1;
661+
update_malformed.failure_code = LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() ^ 1;
663662
nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
664663
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, true, false);
665664

666665
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
667666
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
668667
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
669668
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
670-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
669+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
671670
}
672671

673672
#[test]
@@ -1041,7 +1040,7 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
10411040
assert_eq!(updates_2_1.update_fail_malformed_htlcs.len(), 1);
10421041
let update_malformed = &updates_2_1.update_fail_malformed_htlcs[0];
10431042
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
1044-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
1043+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
10451044
nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
10461045
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates_2_1.commitment_signed, true, false);
10471046

@@ -1063,7 +1062,7 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
10631062
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates_1_0.update_fail_htlcs[0]);
10641063
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates_1_0.commitment_signed, false, false);
10651064
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
1066-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
1065+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
10671066
}
10681067

10691068
#[test]
@@ -1130,7 +1129,7 @@ fn blinded_path_retries() {
11301129
assert_eq!(updates.update_fail_malformed_htlcs.len(), 1);
11311130
let update_malformed = &updates.update_fail_malformed_htlcs[0];
11321131
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
1133-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
1132+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
11341133
$intro_node.node.handle_update_fail_malformed_htlc(nodes[3].node.get_our_node_id(), update_malformed);
11351134
do_commitment_signed_dance(&$intro_node, &nodes[3], &updates.commitment_signed, true, false);
11361135

@@ -1250,7 +1249,7 @@ fn min_htlc() {
12501249
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
12511250
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
12521251
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
1253-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
1252+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
12541253
}
12551254

12561255
#[test]
@@ -1445,7 +1444,7 @@ fn fails_receive_tlvs_authentication() {
14451444
commitment_signed_dance!(nodes[0], nodes[1], update_fail.commitment_signed, false);
14461445
expect_payment_failed_conditions(
14471446
&nodes[0], payment_hash, true,
1448-
PaymentFailedConditions::new().expected_htlc_error_data(0x4000 | 22, &[]),
1447+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[]),
14491448
);
14501449
}
14511450

@@ -1727,7 +1726,8 @@ fn route_blinding_spec_test_vector() {
17271726
match onion_payment::decode_incoming_update_add_htlc_onion(
17281727
&eve_update_add, &eve_node_signer, &logger, &secp_ctx
17291728
) {
1730-
Err(HTLCFailureMsg::Malformed(msg)) => assert_eq!(msg.failure_code, INVALID_ONION_BLINDING),
1729+
Err((HTLCFailureMsg::Malformed(msg), _)) => assert_eq!(msg.failure_code,
1730+
LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()),
17311731
_ => panic!("Unexpected error")
17321732
}
17331733
}

lightning/src/ln/channel.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::ln::chan_utils::{
5050
#[cfg(splicing)]
5151
use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
5252
use crate::ln::chan_utils;
53-
use crate::ln::onion_utils::{HTLCFailReason};
53+
use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason};
5454
use crate::chain::BestBlock;
5555
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator, fee_for_weight};
5656
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
@@ -7581,21 +7581,17 @@ impl<SP: Deref> FundedChannel<SP> where
75817581

75827582
fn internal_htlc_satisfies_config(
75837583
&self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, config: &ChannelConfig,
7584-
) -> Result<(), (&'static str, u16)> {
7584+
) -> Result<(), (&'static str, LocalHTLCFailureReason)> {
75857585
let fee = amt_to_forward.checked_mul(config.forwarding_fee_proportional_millionths as u64)
75867586
.and_then(|prop_fee| (prop_fee / 1000000).checked_add(config.forwarding_fee_base_msat as u64));
75877587
if fee.is_none() || htlc.amount_msat < fee.unwrap() ||
75887588
(htlc.amount_msat - fee.unwrap()) < amt_to_forward {
7589-
return Err((
7590-
"Prior hop has deviated from specified fees parameters or origin node has obsolete ones",
7591-
0x1000 | 12, // fee_insufficient
7592-
));
7589+
return Err(("Prior hop has deviated from specified fees parameters or origin node has obsolete ones",
7590+
LocalHTLCFailureReason::FeeInsufficient));
75937591
}
75947592
if (htlc.cltv_expiry as u64) < outgoing_cltv_value as u64 + config.cltv_expiry_delta as u64 {
7595-
return Err((
7596-
"Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
7597-
0x1000 | 13, // incorrect_cltv_expiry
7598-
));
7593+
return Err(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
7594+
LocalHTLCFailureReason::IncorrectCLTVExpiry));
75997595
}
76007596
Ok(())
76017597
}
@@ -7605,7 +7601,7 @@ impl<SP: Deref> FundedChannel<SP> where
76057601
/// unsuccessful, falls back to the previous one if one exists.
76067602
pub fn htlc_satisfies_config(
76077603
&self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32,
7608-
) -> Result<(), (&'static str, u16)> {
7604+
) -> Result<(), (&'static str, LocalHTLCFailureReason)> {
76097605
self.internal_htlc_satisfies_config(&htlc, amt_to_forward, outgoing_cltv_value, &self.context.config())
76107606
.or_else(|err| {
76117607
if let Some(prev_config) = self.context.prev_config() {
@@ -7620,13 +7616,13 @@ impl<SP: Deref> FundedChannel<SP> where
76207616
/// this function determines whether to fail the HTLC, or forward / claim it.
76217617
pub fn can_accept_incoming_htlc<F: Deref, L: Deref>(
76227618
&self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
7623-
) -> Result<(), (&'static str, u16)>
7619+
) -> Result<(), (&'static str, LocalHTLCFailureReason)>
76247620
where
76257621
F::Target: FeeEstimator,
76267622
L::Target: Logger
76277623
{
76287624
if self.context.channel_state.is_local_shutdown_sent() {
7629-
return Err(("Shutdown was already sent", 0x4000|8))
7625+
return Err(("Shutdown was already sent", LocalHTLCFailureReason::DroppedPending))
76307626
}
76317627

76327628
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
@@ -7637,7 +7633,8 @@ impl<SP: Deref> FundedChannel<SP> where
76377633
// Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
76387634
log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
76397635
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7640-
return Err(("Exceeded our total dust exposure limit on counterparty commitment tx", 0x1000|7))
7636+
return Err(("Exceeded our total dust exposure limit on counterparty commitment tx",
7637+
LocalHTLCFailureReason::DustLimitCounterparty))
76417638
}
76427639
let htlc_success_dust_limit = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
76437640
0
@@ -7651,7 +7648,8 @@ impl<SP: Deref> FundedChannel<SP> where
76517648
if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
76527649
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
76537650
on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7654-
return Err(("Exceeded our dust exposure limit on holder commitment tx", 0x1000|7))
7651+
return Err(("Exceeded our dust exposure limit on holder commitment tx",
7652+
LocalHTLCFailureReason::DustLimitHolder))
76557653
}
76567654
}
76577655

@@ -7689,7 +7687,7 @@ impl<SP: Deref> FundedChannel<SP> where
76897687
}
76907688
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 {
76917689
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.context.channel_id());
7692-
return Err(("Fee spike buffer violation", 0x1000|7));
7690+
return Err(("Fee spike buffer violation", LocalHTLCFailureReason::FeeSpikeBuffer));
76937691
}
76947692
}
76957693

@@ -11150,7 +11148,7 @@ mod tests {
1115011148
use bitcoin::network::Network;
1115111149
#[cfg(splicing)]
1115211150
use bitcoin::Weight;
11153-
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
11151+
use crate::ln::onion_utils::LocalHTLCFailureReason;
1115411152
use crate::types::payment::{PaymentHash, PaymentPreimage};
1115511153
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1115611154
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
@@ -11790,7 +11788,8 @@ mod tests {
1179011788
htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] }
1179111789
};
1179211790
let dummy_holding_cell_malformed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC {
11793-
htlc_id, failure_code: INVALID_ONION_BLINDING, sha256_of_onion: [0; 32],
11791+
htlc_id, failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(),
11792+
sha256_of_onion: [0; 32],
1179411793
};
1179511794
let mut holding_cell_htlc_updates = Vec::with_capacity(12);
1179611795
for i in 0..12 {

0 commit comments

Comments
 (0)