Skip to content

Commit 2630da8

Browse files
committed
Promote V2 channels to FundedChannel on initial commitment_signed receipt
Before this commit, unfunded V2 channels were promoted to `FundedChannel`s in `PendingV2Channel::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 5aca419 commit 2630da8

File tree

2 files changed

+85
-63
lines changed

2 files changed

+85
-63
lines changed

Diff for: lightning/src/ln/channel.rs

+72-44
Original file line numberDiff line numberDiff line change
@@ -1478,32 +1478,56 @@ impl<SP: Deref> Channel<SP> where
14781478
where
14791479
L::Target: Logger
14801480
{
1481-
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1482-
let result = if let ChannelPhase::UnfundedV2(chan) = phase {
1481+
let result = if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
14831482
let logger = WithChannelContext::from(logger, &chan.context, None);
1484-
match chan.funding_tx_constructed(signing_session, &&logger) {
1485-
Ok((chan, commitment_signed, event)) => {
1486-
self.phase = ChannelPhase::Funded(chan);
1487-
Ok((commitment_signed, event))
1488-
},
1489-
Err((chan, e)) => {
1490-
self.phase = ChannelPhase::UnfundedV2(chan);
1491-
Err(e)
1492-
},
1493-
}
1483+
chan.funding_tx_constructed(signing_session, &&logger)
14941484
} else {
1495-
self.phase = phase;
14961485
Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
14971486
};
14981487

1499-
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
15001488
result
15011489
}
15021490

15031491
pub fn force_shutdown(&mut self, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult {
15041492
let (funding, context) = self.funding_and_context_mut();
15051493
context.force_shutdown(funding, should_broadcast, closure_reason)
15061494
}
1495+
1496+
pub fn commitment_signed<L: Deref>(
1497+
&mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
1498+
) -> Result<(Option<ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>>, Option<ChannelMonitorUpdate>), ChannelError>
1499+
where
1500+
L::Target: Logger
1501+
{
1502+
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1503+
match phase {
1504+
ChannelPhase::UnfundedV2(chan) => {
1505+
let mut funded_channel = match chan.into_funded_channel() {
1506+
Ok(funded_channel) => funded_channel,
1507+
Err((pending_channel, err)) => {
1508+
self.phase = ChannelPhase::UnfundedV2(pending_channel);
1509+
return Err(err);
1510+
}
1511+
};
1512+
let res = match funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger) {
1513+
Ok(monitor) => {
1514+
Ok((Some(monitor), None))
1515+
},
1516+
Err(err) => {
1517+
Err(err)
1518+
}
1519+
};
1520+
self.phase = ChannelPhase::Funded(funded_channel);
1521+
res
1522+
},
1523+
ChannelPhase::Funded(mut funded_channel) => {
1524+
let res = funded_channel.commitment_signed(msg, logger).map(|monitor_update_opt| (None, monitor_update_opt));
1525+
self.phase = ChannelPhase::Funded(funded_channel);
1526+
res
1527+
},
1528+
_ => Err(ChannelError::close("Got a commitment_signed message for an unfunded V1 channel!".into())),
1529+
}
1530+
}
15071531
}
15081532

15091533
impl<SP: Deref> From<OutboundV1Channel<SP>> for Channel<SP>
@@ -2194,8 +2218,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21942218
}
21952219

21962220
pub fn funding_tx_constructed<L: Deref>(
2197-
mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2198-
) -> Result<(FundedChannel<SP>, msgs::CommitmentSigned, Option<Event>), (PendingV2Channel<SP>, ChannelError)>
2221+
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2222+
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
21992223
where
22002224
L::Target: Logger
22012225
{
@@ -2211,7 +2235,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22112235
(
22122236
"Multiple outputs matched the expected script and value".to_owned(),
22132237
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2214-
))).map_err(|e| (self, e));
2238+
)));
22152239
}
22162240
output_index = Some(idx as u16);
22172241
}
@@ -2223,7 +2247,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22232247
(
22242248
"No output matched the funding script_pubkey".to_owned(),
22252249
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2226-
))).map_err(|e| (self, e));
2250+
)));
22272251
};
22282252
self.context.channel_transaction_parameters.funding_outpoint = Some(outpoint);
22292253
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
@@ -2237,8 +2261,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22372261
},
22382262
Err(err) => {
22392263
self.context.channel_transaction_parameters.funding_outpoint = None;
2240-
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })))
2241-
.map_err(|e| (self, e));
2264+
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
22422265
},
22432266
};
22442267

@@ -2249,10 +2272,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22492272
false,
22502273
"Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
22512274
);
2252-
return Err((self, ChannelError::Close((
2275+
return Err(ChannelError::Close((
22532276
"V2 channel rejected due to sender error".into(),
22542277
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2255-
))));
2278+
)));
22562279
}
22572280
None
22582281
} else {
@@ -2274,37 +2297,19 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22742297
false,
22752298
"We don't support users providing inputs but somehow we had more than zero inputs",
22762299
);
2277-
return Err((self, ChannelError::Close((
2300+
return Err(ChannelError::Close((
22782301
"V2 channel rejected due to sender error".into(),
22792302
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2280-
))));
2303+
)));
22812304
};
22822305

22832306
self.context.channel_state = ChannelState::FundingNegotiated;
22842307

22852308
// Clear the interactive transaction constructor
22862309
self.interactive_tx_constructor.take();
2310+
self.interactive_tx_signing_session = Some(signing_session);
22872311

2288-
match self.unfunded_context.holder_commitment_point {
2289-
Some(holder_commitment_point) => {
2290-
let funded_chan = FundedChannel {
2291-
funding: self.funding,
2292-
context: self.context,
2293-
interactive_tx_signing_session: Some(signing_session),
2294-
holder_commitment_point,
2295-
is_v2_established: true,
2296-
};
2297-
Ok((funded_chan, commitment_signed, funding_ready_for_sig_event))
2298-
},
2299-
None => {
2300-
Err(ChannelError::close(
2301-
format!(
2302-
"Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
2303-
self.context.channel_id(),
2304-
)))
2305-
.map_err(|e| (self, e))
2306-
},
2307-
}
2312+
Ok((commitment_signed, funding_ready_for_sig_event))
23082313
}
23092314
}
23102315

@@ -9511,6 +9516,8 @@ pub(super) struct PendingV2Channel<SP: Deref> where SP::Target: SignerProvider {
95119516
pub dual_funding_context: DualFundingChannelContext,
95129517
/// The current interactive transaction construction session under negotiation.
95139518
pub interactive_tx_constructor: Option<InteractiveTxConstructor>,
9519+
/// The signing session created after `tx_complete` handling
9520+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
95149521
}
95159522

95169523
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
@@ -9576,6 +9583,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
95769583
our_funding_inputs: funding_inputs,
95779584
},
95789585
interactive_tx_constructor: None,
9586+
interactive_tx_signing_session: None,
95799587
};
95809588
Ok(chan)
95819589
}
@@ -9747,6 +9755,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
97479755
context,
97489756
dual_funding_context,
97499757
interactive_tx_constructor,
9758+
interactive_tx_signing_session: None,
97509759
unfunded_context,
97519760
})
97529761
}
@@ -9824,6 +9833,25 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
98249833
pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
98259834
self.generate_accept_channel_v2_message()
98269835
}
9836+
9837+
pub fn into_funded_channel(self) -> Result<FundedChannel<SP>, (PendingV2Channel<SP>, ChannelError)> {
9838+
let holder_commitment_point = match self.unfunded_context.holder_commitment_point {
9839+
Some(point) => point,
9840+
None => {
9841+
let channel_id = self.context.channel_id();
9842+
return Err((self, ChannelError::close(
9843+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9844+
channel_id))));
9845+
}
9846+
};
9847+
Ok(FundedChannel {
9848+
funding: self.funding,
9849+
context: self.context,
9850+
interactive_tx_signing_session: self.interactive_tx_signing_session,
9851+
holder_commitment_point,
9852+
is_v2_established: true,
9853+
})
9854+
}
98279855
}
98289856

98299857
// Unfunded channel utilities

Diff for: lightning/src/ln/channelmanager.rs

+13-19
Original file line numberDiff line numberDiff line change
@@ -8950,14 +8950,15 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
89508950
let peer_state = &mut *peer_state_lock;
89518951
match peer_state.channel_by_id.entry(msg.channel_id) {
89528952
hash_map::Entry::Occupied(mut chan_entry) => {
8953-
if let Some(chan) = chan_entry.get_mut().as_funded_mut() {
8954-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8955-
let funding_txo = chan.context.get_funding_txo();
8956-
8957-
if chan.interactive_tx_signing_session.is_some() {
8958-
let monitor = try_channel_entry!(
8959-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8960-
chan_entry);
8953+
let chan = chan_entry.get_mut();
8954+
let logger = WithChannelContext::from(&self.logger, &chan.context(), None);
8955+
let funding_txo = chan.context().get_funding_txo();
8956+
let (monitor_opt, monitor_update_opt) = try_channel_entry!(
8957+
self, peer_state, chan.commitment_signed(msg, best_block, &self.signer_provider, &&logger),
8958+
chan_entry);
8959+
8960+
if let Some(chan) = chan.as_funded_mut() {
8961+
if let Some(monitor) = monitor_opt {
89618962
let monitor_res = self.chain_monitor.watch_channel(monitor.channel_id(), monitor);
89628963
if let Ok(persist_state) = monitor_res {
89638964
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
@@ -8972,19 +8973,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
89728973
)
89738974
)), chan_entry)
89748975
}
8975-
} else {
8976-
let monitor_update_opt = try_channel_entry!(
8977-
self, peer_state, chan.commitment_signed(msg, &&logger), chan_entry);
8978-
if let Some(monitor_update) = monitor_update_opt {
8979-
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8980-
peer_state, per_peer_state, chan);
8981-
}
8976+
} else if let Some(monitor_update) = monitor_update_opt {
8977+
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8978+
peer_state, per_peer_state, chan);
89828979
}
8983-
Ok(())
8984-
} else {
8985-
return try_channel_entry!(self, peer_state, Err(ChannelError::close(
8986-
"Got a commitment_signed message for an unfunded channel!".into())), chan_entry);
89878980
}
8981+
Ok(())
89888982
},
89898983
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))
89908984
}

0 commit comments

Comments
 (0)