Skip to content

Commit 127fdfb

Browse files
committed
Add ChannelShutdownState to ChannelDetails
This commit adds the state of channel shutdown to channeldetails
1 parent d327c23 commit 127fdfb

File tree

6 files changed

+198
-9
lines changed

6 files changed

+198
-9
lines changed

fuzz/src/router.rs

+1
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
270270
inbound_htlc_maximum_msat: None,
271271
config: None,
272272
feerate_sat_per_1000_weight: None,
273+
is_channel_shutting_down: 0,
273274
});
274275
}
275276
Some(&first_hops_vec[..])

lightning/src/ln/channel.rs

+30-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
2727
use crate::ln::msgs;
2828
use crate::ln::msgs::DecodeError;
2929
use crate::ln::script::{self, ShutdownScript};
30-
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
30+
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT, ChannelShutdownState};
3131
use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
3232
use crate::ln::chan_utils;
3333
use crate::ln::onion_utils::HTLCFailReason;
@@ -903,6 +903,34 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
903903
(self.channel_state & mask) == (ChannelState::ChannelReady as u32) && !self.monitor_pending_channel_ready
904904
}
905905

906+
/// shutdown state returns the state of the channel in its various stages of shutdown
907+
pub fn shutdown_state(&self) -> u32 {
908+
if self.channel_state & (ChannelState::ShutdownComplete as u32) != 0 {
909+
return ChannelShutdownState::ShutdownComplete as u32;
910+
}
911+
if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 && self.channel_state & (ChannelState::RemoteShutdownSent as u32) == 0 {
912+
return ChannelShutdownState::ShutdownInitiated as u32;
913+
}
914+
if (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != 0) && !self.closing_negotiation_ready(){
915+
return ChannelShutdownState::ResolvingHTLCs as u32;
916+
}
917+
if (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != 0) && self.closing_negotiation_ready(){
918+
return ChannelShutdownState::ClosingSignNegotiation as u32;
919+
}
920+
return ChannelShutdownState::NotShuttingDown as u32;
921+
}
922+
923+
fn closing_negotiation_ready(&self) -> bool {
924+
self.pending_inbound_htlcs.is_empty() &&
925+
self.pending_outbound_htlcs.is_empty() &&
926+
self.pending_update_fee.is_none() &&
927+
self.channel_state &
928+
(BOTH_SIDES_SHUTDOWN_MASK |
929+
ChannelState::AwaitingRemoteRevoke as u32 |
930+
ChannelState::PeerDisconnected as u32 |
931+
ChannelState::MonitorUpdateInProgress as u32) == BOTH_SIDES_SHUTDOWN_MASK
932+
}
933+
906934
/// Returns true if this channel is currently available for use. This is a superset of
907935
/// is_usable() and considers things like the channel being temporarily disabled.
908936
/// Allowed in any state (including after shutdown)
@@ -3956,12 +3984,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
39563984
/// this point if we're the funder we should send the initial closing_signed, and in any case
39573985
/// shutdown should complete within a reasonable timeframe.
39583986
fn closing_negotiation_ready(&self) -> bool {
3959-
self.context.pending_inbound_htlcs.is_empty() && self.context.pending_outbound_htlcs.is_empty() &&
3960-
self.context.channel_state &
3961-
(BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32 |
3962-
ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateInProgress as u32)
3963-
== BOTH_SIDES_SHUTDOWN_MASK &&
3964-
self.context.pending_update_fee.is_none()
3987+
self.context.closing_negotiation_ready()
39653988
}
39663989

39673990
/// Checks if the closing_signed negotiation is making appropriate progress, possibly returning

lightning/src/ln/channelmanager.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,8 @@ pub struct ChannelDetails {
14641464
///
14651465
/// [`confirmations_required`]: ChannelDetails::confirmations_required
14661466
pub is_channel_ready: bool,
1467+
/// Furthur information on the details of the channel shutdown.
1468+
pub channel_shutdown_state: u32,
14671469
/// True if the channel is (a) confirmed and channel_ready messages have been exchanged, (b)
14681470
/// the peer is connected, and (c) the channel is not currently negotiating a shutdown.
14691471
///
@@ -1482,6 +1484,22 @@ pub struct ChannelDetails {
14821484
pub config: Option<ChannelConfig>,
14831485
}
14841486

1487+
/// Furthur information on the details of the channel shutdown.
1488+
pub enum ChannelShutdownState {
1489+
/// Channel has not sent or recieved a shutdown message
1490+
NotShuttingDown = 0,
1491+
/// Local node has sent a shutdown message for this channel
1492+
ShutdownInitiated = 1,
1493+
/// Shutdown Message exchanges have concluded and the channels are in the midst of
1494+
/// resolving all exisiting open htlcs before closing can continue
1495+
ResolvingHTLCs = 2,
1496+
/// All htlcs have been resolved, nodes are currently negotiating channel close onchain fee rates
1497+
ClosingSignNegotiation = 3,
1498+
/// We've successfully negotiated a closing_signed dance. At this point ChannelManager is about
1499+
/// to drop us, but we store this anyway.
1500+
ShutdownComplete = 4,
1501+
}
1502+
14851503
impl ChannelDetails {
14861504
/// Gets the current SCID which should be used to identify this channel for inbound payments.
14871505
/// This should be used for providing invoice hints or in any other context where our
@@ -1551,6 +1569,7 @@ impl ChannelDetails {
15511569
inbound_htlc_minimum_msat: Some(context.get_holder_htlc_minimum_msat()),
15521570
inbound_htlc_maximum_msat: context.get_holder_htlc_maximum_msat(),
15531571
config: Some(context.config()),
1572+
channel_shutdown_state: context.shutdown_state(),
15541573
}
15551574
}
15561575
}
@@ -7343,6 +7362,7 @@ impl Writeable for ChannelDetails {
73437362
(35, self.inbound_htlc_maximum_msat, option),
73447363
(37, user_channel_id_high_opt, option),
73457364
(39, self.feerate_sat_per_1000_weight, option),
7365+
(41, self.channel_shutdown_state, required),
73467366
});
73477367
Ok(())
73487368
}
@@ -7380,6 +7400,7 @@ impl Readable for ChannelDetails {
73807400
(35, inbound_htlc_maximum_msat, option),
73817401
(37, user_channel_id_high_opt, option),
73827402
(39, feerate_sat_per_1000_weight, option),
7403+
(41, channel_shutdown_state, required),
73837404
});
73847405

73857406
// `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with
@@ -7415,6 +7436,7 @@ impl Readable for ChannelDetails {
74157436
inbound_htlc_minimum_msat,
74167437
inbound_htlc_maximum_msat,
74177438
feerate_sat_per_1000_weight,
7439+
channel_shutdown_state: channel_shutdown_state.0.unwrap(),
74187440
})
74197441
}
74207442
}

lightning/src/ln/functional_test_utils.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1951,6 +1951,16 @@ macro_rules! expect_payment_forwarded {
19511951
}
19521952
}
19531953

1954+
#[cfg(test)]
1955+
#[macro_export]
1956+
macro_rules! expect_channel_shutdown_state {
1957+
($node: expr, $chan_id: expr, $state: path) => {
1958+
let chan_details = $node.node.list_channels().into_iter().filter(|cd| cd.channel_id == $chan_id).collect::<Vec<ChannelDetails>>();
1959+
assert_eq!(chan_details.len(), 1);
1960+
assert_eq!(chan_details[0].channel_shutdown_state, $state as u32);
1961+
}
1962+
}
1963+
19541964
#[cfg(any(test, ldk_bench, feature = "_test_utils"))]
19551965
pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
19561966
let events = node.node.get_and_clear_pending_events();

lightning/src/ln/shutdown_tests.rs

+132-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use crate::sign::{EntropySource, SignerProvider};
1313
use crate::chain::transaction::OutPoint;
1414
use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
15-
use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields};
15+
use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, ChannelShutdownState, ChannelDetails};
1616
use crate::routing::router::{PaymentParameters, get_route};
1717
use crate::ln::msgs;
1818
use crate::ln::msgs::{ChannelMessageHandler, ErrorAction};
@@ -67,6 +67,137 @@ fn pre_funding_lock_shutdown_test() {
6767
check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure);
6868
}
6969

70+
#[test]
71+
fn expect_channel_shutdown_state() {
72+
// Test sending a shutdown prior to channel_ready after funding generation
73+
let chanmon_cfgs = create_chanmon_cfgs(2);
74+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
75+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
76+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
77+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
78+
79+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown);
80+
81+
nodes[0].node.close_channel(&chan_1.2, &nodes[1].node.get_our_node_id()).unwrap();
82+
83+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated);
84+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown);
85+
86+
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
87+
nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &node_0_shutdown);
88+
89+
// node1 goes into closingSignNegotiation since there are no HTLCs in flight, note that it
90+
// doesnt mean that node1 has sent/recved its closing signed message
91+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated);
92+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ClosingSignNegotiation);
93+
94+
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
95+
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &node_1_shutdown);
96+
97+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ClosingSignNegotiation);
98+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ClosingSignNegotiation);
99+
100+
let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
101+
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed);
102+
let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id());
103+
nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &node_1_closing_signed);
104+
let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id());
105+
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap());
106+
let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id());
107+
assert!(node_1_none.is_none());
108+
109+
assert!(nodes[0].node.list_channels().is_empty());
110+
assert!(nodes[1].node.list_channels().is_empty());
111+
check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure);
112+
check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure);
113+
}
114+
115+
#[test]
116+
fn expect_channel_shutdown_state_with_htlc() {
117+
// Test sending a shutdown with outstanding updates pending.
118+
let chanmon_cfgs = create_chanmon_cfgs(3);
119+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
120+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
121+
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
122+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
123+
let _chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
124+
125+
let (payment_preimage_0, payment_hash_0, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000);
126+
127+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown);
128+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown);
129+
130+
nodes[0].node.close_channel(&chan_1.2, &nodes[1].node.get_our_node_id()).unwrap();
131+
132+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated);
133+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown);
134+
135+
let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
136+
nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &node_0_shutdown);
137+
138+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated);
139+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ResolvingHTLCs);
140+
141+
let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
142+
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &node_1_shutdown);
143+
144+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ResolvingHTLCs);
145+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ResolvingHTLCs);
146+
147+
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
148+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
149+
150+
// Claim Funds on Node2
151+
nodes[2].node.claim_funds(payment_preimage_0);
152+
check_added_monitors!(nodes[2], 1);
153+
expect_payment_claimed!(nodes[2], payment_hash_0, 100_000);
154+
155+
// Fulfil HTLCs on node1 and node0
156+
let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
157+
assert!(updates.update_add_htlcs.is_empty());
158+
assert!(updates.update_fail_htlcs.is_empty());
159+
assert!(updates.update_fail_malformed_htlcs.is_empty());
160+
assert!(updates.update_fee.is_none());
161+
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
162+
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
163+
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false);
164+
check_added_monitors!(nodes[1], 1);
165+
let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
166+
commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
167+
168+
// Still in "resolvingHTLCs" on chan1 after htlc removed on chan2
169+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ResolvingHTLCs);
170+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ResolvingHTLCs);
171+
172+
assert!(updates_2.update_add_htlcs.is_empty());
173+
assert!(updates_2.update_fail_htlcs.is_empty());
174+
assert!(updates_2.update_fail_malformed_htlcs.is_empty());
175+
assert!(updates_2.update_fee.is_none());
176+
assert_eq!(updates_2.update_fulfill_htlcs.len(), 1);
177+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates_2.update_fulfill_htlcs[0]);
178+
commitment_signed_dance!(nodes[0], nodes[1], updates_2.commitment_signed, false, true);
179+
expect_payment_sent!(nodes[0], payment_preimage_0);
180+
181+
// all htlcs removed, chan1 advances to ClosingSignNegotiation
182+
expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ClosingSignNegotiation);
183+
expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ClosingSignNegotiation);
184+
185+
// ClosingSignNegotion process
186+
let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
187+
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed);
188+
let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id());
189+
nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &node_1_closing_signed);
190+
let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id());
191+
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap());
192+
let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id());
193+
assert!(node_1_none.is_none());
194+
check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure);
195+
check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure);
196+
197+
// Shutdown basically removes the channelDetails, testing of shutdowncomplete state unnecessary
198+
assert!(nodes[0].node.list_channels().is_empty());
199+
}
200+
70201
#[test]
71202
fn updates_shutdown_wait() {
72203
// Test sending a shutdown with outstanding updates pending

lightning/src/routing/router.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2687,7 +2687,8 @@ mod tests {
26872687
inbound_htlc_minimum_msat: None,
26882688
inbound_htlc_maximum_msat: None,
26892689
config: None,
2690-
feerate_sat_per_1000_weight: None
2690+
feerate_sat_per_1000_weight: None,
2691+
channel_shutdown_state: 0,
26912692
}
26922693
}
26932694

@@ -6758,6 +6759,7 @@ pub(crate) mod bench_utils {
67586759
inbound_htlc_maximum_msat: None,
67596760
config: None,
67606761
feerate_sat_per_1000_weight: None,
6762+
channel_shutdown_state: 0,
67616763
}
67626764
}
67636765

0 commit comments

Comments
 (0)