Skip to content

Commit 96a6420

Browse files
committed
Add a Disconnected ChannelState and check/handle it everywhere
Setting/removing it comes next
1 parent 347ffdb commit 96a6420

File tree

1 file changed

+73
-7
lines changed

1 file changed

+73
-7
lines changed

src/ln/channel.rs

+73-7
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,12 +1365,23 @@ 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;
13601374
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
13611375
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK);
13621376
self.channel_update_count += 1;
1377+
} else if self.channel_state & (ChannelState::ChannelFunded as u32) != 0 &&
1378+
self.cur_local_commitment_transaction_number == (1 << 48) - 2 &&
1379+
self.cur_remote_commitment_transaction_number == (1 << 48) - 2 {
1380+
if self.their_cur_commitment_point != Some(msg.next_per_commitment_point) {
1381+
return Err(HandleError{err: "Peer sent a reconnect funding_locked with a different point", action: None});
1382+
}
1383+
// They probably disconnected/reconnected and re-sent the funding_locked, which is required
1384+
return Ok(());
13631385
} else {
13641386
return Err(HandleError{err: "Peer sent a funding_locked at a strange time", action: None});
13651387
}
@@ -1411,6 +1433,9 @@ impl Channel {
14111433
if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
14121434
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
14131435
}
1436+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1437+
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}})});
1438+
}
14141439
if msg.amount_msat > self.channel_value_satoshis * 1000 {
14151440
return Err(HandleError{err: "Remote side tried to send more than the total value of the channel", action: None});
14161441
}
@@ -1489,6 +1514,9 @@ impl Channel {
14891514
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
14901515
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
14911516
}
1517+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1518+
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}})});
1519+
}
14921520

14931521
let mut sha = Sha256::new();
14941522
sha.input(&msg.payment_preimage);
@@ -1502,6 +1530,9 @@ impl Channel {
15021530
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15031531
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
15041532
}
1533+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1534+
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}})});
1535+
}
15051536

15061537
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
15071538
}
@@ -1510,6 +1541,9 @@ impl Channel {
15101541
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15111542
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
15121543
}
1544+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1545+
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}})});
1546+
}
15131547

15141548
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
15151549
}
@@ -1518,6 +1552,9 @@ impl Channel {
15181552
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
15191553
return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", action: None});
15201554
}
1555+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1556+
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}})});
1557+
}
15211558

15221559
let funding_script = self.get_funding_redeemscript();
15231560

@@ -1680,6 +1717,9 @@ impl Channel {
16801717
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
16811718
return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", action: None});
16821719
}
1720+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1721+
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}})});
1722+
}
16831723
if let Some(their_prev_commitment_point) = self.their_prev_commitment_point {
16841724
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 {
16851725
return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", action: None});
@@ -1789,6 +1829,7 @@ impl Channel {
17891829
pub fn remove_uncommitted_htlcs(&mut self) -> Vec<(HTLCSource, [u8; 32])> {
17901830
let mut outbound_drops = Vec::new();
17911831

1832+
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
17921833
if self.channel_state < ChannelState::FundingSent as u32 {
17931834
self.channel_state = ChannelState::ShutdownComplete as u32;
17941835
return outbound_drops;
@@ -1845,13 +1886,19 @@ impl Channel {
18451886
if self.channel_outbound {
18461887
return Err(HandleError{err: "Non-funding remote tried to update channel fee", action: None});
18471888
}
1889+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1890+
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}})});
1891+
}
18481892
Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
18491893
self.channel_update_count += 1;
18501894
self.feerate_per_kw = msg.feerate_per_kw as u64;
18511895
Ok(())
18521896
}
18531897

18541898
pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, [u8; 32])>), HandleError> {
1899+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1900+
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}})});
1901+
}
18551902
if self.channel_state < ChannelState::FundingSent as u32 {
18561903
self.channel_state = ChannelState::ShutdownComplete as u32;
18571904
self.channel_update_count += 1;
@@ -1952,6 +1999,9 @@ impl Channel {
19521999
if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
19532000
return Err(HandleError{err: "Remote end sent us a closing_signed before both sides provided a shutdown", action: None});
19542001
}
2002+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
2003+
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}})});
2004+
}
19552005
if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() {
19562006
return Err(HandleError{err: "Remote end sent us a closing_signed while there were still pending HTLCs", action: None});
19572007
}
@@ -2128,7 +2178,7 @@ impl Channel {
21282178
/// is_usable() and considers things like the channel being temporarily disabled.
21292179
/// Allowed in any state (including after shutdown)
21302180
pub fn is_live(&self) -> bool {
2131-
self.is_usable()
2181+
self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32) == 0)
21322182
}
21332183

21342184
/// Returns true if funding_created was sent/received.
@@ -2428,6 +2478,16 @@ impl Channel {
24282478
return Err(HandleError{err: "Cannot send less than their minimum HTLC value", action: None});
24292479
}
24302480

2481+
if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) {
2482+
// Note that this should never really happen, if we're !is_live() on receipt of an
2483+
// incoming HTLC for relay will result in us rejecting the HTLC and we won't allow
2484+
// the user to send directly into a !is_live() channel. However, if we
2485+
// disconnected during the time the previous hop was doing the commitment dance we may
2486+
// end up getting here after the forwarding delay. In any case, returning an
2487+
// IgnoreError will get ChannelManager to do the right thing and fail backwards now.
2488+
return Err(HandleError{err: "Cannot send an HTLC while disconnected", action: Some(ErrorAction::IgnoreError)});
2489+
}
2490+
24312491
let (_, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) = self.get_pending_htlc_stats(false);
24322492
if outbound_htlc_count + 1 > self.their_max_accepted_htlcs as u32 {
24332493
return Err(HandleError{err: "Cannot push more than their max accepted HTLCs", action: None});
@@ -2492,6 +2552,9 @@ impl Channel {
24922552
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
24932553
panic!("Cannot create commitment tx until remote revokes their previous commitment");
24942554
}
2555+
if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) {
2556+
panic!("Cannot create commitment tx while disconnected, as send_htlc will have returned an Err so a send_commitment precondition has been violated");
2557+
}
24952558
let mut have_updates = false; // TODO initialize with "have we sent a fee update?"
24962559
for htlc in self.pending_outbound_htlcs.iter() {
24972560
if htlc.state == OutboundHTLCState::LocalAnnounced {
@@ -2585,6 +2648,9 @@ impl Channel {
25852648
return Err(HandleError{err: "Shutdown already in progress", action: None});
25862649
}
25872650
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
2651+
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
2652+
return Err(HandleError{err: "Cannot begin shutdown while peer is disconnected, maybe force-close instead?", action: None});
2653+
}
25882654

25892655
let our_closing_script = self.get_closing_scriptpubkey();
25902656

0 commit comments

Comments
 (0)