Skip to content

Commit 001ed44

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 ae0ad73 commit 001ed44

File tree

5 files changed

+210
-160
lines changed

5 files changed

+210
-160
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! There are a bunch of these as their handling is relatively error-prone so they are split out
44
//! here. See also the chanmon_fail_consistency fuzz test.
55
6-
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash};
6+
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSendFailure};
77
use ln::channelmonitor::ChannelMonitorUpdateErr;
88
use ln::features::InitFeatures;
99
use ln::msgs;
@@ -26,7 +26,7 @@ fn test_simple_monitor_permanent_update_fail() {
2626
let (_, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
2727

2828
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure);
29-
if let Err(APIError::ChannelUnavailable {..}) = nodes[0].node.send_payment(route, payment_hash_1, None) {} else { panic!(); }
29+
unwrap_send_err!(nodes[0].node.send_payment(route, payment_hash_1, None), true, APIError::ChannelUnavailable {..}, {});
3030
check_added_monitors!(nodes[0], 1);
3131

3232
let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
@@ -56,7 +56,8 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
5656
let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
5757

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

6263
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
@@ -98,7 +99,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
9899
// Now set it to failed again...
99100
let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
100101
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
101-
if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route, payment_hash_2, None) {} else { panic!(); }
102+
unwrap_send_err!(nodes[0].node.send_payment(route, payment_hash_2, None), false, APIError::MonitorUpdateFailed, {});
102103
check_added_monitors!(nodes[0], 1);
103104

104105
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
@@ -159,7 +160,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
159160
let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
160161

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

165166
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
@@ -423,15 +423,6 @@ const CHECK_CLTV_EXPIRY_SANITY: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_P
423423
#[allow(dead_code)]
424424
const CHECK_CLTV_EXPIRY_SANITY_2: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER;
425425

426-
macro_rules! secp_call {
427-
( $res: expr, $err: expr ) => {
428-
match $res {
429-
Ok(key) => key,
430-
Err(_) => return Err($err),
431-
}
432-
};
433-
}
434-
435426
/// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
436427
pub struct ChannelDetails {
437428
/// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
@@ -469,6 +460,32 @@ pub struct ChannelDetails {
469460
pub is_live: bool,
470461
}
471462

463+
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
464+
/// Err() type describing which state the payment is in, see the description of individual enum
465+
/// states for more.
466+
#[derive(Debug)]
467+
pub enum PaymentSendFailure {
468+
/// A parameter which was passed to send_payment was invalid, preventing us from attempting to
469+
/// send the payment at all. No channel state has been changed or messages sent to peers, and
470+
/// once you've changed the parameter at error, you can freely retry the payment in full.
471+
ParameterError(APIError),
472+
/// All paths which were attempted failed to send, with no channel state change taking place.
473+
/// You can freely retry the payment in full (though you probably want to do so over different
474+
/// paths than the ones selected).
475+
AllFailedRetrySafe(Vec<APIError>),
476+
/// Some paths which were attempted failed to send, though possibly not all. At least some
477+
/// paths have irrevocably committed to the HTLC and retrying the payment in full would result
478+
/// in over-/re-payment.
479+
///
480+
/// The results here are ordered the same as the paths in the route object which was passed to
481+
/// send_payment, and any Errs which are not APIError::MonitorUpdateFailed can be safely
482+
/// retried.
483+
///
484+
/// Any entries which contain Err(APIError::MonitorUpdateFailed) or Ok(()) MUST NOT be retried
485+
/// as they will result in over-/re-payment.
486+
PartialFailure(Vec<Result<(), APIError>>),
487+
}
488+
472489
macro_rules! handle_error {
473490
($self: ident, $internal: expr, $their_node_id: expr, $locked_channel_state: expr) => {
474491
match $internal {
@@ -1184,109 +1201,154 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
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 had too large size once"});
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 had too large size once"}));
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 = channel_lock.borrow_parts();
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, chan_monitor)) => {
1260-
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
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 = channel_lock.borrow_parts();
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!"}));
12671287
}
1288+
if !chan.get().is_live() {
1289+
check_res_push!(Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!"}));
1290+
}
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, chan_monitor)) => {
1298+
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
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,RAACommitmentOrder, PaymentPreimage, PaymentHash};
7+
use ln::channelmanager::{ChannelManager,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSendFailure};
88
use ln::router::{Route, Router};
99
use ln::features::InitFeatures;
1010
use ln::msgs;
@@ -159,6 +159,28 @@ macro_rules! get_feerate {
159159
}
160160
}
161161

162+
macro_rules! unwrap_send_err {
163+
($res: expr, $all_failed: expr, $type: pat, $check: expr) => {
164+
match &$res {
165+
&Err(PaymentSendFailure::AllFailedRetrySafe(ref fails)) if $all_failed => {
166+
assert_eq!(fails.len(), 1);
167+
match fails[0] {
168+
$type => { $check },
169+
_ => panic!(),
170+
}
171+
},
172+
&Err(PaymentSendFailure::PartialFailure(ref fails)) if !$all_failed => {
173+
assert_eq!(fails.len(), 1);
174+
match fails[0] {
175+
Err($type) => { $check },
176+
_ => panic!(),
177+
}
178+
},
179+
_ => panic!(),
180+
}
181+
}
182+
}
183+
162184
pub fn create_funding_transaction(node: &Node, expected_chan_value: u64, expected_user_chan_id: u64) -> ([u8; 32], Transaction, OutPoint) {
163185
let chan_id = *node.network_chan_count.borrow();
164186

@@ -786,12 +808,8 @@ pub fn route_over_limit(origin_node: &Node, expected_route: &[&Node], recv_value
786808
}
787809

788810
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
789-
790-
let err = origin_node.node.send_payment(route, our_payment_hash, None).err().unwrap();
791-
match err {
792-
APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
793-
_ => panic!("Unknown error variants"),
794-
};
811+
unwrap_send_err!(origin_node.node.send_payment(route, our_payment_hash, None), true, APIError::ChannelUnavailable { err },
812+
assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
795813
}
796814

797815
pub fn send_payment(origin: &Node, expected_route: &[&Node], recv_value: u64, expected_value: u64) {

0 commit comments

Comments
 (0)