Skip to content

Commit c109563

Browse files
committed
Promote V2 channels to Channel on initial commitment_signed receipt
Before this commit, unfunded V2 channels were promoted to `Channel`s in the `Funded` channel phase in `funding_tx_constructed`. Since a monitor is only created upon receipt of an initial `commitment_signed`, this would cause a crash if the channel was read from persisted data between those two events. Consequently, we also need to hold an `interactive_tx_signing_session` for both of our unfunded V2 channel structs.
1 parent 5553df6 commit c109563

File tree

2 files changed

+97
-48
lines changed

2 files changed

+97
-48
lines changed

lightning/src/ln/channel.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
19881988
}
19891989

19901990
pub fn funding_tx_constructed<L: Deref>(
1991-
&mut self, signing_session: &mut InteractiveTxSigningSession, logger: &L
1991+
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
19921992
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
19931993
where
19941994
L::Target: Logger
@@ -2077,6 +2077,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
20772077

20782078
// Clear the interactive transaction constructor
20792079
self.interactive_tx_constructor.take();
2080+
self.interactive_tx_signing_session = Some(signing_session);
20802081

20812082
Ok((commitment_signed, funding_ready_for_sig_event))
20822083
}
@@ -9029,6 +9030,8 @@ pub(super) struct PendingV2Channel<SP: Deref> where SP::Target: SignerProvider {
90299030
pub dual_funding_context: DualFundingChannelContext,
90309031
/// The current interactive transaction construction session under negotiation.
90319032
pub interactive_tx_constructor: Option<InteractiveTxConstructor>,
9033+
/// The signing session created after `tx_complete` handling
9034+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
90329035
}
90339036

90349037
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
@@ -9093,6 +9096,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
90939096
our_funding_inputs: funding_inputs,
90949097
},
90959098
interactive_tx_constructor: None,
9099+
interactive_tx_signing_session: None,
90969100
};
90979101
Ok(chan)
90989102
}
@@ -9269,6 +9273,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
92699273
context,
92709274
dual_funding_context,
92719275
interactive_tx_constructor,
9276+
interactive_tx_signing_session: None,
92729277
unfunded_context,
92739278
})
92749279
}
@@ -9347,10 +9352,17 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
93479352
self.generate_accept_channel_v2_message()
93489353
}
93499354

9350-
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<FundedChannel<SP>, ChannelError>{
9351-
let holder_commitment_point = self.unfunded_context.holder_commitment_point.ok_or(ChannelError::close(
9352-
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9353-
self.context.channel_id())))?;
9355+
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<FundedChannel<SP>, (PendingV2Channel<SP>, ChannelError)> {
9356+
let holder_commitment_point = match self.unfunded_context.holder_commitment_point {
9357+
Some(holder_commitment_point) => holder_commitment_point,
9358+
None => {
9359+
let channel_id = self.context.channel_id();
9360+
return Err((self, ChannelError::close(
9361+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9362+
channel_id))));
9363+
}
9364+
};
9365+
93549366
let channel = FundedChannel {
93559367
context: self.context,
93569368
interactive_tx_signing_session: Some(signing_session),

lightning/src/ln/channelmanager.rs

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8315,26 +8315,21 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
83158315
if let Some(msg_send_event) = msg_send_event_opt {
83168316
peer_state.pending_msg_events.push(msg_send_event);
83178317
};
8318-
if let Some(mut signing_session) = signing_session_opt {
8318+
if let Some(signing_session) = signing_session_opt {
83198319
let (commitment_signed, funding_ready_for_sig_event_opt) = match chan_phase_entry.get_mut().as_unfunded_v2_mut() {
83208320
Some(chan) => {
8321-
chan.funding_tx_constructed(&mut signing_session, &self.logger)
8321+
let (commitment_signed, funding_ready_for_sig_event_opt) =
8322+
chan.funding_tx_constructed(signing_session, &self.logger)
8323+
.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8324+
(commitment_signed, funding_ready_for_sig_event_opt)
83228325
},
8323-
None => Err(ChannelError::Warn(
8324-
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
8325-
.into())),
8326-
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8327-
let (channel_id, channel_phase) = chan_phase_entry.remove_entry();
8328-
let channel = match channel_phase.into_unfunded_v2() {
8329-
Some(chan) => chan.into_channel(signing_session),
83308326
None => {
8331-
debug_assert!(false); // It cannot be another variant as we are in the `Ok` branch of the above match.
8332-
Err(ChannelError::Warn(
8327+
debug_assert!(false, "Should be in UnfundedV2 phase as checked earlier");
8328+
return Err(ChannelError::Warn(
83338329
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
8334-
.into()))
8335-
},
8336-
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8337-
peer_state.channel_by_id.insert(channel_id, Channel::from(channel));
8330+
.into())).map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id));
8331+
}
8332+
};
83388333
if let Some(funding_ready_for_sig_event) = funding_ready_for_sig_event_opt {
83398334
let mut pending_events = self.pending_events.lock().unwrap();
83408335
pending_events.push_back((funding_ready_for_sig_event, None));
@@ -8850,46 +8845,88 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
88508845
})?;
88518846
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
88528847
let peer_state = &mut *peer_state_lock;
8853-
match peer_state.channel_by_id.entry(msg.channel_id) {
8854-
hash_map::Entry::Occupied(mut chan_phase_entry) => {
8855-
if let Some(chan) = chan_phase_entry.get_mut().as_funded_mut() {
8856-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8857-
let funding_txo = chan.context.get_funding_txo();
8858-
8859-
if chan.interactive_tx_signing_session.is_some() {
8860-
let monitor = try_chan_phase_entry!(
8861-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8862-
chan_phase_entry);
8863-
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
8864-
if let Ok(persist_state) = monitor_res {
8865-
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
8866-
per_peer_state, chan, INITIAL_MONITOR);
8867-
} else {
8868-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8869-
log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
8870-
try_chan_phase_entry!(self, peer_state, Err(ChannelError::Close(
8848+
let (channel_id, mut funded_channel) = match peer_state.channel_by_id.entry(msg.channel_id) {
8849+
hash_map::Entry::Occupied(mut channel_entry) => {
8850+
match channel_entry.get_mut() {
8851+
Channel::UnfundedV2(chan) => {
8852+
if let Some(signing_session) = chan.interactive_tx_signing_session.take() {
8853+
let (channel_id, mut channel) = channel_entry.remove_entry();
8854+
if let Channel::UnfundedV2(chan) = channel {
88718855
(
8872-
"Channel funding outpoint was a duplicate".to_owned(),
8873-
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8856+
channel_id,
8857+
chan.into_channel(signing_session)
8858+
.map_err(|(mut chan, err)|
8859+
convert_chan_phase_err!(self, peer_state, err, chan.context, &channel_id, UNFUNDED_CHANNEL).1
8860+
)?
88748861
)
8875-
)), chan_phase_entry)
8862+
} else {
8863+
debug_assert!(false, "The channel phase was not UnfundedV2");
8864+
let err = ChannelError::close(
8865+
"Closing due to unexpected sender error".into());
8866+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut channel,
8867+
&channel_id).1)
8868+
}
8869+
} else {
8870+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8871+
"Got a commitment_signed message for a V2 channel before funding transaction constructed!".into())), channel_entry);
88768872
}
8877-
} else {
8873+
},
8874+
Channel::Funded(chan) => {
8875+
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8876+
let funding_txo = chan.context.get_funding_txo();
88788877
let monitor_update_opt = try_chan_phase_entry!(
8879-
self, peer_state, chan.commitment_signed(msg, &&logger), chan_phase_entry);
8878+
self, peer_state, chan.commitment_signed(msg, &&logger), channel_entry);
88808879
if let Some(monitor_update) = monitor_update_opt {
88818880
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
88828881
peer_state, per_peer_state, chan);
88838882
}
8883+
return Ok(())
8884+
},
8885+
_ => {
8886+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8887+
"Got a commitment_signed message for an unfunded channel!".into())), channel_entry);
88848888
}
8885-
Ok(())
8886-
} else {
8887-
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8888-
"Got a commitment_signed message for an unfunded channel!".into())), chan_phase_entry);
88898889
}
88908890
},
8891-
hash_map::Entry::Vacant(_) => Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
8891+
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(
8892+
format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}",
8893+
counterparty_node_id), msg.channel_id))
8894+
};
8895+
let logger = WithChannelContext::from(&self.logger, &funded_channel.context, None);
8896+
let monitor = match funded_channel.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger) {
8897+
Ok(monitor) => monitor,
8898+
Err(err) => {
8899+
let channel = &mut Channel::Funded(funded_channel);
8900+
return Err(convert_chan_phase_err!(self, peer_state, err, channel, &channel_id).1);
8901+
}
8902+
};
8903+
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
8904+
if let Ok(persist_state) = monitor_res {
8905+
let mut occupied_entry = peer_state.channel_by_id.entry(channel_id).insert(Channel::Funded(funded_channel));
8906+
let channel_entry = occupied_entry.get_mut();
8907+
match channel_entry {
8908+
Channel::Funded(chan) => { handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
8909+
per_peer_state, chan, INITIAL_MONITOR); },
8910+
channel => {
8911+
debug_assert!(false, "Expected a Channel::Funded");
8912+
let err = ChannelError::close(
8913+
"Closing due to unexpected sender error".into());
8914+
return Err(convert_chan_phase_err!(self, peer_state, err, channel,
8915+
&channel_id).1)
8916+
},
8917+
}
8918+
} else {
8919+
log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
8920+
let err = ChannelError::Close(
8921+
(
8922+
"Channel funding outpoint was a duplicate".to_owned(),
8923+
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8924+
)
8925+
);
8926+
let chan = &mut Channel::Funded(funded_channel);
8927+
return Err(convert_chan_phase_err!(self, peer_state, err, chan, &channel_id).1);
88928928
}
8929+
Ok(())
88938930
}
88948931

88958932
fn push_decode_update_add_htlcs(&self, mut update_add_htlcs: (u64, Vec<msgs::UpdateAddHTLC>)) {

0 commit comments

Comments
 (0)