Skip to content

Commit 950b697

Browse files
committed
ln/refactor: introduce enum for bolt 04 failure codes
1 parent 87a5756 commit 950b697

13 files changed

+656
-374
lines changed

lightning/src/ln/async_payments_tests.rs

Lines changed: 7 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,10 @@ 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!(
183+
update_malformed.failure_code,
184+
LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()
185+
);
183186
nodes[1]
184187
.node
185188
.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
@@ -196,7 +199,8 @@ fn invalid_keysend_payment_secret() {
196199
&nodes[0],
197200
payment_hash,
198201
false,
199-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]),
202+
PaymentFailedConditions::new()
203+
.expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]),
200204
);
201205
}
202206

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 23 additions & 24 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;
@@ -118,7 +117,7 @@ pub fn fail_blinded_htlc_backwards(
118117
match i {
119118
0 => {
120119
let mut payment_failed_conditions = PaymentFailedConditions::new()
121-
.expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]);
120+
.expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]);
122121
if retry_expected {
123122
payment_failed_conditions = payment_failed_conditions.retry_expected();
124123
}
@@ -137,7 +136,7 @@ pub fn fail_blinded_htlc_backwards(
137136
assert_eq!(blinded_node_updates.update_fail_malformed_htlcs.len(), 1);
138137
let update_malformed = &blinded_node_updates.update_fail_malformed_htlcs[0];
139138
assert_eq!(update_malformed.sha256_of_onion, [0; 32]);
140-
assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING);
139+
assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code());
141140
nodes[i-1].node.handle_update_fail_malformed_htlc(nodes[i].node.get_our_node_id(), update_malformed);
142141
do_commitment_signed_dance(&nodes[i-1], &nodes[i], &blinded_node_updates.commitment_signed, true, false);
143142
}
@@ -437,11 +436,11 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
437436
match check {
438437
ForwardCheckFail::ForwardPayloadEncodedAsReceive => {
439438
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
440-
PaymentFailedConditions::new().expected_htlc_error_data(0x4000 | 22, &[0; 0]));
439+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[0; 0]));
441440
}
442441
_ => {
443442
expect_payment_failed_conditions(&nodes[0], payment_hash, false,
444-
PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]));
443+
PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]));
445444
}
446445
};
447446
return
@@ -469,20 +468,20 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
469468

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

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

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

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

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

553552
enum ProcessPendingHTLCsCheck {
@@ -655,20 +654,20 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
655654

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

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

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

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

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

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

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

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

@@ -1728,7 +1727,8 @@ fn route_blinding_spec_test_vector() {
17281727
match onion_payment::decode_incoming_update_add_htlc_onion(
17291728
&eve_update_add, &eve_node_signer, &logger, &secp_ctx
17301729
) {
1731-
Err(HTLCFailureMsg::Malformed(msg)) => assert_eq!(msg.failure_code, INVALID_ONION_BLINDING),
1730+
Err((HTLCFailureMsg::Malformed(msg), _)) => assert_eq!(msg.failure_code,
1731+
LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()),
17321732
_ => panic!("Unexpected error")
17331733
}
17341734
}
@@ -2160,7 +2160,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
21602160
}
21612161
{
21622162
let payment_failed_conditions = PaymentFailedConditions::new()
2163-
.expected_htlc_error_data(0x4000 | 22, &[0; 0]);
2163+
.expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[0; 0]);
21642164
expect_payment_failed_conditions(&nodes[0], payment_hash, true, payment_failed_conditions);
21652165
}
21662166
}
@@ -2453,10 +2453,9 @@ fn test_trampoline_forward_rejection() {
24532453
do_commitment_signed_dance(&nodes[0], &nodes[1], &unblinded_node_updates.commitment_signed, false, false);
24542454
}
24552455
{
2456-
// Expect a PERM|10 (unknown_next_peer) error while we are unable to route forwarding
2457-
// Trampoline payments.
2456+
// Expect UnknownNextPeer error while we are unable to route forwarding Trampoline payments.
24582457
let payment_failed_conditions = PaymentFailedConditions::new()
2459-
.expected_htlc_error_data(0x4000 | 10, &[0; 0]);
2458+
.expected_htlc_error_data(LocalHTLCFailureReason::UnknownNextPeer, &[0; 0]);
24602459
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
24612460
}
24622461
}

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};
@@ -7548,21 +7548,17 @@ impl<SP: Deref> FundedChannel<SP> where
75487548

75497549
fn internal_htlc_satisfies_config(
75507550
&self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, config: &ChannelConfig,
7551-
) -> Result<(), (&'static str, u16)> {
7551+
) -> Result<(), (&'static str, LocalHTLCFailureReason)> {
75527552
let fee = amt_to_forward.checked_mul(config.forwarding_fee_proportional_millionths as u64)
75537553
.and_then(|prop_fee| (prop_fee / 1000000).checked_add(config.forwarding_fee_base_msat as u64));
75547554
if fee.is_none() || htlc.amount_msat < fee.unwrap() ||
75557555
(htlc.amount_msat - fee.unwrap()) < amt_to_forward {
7556-
return Err((
7557-
"Prior hop has deviated from specified fees parameters or origin node has obsolete ones",
7558-
0x1000 | 12, // fee_insufficient
7559-
));
7556+
return Err(("Prior hop has deviated from specified fees parameters or origin node has obsolete ones",
7557+
LocalHTLCFailureReason::FeeInsufficient));
75607558
}
75617559
if (htlc.cltv_expiry as u64) < outgoing_cltv_value as u64 + config.cltv_expiry_delta as u64 {
7562-
return Err((
7563-
"Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
7564-
0x1000 | 13, // incorrect_cltv_expiry
7565-
));
7560+
return Err(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta",
7561+
LocalHTLCFailureReason::IncorrectCLTVExpiry));
75667562
}
75677563
Ok(())
75687564
}
@@ -7572,7 +7568,7 @@ impl<SP: Deref> FundedChannel<SP> where
75727568
/// unsuccessful, falls back to the previous one if one exists.
75737569
pub fn htlc_satisfies_config(
75747570
&self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32,
7575-
) -> Result<(), (&'static str, u16)> {
7571+
) -> Result<(), (&'static str, LocalHTLCFailureReason)> {
75767572
self.internal_htlc_satisfies_config(&htlc, amt_to_forward, outgoing_cltv_value, &self.context.config())
75777573
.or_else(|err| {
75787574
if let Some(prev_config) = self.context.prev_config() {
@@ -7587,13 +7583,13 @@ impl<SP: Deref> FundedChannel<SP> where
75877583
/// this function determines whether to fail the HTLC, or forward / claim it.
75887584
pub fn can_accept_incoming_htlc<F: Deref, L: Deref>(
75897585
&self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
7590-
) -> Result<(), (&'static str, u16)>
7586+
) -> Result<(), (&'static str, LocalHTLCFailureReason)>
75917587
where
75927588
F::Target: FeeEstimator,
75937589
L::Target: Logger
75947590
{
75957591
if self.context.channel_state.is_local_shutdown_sent() {
7596-
return Err(("Shutdown was already sent", 0x4000|8))
7592+
return Err(("Shutdown was already sent", LocalHTLCFailureReason::DroppedPending))
75977593
}
75987594

75997595
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
@@ -7604,7 +7600,8 @@ impl<SP: Deref> FundedChannel<SP> where
76047600
// Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
76057601
log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
76067602
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7607-
return Err(("Exceeded our total dust exposure limit on counterparty commitment tx", 0x1000|7))
7603+
return Err(("Exceeded our total dust exposure limit on counterparty commitment tx",
7604+
LocalHTLCFailureReason::DustLimitCounterparty))
76087605
}
76097606
let htlc_success_dust_limit = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
76107607
0
@@ -7618,7 +7615,8 @@ impl<SP: Deref> FundedChannel<SP> where
76187615
if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
76197616
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
76207617
on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7621-
return Err(("Exceeded our dust exposure limit on holder commitment tx", 0x1000|7))
7618+
return Err(("Exceeded our dust exposure limit on holder commitment tx",
7619+
LocalHTLCFailureReason::DustLimitHolder))
76227620
}
76237621
}
76247622

@@ -7656,7 +7654,7 @@ impl<SP: Deref> FundedChannel<SP> where
76567654
}
76577655
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 {
76587656
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.context.channel_id());
7659-
return Err(("Fee spike buffer violation", 0x1000|7));
7657+
return Err(("Fee spike buffer violation", LocalHTLCFailureReason::FeeSpikeBuffer));
76607658
}
76617659
}
76627660

@@ -11119,7 +11117,7 @@ mod tests {
1111911117
use bitcoin::network::Network;
1112011118
#[cfg(splicing)]
1112111119
use bitcoin::Weight;
11122-
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
11120+
use crate::ln::onion_utils::LocalHTLCFailureReason;
1112311121
use crate::types::payment::{PaymentHash, PaymentPreimage};
1112411122
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1112511123
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
@@ -11759,7 +11757,8 @@ mod tests {
1175911757
htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] }
1176011758
};
1176111759
let dummy_holding_cell_malformed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC {
11762-
htlc_id, failure_code: INVALID_ONION_BLINDING, sha256_of_onion: [0; 32],
11760+
htlc_id, failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(),
11761+
sha256_of_onion: [0; 32],
1176311762
};
1176411763
let mut holding_cell_htlc_updates = Vec::with_capacity(12);
1176511764
for i in 0..12 {

0 commit comments

Comments
 (0)