Skip to content

Commit 5e123ef

Browse files
committed
Implement multipath sends using payment_secret.
This rather dramatically changes the return type of send_payment making it much clearer when resending is safe and allowing us to return a list of Results since different paths may have different return values.
1 parent 49a706d commit 5e123ef

File tree

5 files changed

+212
-167
lines changed

5 files changed

+212
-167
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! here. See also the chanmon_fail_consistency fuzz test.
55
66
use chain::transaction::OutPoint;
7-
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash};
7+
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSendFailure};
88
use ln::channelmonitor::ChannelMonitorUpdateErr;
99
use ln::features::InitFeatures;
1010
use ln::msgs;
@@ -30,7 +30,7 @@ fn test_simple_monitor_permanent_update_fail() {
3030
let (_, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]);
3131

3232
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure);
33-
if let Err(APIError::ChannelUnavailable {..}) = nodes[0].node.send_payment(route, payment_hash_1, None) {} else { panic!(); }
33+
unwrap_send_err!(nodes[0].node.send_payment(route, payment_hash_1, None), true, APIError::ChannelUnavailable {..}, {});
3434
check_added_monitors!(nodes[0], 2);
3535

3636
let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
@@ -63,7 +63,8 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
6363
let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]);
6464

6565
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
66-
if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route.clone(), payment_hash_1, None) {} else { panic!(); }
66+
67+
unwrap_send_err!(nodes[0].node.send_payment(route.clone(), payment_hash_1, None), false, APIError::MonitorUpdateFailed, {});
6768
check_added_monitors!(nodes[0], 1);
6869

6970
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
@@ -106,7 +107,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
106107
// Now set it to failed again...
107108
let (_, payment_hash_2) = get_payment_preimage_hash!(&nodes[0]);
108109
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
109-
if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route, payment_hash_2, None) {} else { panic!(); }
110+
unwrap_send_err!(nodes[0].node.send_payment(route, payment_hash_2, None), false, APIError::MonitorUpdateFailed, {});
110111
check_added_monitors!(nodes[0], 1);
111112

112113
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
@@ -169,7 +170,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
169170
let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
170171

171172
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
172-
if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route.clone(), payment_hash_2, None) {} else { panic!(); }
173+
unwrap_send_err!(nodes[0].node.send_payment(route.clone(), payment_hash_2, None), false, APIError::MonitorUpdateFailed, {});
173174
check_added_monitors!(nodes[0], 1);
174175

175176
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());

lightning/src/ln/channelmanager.rs

Lines changed: 151 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -443,15 +443,6 @@ const CHECK_CLTV_EXPIRY_SANITY: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_P
443443
#[allow(dead_code)]
444444
const CHECK_CLTV_EXPIRY_SANITY_2: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER;
445445

446-
macro_rules! secp_call {
447-
( $res: expr, $err: expr ) => {
448-
match $res {
449-
Ok(key) => key,
450-
Err(_) => return Err($err),
451-
}
452-
};
453-
}
454-
455446
/// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
456447
pub struct ChannelDetails {
457448
/// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
@@ -488,6 +479,32 @@ pub struct ChannelDetails {
488479
pub is_live: bool,
489480
}
490481

482+
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
483+
/// Err() type describing which state the payment is in, see the description of individual enum
484+
/// states for more.
485+
#[derive(Debug)]
486+
pub enum PaymentSendFailure {
487+
/// A parameter which was passed to send_payment was invalid, preventing us from attempting to
488+
/// send the payment at all. No channel state has been changed or messages sent to peers, and
489+
/// once you've changed the parameter at error, you can freely retry the payment in full.
490+
ParameterError(APIError),
491+
/// All paths which were attempted failed to send, with no channel state change taking place.
492+
/// You can freely retry the payment in full (though you probably want to do so over different
493+
/// paths than the ones selected).
494+
AllFailedRetrySafe(Vec<APIError>),
495+
/// Some paths which were attempted failed to send, though possibly not all. At least some
496+
/// paths have irrevocably committed to the HTLC and retrying the payment in full would result
497+
/// in over-/re-payment.
498+
///
499+
/// The results here are ordered the same as the paths in the route object which was passed to
500+
/// send_payment, and any Errs which are not APIError::MonitorUpdateFailed can be safely
501+
/// retried.
502+
///
503+
/// Any entries which contain Err(APIError::MonitorUpdateFailed) or Ok(()) MUST NOT be retried
504+
/// as they will result in over-/re-payment.
505+
PartialFailure(Vec<Result<(), APIError>>),
506+
}
507+
491508
macro_rules! handle_error {
492509
($self: ident, $internal: expr, $their_node_id: expr, $locked_channel_state: expr) => {
493510
match $internal {
@@ -1184,109 +1201,154 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref> ChannelMan
11841201
/// payment_preimage tracking (which you should already be doing as they represent "proof of
11851202
/// payment") and prevent double-sends yourself.
11861203
///
1187-
/// May generate a SendHTLCs message event on success, which should be relayed.
1204+
/// May generate SendHTLCs message(s) event on success, which should be relayed.
1205+
///
1206+
/// Each path may have a different return value, and PaymentSendValue may return a Vec with
1207+
/// each entry matching the corresponding-index entry in the route paths.
11881208
///
1189-
/// Raises APIError::RoutError when invalid route or forward parameter
1190-
/// (cltv_delta, fee, node public key) is specified.
1191-
/// Raises APIError::ChannelUnavailable if the next-hop channel is not available for updates
1192-
/// (including due to previous monitor update failure or new permanent monitor update failure).
1193-
/// Raised APIError::MonitorUpdateFailed if a new monitor update failure prevented sending the
1194-
/// relevant updates.
1209+
/// In general, a path may raise:
1210+
/// * APIError::RouteError when an invalid route or forwarding parameter (cltv_delta, fee,
1211+
/// node public key) is specified.
1212+
/// * APIError::ChannelUnavailable if the next-hop channel is not available for updates
1213+
/// (including due to previous monitor update failure or new permanent monitor update
1214+
/// failure).
1215+
/// * APIError::MonitorUpdateFailed if a new monitor update failure prevented sending the
1216+
/// relevant updates.
11951217
///
1196-
/// In case of APIError::RouteError/APIError::ChannelUnavailable, the payment send has failed
1197-
/// and you may wish to retry via a different route immediately.
1198-
/// In case of APIError::MonitorUpdateFailed, the commitment update has been irrevocably
1199-
/// committed on our end and we're just waiting for a monitor update to send it. Do NOT retry
1200-
/// the payment via a different route unless you intend to pay twice!
1218+
/// Note that depending on the type of the PaymentSendFailure the HTLC may have been
1219+
/// irrevocably committed to on our end. In such a case, do NOT retry the payment with a
1220+
/// different route unless you intend to pay twice!
12011221
///
12021222
/// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
12031223
/// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
12041224
/// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
12051225
/// must not contain multiple paths as otherwise the multipath data cannot be sent.
12061226
/// If a payment_secret *is* provided, we assume that the invoice had the basic_mpp feature bit
12071227
/// set (either as required or as available).
1208-
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash, payment_secret: Option<&[u8; 32]>) -> Result<(), APIError> {
1209-
if route.paths.len() < 1 || route.paths.len() > 1 {
1210-
return Err(APIError::RouteError{err: "We currently don't support MPP, and we need at least one path"});
1228+
pub fn send_payment(&self, route: Route, payment_hash: PaymentHash, payment_secret: Option<&[u8; 32]>) -> Result<(), PaymentSendFailure> {
1229+
if route.paths.len() < 1 {
1230+
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"}));
12111231
}
1212-
if route.paths[0].len() < 1 || route.paths[0].len() > 20 {
1213-
return Err(APIError::RouteError{err: "Path didn't go anywhere/had bogus size"});
1232+
if route.paths.len() > 10 {
1233+
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "Sending over more than 10 paths is not currently supported"}));
12141234
}
1235+
let mut total_value = 0;
12151236
let our_node_id = self.get_our_node_id();
1216-
for (idx, hop) in route.paths[0].iter().enumerate() {
1217-
if idx != route.paths[0].len() - 1 && hop.pubkey == our_node_id {
1218-
return Err(APIError::RouteError{err: "Path went through us but wasn't a simple rebalance loop to us"});
1237+
for path in route.paths.iter() {
1238+
if path.len() < 1 || path.len() > 20 {
1239+
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "Path didn't go anywhere/had bogus size"}));
1240+
}
1241+
for (idx, hop) in path.iter().enumerate() {
1242+
if idx != path.len() - 1 && hop.pubkey == our_node_id {
1243+
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "Path went through us but wasn't a simple rebalance loop to us"}));
1244+
}
12191245
}
1246+
total_value += path.last().unwrap().fee_msat;
12201247
}
1221-
1222-
let (session_priv, prng_seed) = self.keys_manager.get_onion_rand();
1223-
12241248
let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1;
1249+
let mut results = Vec::new();
1250+
'path_loop: for path in route.paths.iter() {
1251+
macro_rules! check_res_push {
1252+
($res: expr) => { match $res {
1253+
Ok(r) => r,
1254+
Err(e) => {
1255+
results.push(Err(e));
1256+
continue 'path_loop;
1257+
},
1258+
}
1259+
}
1260+
}
12251261

1226-
let onion_keys = secp_call!(onion_utils::construct_onion_keys(&self.secp_ctx, &route.paths[0], &session_priv),
1227-
APIError::RouteError{err: "Pubkey along hop was maliciously selected"});
1228-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], payment_secret, cur_height)?;
1229-
if onion_utils::route_size_insane(&onion_payloads) {
1230-
return Err(APIError::RouteError{err: "Route size too large considering onion data"});
1231-
}
1232-
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, &payment_hash);
1262+
log_trace!(self, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
1263+
let (session_priv, prng_seed) = self.keys_manager.get_onion_rand();
12331264

1234-
let _ = self.total_consistency_lock.read().unwrap();
1265+
let onion_keys = check_res_push!(onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv)
1266+
.map_err(|_| APIError::RouteError{err: "Pubkey along hop was maliciously selected"}));
1267+
let (onion_payloads, htlc_msat, htlc_cltv) = check_res_push!(onion_utils::build_onion_payloads(&path, total_value, payment_secret, cur_height));
1268+
if onion_utils::route_size_insane(&onion_payloads) {
1269+
check_res_push!(Err(APIError::RouteError{err: "Route size too large considering onion data"}));
1270+
}
1271+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, &payment_hash);
12351272

1236-
let mut channel_lock = self.channel_state.lock().unwrap();
1237-
let err: Result<(), _> = loop {
1273+
let _ = self.total_consistency_lock.read().unwrap();
12381274

1239-
let id = match channel_lock.short_to_id.get(&route.paths[0].first().unwrap().short_channel_id) {
1240-
None => return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!"}),
1241-
Some(id) => id.clone(),
1242-
};
1275+
let mut channel_lock = self.channel_state.lock().unwrap();
1276+
let err: Result<(), _> = loop {
1277+
let id = match channel_lock.short_to_id.get(&path.first().unwrap().short_channel_id) {
1278+
None => check_res_push!(Err(APIError::ChannelUnavailable{err: "No channel available with first hop!"})),
1279+
Some(id) => id.clone(),
1280+
};
12431281

1244-
let channel_state = &mut *channel_lock;
1245-
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(id) {
1246-
match {
1247-
if chan.get().get_their_node_id() != route.paths[0].first().unwrap().pubkey {
1248-
return Err(APIError::RouteError{err: "Node ID mismatch on first hop!"});
1249-
}
1250-
if !chan.get().is_live() {
1251-
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!"});
1252-
}
1253-
break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
1254-
path: route.paths[0].clone(),
1255-
session_priv: session_priv.clone(),
1256-
first_hop_htlc_msat: htlc_msat,
1257-
}, onion_packet), channel_state, chan)
1258-
} {
1259-
Some((update_add, commitment_signed, monitor_update)) => {
1260-
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
1261-
maybe_break_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, true);
1262-
// Note that MonitorUpdateFailed here indicates (per function docs)
1263-
// that we will resent the commitment update once we unfree monitor
1264-
// updating, so we have to take special care that we don't return
1265-
// something else in case we will resend later!
1266-
return Err(APIError::MonitorUpdateFailed);
1282+
let channel_state = &mut *channel_lock;
1283+
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(id) {
1284+
match {
1285+
if chan.get().get_their_node_id() != path.first().unwrap().pubkey {
1286+
check_res_push!(Err(APIError::RouteError{err: "Node ID mismatch on first hop!"}));
1287+
}
1288+
if !chan.get().is_live() {
1289+
check_res_push!(Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!"}));
12671290
}
1291+
break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
1292+
path: path.clone(),
1293+
session_priv: session_priv.clone(),
1294+
first_hop_htlc_msat: htlc_msat,
1295+
}, onion_packet), channel_state, chan)
1296+
} {
1297+
Some((update_add, commitment_signed, monitor_update)) => {
1298+
if let Err(e) = self.monitor.update_monitor(chan.get().get_funding_txo().unwrap(), monitor_update) {
1299+
maybe_break_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, true);
1300+
// Note that MonitorUpdateFailed here indicates (per function docs)
1301+
// that we will resent the commitment update once we unfree monitor
1302+
// updating, so we have to take special care that we don't return
1303+
// something else in case we will resend later!
1304+
check_res_push!(Err(APIError::MonitorUpdateFailed));
1305+
}
12681306

1269-
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
1270-
node_id: route.paths[0].first().unwrap().pubkey,
1271-
updates: msgs::CommitmentUpdate {
1272-
update_add_htlcs: vec![update_add],
1273-
update_fulfill_htlcs: Vec::new(),
1274-
update_fail_htlcs: Vec::new(),
1275-
update_fail_malformed_htlcs: Vec::new(),
1276-
update_fee: None,
1277-
commitment_signed,
1278-
},
1279-
});
1280-
},
1281-
None => {},
1282-
}
1283-
} else { unreachable!(); }
1284-
return Ok(());
1285-
};
1307+
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
1308+
node_id: path.first().unwrap().pubkey,
1309+
updates: msgs::CommitmentUpdate {
1310+
update_add_htlcs: vec![update_add],
1311+
update_fulfill_htlcs: Vec::new(),
1312+
update_fail_htlcs: Vec::new(),
1313+
update_fail_malformed_htlcs: Vec::new(),
1314+
update_fee: None,
1315+
commitment_signed,
1316+
},
1317+
});
1318+
},
1319+
None => {},
1320+
}
1321+
} else { unreachable!(); }
1322+
results.push(Ok(()));
1323+
continue 'path_loop;
1324+
};
12861325

1287-
match handle_error!(self, err, route.paths[0].first().unwrap().pubkey, channel_lock) {
1288-
Ok(_) => unreachable!(),
1289-
Err(e) => { Err(APIError::ChannelUnavailable { err: e.err }) }
1326+
match handle_error!(self, err, path.first().unwrap().pubkey, channel_lock) {
1327+
Ok(_) => unreachable!(),
1328+
Err(e) => {
1329+
check_res_push!(Err(APIError::ChannelUnavailable { err: e.err }));
1330+
},
1331+
}
1332+
}
1333+
let mut has_ok = false;
1334+
let mut has_err = false;
1335+
for res in results.iter() {
1336+
if res.is_ok() { has_ok = true; }
1337+
if res.is_err() { has_err = true; }
1338+
if let &Err(APIError::MonitorUpdateFailed) = res {
1339+
// MonitorUpdateFailed is inherently unsafe to retry, so we call it a
1340+
// PartialFailure.
1341+
has_err = true;
1342+
has_ok = true;
1343+
break;
1344+
}
1345+
}
1346+
if has_err && has_ok {
1347+
Err(PaymentSendFailure::PartialFailure(results))
1348+
} else if has_err {
1349+
Err(PaymentSendFailure::AllFailedRetrySafe(results.drain(..).map(|r| r.unwrap_err()).collect()))
1350+
} else {
1351+
Ok(())
12901352
}
12911353
}
12921354

lightning/src/ln/functional_test_utils.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use chain::chaininterface;
55
use chain::transaction::OutPoint;
66
use chain::keysinterface::KeysInterface;
7-
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash};
7+
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSendFailure};
88
use ln::channelmonitor::{ChannelMonitor, ManyChannelMonitor};
99
use ln::router::{Route, Router, RouterReadArgs};
1010
use ln::features::InitFeatures;
@@ -273,6 +273,28 @@ macro_rules! get_local_commitment_txn {
273273
}
274274
}
275275

276+
macro_rules! unwrap_send_err {
277+
($res: expr, $all_failed: expr, $type: pat, $check: expr) => {
278+
match &$res {
279+
&Err(PaymentSendFailure::AllFailedRetrySafe(ref fails)) if $all_failed => {
280+
assert_eq!(fails.len(), 1);
281+
match fails[0] {
282+
$type => { $check },
283+
_ => panic!(),
284+
}
285+
},
286+
&Err(PaymentSendFailure::PartialFailure(ref fails)) if !$all_failed => {
287+
assert_eq!(fails.len(), 1);
288+
match fails[0] {
289+
Err($type) => { $check },
290+
_ => panic!(),
291+
}
292+
},
293+
_ => panic!(),
294+
}
295+
}
296+
}
297+
276298
pub fn create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, expected_chan_value: u64, expected_user_chan_id: u64) -> ([u8; 32], Transaction, OutPoint) {
277299
let chan_id = *node.network_chan_count.borrow();
278300

@@ -915,12 +937,8 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou
915937
}
916938

917939
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
918-
919-
let err = origin_node.node.send_payment(route, our_payment_hash, None).err().unwrap();
920-
match err {
921-
APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
922-
_ => panic!("Unknown error variants"),
923-
};
940+
unwrap_send_err!(origin_node.node.send_payment(route, our_payment_hash, None), true, APIError::ChannelUnavailable { err },
941+
assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
924942
}
925943

926944
pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, expected_value: u64) {

0 commit comments

Comments
 (0)