Skip to content

Commit 9feb827

Browse files
committed
Add a Disconnected ChannelState and check/handle it everywhere
Setting/removing it comes next
1 parent 6803c47 commit 9feb827

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed

src/ln/channel.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ enum HTLCUpdateAwaitingACK {
203203
},
204204
}
205205

206+
/// There are a few "states" and then a number of flags which can be applied:
207+
/// We first move through init with OurInitSent -> TheirInitSent -> FundingCreated -> FundingSent.
208+
/// TheirFundingLocked and OurFundingLocked then get set on FundingSent, and when both are set we
209+
/// move on to ChannelFunded.
210+
/// Note that PeerDisconnected can be set on both ChannelFunded and FundingSent.
211+
/// ChannelFunded can then get all remaining flags set on it, until we finish shutdown, then we
212+
/// move on to ShutdownComplete, at which point most calls into this channel are disallowed.
206213
enum ChannelState {
207214
/// Implies we have (or are prepared to) send our open_channel/accept_channel message
208215
OurInitSent = (1 << 0),
@@ -223,25 +230,29 @@ enum ChannelState {
223230
/// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded.
224231
OurFundingLocked = (1 << 5),
225232
ChannelFunded = 64,
233+
/// Flag which is set on ChannelFunded and FundingSent indicating remote side is considered
234+
/// "disconnected" and no updates are allowed until after we've done a channel_reestablish
235+
/// dance.
236+
PeerDisconnected = (1 << 7),
226237
/// Flag which implies that we have sent a commitment_signed but are awaiting the responding
227238
/// revoke_and_ack message. During this time period, we can't generate new commitment_signed
228239
/// messages as then we will be unable to determine which HTLCs they included in their
229240
/// revoke_and_ack implicit ACK, so instead we have to hold them away temporarily to be sent
230241
/// later.
231242
/// Flag is set on ChannelFunded.
232-
AwaitingRemoteRevoke = (1 << 7),
243+
AwaitingRemoteRevoke = (1 << 8),
233244
/// Flag which is set on ChannelFunded or FundingSent after receiving a shutdown message from
234245
/// the remote end. If set, they may not add any new HTLCs to the channel, and we are expected
235246
/// to respond with our own shutdown message when possible.
236-
RemoteShutdownSent = (1 << 8),
247+
RemoteShutdownSent = (1 << 9),
237248
/// Flag which is set on ChannelFunded or FundingSent after sending a shutdown message. At this
238249
/// point, we may not add any new HTLCs to the channel.
239250
/// TODO: Investigate some kind of timeout mechanism by which point the remote end must provide
240251
/// us their shutdown.
241-
LocalShutdownSent = (1 << 9),
252+
LocalShutdownSent = (1 << 10),
242253
/// We've successfully negotiated a closing_signed dance. At this point ChannelManager is about
243254
/// to drop us, but we store this anyway.
244-
ShutdownComplete = (1 << 10),
255+
ShutdownComplete = 2048,
245256
}
246257
const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 | ChannelState::RemoteShutdownSent as u32);
247258

@@ -1061,7 +1072,7 @@ impl Channel {
10611072
// can claim it even if the channel hits the chain before we see their next commitment.
10621073
self.channel_monitor.provide_payment_preimage(&payment_hash_calc, &payment_preimage_arg);
10631074

1064-
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
1075+
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32)) != 0 {
10651076
for pending_update in self.holding_cell_htlc_updates.iter() {
10661077
match pending_update {
10671078
&HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => {
@@ -1137,7 +1148,7 @@ impl Channel {
11371148
}
11381149

11391150
// Now update local state:
1140-
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
1151+
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32)) != 0 {
11411152
for pending_update in self.holding_cell_htlc_updates.iter() {
11421153
match pending_update {
11431154
&HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => {
@@ -1354,6 +1365,9 @@ impl Channel {
13541365
}
13551366

13561367
pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), HandleError> {
1368+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1369+
return Err(HandleError{err: "Peer sent funding_locked when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent funding_locked when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1370+
}
13571371
let non_shutdown_state = self.channel_state & (!BOTH_SIDES_SHUTDOWN_MASK);
13581372
if non_shutdown_state == ChannelState::FundingSent as u32 {
13591373
self.channel_state |= ChannelState::TheirFundingLocked as u32;
@@ -1411,6 +1425,9 @@ impl Channel {
14111425
if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
14121426
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
14131427
}
1428+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1429+
return Err(HandleError{err: "Peer sent update_add_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_add_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1430+
}
14141431
if msg.amount_msat > self.channel_value_satoshis * 1000 {
14151432
return Err(HandleError{err: "Remote side tried to send more than the total value of the channel", action: None});
14161433
}
@@ -1489,6 +1506,9 @@ impl Channel {
14891506
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
14901507
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
14911508
}
1509+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1510+
return Err(HandleError{err: "Peer sent update_fulfill_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fulfill_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1511+
}
14921512

14931513
let mut sha = Sha256::new();
14941514
sha.input(&msg.payment_preimage);
@@ -1502,6 +1522,9 @@ impl Channel {
15021522
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15031523
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
15041524
}
1525+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1526+
return Err(HandleError{err: "Peer sent update_fail_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fail_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1527+
}
15051528

15061529
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
15071530
}
@@ -1510,6 +1533,9 @@ impl Channel {
15101533
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15111534
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
15121535
}
1536+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1537+
return Err(HandleError{err: "Peer sent update_fail_malformed_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fail_malformed_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1538+
}
15131539

15141540
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
15151541
}
@@ -1518,6 +1544,9 @@ impl Channel {
15181544
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15191545
return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", action: None});
15201546
}
1547+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1548+
return Err(HandleError{err: "Peer sent commitment_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent commitment_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1549+
}
15211550

15221551
let funding_script = self.get_funding_redeemscript();
15231552

@@ -1680,6 +1709,9 @@ impl Channel {
16801709
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16811710
return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", action: None});
16821711
}
1712+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1713+
return Err(HandleError{err: "Peer sent revoke_and_ack when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent revoke_and_ack when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1714+
}
16831715
if let Some(their_prev_commitment_point) = self.their_prev_commitment_point {
16841716
if PublicKey::from_secret_key(&self.secp_ctx, &secp_call!(SecretKey::from_slice(&self.secp_ctx, &msg.per_commitment_secret), "Peer provided an invalid per_commitment_secret", self.channel_id())) != their_prev_commitment_point {
16851717
return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", action: None});
@@ -1789,6 +1821,7 @@ impl Channel {
17891821
pub fn remove_uncommitted_htlcs(&mut self) -> Vec<(HTLCSource, [u8; 32])> {
17901822
let mut outbound_drops = Vec::new();
17911823

1824+
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
17921825
if self.channel_state < ChannelState::FundingSent as u32 {
17931826
self.channel_state = ChannelState::ShutdownComplete as u32;
17941827
return outbound_drops;
@@ -1845,13 +1878,19 @@ impl Channel {
18451878
if self.channel_outbound {
18461879
return Err(HandleError{err: "Non-funding remote tried to update channel fee", action: None});
18471880
}
1881+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1882+
return Err(HandleError{err: "Peer sent update_fee when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fee when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1883+
}
18481884
Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
18491885
self.channel_update_count += 1;
18501886
self.feerate_per_kw = msg.feerate_per_kw as u64;
18511887
Ok(())
18521888
}
18531889

18541890
pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, [u8; 32])>), HandleError> {
1891+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1892+
return Err(HandleError{err: "Peer sent shutdown when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent shutdown when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1893+
}
18551894
if self.channel_state < ChannelState::FundingSent as u32 {
18561895
self.channel_state = ChannelState::ShutdownComplete as u32;
18571896
self.channel_update_count += 1;
@@ -1952,6 +1991,9 @@ impl Channel {
19521991
if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
19531992
return Err(HandleError{err: "Remote end sent us a closing_signed before both sides provided a shutdown", action: None});
19541993
}
1994+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1995+
return Err(HandleError{err: "Peer sent closing_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent closing_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
1996+
}
19551997
if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() {
19561998
return Err(HandleError{err: "Remote end sent us a closing_signed while there were still pending HTLCs", action: None});
19571999
}
@@ -2128,7 +2170,7 @@ impl Channel {
21282170
/// is_usable() and considers things like the channel being temporarily disabled.
21292171
/// Allowed in any state (including after shutdown)
21302172
pub fn is_live(&self) -> bool {
2131-
self.is_usable()
2173+
self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32) == 0)
21322174
}
21332175

21342176
/// Returns true if funding_created was sent/received.
@@ -2428,6 +2470,16 @@ impl Channel {
24282470
return Err(HandleError{err: "Cannot send less than their minimum HTLC value", action: None});
24292471
}
24302472

2473+
if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) {
2474+
// Note that this should never really happen, if we're !is_live() on receipt of an
2475+
// incoming HTLC for relay will result in us rejecting the HTLC and we won't allow
2476+
// the user to send directly into a !is_live() channel. However, if we we
2477+
// disconnected during the time the previous hop was doing the commitment dance we may
2478+
// end up getting here after the forwarding delay. In any case, returning an
2479+
// IgnoreError will get ChannelManager to do the right thing and fail backwards now.
2480+
return Err(HandleError{err: "Cannot send an HTLC while disconnected", action: Some(ErrorAction::IgnoreError)});
2481+
}
2482+
24312483
let (_, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) = self.get_pending_htlc_stats(false);
24322484
if outbound_htlc_count + 1 > self.their_max_accepted_htlcs as u32 {
24332485
return Err(HandleError{err: "Cannot push more than their max accepted HTLCs", action: None});
@@ -2492,6 +2544,9 @@ impl Channel {
24922544
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
24932545
panic!("Cannot create commitment tx until remote revokes their previous commitment");
24942546
}
2547+
if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) {
2548+
panic!("Cannot create commitment tx while disconnected, as send_htlc will have returned an Err so a send_commitment precondition has been violated");
2549+
}
24952550
let mut have_updates = false; // TODO initialize with "have we sent a fee update?"
24962551
for htlc in self.pending_outbound_htlcs.iter() {
24972552
if htlc.state == OutboundHTLCState::LocalAnnounced {
@@ -2585,6 +2640,9 @@ impl Channel {
25852640
return Err(HandleError{err: "Shutdown already in progress", action: None});
25862641
}
25872642
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
2643+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
2644+
return Err(HandleError{err: "Cannot begin shutdown while peer is disconnected, maybe force-close instead?", action: None});
2645+
}
25882646

25892647
let our_closing_script = self.get_closing_scriptpubkey();
25902648

0 commit comments

Comments
 (0)