Skip to content

Commit 52edb35

Browse files
authored
Merge pull request #1893 from valentinewallace/2022-12-jit-forwards-followup
HTLC JIT channel interception followup + minor cleanups
2 parents 4dafa43 + e0820ae commit 52edb35

File tree

7 files changed

+40
-31
lines changed

7 files changed

+40
-31
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ fn check_api_err(api_err: APIError) {
253253
match api_err {
254254
APIError::APIMisuseError { .. } => panic!("We can't misuse the API"),
255255
APIError::FeeRateTooHigh { .. } => panic!("We can't send too much fee?"),
256-
APIError::RouteError { .. } => panic!("Our routes should work"),
256+
APIError::InvalidRoute { .. } => panic!("Our routes should work"),
257257
APIError::ChannelUnavailable { err } => {
258258
// Test the error against a list of errors we can hit, and reject
259259
// all others. If you hit this panic, the list of acceptable errors

lightning/src/ln/channelmanager.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,10 +2419,10 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
24192419
let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted");
24202420

24212421
let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv)
2422-
.map_err(|_| APIError::RouteError{err: "Pubkey along hop was maliciously selected"})?;
2422+
.map_err(|_| APIError::InvalidRoute{err: "Pubkey along hop was maliciously selected"})?;
24232423
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, cur_height, keysend_preimage)?;
24242424
if onion_utils::route_size_insane(&onion_payloads) {
2425-
return Err(APIError::RouteError{err: "Route size too large considering onion data"});
2425+
return Err(APIError::InvalidRoute{err: "Route size too large considering onion data"});
24262426
}
24272427
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, payment_hash);
24282428

@@ -2439,7 +2439,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
24392439
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(id) {
24402440
match {
24412441
if chan.get().get_counterparty_node_id() != path.first().unwrap().pubkey {
2442-
return Err(APIError::RouteError{err: "Node ID mismatch on first hop!"});
2442+
return Err(APIError::InvalidRoute{err: "Node ID mismatch on first hop!"});
24432443
}
24442444
if !chan.get().is_live() {
24452445
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!".to_owned()});
@@ -2514,7 +2514,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
25142514
/// fields for more info.
25152515
///
25162516
/// If a pending payment is currently in-flight with the same [`PaymentId`] provided, this
2517-
/// method will error with an [`APIError::RouteError`]. Note, however, that once a payment
2517+
/// method will error with an [`APIError::InvalidRoute`]. Note, however, that once a payment
25182518
/// is no longer pending (either via [`ChannelManager::abandon_payment`], or handling of an
25192519
/// [`Event::PaymentSent`]) LDK will not stop you from sending a second payment with the same
25202520
/// [`PaymentId`].
@@ -2533,7 +2533,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
25332533
/// PaymentSendFailure for more info.
25342534
///
25352535
/// In general, a path may raise:
2536-
/// * [`APIError::RouteError`] when an invalid route or forwarding parameter (cltv_delta, fee,
2536+
/// * [`APIError::InvalidRoute`] when an invalid route or forwarding parameter (cltv_delta, fee,
25372537
/// node public key) is specified.
25382538
/// * [`APIError::ChannelUnavailable`] if the next-hop channel is not available for updates
25392539
/// (including due to previous monitor update failure or new permanent monitor update
@@ -2598,7 +2598,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
25982598

25992599
fn send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> {
26002600
if route.paths.len() < 1 {
2601-
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"}));
2601+
return Err(PaymentSendFailure::ParameterError(APIError::InvalidRoute{err: "There must be at least one path to send over"}));
26022602
}
26032603
if payment_secret.is_none() && route.paths.len() > 1 {
26042604
return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError{err: "Payment secret is required for multi-path payments".to_string()}));
@@ -2608,12 +2608,12 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
26082608
let mut path_errs = Vec::with_capacity(route.paths.len());
26092609
'path_check: for path in route.paths.iter() {
26102610
if path.len() < 1 || path.len() > 20 {
2611-
path_errs.push(Err(APIError::RouteError{err: "Path didn't go anywhere/had bogus size"}));
2611+
path_errs.push(Err(APIError::InvalidRoute{err: "Path didn't go anywhere/had bogus size"}));
26122612
continue 'path_check;
26132613
}
26142614
for (idx, hop) in path.iter().enumerate() {
26152615
if idx != path.len() - 1 && hop.pubkey == our_node_id {
2616-
path_errs.push(Err(APIError::RouteError{err: "Path went through us but wasn't a simple rebalance loop to us"}));
2616+
path_errs.push(Err(APIError::InvalidRoute{err: "Path went through us but wasn't a simple rebalance loop to us"}));
26172617
continue 'path_check;
26182618
}
26192619
}
@@ -3092,20 +3092,20 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
30923092
let next_hop_scid = match self.channel_state.lock().unwrap().by_id.get(next_hop_channel_id) {
30933093
Some(chan) => {
30943094
if !chan.is_usable() {
3095-
return Err(APIError::APIMisuseError {
3096-
err: format!("Channel with id {:?} not fully established", next_hop_channel_id)
3095+
return Err(APIError::ChannelUnavailable {
3096+
err: format!("Channel with id {} not fully established", log_bytes!(*next_hop_channel_id))
30973097
})
30983098
}
30993099
chan.get_short_channel_id().unwrap_or(chan.outbound_scid_alias())
31003100
},
3101-
None => return Err(APIError::APIMisuseError {
3102-
err: format!("Channel with id {:?} not found", next_hop_channel_id)
3101+
None => return Err(APIError::ChannelUnavailable {
3102+
err: format!("Channel with id {} not found", log_bytes!(*next_hop_channel_id))
31033103
})
31043104
};
31053105

31063106
let payment = self.pending_intercepted_htlcs.lock().unwrap().remove(&intercept_id)
31073107
.ok_or_else(|| APIError::APIMisuseError {
3108-
err: format!("Payment with intercept id {:?} not found", intercept_id.0)
3108+
err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0))
31093109
})?;
31103110

31113111
let routing = match payment.forward_info.routing {
@@ -3140,7 +3140,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
31403140

31413141
let payment = self.pending_intercepted_htlcs.lock().unwrap().remove(&intercept_id)
31423142
.ok_or_else(|| APIError::APIMisuseError {
3143-
err: format!("Payment with InterceptId {:?} not found", intercept_id)
3143+
err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0))
31443144
})?;
31453145

31463146
if let PendingHTLCRouting::Forward { short_channel_id, .. } = payment.forward_info.routing {

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6023,7 +6023,7 @@ fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
60236023
.with_features(channelmanager::provided_invoice_features());
60246024
let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000, 0);
60256025
route.paths[0].last_mut().unwrap().cltv_expiry_delta = 500000001;
6026-
unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret), PaymentId(our_payment_hash.0)), true, APIError::RouteError { ref err },
6026+
unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret), PaymentId(our_payment_hash.0)), true, APIError::InvalidRoute { ref err },
60276027
assert_eq!(err, &"Channel CLTV overflowed?"));
60286028
}
60296029

lightning/src/ln/onion_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ pub(super) fn build_onion_payloads(path: &Vec<RouteHop>, total_msat: u64, paymen
182182
});
183183
cur_value_msat += hop.fee_msat;
184184
if cur_value_msat >= 21000000 * 100000000 * 1000 {
185-
return Err(APIError::RouteError{err: "Channel fees overflowed?"});
185+
return Err(APIError::InvalidRoute{err: "Channel fees overflowed?"});
186186
}
187187
cur_cltv += hop.cltv_expiry_delta as u32;
188188
if cur_cltv >= 500000000 {
189-
return Err(APIError::RouteError{err: "Channel CLTV overflowed?"});
189+
return Err(APIError::InvalidRoute{err: "Channel CLTV overflowed?"});
190190
}
191191
last_short_channel_id = hop.short_channel_id;
192192
}

lightning/src/ln/payment_tests.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIM
2020
use crate::ln::msgs;
2121
use crate::ln::msgs::ChannelMessageHandler;
2222
use crate::routing::gossip::RoutingFees;
23-
use crate::routing::router::{find_route, get_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
23+
use crate::routing::router::{get_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
2424
use crate::util::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
2525
use crate::util::test_utils;
2626
use crate::util::errors::APIError;
@@ -1429,9 +1429,10 @@ fn do_test_intercepted_payment(test: InterceptTest) {
14291429
final_value_msat: amt_msat,
14301430
final_cltv_expiry_delta: TEST_FINAL_CLTV,
14311431
};
1432-
let route = find_route(
1433-
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, None, nodes[0].logger,
1434-
&scorer, &random_seed_bytes
1432+
let route = get_route(
1433+
&nodes[0].node.get_our_node_id(), &route_params.payment_params,
1434+
&nodes[0].network_graph.read_only(), None, route_params.final_value_msat,
1435+
route_params.final_cltv_expiry_delta, nodes[0].logger, &scorer, &random_seed_bytes
14351436
).unwrap();
14361437

14371438
let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60).unwrap();
@@ -1466,7 +1467,7 @@ fn do_test_intercepted_payment(test: InterceptTest) {
14661467

14671468
// Check for unknown channel id error.
14681469
let unknown_chan_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &[42; 32], nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err();
1469-
assert_eq!(unknown_chan_id_err , APIError::APIMisuseError { err: format!("Channel with id {:?} not found", [42; 32]) });
1470+
assert_eq!(unknown_chan_id_err , APIError::ChannelUnavailable { err: format!("Channel with id {} not found", log_bytes!([42; 32])) });
14701471

14711472
if test == InterceptTest::Fail {
14721473
// Ensure we can fail the intercepted payment back.
@@ -1490,7 +1491,7 @@ fn do_test_intercepted_payment(test: InterceptTest) {
14901491
// Check that we'll fail as expected when sending to a channel that isn't in `ChannelReady` yet.
14911492
let temp_chan_id = nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
14921493
let unusable_chan_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &temp_chan_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err();
1493-
assert_eq!(unusable_chan_err , APIError::APIMisuseError { err: format!("Channel with id {:?} not fully established", temp_chan_id) });
1494+
assert_eq!(unusable_chan_err , APIError::ChannelUnavailable { err: format!("Channel with id {} not fully established", log_bytes!(temp_chan_id)) });
14941495
assert_eq!(nodes[1].node.get_and_clear_pending_msg_events().len(), 1);
14951496

14961497
// Open the just-in-time channel so the payment can then be forwarded.
@@ -1540,8 +1541,7 @@ fn do_test_intercepted_payment(test: InterceptTest) {
15401541
};
15411542
connect_block(&nodes[0], &block);
15421543
connect_block(&nodes[1], &block);
1543-
let block_count = 183; // find_route adds a random CLTV offset, so hardcode rather than summing consts
1544-
for _ in 0..block_count {
1544+
for _ in 0..TEST_FINAL_CLTV {
15451545
block.header.prev_blockhash = block.block_hash();
15461546
connect_block(&nodes[0], &block);
15471547
connect_block(&nodes[1], &block);
@@ -1561,6 +1561,8 @@ fn do_test_intercepted_payment(test: InterceptTest) {
15611561
// Check for unknown intercept id error.
15621562
let (_, channel_id) = open_zero_conf_channel(&nodes[1], &nodes[2], None);
15631563
let unknown_intercept_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &channel_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err();
1564-
assert_eq!(unknown_intercept_id_err , APIError::APIMisuseError { err: format!("Payment with intercept id {:?} not found", intercept_id.0) });
1564+
assert_eq!(unknown_intercept_id_err , APIError::APIMisuseError { err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) });
1565+
let unknown_intercept_id_err = nodes[1].node.fail_intercepted_htlc(intercept_id).unwrap_err();
1566+
assert_eq!(unknown_intercept_id_err , APIError::APIMisuseError { err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) });
15651567
}
15661568
}

lightning/src/util/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub enum APIError {
3535
},
3636
/// A malformed Route was provided (eg overflowed value, node id mismatch, overly-looped route,
3737
/// too-many-hops, etc).
38-
RouteError {
38+
InvalidRoute {
3939
/// A human-readable error message
4040
err: &'static str
4141
},
@@ -74,7 +74,7 @@ impl fmt::Debug for APIError {
7474
match *self {
7575
APIError::APIMisuseError {ref err} => write!(f, "Misuse error: {}", err),
7676
APIError::FeeRateTooHigh {ref err, ref feerate} => write!(f, "{} feerate: {}", err, feerate),
77-
APIError::RouteError {ref err} => write!(f, "Route error: {}", err),
77+
APIError::InvalidRoute {ref err} => write!(f, "Invalid route provided: {}", err),
7878
APIError::ChannelUnavailable {ref err} => write!(f, "Channel unavailable: {}", err),
7979
APIError::MonitorUpdateInProgress => f.write_str("Client indicated a channel monitor update is in progress but not yet complete"),
8080
APIError::IncompatibleShutdownScript { ref script } => {

lightning/src/util/persist.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@
1010
1111
use core::ops::Deref;
1212
use bitcoin::hashes::hex::ToHex;
13-
use crate::io::{self};
13+
use crate::io;
1414
use crate::routing::scoring::WriteableScore;
1515

16-
use crate::{chain::{keysinterface::{Sign, KeysInterface}, self, transaction::{OutPoint}, chaininterface::{BroadcasterInterface, FeeEstimator}, chainmonitor::{Persist, MonitorUpdateId}, channelmonitor::{ChannelMonitor, ChannelMonitorUpdate}}, ln::channelmanager::ChannelManager, routing::gossip::NetworkGraph};
16+
use crate::chain;
17+
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
18+
use crate::chain::chainmonitor::{Persist, MonitorUpdateId};
19+
use crate::chain::keysinterface::{Sign, KeysInterface};
20+
use crate::chain::transaction::OutPoint;
21+
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate};
22+
use crate::ln::channelmanager::ChannelManager;
23+
use crate::routing::gossip::NetworkGraph;
1724
use super::{logger::Logger, ser::Writeable};
1825

1926
/// Trait for a key-value store for persisting some writeable object at some key

0 commit comments

Comments
 (0)