Skip to content

Commit ba29649

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 df21960 commit ba29649

File tree

2 files changed

+85
-63
lines changed

2 files changed

+85
-63
lines changed

lightning/src/ln/channel.rs

+72-44
Original file line numberDiff line numberDiff line change
@@ -1474,32 +1474,56 @@ impl<SP: Deref> Channel<SP> where
14741474
where
14751475
L::Target: Logger
14761476
{
1477-
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1478-
let result = if let ChannelPhase::UnfundedV2(chan) = phase {
1477+
let result = if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
14791478
let logger = WithChannelContext::from(logger, &chan.context, None);
1480-
match chan.funding_tx_constructed(signing_session, &&logger) {
1481-
Ok((chan, commitment_signed, event)) => {
1482-
self.phase = ChannelPhase::Funded(chan);
1483-
Ok((commitment_signed, event))
1484-
},
1485-
Err((chan, e)) => {
1486-
self.phase = ChannelPhase::UnfundedV2(chan);
1487-
Err(e)
1488-
},
1489-
}
1479+
chan.funding_tx_constructed(signing_session, &&logger)
14901480
} else {
1491-
self.phase = phase;
14921481
Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
14931482
};
14941483

1495-
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
14961484
result
14971485
}
14981486

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

15051529
impl<SP: Deref> From<OutboundV1Channel<SP>> for Channel<SP>
@@ -2190,8 +2214,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21902214
}
21912215

21922216
pub fn funding_tx_constructed<L: Deref>(
2193-
mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2194-
) -> Result<(FundedChannel<SP>, msgs::CommitmentSigned, Option<Event>), (PendingV2Channel<SP>, ChannelError)>
2217+
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2218+
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
21952219
where
21962220
L::Target: Logger
21972221
{
@@ -2207,7 +2231,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22072231
(
22082232
"Multiple outputs matched the expected script and value".to_owned(),
22092233
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2210-
))).map_err(|e| (self, e));
2234+
)));
22112235
}
22122236
output_index = Some(idx as u16);
22132237
}
@@ -2219,7 +2243,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22192243
(
22202244
"No output matched the funding script_pubkey".to_owned(),
22212245
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2222-
))).map_err(|e| (self, e));
2246+
)));
22232247
};
22242248
self.context.channel_transaction_parameters.funding_outpoint = Some(outpoint);
22252249
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
@@ -2233,8 +2257,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22332257
},
22342258
Err(err) => {
22352259
self.context.channel_transaction_parameters.funding_outpoint = None;
2236-
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })))
2237-
.map_err(|e| (self, e));
2260+
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
22382261
},
22392262
};
22402263

@@ -2245,10 +2268,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22452268
false,
22462269
"Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
22472270
);
2248-
return Err((self, ChannelError::Close((
2271+
return Err(ChannelError::Close((
22492272
"V2 channel rejected due to sender error".into(),
22502273
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2251-
))));
2274+
)));
22522275
}
22532276
None
22542277
} else {
@@ -2270,37 +2293,19 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22702293
false,
22712294
"We don't support users providing inputs but somehow we had more than zero inputs",
22722295
);
2273-
return Err((self, ChannelError::Close((
2296+
return Err(ChannelError::Close((
22742297
"V2 channel rejected due to sender error".into(),
22752298
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2276-
))));
2299+
)));
22772300
};
22782301

22792302
self.context.channel_state = ChannelState::FundingNegotiated;
22802303

22812304
// Clear the interactive transaction constructor
22822305
self.interactive_tx_constructor.take();
2306+
self.interactive_tx_signing_session = Some(signing_session);
22832307

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

@@ -9527,6 +9532,8 @@ pub(super) struct PendingV2Channel<SP: Deref> where SP::Target: SignerProvider {
95279532
pub dual_funding_context: DualFundingChannelContext,
95289533
/// The current interactive transaction construction session under negotiation.
95299534
pub interactive_tx_constructor: Option<InteractiveTxConstructor>,
9535+
/// The signing session created after `tx_complete` handling
9536+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
95309537
}
95319538

95329539
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
@@ -9592,6 +9599,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
95929599
our_funding_inputs: funding_inputs,
95939600
},
95949601
interactive_tx_constructor: None,
9602+
interactive_tx_signing_session: None,
95959603
};
95969604
Ok(chan)
95979605
}
@@ -9763,6 +9771,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
97639771
context,
97649772
dual_funding_context,
97659773
interactive_tx_constructor,
9774+
interactive_tx_signing_session: None,
97669775
unfunded_context,
97679776
})
97689777
}
@@ -9840,6 +9849,25 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
98409849
pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
98419850
self.generate_accept_channel_v2_message()
98429851
}
9852+
9853+
pub fn into_funded_channel(self) -> Result<FundedChannel<SP>, (PendingV2Channel<SP>, ChannelError)> {
9854+
let holder_commitment_point = match self.unfunded_context.holder_commitment_point {
9855+
Some(point) => point,
9856+
None => {
9857+
let channel_id = self.context.channel_id();
9858+
return Err((self, ChannelError::close(
9859+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9860+
channel_id))));
9861+
}
9862+
};
9863+
Ok(FundedChannel {
9864+
funding: self.funding,
9865+
context: self.context,
9866+
interactive_tx_signing_session: self.interactive_tx_signing_session,
9867+
holder_commitment_point,
9868+
is_v2_established: true,
9869+
})
9870+
}
98439871
}
98449872

98459873
// Unfunded channel utilities

lightning/src/ln/channelmanager.rs

+13-19
Original file line numberDiff line numberDiff line change
@@ -8947,14 +8947,15 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
89478947
let peer_state = &mut *peer_state_lock;
89488948
match peer_state.channel_by_id.entry(msg.channel_id) {
89498949
hash_map::Entry::Occupied(mut chan_entry) => {
8950-
if let Some(chan) = chan_entry.get_mut().as_funded_mut() {
8951-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8952-
let funding_txo = chan.context.get_funding_txo();
8953-
8954-
if chan.interactive_tx_signing_session.is_some() {
8955-
let monitor = try_channel_entry!(
8956-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8957-
chan_entry);
8950+
let chan = chan_entry.get_mut();
8951+
let logger = WithChannelContext::from(&self.logger, &chan.context(), None);
8952+
let funding_txo = chan.context().get_funding_txo();
8953+
let (monitor_opt, monitor_update_opt) = try_channel_entry!(
8954+
self, peer_state, chan.commitment_signed(msg, best_block, &self.signer_provider, &&logger),
8955+
chan_entry);
8956+
8957+
if let Some(chan) = chan.as_funded_mut() {
8958+
if let Some(monitor) = monitor_opt {
89588959
let monitor_res = self.chain_monitor.watch_channel(monitor.channel_id(), monitor);
89598960
if let Ok(persist_state) = monitor_res {
89608961
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
@@ -8969,19 +8970,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
89698970
)
89708971
)), chan_entry)
89718972
}
8972-
} else {
8973-
let monitor_update_opt = try_channel_entry!(
8974-
self, peer_state, chan.commitment_signed(msg, &&logger), chan_entry);
8975-
if let Some(monitor_update) = monitor_update_opt {
8976-
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8977-
peer_state, per_peer_state, chan);
8978-
}
8973+
} else if let Some(monitor_update) = monitor_update_opt {
8974+
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8975+
peer_state, per_peer_state, chan);
89798976
}
8980-
Ok(())
8981-
} else {
8982-
return try_channel_entry!(self, peer_state, Err(ChannelError::close(
8983-
"Got a commitment_signed message for an unfunded channel!".into())), chan_entry);
89848977
}
8978+
Ok(())
89858979
},
89868980
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))
89878981
}

0 commit comments

Comments
 (0)