Skip to content

Commit 0b7b89e

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 64abcff commit 0b7b89e

File tree

2 files changed

+106
-48
lines changed

2 files changed

+106
-48
lines changed

lightning/src/ln/channel.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8746,6 +8746,8 @@ pub(super) struct OutboundV2Channel<SP: Deref> where SP::Target: SignerProvider
87468746
pub dual_funding_context: DualFundingChannelContext,
87478747
/// The current interactive transaction construction session under negotiation.
87488748
interactive_tx_constructor: Option<InteractiveTxConstructor>,
8749+
/// The signing session created after `tx_complete` handling
8750+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
87498751
}
87508752

87518753
impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
@@ -8805,6 +8807,7 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
88058807
our_funding_inputs: funding_inputs,
88068808
},
88078809
interactive_tx_constructor: None,
8810+
interactive_tx_signing_session: None,
88088811
};
88098812
Ok(chan)
88108813
}
@@ -8872,13 +8875,11 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
88728875
}
88738876
}
88748877

8875-
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
8876-
let channel = Channel {
8878+
pub fn into_channel(self) -> Channel<SP> {
8879+
Channel {
88778880
context: self.context,
8878-
interactive_tx_signing_session: Some(signing_session),
8879-
};
8880-
8881-
Ok(channel)
8881+
interactive_tx_signing_session: self.interactive_tx_signing_session,
8882+
}
88828883
}
88838884
}
88848885

@@ -8889,6 +8890,8 @@ pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
88898890
pub dual_funding_context: DualFundingChannelContext,
88908891
/// The current interactive transaction construction session under negotiation.
88918892
interactive_tx_constructor: Option<InteractiveTxConstructor>,
8893+
/// The signing session created after `tx_complete` handling
8894+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
88928895
}
88938896

88948897
impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
@@ -8990,6 +8993,7 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
89908993
context,
89918994
dual_funding_context,
89928995
interactive_tx_constructor,
8996+
interactive_tx_signing_session: None,
89938997
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
89948998
})
89958999
}
@@ -9066,13 +9070,11 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
90669070
self.generate_accept_channel_v2_message()
90679071
}
90689072

9069-
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
9070-
let channel = Channel {
9073+
pub fn into_channel(self) -> Channel<SP> {
9074+
Channel {
90719075
context: self.context,
9072-
interactive_tx_signing_session: Some(signing_session),
9073-
};
9074-
9075-
Ok(channel)
9076+
interactive_tx_signing_session: self.interactive_tx_signing_session,
9077+
}
90769078
}
90779079
}
90789080

lightning/src/ln/channelmanager.rs

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8350,7 +8350,7 @@ where
83508350
peer_state.pending_msg_events.push(msg_send_event);
83518351
};
83528352
if let Some(mut signing_session) = signing_session_opt {
8353-
let (commitment_signed, funding_ready_for_sig_event_opt) = match chan_phase_entry.get_mut() {
8353+
let (commitment_signed, funding_ready_for_sig_event_opt) = match channel_phase {
83548354
ChannelPhase::UnfundedOutboundV2(chan) => {
83558355
chan.funding_tx_constructed(&mut signing_session, &self.logger)
83568356
},
@@ -8361,18 +8361,17 @@ where
83618361
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
83628362
.into())),
83638363
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8364-
let (channel_id, channel_phase) = chan_phase_entry.remove_entry();
8365-
let channel = match channel_phase {
8366-
ChannelPhase::UnfundedOutboundV2(chan) => chan.into_channel(signing_session),
8367-
ChannelPhase::UnfundedInboundV2(chan) => chan.into_channel(signing_session),
8364+
match channel_phase {
8365+
ChannelPhase::UnfundedOutboundV2(chan) => chan.interactive_tx_signing_session = Some(signing_session),
8366+
ChannelPhase::UnfundedInboundV2(chan) => chan.interactive_tx_signing_session = Some(signing_session),
83688367
_ => {
83698368
debug_assert!(false); // It cannot be another variant as we are in the `Ok` branch of the above match.
8370-
Err(ChannelError::Warn(
8369+
let err = ChannelError::Warn(
83718370
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
8372-
.into()))
8371+
.into());
8372+
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id));
83738373
},
8374-
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8375-
peer_state.channel_by_id.insert(channel_id, ChannelPhase::Funded(channel));
8374+
}
83768375
if let Some(funding_ready_for_sig_event) = funding_ready_for_sig_event_opt {
83778376
let mut pending_events = self.pending_events.lock().unwrap();
83788377
pending_events.push_back((funding_ready_for_sig_event, None));
@@ -8892,46 +8891,103 @@ where
88928891
})?;
88938892
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
88948893
let peer_state = &mut *peer_state_lock;
8895-
match peer_state.channel_by_id.entry(msg.channel_id) {
8894+
let (channel_id, mut chan) = match peer_state.channel_by_id.entry(msg.channel_id) {
88968895
hash_map::Entry::Occupied(mut chan_phase_entry) => {
8897-
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
8898-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8899-
let funding_txo = chan.context.get_funding_txo();
8900-
8901-
if chan.interactive_tx_signing_session.is_some() {
8902-
let monitor = try_chan_phase_entry!(
8903-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8904-
chan_phase_entry);
8905-
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
8906-
if let Ok(persist_state) = monitor_res {
8907-
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
8908-
per_peer_state, chan, INITIAL_MONITOR);
8896+
let channel_phase = chan_phase_entry.get_mut();
8897+
match channel_phase {
8898+
ChannelPhase::UnfundedOutboundV2(chan) => {
8899+
if chan.interactive_tx_signing_session.is_some() {
8900+
let (channel_id, mut channel_phase) = chan_phase_entry.remove_entry();
8901+
match channel_phase {
8902+
ChannelPhase::UnfundedOutboundV2(chan) => {
8903+
(channel_id, chan.into_channel())
8904+
}
8905+
_ => {
8906+
debug_assert!(false, "The channel phase was not UnfundedOutboundV2");
8907+
let err = ChannelError::close(
8908+
"Closing due to unexpected sender error".into());
8909+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut channel_phase,
8910+
&channel_id).1)
8911+
}
8912+
}
89098913
} else {
8910-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8911-
log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
8912-
try_chan_phase_entry!(self, peer_state, Err(ChannelError::Close(
8913-
(
8914-
"Channel funding outpoint was a duplicate".to_owned(),
8915-
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8916-
)
8917-
)), chan_phase_entry)
8914+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8915+
"Got a commitment_signed message for a V2 channel before funding transaction constructed!".into())), chan_phase_entry);
89188916
}
8919-
} else {
8917+
},
8918+
ChannelPhase::UnfundedInboundV2(chan) => {
8919+
// TODO(dual_funding): This should be somewhat DRYable when #3418 is merged.
8920+
if chan.interactive_tx_signing_session.is_some() {
8921+
let (channel_id, mut channel_phase) = chan_phase_entry.remove_entry();
8922+
match channel_phase {
8923+
ChannelPhase::UnfundedInboundV2(chan) => {
8924+
(channel_id, chan.into_channel())
8925+
}
8926+
_ => {
8927+
debug_assert!(false, "The channel phase was not UnfundedInboundV2");
8928+
let err = ChannelError::close(
8929+
"Closing due to unexpected sender error".into());
8930+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut channel_phase,
8931+
&channel_id).1)
8932+
}
8933+
}
8934+
} else {
8935+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8936+
"Got a commitment_signed message for a V2 channel before funding transaction constructed!".into())), chan_phase_entry);
8937+
}
8938+
},
8939+
ChannelPhase::Funded(chan) => {
8940+
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8941+
let funding_txo = chan.context.get_funding_txo();
89208942
let monitor_update_opt = try_chan_phase_entry!(
89218943
self, peer_state, chan.commitment_signed(msg, &&logger), chan_phase_entry);
89228944
if let Some(monitor_update) = monitor_update_opt {
89238945
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
89248946
peer_state, per_peer_state, chan);
89258947
}
8948+
return Ok(())
8949+
},
8950+
_ => {
8951+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8952+
"Got a commitment_signed message for an unfunded channel!".into())), chan_phase_entry);
89268953
}
8927-
Ok(())
8928-
} else {
8929-
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8930-
"Got a commitment_signed message for an unfunded channel!".into())), chan_phase_entry);
89318954
}
89328955
},
8933-
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))
8956+
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(
8957+
format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}",
8958+
counterparty_node_id), msg.channel_id))
8959+
};
8960+
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8961+
let monitor = match chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger) {
8962+
Ok(monitor) => monitor,
8963+
Err(err) => return Err(convert_chan_phase_err!(self, peer_state, err, &mut ChannelPhase::Funded(chan), &channel_id).1),
8964+
};
8965+
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
8966+
if let Ok(persist_state) = monitor_res {
8967+
let mut occupied_entry = peer_state.channel_by_id.entry(channel_id).insert(ChannelPhase::Funded(chan));
8968+
let channel_phase_entry = occupied_entry.get_mut();
8969+
match channel_phase_entry {
8970+
ChannelPhase::Funded(chan) => { handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
8971+
per_peer_state, chan, INITIAL_MONITOR); },
8972+
channel_phase => {
8973+
debug_assert!(false, "Expected a ChannelPhase::Funded");
8974+
let err = ChannelError::close(
8975+
"Closing due to unexpected sender error".into());
8976+
return Err(convert_chan_phase_err!(self, peer_state, err, channel_phase,
8977+
&channel_id).1)
8978+
},
8979+
}
8980+
} else {
8981+
log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
8982+
let err = ChannelError::Close(
8983+
(
8984+
"Channel funding outpoint was a duplicate".to_owned(),
8985+
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8986+
)
8987+
);
8988+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut ChannelPhase::Funded(chan), &channel_id).1);
89348989
}
8990+
Ok(())
89358991
}
89368992

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

0 commit comments

Comments
 (0)