Skip to content

Commit ac0f53f

Browse files
committed
Free holding cell upon handling an invalid interactive-tx message
After cad88af, a few code paths that also lead to a quiescence exit were not accounted for. This commit addresses the path where we exit quiescence due to a processing error on a counterparty's `tx_add_input/output`, `tx_remove_input/output`, or `tx_complete` message.
1 parent 0a20fa5 commit ac0f53f

File tree

3 files changed

+221
-45
lines changed

3 files changed

+221
-45
lines changed

lightning/src/ln/channel.rs

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,18 @@ pub enum UpdateFulfillCommitFetch {
12041204
DuplicateClaim {},
12051205
}
12061206

1207+
/// Error returned when processing an invalid interactive-tx message from our counterparty.
1208+
pub(super) struct InteractiveTxMsgError {
1209+
/// The underlying error.
1210+
pub(super) err: ChannelError,
1211+
/// If a splice was in progress when processing the message, this contains the splice funding
1212+
/// information for emitting a `SpliceFailed` event.
1213+
pub(super) splice_funding_failed: Option<SpliceFundingFailed>,
1214+
/// Whether we were quiescent when we received the message, and are no longer due to aborting
1215+
/// the session.
1216+
pub(super) exited_quiescence: bool,
1217+
}
1218+
12071219
/// The return value of `monitor_updating_restored`
12081220
pub(super) struct MonitorRestoreUpdates {
12091221
pub raa: Option<msgs::RevokeAndACK>,
@@ -1846,104 +1858,118 @@ where
18461858

18471859
fn fail_interactive_tx_negotiation<L: Logger>(
18481860
&mut self, reason: AbortReason, logger: &L,
1849-
) -> (ChannelError, Option<SpliceFundingFailed>) {
1861+
) -> InteractiveTxMsgError {
18501862
let logger = WithChannelContext::from(logger, &self.context(), None);
18511863
log_info!(logger, "Failed interactive transaction negotiation: {reason}");
18521864

1853-
let splice_funding_failed = match &mut self.phase {
1865+
let (splice_funding_failed, exited_quiescence) = match &mut self.phase {
18541866
ChannelPhase::Undefined => unreachable!(),
1855-
ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => None,
1867+
ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {
1868+
(None, false)
1869+
},
18561870
ChannelPhase::UnfundedV2(pending_v2_channel) => {
18571871
pending_v2_channel.interactive_tx_constructor.take();
1858-
None
1872+
(None, false)
18591873
},
18601874
ChannelPhase::Funded(funded_channel) => {
18611875
if funded_channel.should_reset_pending_splice_state(false) {
1862-
funded_channel.reset_pending_splice_state()
1876+
(funded_channel.reset_pending_splice_state(), true)
18631877
} else {
18641878
debug_assert!(false, "We should never fail an interactive funding negotiation once we're exchanging tx_signatures");
1865-
None
1879+
(None, false)
18661880
}
18671881
},
18681882
};
18691883

1870-
(ChannelError::Abort(reason), splice_funding_failed)
1884+
InteractiveTxMsgError {
1885+
err: ChannelError::Abort(reason),
1886+
splice_funding_failed,
1887+
exited_quiescence,
1888+
}
18711889
}
18721890

18731891
pub fn tx_add_input<L: Logger>(
18741892
&mut self, msg: &msgs::TxAddInput, logger: &L,
1875-
) -> Result<InteractiveTxMessageSend, (ChannelError, Option<SpliceFundingFailed>)> {
1893+
) -> Result<InteractiveTxMessageSend, InteractiveTxMsgError> {
18761894
match self.interactive_tx_constructor_mut() {
18771895
Some(interactive_tx_constructor) => interactive_tx_constructor
18781896
.handle_tx_add_input(msg)
18791897
.map_err(|reason| self.fail_interactive_tx_negotiation(reason, logger)),
1880-
None => Err((
1881-
ChannelError::WarnAndDisconnect(
1898+
None => Err(InteractiveTxMsgError {
1899+
err: ChannelError::WarnAndDisconnect(
18821900
"Received unexpected interactive transaction negotiation message".to_owned(),
18831901
),
1884-
None,
1885-
)),
1902+
splice_funding_failed: None,
1903+
exited_quiescence: false,
1904+
}),
18861905
}
18871906
}
18881907

18891908
pub fn tx_add_output<L: Logger>(
18901909
&mut self, msg: &msgs::TxAddOutput, logger: &L,
1891-
) -> Result<InteractiveTxMessageSend, (ChannelError, Option<SpliceFundingFailed>)> {
1910+
) -> Result<InteractiveTxMessageSend, InteractiveTxMsgError> {
18921911
match self.interactive_tx_constructor_mut() {
18931912
Some(interactive_tx_constructor) => interactive_tx_constructor
18941913
.handle_tx_add_output(msg)
18951914
.map_err(|reason| self.fail_interactive_tx_negotiation(reason, logger)),
1896-
None => Err((
1897-
ChannelError::WarnAndDisconnect(
1915+
None => Err(InteractiveTxMsgError {
1916+
err: ChannelError::WarnAndDisconnect(
18981917
"Received unexpected interactive transaction negotiation message".to_owned(),
18991918
),
1900-
None,
1901-
)),
1919+
splice_funding_failed: None,
1920+
exited_quiescence: false,
1921+
}),
19021922
}
19031923
}
19041924

19051925
pub fn tx_remove_input<L: Logger>(
19061926
&mut self, msg: &msgs::TxRemoveInput, logger: &L,
1907-
) -> Result<InteractiveTxMessageSend, (ChannelError, Option<SpliceFundingFailed>)> {
1927+
) -> Result<InteractiveTxMessageSend, InteractiveTxMsgError> {
19081928
match self.interactive_tx_constructor_mut() {
19091929
Some(interactive_tx_constructor) => interactive_tx_constructor
19101930
.handle_tx_remove_input(msg)
19111931
.map_err(|reason| self.fail_interactive_tx_negotiation(reason, logger)),
1912-
None => Err((
1913-
ChannelError::WarnAndDisconnect(
1932+
None => Err(InteractiveTxMsgError {
1933+
err: ChannelError::WarnAndDisconnect(
19141934
"Received unexpected interactive transaction negotiation message".to_owned(),
19151935
),
1916-
None,
1917-
)),
1936+
splice_funding_failed: None,
1937+
exited_quiescence: false,
1938+
}),
19181939
}
19191940
}
19201941

19211942
pub fn tx_remove_output<L: Logger>(
19221943
&mut self, msg: &msgs::TxRemoveOutput, logger: &L,
1923-
) -> Result<InteractiveTxMessageSend, (ChannelError, Option<SpliceFundingFailed>)> {
1944+
) -> Result<InteractiveTxMessageSend, InteractiveTxMsgError> {
19241945
match self.interactive_tx_constructor_mut() {
19251946
Some(interactive_tx_constructor) => interactive_tx_constructor
19261947
.handle_tx_remove_output(msg)
19271948
.map_err(|reason| self.fail_interactive_tx_negotiation(reason, logger)),
1928-
None => Err((
1929-
ChannelError::WarnAndDisconnect(
1949+
None => Err(InteractiveTxMsgError {
1950+
err: ChannelError::WarnAndDisconnect(
19301951
"Received unexpected interactive transaction negotiation message".to_owned(),
19311952
),
1932-
None,
1933-
)),
1953+
splice_funding_failed: None,
1954+
exited_quiescence: false,
1955+
}),
19341956
}
19351957
}
19361958

19371959
pub fn tx_complete<F: FeeEstimator, L: Logger>(
19381960
&mut self, msg: &msgs::TxComplete, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
1939-
) -> Result<TxCompleteResult, (ChannelError, Option<SpliceFundingFailed>)> {
1961+
) -> Result<TxCompleteResult, InteractiveTxMsgError> {
19401962
let tx_complete_action = match self.interactive_tx_constructor_mut() {
19411963
Some(interactive_tx_constructor) => interactive_tx_constructor
19421964
.handle_tx_complete(msg)
19431965
.map_err(|reason| self.fail_interactive_tx_negotiation(reason, logger))?,
19441966
None => {
19451967
let err = "Received unexpected interactive transaction negotiation message";
1946-
return Err((ChannelError::WarnAndDisconnect(err.to_owned()), None));
1968+
return Err(InteractiveTxMsgError {
1969+
err: ChannelError::WarnAndDisconnect(err.to_owned()),
1970+
splice_funding_failed: None,
1971+
exited_quiescence: false,
1972+
});
19471973
},
19481974
};
19491975

lightning/src/ln/channelmanager.rs

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ use crate::ln::chan_utils::selected_commitment_sat_per_1000_weight;
5959
use crate::ln::channel::QuiescentAction;
6060
use crate::ln::channel::{
6161
self, hold_time_since, Channel, ChannelError, ChannelUpdateStatus, DisconnectResult,
62-
FundedChannel, FundingTxSigned, InboundV1Channel, OutboundHop, OutboundV1Channel,
63-
PendingV2Channel, ReconnectionMsg, ShutdownResult, SpliceFundingFailed, StfuResponse,
62+
FundedChannel, FundingTxSigned, InboundV1Channel, InteractiveTxMsgError, OutboundHop,
63+
OutboundV1Channel, PendingV2Channel, ReconnectionMsg, ShutdownResult, StfuResponse,
6464
UpdateFulfillCommitFetch, WithChannelContext,
6565
};
6666
use crate::ln::channel_state::ChannelDetails;
@@ -938,6 +938,7 @@ struct MsgHandleErrInternal {
938938
closes_channel: bool,
939939
shutdown_finish: Option<(ShutdownResult, Option<(msgs::ChannelUpdate, NodeId, NodeId)>)>,
940940
tx_abort: Option<msgs::TxAbort>,
941+
exited_quiescence: bool,
941942
}
942943

943944
impl MsgHandleErrInternal {
@@ -952,6 +953,7 @@ impl MsgHandleErrInternal {
952953
closes_channel: false,
953954
shutdown_finish: None,
954955
tx_abort: None,
956+
exited_quiescence: false,
955957
}
956958
}
957959

@@ -970,7 +972,13 @@ impl MsgHandleErrInternal {
970972
}
971973

972974
fn from_no_close(err: msgs::LightningError) -> Self {
973-
Self { err, closes_channel: false, shutdown_finish: None, tx_abort: None }
975+
Self {
976+
err,
977+
closes_channel: false,
978+
shutdown_finish: None,
979+
tx_abort: None,
980+
exited_quiescence: false,
981+
}
974982
}
975983

976984
fn from_finish_shutdown(
@@ -991,6 +999,7 @@ impl MsgHandleErrInternal {
991999
closes_channel: true,
9921000
shutdown_finish: Some((shutdown_res, channel_update)),
9931001
tx_abort: None,
1002+
exited_quiescence: false,
9941003
}
9951004
}
9961005

@@ -1026,7 +1035,13 @@ impl MsgHandleErrInternal {
10261035
},
10271036
},
10281037
};
1029-
Self { err, closes_channel: false, shutdown_finish: None, tx_abort }
1038+
Self {
1039+
err,
1040+
closes_channel: false,
1041+
shutdown_finish: None,
1042+
tx_abort,
1043+
exited_quiescence: false,
1044+
}
10301045
}
10311046

10321047
fn dont_send_error_message(&mut self) {
@@ -1042,6 +1057,11 @@ impl MsgHandleErrInternal {
10421057
fn closes_channel(&self) -> bool {
10431058
self.closes_channel
10441059
}
1060+
1061+
fn with_exited_quiescence(mut self, exited_quiescence: bool) -> Self {
1062+
self.exited_quiescence = exited_quiescence;
1063+
self
1064+
}
10451065
}
10461066

10471067
/// For events which result in both a RevokeAndACK and a CommitmentUpdate, by default they should
@@ -4350,15 +4370,26 @@ impl<
43504370
});
43514371
}
43524372

4353-
if let Some(msg_event) = msg_event {
4373+
let mut holding_cell_res = None;
4374+
if msg_event.is_some() || err_internal.exited_quiescence {
43544375
let per_peer_state = self.per_peer_state.read().unwrap();
43554376
if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) {
43564377
let mut peer_state = peer_state_mutex.lock().unwrap();
4357-
if peer_state.is_connected {
4358-
peer_state.pending_msg_events.push(msg_event);
4378+
if let Some(msg_event) = msg_event {
4379+
if peer_state.is_connected {
4380+
peer_state.pending_msg_events.push(msg_event);
4381+
}
43594382
}
4383+
// We need to enqueue the `tx_abort` in `pending_msg_events` above before we
4384+
// enqueue any commitment updates generated by freeing holding cell HTLCs.
4385+
holding_cell_res = err_internal
4386+
.exited_quiescence
4387+
.then(|| self.check_free_peer_holding_cells(&mut peer_state));
43604388
}
43614389
}
4390+
if let Some(res) = holding_cell_res {
4391+
self.handle_holding_cell_free_result(res);
4392+
}
43624393

43634394
// Return error in case higher-API need one
43644395
err_internal.err
@@ -11301,9 +11332,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1130111332
}
1130211333

1130311334
fn internal_tx_msg<
11304-
HandleTxMsgFn: Fn(
11305-
&mut Channel<SP>,
11306-
) -> Result<InteractiveTxMessageSend, (ChannelError, Option<SpliceFundingFailed>)>,
11335+
HandleTxMsgFn: Fn(&mut Channel<SP>) -> Result<InteractiveTxMessageSend, InteractiveTxMsgError>,
1130711336
>(
1130811337
&self, counterparty_node_id: &PublicKey, channel_id: ChannelId,
1130911338
tx_msg_handler: HandleTxMsgFn,
@@ -11324,7 +11353,11 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1132411353
peer_state.pending_msg_events.push(msg_send_event);
1132511354
Ok(NotifyOption::SkipPersistHandleEvents)
1132611355
},
11327-
Err((error, splice_funding_failed)) => {
11356+
Err(InteractiveTxMsgError {
11357+
err,
11358+
splice_funding_failed,
11359+
exited_quiescence,
11360+
}) => {
1132811361
if let Some(splice_funding_failed) = splice_funding_failed {
1132911362
let pending_events = &mut self.pending_events.lock().unwrap();
1133011363
pending_events.push_back((
@@ -11340,7 +11373,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1134011373
None,
1134111374
));
1134211375
}
11343-
Err(MsgHandleErrInternal::from_chan_no_close(error, channel_id))
11376+
debug_assert!(!exited_quiescence || matches!(err, ChannelError::Abort(_)));
11377+
11378+
Err(MsgHandleErrInternal::from_chan_no_close(err, channel_id)
11379+
.with_exited_quiescence(exited_quiescence))
1134411380
},
1134511381
}
1134611382
},
@@ -11470,7 +11506,11 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1147011506

1147111507
Ok(persist)
1147211508
},
11473-
Err((error, splice_funding_failed)) => {
11509+
Err(InteractiveTxMsgError {
11510+
err,
11511+
splice_funding_failed,
11512+
exited_quiescence,
11513+
}) => {
1147411514
if let Some(splice_funding_failed) = splice_funding_failed {
1147511515
let pending_events = &mut self.pending_events.lock().unwrap();
1147611516
pending_events.push_back((
@@ -11486,7 +11526,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1148611526
None,
1148711527
));
1148811528
}
11489-
Err(MsgHandleErrInternal::from_chan_no_close(error, msg.channel_id))
11529+
debug_assert!(!exited_quiescence || matches!(err, ChannelError::Abort(_)));
11530+
11531+
Err(MsgHandleErrInternal::from_chan_no_close(err, msg.channel_id)
11532+
.with_exited_quiescence(exited_quiescence))
1149011533
},
1149111534
}
1149211535
},

0 commit comments

Comments
 (0)