Skip to content

Commit 1f272c0

Browse files
Change PaymentPathFailed's optional network update to a Failure enum
This let us capture the errors when we fail without committing to an HTLC vs failing via update_fail.
1 parent ea1c101 commit 1f272c0

File tree

7 files changed

+99
-62
lines changed

7 files changed

+99
-62
lines changed

lightning-background-processor/src/lib.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
3333
use lightning::routing::utxo::UtxoLookup;
3434
use lightning::routing::router::Router;
3535
use lightning::routing::scoring::{Score, WriteableScore};
36-
use lightning::util::events::{Event, EventHandler, EventsProvider};
36+
use lightning::util::events::{Event, EventHandler, EventsProvider, Failure};
3737
use lightning::util::logger::Logger;
3838
use lightning::util::persist::Persister;
3939
use lightning_rapid_gossip_sync::RapidGossipSync;
@@ -215,10 +215,10 @@ where
215215
fn handle_network_graph_update<L: Deref>(
216216
network_graph: &NetworkGraph<L>, event: &Event
217217
) where L::Target: Logger {
218-
if let Event::PaymentPathFailed { ref network_update, .. } = event {
219-
if let Some(network_update) = network_update {
220-
network_graph.handle_network_update(&network_update);
221-
}
218+
if let Event::PaymentPathFailed {
219+
failure: Failure::OnPath { network_update: Some(ref upd) }, .. } = event
220+
{
221+
network_graph.handle_network_update(upd);
222222
}
223223
}
224224

@@ -673,7 +673,7 @@ mod tests {
673673
use lightning::routing::router::{DefaultRouter, RouteHop};
674674
use lightning::routing::scoring::{ChannelUsage, Score};
675675
use lightning::util::config::UserConfig;
676-
use lightning::util::events::{Event, MessageSendEventsProvider, MessageSendEvent};
676+
use lightning::util::events::{Event, Failure, MessageSendEventsProvider, MessageSendEvent};
677677
use lightning::util::ser::Writeable;
678678
use lightning::util::test_utils;
679679
use lightning::util::persist::KVStorePersister;
@@ -1365,7 +1365,7 @@ mod tests {
13651365
payment_id: None,
13661366
payment_hash: PaymentHash([42; 32]),
13671367
payment_failed_permanently: false,
1368-
network_update: None,
1368+
failure: Failure::OnPath { network_update: None },
13691369
path: path.clone(),
13701370
short_channel_id: Some(scored_scid),
13711371
retry: None,
@@ -1385,7 +1385,7 @@ mod tests {
13851385
payment_id: None,
13861386
payment_hash: PaymentHash([42; 32]),
13871387
payment_failed_permanently: true,
1388-
network_update: None,
1388+
failure: Failure::OnPath { network_update: None },
13891389
path: path.clone(),
13901390
short_channel_id: None,
13911391
retry: None,

lightning/src/ln/functional_test_utils.rs

+20-19
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::util::enforcing_trait_impls::EnforcingSigner;
2424
use crate::util::scid_utils;
2525
use crate::util::test_utils;
2626
use crate::util::test_utils::{panicking, TestChainMonitor};
27-
use crate::util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose};
27+
use crate::util::events::{Event, Failure, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose};
2828
use crate::util::errors::APIError;
2929
use crate::util::config::UserConfig;
3030
use crate::util::ser::{ReadableArgs, Writeable};
@@ -1818,7 +1818,7 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
18181818
) {
18191819
if conditions.expected_mpp_parts_remain { assert_eq!(payment_failed_events.len(), 1); } else { assert_eq!(payment_failed_events.len(), 2); }
18201820
let expected_payment_id = match &payment_failed_events[0] {
1821-
Event::PaymentPathFailed { payment_hash, payment_failed_permanently, path, retry, payment_id, network_update, short_channel_id,
1821+
Event::PaymentPathFailed { payment_hash, payment_failed_permanently, path, retry, payment_id, failure, short_channel_id,
18221822
#[cfg(test)]
18231823
error_code,
18241824
#[cfg(test)]
@@ -1843,23 +1843,24 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>(
18431843
}
18441844

18451845
if let Some(chan_closed) = conditions.expected_blamed_chan_closed {
1846-
match network_update {
1847-
Some(NetworkUpdate::ChannelUpdateMessage { ref msg }) if !chan_closed => {
1848-
if let Some(scid) = conditions.expected_blamed_scid {
1849-
assert_eq!(msg.contents.short_channel_id, scid);
1850-
}
1851-
const CHAN_DISABLED_FLAG: u8 = 2;
1852-
assert_eq!(msg.contents.flags & CHAN_DISABLED_FLAG, 0);
1853-
},
1854-
Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) if chan_closed => {
1855-
if let Some(scid) = conditions.expected_blamed_scid {
1856-
assert_eq!(*short_channel_id, scid);
1857-
}
1858-
assert!(is_permanent);
1859-
},
1860-
Some(_) => panic!("Unexpected update type"),
1861-
None => panic!("Expected update"),
1862-
}
1846+
if let Failure::OnPath { network_update: Some(upd) } = failure {
1847+
match upd {
1848+
NetworkUpdate::ChannelUpdateMessage { ref msg } if !chan_closed => {
1849+
if let Some(scid) = conditions.expected_blamed_scid {
1850+
assert_eq!(msg.contents.short_channel_id, scid);
1851+
}
1852+
const CHAN_DISABLED_FLAG: u8 = 2;
1853+
assert_eq!(msg.contents.flags & CHAN_DISABLED_FLAG, 0);
1854+
},
1855+
NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } if chan_closed => {
1856+
if let Some(scid) = conditions.expected_blamed_scid {
1857+
assert_eq!(*short_channel_id, scid);
1858+
}
1859+
assert!(is_permanent);
1860+
},
1861+
_ => panic!("Unexpected update type"),
1862+
}
1863+
} else { panic!("Expected network update"); }
18631864
}
18641865

18651866
payment_id.unwrap()

lightning/src/ln/functional_tests.rs

+12-17
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::ln::msgs;
3131
use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction};
3232
use crate::util::enforcing_trait_impls::EnforcingSigner;
3333
use crate::util::test_utils;
34-
use crate::util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose, ClosureReason, HTLCDestination};
34+
use crate::util::events::{Event, Failure, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose, ClosureReason, HTLCDestination};
3535
use crate::util::errors::APIError;
3636
use crate::util::ser::{Writeable, ReadableArgs};
3737
use crate::util::config::UserConfig;
@@ -3235,12 +3235,12 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
32353235
let events = nodes[0].node.get_and_clear_pending_events();
32363236
assert_eq!(events.len(), 6);
32373237
match events[0] {
3238-
Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
3238+
Event::PaymentPathFailed { ref payment_hash, ref failure, .. } => {
32393239
assert!(failed_htlcs.insert(payment_hash.0));
32403240
// If we delivered B's RAA we got an unknown preimage error, not something
32413241
// that we should update our routing table for.
32423242
if !deliver_bs_raa {
3243-
assert!(network_update.is_some());
3243+
if let Failure::OnPath { network_update: Some(_) } = failure { } else { panic!("Unexpected path failure") }
32443244
}
32453245
},
32463246
_ => panic!("Unexpected event"),
@@ -3252,9 +3252,8 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
32523252
_ => panic!("Unexpected event"),
32533253
}
32543254
match events[2] {
3255-
Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
3255+
Event::PaymentPathFailed { ref payment_hash, failure: Failure::OnPath { network_update: Some(_) }, .. } => {
32563256
assert!(failed_htlcs.insert(payment_hash.0));
3257-
assert!(network_update.is_some());
32583257
},
32593258
_ => panic!("Unexpected event"),
32603259
}
@@ -3265,9 +3264,8 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
32653264
_ => panic!("Unexpected event"),
32663265
}
32673266
match events[4] {
3268-
Event::PaymentPathFailed { ref payment_hash, ref network_update, .. } => {
3267+
Event::PaymentPathFailed { ref payment_hash, failure: Failure::OnPath { network_update: Some(_) }, .. } => {
32693268
assert!(failed_htlcs.insert(payment_hash.0));
3270-
assert!(network_update.is_some());
32713269
},
32723270
_ => panic!("Unexpected event"),
32733271
}
@@ -5148,14 +5146,14 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
51485146
let mut as_failds = HashSet::new();
51495147
let mut as_updates = 0;
51505148
for event in as_events.iter() {
5151-
if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref network_update, .. } = event {
5149+
if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref failure, .. } = event {
51525150
assert!(as_failds.insert(*payment_hash));
51535151
if *payment_hash != payment_hash_2 {
51545152
assert_eq!(*payment_failed_permanently, deliver_last_raa);
51555153
} else {
51565154
assert!(!payment_failed_permanently);
51575155
}
5158-
if network_update.is_some() {
5156+
if let Failure::OnPath { network_update: Some(_) } = failure {
51595157
as_updates += 1;
51605158
}
51615159
} else if let &Event::PaymentFailed { .. } = event {
@@ -5174,14 +5172,14 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
51745172
let mut bs_failds = HashSet::new();
51755173
let mut bs_updates = 0;
51765174
for event in bs_events.iter() {
5177-
if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref network_update, .. } = event {
5175+
if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref failure, .. } = event {
51785176
assert!(bs_failds.insert(*payment_hash));
51795177
if *payment_hash != payment_hash_1 && *payment_hash != payment_hash_5 {
51805178
assert_eq!(*payment_failed_permanently, deliver_last_raa);
51815179
} else {
51825180
assert!(!payment_failed_permanently);
51835181
}
5184-
if network_update.is_some() {
5182+
if let Failure::OnPath { network_update: Some(_) } = failure {
51855183
bs_updates += 1;
51865184
}
51875185
} else if let &Event::PaymentFailed { .. } = event {
@@ -5695,11 +5693,10 @@ fn test_fail_holding_cell_htlc_upon_free() {
56955693
let events = nodes[0].node.get_and_clear_pending_events();
56965694
assert_eq!(events.len(), 2);
56975695
match &events[0] {
5698-
&Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref short_channel_id, .. } => {
5696+
&Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, failure: Failure::OnPath { network_update: None }, ref short_channel_id, .. } => {
56995697
assert_eq!(PaymentId(our_payment_hash.0), *payment_id.as_ref().unwrap());
57005698
assert_eq!(our_payment_hash.clone(), *payment_hash);
57015699
assert_eq!(*payment_failed_permanently, false);
5702-
assert_eq!(*network_update, None);
57035700
assert_eq!(*short_channel_id, Some(route.paths[0][0].short_channel_id));
57045701
},
57055702
_ => panic!("Unexpected event"),
@@ -5785,11 +5782,10 @@ fn test_free_and_fail_holding_cell_htlcs() {
57855782
let events = nodes[0].node.get_and_clear_pending_events();
57865783
assert_eq!(events.len(), 2);
57875784
match &events[0] {
5788-
&Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref short_channel_id, .. } => {
5785+
&Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, failure: Failure::OnPath { network_update: None }, ref short_channel_id, .. } => {
57895786
assert_eq!(payment_id_2, *payment_id.as_ref().unwrap());
57905787
assert_eq!(payment_hash_2.clone(), *payment_hash);
57915788
assert_eq!(*payment_failed_permanently, false);
5792-
assert_eq!(*network_update, None);
57935789
assert_eq!(*short_channel_id, Some(route_2.paths[0][0].short_channel_id));
57945790
},
57955791
_ => panic!("Unexpected event"),
@@ -6687,8 +6683,7 @@ fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() {
66876683
// Expect a PaymentPathFailed event with a ChannelFailure network update for the channel between
66886684
// the node originating the error to its next hop.
66896685
match events_5[0] {
6690-
Event::PaymentPathFailed { network_update:
6691-
Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }), error_code, ..
6686+
Event::PaymentPathFailed { error_code, failure: Failure::OnPath { network_update: Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) }, ..
66926687
} => {
66936688
assert_eq!(short_channel_id, chan_2.0.contents.short_channel_id);
66946689
assert!(is_permanent);

lightning/src/ln/onion_route_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::ln::features::{InitFeatures, InvoiceFeatures};
2323
use crate::ln::msgs;
2424
use crate::ln::msgs::{ChannelMessageHandler, ChannelUpdate};
2525
use crate::ln::wire::Encode;
26-
use crate::util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
26+
use crate::util::events::{Event, Failure, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
2727
use crate::util::ser::{Writeable, Writer};
2828
use crate::util::test_utils;
2929
use crate::util::config::{UserConfig, ChannelConfig};
@@ -167,7 +167,7 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case:
167167

168168
let events = nodes[0].node.get_and_clear_pending_events();
169169
assert_eq!(events.len(), 2);
170-
if let &Event::PaymentPathFailed { ref payment_failed_permanently, ref network_update, ref short_channel_id, ref error_code, .. } = &events[0] {
170+
if let &Event::PaymentPathFailed { ref payment_failed_permanently, ref short_channel_id, ref error_code, failure: Failure::OnPath { ref network_update }, .. } = &events[0] {
171171
assert_eq!(*payment_failed_permanently, !expected_retryable);
172172
assert_eq!(*error_code, expected_error_code);
173173
if expected_channel_update.is_some() {

lightning/src/ln/outbound_payment.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ impl OutboundPayments {
12051205
payment_id: Some(*payment_id),
12061206
payment_hash: payment_hash.clone(),
12071207
payment_failed_permanently: !payment_retryable,
1208-
network_update,
1208+
failure: events::Failure::OnPath { network_update },
12091209
path: path.clone(),
12101210
short_channel_id,
12111211
retry,
@@ -1248,13 +1248,13 @@ fn push_payment_path_failed_evs<I: Iterator<Item = Result<(), APIError>>>(
12481248
) {
12491249
let mut events = pending_events.lock().unwrap();
12501250
for (path, path_res) in paths.into_iter().zip(path_results) {
1251-
if path_res.is_err() {
1251+
if let Err(e) = path_res {
12521252
let scid = path[0].short_channel_id;
12531253
events.push(events::Event::PaymentPathFailed {
12541254
payment_id: Some(payment_id),
12551255
payment_hash,
12561256
payment_failed_permanently: false,
1257-
network_update: None,
1257+
failure: events::Failure::InitialSend { err: e },
12581258
path,
12591259
short_channel_id: Some(scid),
12601260
retry: None,

lightning/src/ln/payment_tests.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::ln::outbound_payment::Retry;
2424
use crate::routing::gossip::{EffectiveCapacity, RoutingFees};
2525
use crate::routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RouteParameters};
2626
use crate::routing::scoring::ChannelUsage;
27-
use crate::util::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
27+
use crate::util::events::{ClosureReason, Event, Failure, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
2828
use crate::util::test_utils;
2929
use crate::util::errors::APIError;
3030
use crate::util::ser::Writeable;
@@ -2135,9 +2135,12 @@ fn retry_multi_path_single_failed_payment() {
21352135
assert_eq!(events.len(), 1);
21362136
match events[0] {
21372137
Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently: false,
2138-
network_update: None, short_channel_id: Some(expected_scid), .. } => {
2138+
failure: Failure::InitialSend { err: APIError::ChannelUnavailable { err: ref err_msg }},
2139+
short_channel_id: Some(expected_scid), .. } =>
2140+
{
21392141
assert_eq!(payment_hash, ev_payment_hash);
21402142
assert_eq!(expected_scid, route.paths[1][0].short_channel_id);
2143+
assert!(err_msg.contains("max HTLC"));
21412144
},
21422145
_ => panic!("Unexpected event"),
21432146
}
@@ -2206,9 +2209,12 @@ fn immediate_retry_on_failure() {
22062209
assert_eq!(events.len(), 1);
22072210
match events[0] {
22082211
Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently: false,
2209-
network_update: None, short_channel_id: Some(expected_scid), .. } => {
2212+
failure: Failure::InitialSend { err: APIError::ChannelUnavailable { err: ref err_msg }},
2213+
short_channel_id: Some(expected_scid), .. } =>
2214+
{
22102215
assert_eq!(payment_hash, ev_payment_hash);
22112216
assert_eq!(expected_scid, route.paths[1][0].short_channel_id);
2217+
assert!(err_msg.contains("max HTLC"));
22122218
},
22132219
_ => panic!("Unexpected event"),
22142220
}

0 commit comments

Comments
 (0)