Skip to content

Commit 989fa7e

Browse files
committed
Don't fail channel creation when peer suddenly disconnects
- Instead broadcast the OpenChannel message again when the peer reconnects - Or fail the channel creation in around two minutes, if channel does not reestablish.
1 parent 1f399b0 commit 989fa7e

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

lightning/src/ln/channelmanager.rs

+63-2
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,9 @@ pub(super) struct PeerState<SP: Deref> where SP::Target: SignerProvider {
721721
/// removed, and an InboundV1Channel is created and placed in the `inbound_v1_channel_by_id` table. If
722722
/// the channel is rejected, then the entry is simply removed.
723723
pub(super) inbound_channel_request_by_id: HashMap<ChannelId, InboundChannelRequest>,
724+
///
725+
/// Outbound channel unsent by us.
726+
pub(super) outbound_channel_unsent_by_id: HashMap<ChannelId, OutboundChannelRequest>,
724727
/// The latest `InitFeatures` we heard from the peer.
725728
latest_features: InitFeatures,
726729
/// Messages to send to the peer - pushed to in the same lock that they are generated in (except
@@ -797,6 +800,18 @@ pub(super) struct InboundChannelRequest {
797800
/// accepted. An unaccepted channel that exceeds this limit will be abandoned.
798801
const UNACCEPTED_INBOUND_CHANNEL_AGE_LIMIT_TICKS: i32 = 2;
799802

803+
/// A not-yet-accpted outbound channel.
804+
pub(super) struct OutboundChannelRequest {
805+
/// The original OpenChannel message.
806+
pub open_channel_msg: MessageSendEvent,
807+
/// The number of ticks remaining before the request expires
808+
pub ticks_remaining: i32,
809+
}
810+
811+
/// The number of ticks that may elapse while waiting for an outbound channel request to be sent.
812+
/// An unsent channel that exceeds this limit will be abondoned.
813+
const UNSENT_OUTBOUND_CHANNEL_AGE_LIMIT_TICKS: i32 = 2;
814+
800815
/// Stores a PaymentSecret and any other data we may need to validate an inbound payment is
801816
/// actually ours and not some duplicate HTLC sent to us by a node along the route.
802817
///
@@ -2400,6 +2415,7 @@ where
24002415
/// [`Event::FundingGenerationReady::user_channel_id`]: events::Event::FundingGenerationReady::user_channel_id
24012416
/// [`Event::FundingGenerationReady::temporary_channel_id`]: events::Event::FundingGenerationReady::temporary_channel_id
24022417
/// [`Event::ChannelClosed::channel_id`]: events::Event::ChannelClosed::channel_id
2418+
24032419
pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_channel_id: u128, override_config: Option<UserConfig>) -> Result<ChannelId, APIError> {
24042420
if channel_value_satoshis < 1000 {
24052421
return Err(APIError::APIMisuseError { err: format!("Channel value must be at least 1000 satoshis. It was {}", channel_value_satoshis) });
@@ -2444,10 +2460,22 @@ where
24442460
hash_map::Entry::Vacant(entry) => { entry.insert(ChannelPhase::UnfundedOutboundV1(channel)); }
24452461
}
24462462

2447-
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
2463+
let msg_event = events::MessageSendEvent::SendOpenChannel {
24482464
node_id: their_network_key,
24492465
msg: res,
2450-
});
2466+
};
2467+
2468+
if peer_state.is_connected {
2469+
peer_state.pending_msg_events.push(msg_event);
2470+
}
2471+
2472+
else {
2473+
peer_state.outbound_channel_unsent_by_id.insert(temporary_channel_id, OutboundChannelRequest {
2474+
open_channel_msg: msg_event,
2475+
ticks_remaining: UNSENT_OUTBOUND_CHANNEL_AGE_LIMIT_TICKS,
2476+
});
2477+
}
2478+
24512479
Ok(temporary_channel_id)
24522480
}
24532481

@@ -5009,6 +5037,21 @@ where
50095037
}
50105038
peer_state.inbound_channel_request_by_id.retain(|_, req| req.ticks_remaining > 0);
50115039

5040+
5041+
// Check if the channel was sent in timely manner and if not closing the channel between peer and counterparty
5042+
for (chan_id, req) in peer_state.outbound_channel_unsent_by_id.iter_mut() {
5043+
if { req.ticks_remaining -= 1 ; req.ticks_remaining } <= 0 {
5044+
5045+
let node_id_ = match req.open_channel_msg {
5046+
MessageSendEvent::SendOpenChannel{ node_id, msg: _} => Some(node_id),
5047+
_ => None,
5048+
};
5049+
5050+
let _ = self.force_close_sending_error(&chan_id, &node_id_.unwrap(), true);
5051+
}
5052+
}
5053+
peer_state.outbound_channel_unsent_by_id.retain(|_, req| req.ticks_remaining > 0);
5054+
50125055
if peer_state.ok_to_remove(true) {
50135056
pending_peers_awaiting_removal.push(counterparty_node_id);
50145057
}
@@ -8689,6 +8732,7 @@ where
86898732
e.insert(Mutex::new(PeerState {
86908733
channel_by_id: HashMap::new(),
86918734
inbound_channel_request_by_id: HashMap::new(),
8735+
outbound_channel_unsent_by_id: HashMap::new(),
86928736
latest_features: init_msg.features.clone(),
86938737
pending_msg_events: Vec::new(),
86948738
in_flight_monitor_updates: BTreeMap::new(),
@@ -8724,11 +8768,24 @@ where
87248768
let peer_state = &mut *peer_state_lock;
87258769
let pending_msg_events = &mut peer_state.pending_msg_events;
87268770

8771+
// For the pending OpenChannelMessage that were not sent due to peer disconnecting at time of channel creation
8772+
for (_, chan_request) in peer_state.outbound_channel_unsent_by_id.iter_mut() {
8773+
pending_msg_events.push(chan_request.open_channel_msg.clone());
8774+
}
8775+
87278776
peer_state.channel_by_id.iter_mut().filter_map(|(_, phase)|
87288777
if let ChannelPhase::Funded(chan) = phase { Some(chan) } else {
87298778
// Since unfunded channel maps are cleared upon disconnecting a peer, and they're not persisted
87308779
// (so won't be recovered after a crash), they shouldn't exist here and we would never need to
87318780
// worry about closing and removing them.
8781+
8782+
// TODO: Make this optional exception work
8783+
// // An exception are the channel created just when peer was disconnected, so the process of
8784+
// // channel creation was held mid way.
8785+
// if !&peer_state.outbound_channel_unsent_by_id.contains_key(chan_id) {
8786+
// debug_assert!(false);
8787+
// }
8788+
87328789
debug_assert!(false);
87338790
None
87348791
}
@@ -8738,6 +8795,9 @@ where
87388795
msg: chan.get_channel_reestablish(&self.logger),
87398796
});
87408797
});
8798+
8799+
// And now the request are sent to pending_msg_events, we can clear the vector
8800+
peer_state.outbound_channel_unsent_by_id.clear();
87418801
}
87428802

87438803
return NotifyOption::SkipPersistHandleEvents;
@@ -10085,6 +10145,7 @@ where
1008510145
PeerState {
1008610146
channel_by_id,
1008710147
inbound_channel_request_by_id: HashMap::new(),
10148+
outbound_channel_unsent_by_id: HashMap::new(),
1008810149
latest_features: InitFeatures::empty(),
1008910150
pending_msg_events: Vec::new(),
1009010151
in_flight_monitor_updates: BTreeMap::new(),

0 commit comments

Comments
 (0)