Skip to content

Commit 9f9a7a9

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 d71c31d commit 9f9a7a9

File tree

2 files changed

+80
-66
lines changed

2 files changed

+80
-66
lines changed

lightning/src/ln/channel.rs

+67-47
Original file line numberDiff line numberDiff line change
@@ -1478,32 +1478,67 @@ 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+
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()))
1497-
};
1498-
1499-
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1500-
result
1486+
}
15011487
}
15021488

15031489
pub fn force_shutdown(&mut self, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult {
15041490
let (funding, context) = self.funding_and_context_mut();
15051491
context.force_shutdown(funding, should_broadcast, closure_reason)
15061492
}
1493+
1494+
pub fn commitment_signed<L: Deref>(
1495+
&mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
1496+
) -> Result<(Option<ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>>, Option<ChannelMonitorUpdate>), ChannelError>
1497+
where
1498+
L::Target: Logger
1499+
{
1500+
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1501+
match phase {
1502+
ChannelPhase::UnfundedV2(chan) => {
1503+
let holder_commitment_point = match chan.unfunded_context.holder_commitment_point {
1504+
Some(point) => point,
1505+
None => {
1506+
let channel_id = chan.context.channel_id();
1507+
// TODO(dual_funding): Add async signing support.
1508+
return Err( ChannelError::close(
1509+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
1510+
channel_id)));
1511+
}
1512+
};
1513+
let mut funded_channel = FundedChannel {
1514+
funding: chan.funding,
1515+
context: chan.context,
1516+
interactive_tx_signing_session: chan.interactive_tx_signing_session,
1517+
holder_commitment_point,
1518+
is_v2_established: true,
1519+
};
1520+
let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
1521+
.map(|monitor| (Some(monitor), None))
1522+
// TODO: Change to `inspect_err` when MSRV is high enough.
1523+
.map_err(|err| {
1524+
// We always expect a `ChannelError` close.
1525+
debug_assert!(matches!(err, ChannelError::Close(_)));
1526+
err
1527+
});
1528+
self.phase = ChannelPhase::Funded(funded_channel);
1529+
res
1530+
},
1531+
ChannelPhase::Funded(mut funded_channel) => {
1532+
let res = funded_channel.commitment_signed(msg, logger).map(|monitor_update_opt| (None, monitor_update_opt));
1533+
self.phase = ChannelPhase::Funded(funded_channel);
1534+
res
1535+
},
1536+
_ => {
1537+
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1538+
Err(ChannelError::close("Got a commitment_signed message for an unfunded V1 channel!".into()))
1539+
}
1540+
}
1541+
}
15071542
}
15081543

15091544
impl<SP: Deref> From<OutboundV1Channel<SP>> for Channel<SP>
@@ -2194,8 +2229,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21942229
}
21952230

21962231
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)>
2232+
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2233+
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
21992234
where
22002235
L::Target: Logger
22012236
{
@@ -2211,7 +2246,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22112246
(
22122247
"Multiple outputs matched the expected script and value".to_owned(),
22132248
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2214-
))).map_err(|e| (self, e));
2249+
)));
22152250
}
22162251
output_index = Some(idx as u16);
22172252
}
@@ -2223,7 +2258,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22232258
(
22242259
"No output matched the funding script_pubkey".to_owned(),
22252260
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2226-
))).map_err(|e| (self, e));
2261+
)));
22272262
};
22282263
self.context.channel_transaction_parameters.funding_outpoint = Some(outpoint);
22292264
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
@@ -2237,8 +2272,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22372272
},
22382273
Err(err) => {
22392274
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));
2275+
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
22422276
},
22432277
};
22442278

@@ -2249,10 +2283,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22492283
false,
22502284
"Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
22512285
);
2252-
return Err((self, ChannelError::Close((
2286+
return Err(ChannelError::Close((
22532287
"V2 channel rejected due to sender error".into(),
22542288
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2255-
))));
2289+
)));
22562290
}
22572291
None
22582292
} else {
@@ -2274,37 +2308,19 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22742308
false,
22752309
"We don't support users providing inputs but somehow we had more than zero inputs",
22762310
);
2277-
return Err((self, ChannelError::Close((
2311+
return Err(ChannelError::Close((
22782312
"V2 channel rejected due to sender error".into(),
22792313
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2280-
))));
2314+
)));
22812315
};
22822316

22832317
self.context.channel_state = ChannelState::FundingNegotiated;
22842318

22852319
// Clear the interactive transaction constructor
22862320
self.interactive_tx_constructor.take();
2321+
self.interactive_tx_signing_session = Some(signing_session);
22872322

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-
}
2323+
Ok((commitment_signed, funding_ready_for_sig_event))
23082324
}
23092325
}
23102326

@@ -9511,6 +9527,8 @@ pub(super) struct PendingV2Channel<SP: Deref> where SP::Target: SignerProvider {
95119527
pub dual_funding_context: DualFundingChannelContext,
95129528
/// The current interactive transaction construction session under negotiation.
95139529
pub interactive_tx_constructor: Option<InteractiveTxConstructor>,
9530+
/// The signing session created after `tx_complete` handling
9531+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
95149532
}
95159533

95169534
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
@@ -9576,6 +9594,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
95769594
our_funding_inputs: funding_inputs,
95779595
},
95789596
interactive_tx_constructor: None,
9597+
interactive_tx_signing_session: None,
95799598
};
95809599
Ok(chan)
95819600
}
@@ -9747,6 +9766,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
97479766
context,
97489767
dual_funding_context,
97499768
interactive_tx_constructor,
9769+
interactive_tx_signing_session: None,
97509770
unfunded_context,
97519771
})
97529772
}

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)