Skip to content

Commit d43ba3c

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 b5ed7f7 commit d43ba3c

File tree

2 files changed

+84
-62
lines changed

2 files changed

+84
-62
lines changed

lightning/src/ln/channel.rs

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,27 +1441,51 @@ impl<SP: Deref> Channel<SP> where
14411441
where
14421442
L::Target: Logger
14431443
{
1444-
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1445-
let result = if let ChannelPhase::UnfundedV2(chan) = phase {
1444+
let result = if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
14461445
let logger = WithChannelContext::from(logger, &chan.context, None);
1447-
match chan.funding_tx_constructed(signing_session, &&logger) {
1448-
Ok((chan, commitment_signed, event)) => {
1449-
self.phase = ChannelPhase::Funded(chan);
1450-
Ok((commitment_signed, event))
1451-
},
1452-
Err((chan, e)) => {
1453-
self.phase = ChannelPhase::UnfundedV2(chan);
1454-
Err(e)
1455-
},
1456-
}
1446+
chan.funding_tx_constructed(signing_session, &&logger)
14571447
} else {
1458-
self.phase = phase;
14591448
Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
14601449
};
14611450

1462-
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
14631451
result
14641452
}
1453+
1454+
pub fn commitment_signed<L: Deref>(
1455+
&mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
1456+
) -> Result<(Option<ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>>, Option<ChannelMonitorUpdate>), ChannelError>
1457+
where
1458+
L::Target: Logger
1459+
{
1460+
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1461+
match phase {
1462+
ChannelPhase::UnfundedV2(chan) => {
1463+
let mut funded_channel = match chan.into_funded_channel() {
1464+
Ok(funded_channel) => funded_channel,
1465+
Err((pending_channel, err)) => {
1466+
self.phase = ChannelPhase::UnfundedV2(pending_channel);
1467+
return Err(err);
1468+
}
1469+
};
1470+
let res = match funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger) {
1471+
Ok(monitor) => {
1472+
Ok((Some(monitor), None))
1473+
},
1474+
Err(err) => {
1475+
Err(err)
1476+
}
1477+
};
1478+
self.phase = ChannelPhase::Funded(funded_channel);
1479+
res
1480+
},
1481+
ChannelPhase::Funded(mut funded_channel) => {
1482+
let res = funded_channel.commitment_signed(msg, logger).map(|monitor_update_opt| (None, monitor_update_opt));
1483+
self.phase = ChannelPhase::Funded(funded_channel);
1484+
res
1485+
},
1486+
_ => Err(ChannelError::close("Got a commitment_signed message for an unfunded V1 channel!".into())),
1487+
}
1488+
}
14651489
}
14661490

14671491
impl<SP: Deref> From<OutboundV1Channel<SP>> for Channel<SP>
@@ -2103,8 +2127,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21032127
}
21042128

21052129
pub fn funding_tx_constructed<L: Deref>(
2106-
mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2107-
) -> Result<(FundedChannel<SP>, msgs::CommitmentSigned, Option<Event>), (PendingV2Channel<SP>, ChannelError)>
2130+
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2131+
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
21082132
where
21092133
L::Target: Logger
21102134
{
@@ -2120,7 +2144,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21202144
(
21212145
"Multiple outputs matched the expected script and value".to_owned(),
21222146
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2123-
))).map_err(|e| (self, e));
2147+
)));
21242148
}
21252149
output_index = Some(idx as u16);
21262150
}
@@ -2132,7 +2156,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21322156
(
21332157
"No output matched the funding script_pubkey".to_owned(),
21342158
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2135-
))).map_err(|e| (self, e));
2159+
)));
21362160
};
21372161
self.context.channel_transaction_parameters.funding_outpoint = Some(outpoint);
21382162
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
@@ -2146,8 +2170,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21462170
},
21472171
Err(err) => {
21482172
self.context.channel_transaction_parameters.funding_outpoint = None;
2149-
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })))
2150-
.map_err(|e| (self, e));
2173+
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
21512174
},
21522175
};
21532176

@@ -2158,10 +2181,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21582181
false,
21592182
"Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
21602183
);
2161-
return Err((self, ChannelError::Close((
2184+
return Err(ChannelError::Close((
21622185
"V2 channel rejected due to sender error".into(),
21632186
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2164-
))));
2187+
)));
21652188
}
21662189
None
21672190
} else {
@@ -2183,36 +2206,19 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21832206
false,
21842207
"We don't support users providing inputs but somehow we had more than zero inputs",
21852208
);
2186-
return Err((self, ChannelError::Close((
2209+
return Err(ChannelError::Close((
21872210
"V2 channel rejected due to sender error".into(),
21882211
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2189-
))));
2212+
)));
21902213
};
21912214

21922215
self.context.channel_state = ChannelState::FundingNegotiated;
21932216

21942217
// Clear the interactive transaction constructor
21952218
self.interactive_tx_constructor.take();
2219+
self.interactive_tx_signing_session = Some(signing_session);
21962220

2197-
match self.unfunded_context.holder_commitment_point {
2198-
Some(holder_commitment_point) => {
2199-
let funded_chan = FundedChannel {
2200-
context: self.context,
2201-
interactive_tx_signing_session: Some(signing_session),
2202-
holder_commitment_point,
2203-
is_v2_established: true,
2204-
};
2205-
Ok((funded_chan, commitment_signed, funding_ready_for_sig_event))
2206-
},
2207-
None => {
2208-
Err(ChannelError::close(
2209-
format!(
2210-
"Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
2211-
self.context.channel_id(),
2212-
)))
2213-
.map_err(|e| (self, e))
2214-
},
2215-
}
2221+
Ok((commitment_signed, funding_ready_for_sig_event))
22162222
}
22172223
}
22182224

@@ -9135,6 +9141,8 @@ pub(super) struct PendingV2Channel<SP: Deref> where SP::Target: SignerProvider {
91359141
pub dual_funding_context: DualFundingChannelContext,
91369142
/// The current interactive transaction construction session under negotiation.
91379143
pub interactive_tx_constructor: Option<InteractiveTxConstructor>,
9144+
/// The signing session created after `tx_complete` handling
9145+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
91389146
}
91399147

91409148
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
@@ -9199,6 +9207,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
91999207
our_funding_inputs: funding_inputs,
92009208
},
92019209
interactive_tx_constructor: None,
9210+
interactive_tx_signing_session: None,
92029211
};
92039212
Ok(chan)
92049213
}
@@ -9375,6 +9384,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
93759384
context,
93769385
dual_funding_context,
93779386
interactive_tx_constructor,
9387+
interactive_tx_signing_session: None,
93789388
unfunded_context,
93799389
})
93809390
}
@@ -9452,6 +9462,24 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
94529462
pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
94539463
self.generate_accept_channel_v2_message()
94549464
}
9465+
9466+
pub fn into_funded_channel(self) -> Result<FundedChannel<SP>, (PendingV2Channel<SP>, ChannelError)> {
9467+
let holder_commitment_point = match self.unfunded_context.holder_commitment_point {
9468+
Some(point) => point,
9469+
None => {
9470+
let channel_id = self.context.channel_id();
9471+
return Err((self, ChannelError::close(
9472+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9473+
channel_id))));
9474+
}
9475+
};
9476+
Ok(FundedChannel {
9477+
context: self.context,
9478+
interactive_tx_signing_session: self.interactive_tx_signing_session,
9479+
holder_commitment_point,
9480+
is_v2_established: true,
9481+
})
9482+
}
94559483
}
94569484

94579485
// Unfunded channel utilities

lightning/src/ln/channelmanager.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8841,14 +8841,15 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
88418841
let peer_state = &mut *peer_state_lock;
88428842
match peer_state.channel_by_id.entry(msg.channel_id) {
88438843
hash_map::Entry::Occupied(mut chan_entry) => {
8844-
if let Some(chan) = chan_entry.get_mut().as_funded_mut() {
8845-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8846-
let funding_txo = chan.context.get_funding_txo();
8847-
8848-
if chan.interactive_tx_signing_session.is_some() {
8849-
let monitor = try_channel_entry!(
8850-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8851-
chan_entry);
8844+
let chan = chan_entry.get_mut();
8845+
let logger = WithChannelContext::from(&self.logger, &chan.context(), None);
8846+
let funding_txo = chan.context().get_funding_txo();
8847+
let (monitor_opt, monitor_update_opt) = try_channel_entry!(
8848+
self, peer_state, chan.commitment_signed(msg, best_block, &self.signer_provider, &&logger),
8849+
chan_entry);
8850+
8851+
if let Some(chan) = chan.as_funded_mut() {
8852+
if let Some(monitor) = monitor_opt {
88528853
let monitor_res = self.chain_monitor.watch_channel(monitor.channel_id(), monitor);
88538854
if let Ok(persist_state) = monitor_res {
88548855
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
@@ -8863,19 +8864,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
88638864
)
88648865
)), chan_entry)
88658866
}
8866-
} else {
8867-
let monitor_update_opt = try_channel_entry!(
8868-
self, peer_state, chan.commitment_signed(msg, &&logger), chan_entry);
8869-
if let Some(monitor_update) = monitor_update_opt {
8870-
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8871-
peer_state, per_peer_state, chan);
8872-
}
8867+
} else if let Some(monitor_update) = monitor_update_opt {
8868+
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8869+
peer_state, per_peer_state, chan);
88738870
}
8874-
Ok(())
8875-
} else {
8876-
return try_channel_entry!(self, peer_state, Err(ChannelError::close(
8877-
"Got a commitment_signed message for an unfunded channel!".into())), chan_entry);
88788871
}
8872+
Ok(())
88798873
},
88808874
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))
88818875
}

0 commit comments

Comments
 (0)