Skip to content

Commit 4a1977a

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 0479ada commit 4a1977a

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
@@ -8744,6 +8744,8 @@ pub(super) struct OutboundV2Channel<SP: Deref> where SP::Target: SignerProvider
87448744
pub dual_funding_context: DualFundingChannelContext,
87458745
/// The current interactive transaction construction session under negotiation.
87468746
interactive_tx_constructor: Option<InteractiveTxConstructor>,
8747+
/// The signing session created after `tx_complete` handling
8748+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
87478749
}
87488750

87498751
impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
@@ -8803,6 +8805,7 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
88038805
our_funding_inputs: funding_inputs,
88048806
},
88058807
interactive_tx_constructor: None,
8808+
interactive_tx_signing_session: None,
88068809
};
88078810
Ok(chan)
88088811
}
@@ -8870,13 +8873,11 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
88708873
}
88718874
}
88728875

8873-
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
8874-
let channel = Channel {
8876+
pub fn into_channel(self) -> Channel<SP> {
8877+
Channel {
88758878
context: self.context,
8876-
interactive_tx_signing_session: Some(signing_session),
8877-
};
8878-
8879-
Ok(channel)
8879+
interactive_tx_signing_session: self.interactive_tx_signing_session,
8880+
}
88808881
}
88818882
}
88828883

@@ -8887,6 +8888,8 @@ pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
88878888
pub dual_funding_context: DualFundingChannelContext,
88888889
/// The current interactive transaction construction session under negotiation.
88898890
interactive_tx_constructor: Option<InteractiveTxConstructor>,
8891+
/// The signing session created after `tx_complete` handling
8892+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
88908893
}
88918894

88928895
impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
@@ -8988,6 +8991,7 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
89888991
context,
89898992
dual_funding_context,
89908993
interactive_tx_constructor,
8994+
interactive_tx_signing_session: None,
89918995
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
89928996
})
89938997
}
@@ -9064,13 +9068,11 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
90649068
self.generate_accept_channel_v2_message()
90659069
}
90669070

9067-
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
9068-
let channel = Channel {
9071+
pub fn into_channel(self) -> Channel<SP> {
9072+
Channel {
90699073
context: self.context,
9070-
interactive_tx_signing_session: Some(signing_session),
9071-
};
9072-
9073-
Ok(channel)
9074+
interactive_tx_signing_session: self.interactive_tx_signing_session,
9075+
}
90749076
}
90759077
}
90769078

lightning/src/ln/channelmanager.rs

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8251,7 +8251,7 @@ where
82518251
peer_state.pending_msg_events.push(msg_send_event);
82528252
};
82538253
if let Some(mut signing_session) = signing_session_opt {
8254-
let (commitment_signed, funding_ready_for_sig_event_opt) = match chan_phase_entry.get_mut() {
8254+
let (commitment_signed, funding_ready_for_sig_event_opt) = match channel_phase {
82558255
ChannelPhase::UnfundedOutboundV2(chan) => {
82568256
chan.funding_tx_constructed(&mut signing_session, &self.logger)
82578257
},
@@ -8262,18 +8262,17 @@ where
82628262
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
82638263
.into())),
82648264
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8265-
let (channel_id, channel_phase) = chan_phase_entry.remove_entry();
8266-
let channel = match channel_phase {
8267-
ChannelPhase::UnfundedOutboundV2(chan) => chan.into_channel(signing_session),
8268-
ChannelPhase::UnfundedInboundV2(chan) => chan.into_channel(signing_session),
8265+
match channel_phase {
8266+
ChannelPhase::UnfundedOutboundV2(chan) => chan.interactive_tx_signing_session = Some(signing_session),
8267+
ChannelPhase::UnfundedInboundV2(chan) => chan.interactive_tx_signing_session = Some(signing_session),
82698268
_ => {
82708269
debug_assert!(false); // It cannot be another variant as we are in the `Ok` branch of the above match.
8271-
Err(ChannelError::Warn(
8270+
let err = ChannelError::Warn(
82728271
"Got a tx_complete message with no interactive transaction construction expected or in-progress"
8273-
.into()))
8272+
.into());
8273+
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id));
82748274
},
8275-
}.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
8276-
peer_state.channel_by_id.insert(channel_id, ChannelPhase::Funded(channel));
8275+
}
82778276
if let Some(funding_ready_for_sig_event) = funding_ready_for_sig_event_opt {
82788277
let mut pending_events = self.pending_events.lock().unwrap();
82798278
pending_events.push_back((funding_ready_for_sig_event, None));
@@ -8786,46 +8785,103 @@ where
87868785
})?;
87878786
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
87888787
let peer_state = &mut *peer_state_lock;
8789-
match peer_state.channel_by_id.entry(msg.channel_id) {
8788+
let (channel_id, mut chan) = match peer_state.channel_by_id.entry(msg.channel_id) {
87908789
hash_map::Entry::Occupied(mut chan_phase_entry) => {
8791-
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
8792-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8793-
let funding_txo = chan.context.get_funding_txo();
8794-
8795-
if chan.interactive_tx_signing_session.is_some() {
8796-
let monitor = try_chan_phase_entry!(
8797-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8798-
chan_phase_entry);
8799-
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
8800-
if let Ok(persist_state) = monitor_res {
8801-
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
8802-
per_peer_state, chan, INITIAL_MONITOR);
8790+
let channel_phase = chan_phase_entry.get_mut();
8791+
match channel_phase {
8792+
ChannelPhase::UnfundedOutboundV2(chan) => {
8793+
if chan.interactive_tx_signing_session.is_some() {
8794+
let (channel_id, mut channel_phase) = chan_phase_entry.remove_entry();
8795+
match channel_phase {
8796+
ChannelPhase::UnfundedOutboundV2(chan) => {
8797+
(channel_id, chan.into_channel())
8798+
}
8799+
_ => {
8800+
debug_assert!(false, "The channel phase was not UnfundedOutboundV2");
8801+
let err = ChannelError::close(
8802+
"Closing due to unexpected sender error".into());
8803+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut channel_phase,
8804+
&channel_id).1)
8805+
}
8806+
}
88038807
} else {
8804-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8805-
log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
8806-
try_chan_phase_entry!(self, peer_state, Err(ChannelError::Close(
8807-
(
8808-
"Channel funding outpoint was a duplicate".to_owned(),
8809-
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8810-
)
8811-
)), chan_phase_entry)
8808+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8809+
"Got a commitment_signed message for a V2 channel before funding transaction constructed!".into())), chan_phase_entry);
88128810
}
8813-
} else {
8811+
},
8812+
ChannelPhase::UnfundedInboundV2(chan) => {
8813+
// TODO(dual_funding): This should be somewhat DRYable when #3418 is merged.
8814+
if chan.interactive_tx_signing_session.is_some() {
8815+
let (channel_id, mut channel_phase) = chan_phase_entry.remove_entry();
8816+
match channel_phase {
8817+
ChannelPhase::UnfundedInboundV2(chan) => {
8818+
(channel_id, chan.into_channel())
8819+
}
8820+
_ => {
8821+
debug_assert!(false, "The channel phase was not UnfundedInboundV2");
8822+
let err = ChannelError::close(
8823+
"Closing due to unexpected sender error".into());
8824+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut channel_phase,
8825+
&channel_id).1)
8826+
}
8827+
}
8828+
} else {
8829+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8830+
"Got a commitment_signed message for a V2 channel before funding transaction constructed!".into())), chan_phase_entry);
8831+
}
8832+
},
8833+
ChannelPhase::Funded(chan) => {
8834+
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8835+
let funding_txo = chan.context.get_funding_txo();
88148836
let monitor_update_opt = try_chan_phase_entry!(
88158837
self, peer_state, chan.commitment_signed(msg, &&logger), chan_phase_entry);
88168838
if let Some(monitor_update) = monitor_update_opt {
88178839
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
88188840
peer_state, per_peer_state, chan);
88198841
}
8842+
return Ok(())
8843+
},
8844+
_ => {
8845+
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8846+
"Got a commitment_signed message for an unfunded channel!".into())), chan_phase_entry);
88208847
}
8821-
Ok(())
8822-
} else {
8823-
return try_chan_phase_entry!(self, peer_state, Err(ChannelError::close(
8824-
"Got a commitment_signed message for an unfunded channel!".into())), chan_phase_entry);
88258848
}
88268849
},
8827-
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))
8850+
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(
8851+
format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}",
8852+
counterparty_node_id), msg.channel_id))
8853+
};
8854+
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8855+
let monitor = match chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger) {
8856+
Ok(monitor) => monitor,
8857+
Err(err) => return Err(convert_chan_phase_err!(self, peer_state, err, &mut ChannelPhase::Funded(chan), &channel_id).1),
8858+
};
8859+
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
8860+
if let Ok(persist_state) = monitor_res {
8861+
let mut occupied_entry = peer_state.channel_by_id.entry(channel_id).insert(ChannelPhase::Funded(chan));
8862+
let channel_phase_entry = occupied_entry.get_mut();
8863+
match channel_phase_entry {
8864+
ChannelPhase::Funded(chan) => { handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
8865+
per_peer_state, chan, INITIAL_MONITOR); },
8866+
channel_phase => {
8867+
debug_assert!(false, "Expected a ChannelPhase::Funded");
8868+
let err = ChannelError::close(
8869+
"Closing due to unexpected sender error".into());
8870+
return Err(convert_chan_phase_err!(self, peer_state, err, channel_phase,
8871+
&channel_id).1)
8872+
},
8873+
}
8874+
} else {
8875+
log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
8876+
let err = ChannelError::Close(
8877+
(
8878+
"Channel funding outpoint was a duplicate".to_owned(),
8879+
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8880+
)
8881+
);
8882+
return Err(convert_chan_phase_err!(self, peer_state, err, &mut ChannelPhase::Funded(chan), &channel_id).1);
88288883
}
8884+
Ok(())
88298885
}
88308886

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

0 commit comments

Comments
 (0)