Skip to content

Commit 9fdc349

Browse files
committed
Properly handle ChannelError::Close results in send_payment.
Best reviewed with -b
1 parent 31ec11f commit 9fdc349

File tree

1 file changed

+77
-50
lines changed

1 file changed

+77
-50
lines changed

src/ln/channelmanager.rs

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,24 @@ macro_rules! handle_error {
464464
}
465465
}
466466

467+
macro_rules! break_chan_entry {
468+
($self: ident, $res: expr, $channel_state: expr, $entry: expr) => {
469+
match $res {
470+
Ok(res) => res,
471+
Err(ChannelError::Ignore(msg)) => {
472+
break Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $entry.key().clone()))
473+
},
474+
Err(ChannelError::Close(msg)) => {
475+
let (channel_id, mut chan) = $entry.remove_entry();
476+
if let Some(short_id) = chan.get_short_channel_id() {
477+
$channel_state.short_to_id.remove(&short_id);
478+
}
479+
break Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, chan.force_shutdown(), $self.get_channel_update(&chan).ok()))
480+
},
481+
}
482+
}
483+
}
484+
467485
macro_rules! try_chan_entry {
468486
($self: ident, $res: expr, $channel_state: expr, $entry: expr) => {
469487
match $res {
@@ -1259,63 +1277,72 @@ impl ChannelManager {
12591277
let onion_packet = ChannelManager::construct_onion_packet(onion_payloads, onion_keys, &payment_hash);
12601278

12611279
let _ = self.total_consistency_lock.read().unwrap();
1262-
let mut channel_state = self.channel_state.lock().unwrap();
12631280

1264-
let id = match channel_state.short_to_id.get(&route.hops.first().unwrap().short_channel_id) {
1265-
None => return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!"}),
1266-
Some(id) => id.clone(),
1267-
};
1281+
let err: Result<(), _> = loop {
1282+
let mut channel_lock = self.channel_state.lock().unwrap();
12681283

1269-
let res = {
1270-
let chan = channel_state.by_id.get_mut(&id).unwrap();
1271-
if chan.get_their_node_id() != route.hops.first().unwrap().pubkey {
1272-
return Err(APIError::RouteError{err: "Node ID mismatch on first hop!"});
1273-
}
1274-
if chan.is_awaiting_monitor_update() {
1275-
return Err(APIError::MonitorUpdateFailed);
1276-
}
1277-
if !chan.is_live() {
1278-
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected!"});
1284+
let id = match channel_lock.short_to_id.get(&route.hops.first().unwrap().short_channel_id) {
1285+
None => return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!"}),
1286+
Some(id) => id.clone(),
1287+
};
1288+
1289+
match {
1290+
let channel_state = channel_lock.borrow_parts();
1291+
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(id) {
1292+
if chan.get().get_their_node_id() != route.hops.first().unwrap().pubkey {
1293+
return Err(APIError::RouteError{err: "Node ID mismatch on first hop!"});
1294+
}
1295+
if chan.get().is_awaiting_monitor_update() {
1296+
return Err(APIError::MonitorUpdateFailed);
1297+
}
1298+
if !chan.get().is_live() {
1299+
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected!"});
1300+
}
1301+
break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
1302+
route: route.clone(),
1303+
session_priv: session_priv.clone(),
1304+
first_hop_htlc_msat: htlc_msat,
1305+
}, onion_packet), channel_state, chan)
1306+
} else { unreachable!(); }
1307+
} {
1308+
Some((update_add, commitment_signed, chan_monitor)) => {
1309+
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
1310+
self.handle_monitor_update_fail(channel_lock, &id, e, RAACommitmentOrder::CommitmentFirst);
1311+
return Err(APIError::MonitorUpdateFailed);
1312+
}
1313+
1314+
channel_lock.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
1315+
node_id: route.hops.first().unwrap().pubkey,
1316+
updates: msgs::CommitmentUpdate {
1317+
update_add_htlcs: vec![update_add],
1318+
update_fulfill_htlcs: Vec::new(),
1319+
update_fail_htlcs: Vec::new(),
1320+
update_fail_malformed_htlcs: Vec::new(),
1321+
update_fee: None,
1322+
commitment_signed,
1323+
},
1324+
});
1325+
},
1326+
None => {},
12791327
}
1280-
chan.send_htlc_and_commit(htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
1281-
route: route.clone(),
1282-
session_priv: session_priv.clone(),
1283-
first_hop_htlc_msat: htlc_msat,
1284-
}, onion_packet).map_err(|he|
1285-
match he {
1286-
ChannelError::Close(err) => {
1287-
// TODO: We need to close the channel here, but for that to be safe we have
1288-
// to do all channel closure inside the channel_state lock which is a
1289-
// somewhat-larger refactor, so we leave that for later.
1290-
APIError::ChannelUnavailable { err }
1291-
},
1292-
ChannelError::Ignore(err) => APIError::ChannelUnavailable { err },
1293-
}
1294-
)?
1328+
return Ok(());
12951329
};
1296-
match res {
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-
self.handle_monitor_update_fail(channel_state, &id, e, RAACommitmentOrder::CommitmentFirst);
1300-
return Err(APIError::MonitorUpdateFailed);
1301-
}
13021330

1303-
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
1304-
node_id: route.hops.first().unwrap().pubkey,
1305-
updates: msgs::CommitmentUpdate {
1306-
update_add_htlcs: vec![update_add],
1307-
update_fulfill_htlcs: Vec::new(),
1308-
update_fail_htlcs: Vec::new(),
1309-
update_fail_malformed_htlcs: Vec::new(),
1310-
update_fee: None,
1311-
commitment_signed,
1312-
},
1313-
});
1331+
match handle_error!(self, err, route.hops.first().unwrap().pubkey) {
1332+
Ok(_) => unreachable!(),
1333+
Err(e) => {
1334+
if let Some(msgs::ErrorAction::IgnoreError) = e.action {
1335+
} else {
1336+
log_error!(self, "Got bad keys: {}!", e.err);
1337+
let mut channel_state = self.channel_state.lock().unwrap();
1338+
channel_state.pending_msg_events.push(events::MessageSendEvent::HandleError {
1339+
node_id: route.hops.first().unwrap().pubkey,
1340+
action: e.action,
1341+
});
1342+
}
1343+
Err(APIError::ChannelUnavailable { err: e.err })
13141344
},
1315-
None => {},
13161345
}
1317-
1318-
Ok(())
13191346
}
13201347

13211348
/// Call this upon creation of a funding transaction for the given channel.

0 commit comments

Comments
 (0)