Skip to content

Commit 437fbbf

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 db6b380 commit 437fbbf

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>
@@ -2101,8 +2125,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21012125
}
21022126

21032127
pub fn funding_tx_constructed<L: Deref>(
2104-
mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2105-
) -> Result<(FundedChannel<SP>, msgs::CommitmentSigned, Option<Event>), (PendingV2Channel<SP>, ChannelError)>
2128+
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2129+
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
21062130
where
21072131
L::Target: Logger
21082132
{
@@ -2118,7 +2142,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21182142
(
21192143
"Multiple outputs matched the expected script and value".to_owned(),
21202144
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2121-
))).map_err(|e| (self, e));
2145+
)));
21222146
}
21232147
output_index = Some(idx as u16);
21242148
}
@@ -2130,7 +2154,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21302154
(
21312155
"No output matched the funding script_pubkey".to_owned(),
21322156
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2133-
))).map_err(|e| (self, e));
2157+
)));
21342158
};
21352159
self.context.channel_transaction_parameters.funding_outpoint = Some(outpoint);
21362160
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
@@ -2144,8 +2168,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21442168
},
21452169
Err(err) => {
21462170
self.context.channel_transaction_parameters.funding_outpoint = None;
2147-
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })))
2148-
.map_err(|e| (self, e));
2171+
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
21492172
},
21502173
};
21512174

@@ -2156,10 +2179,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21562179
false,
21572180
"Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
21582181
);
2159-
return Err((self, ChannelError::Close((
2182+
return Err(ChannelError::Close((
21602183
"V2 channel rejected due to sender error".into(),
21612184
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2162-
))));
2185+
)));
21632186
}
21642187
None
21652188
} else {
@@ -2181,36 +2204,19 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21812204
false,
21822205
"We don't support users providing inputs but somehow we had more than zero inputs",
21832206
);
2184-
return Err((self, ChannelError::Close((
2207+
return Err(ChannelError::Close((
21852208
"V2 channel rejected due to sender error".into(),
21862209
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
2187-
))));
2210+
)));
21882211
};
21892212

21902213
self.context.channel_state = ChannelState::FundingNegotiated;
21912214

21922215
// Clear the interactive transaction constructor
21932216
self.interactive_tx_constructor.take();
2217+
self.interactive_tx_signing_session = Some(signing_session);
21942218

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

@@ -9133,6 +9139,8 @@ pub(super) struct PendingV2Channel<SP: Deref> where SP::Target: SignerProvider {
91339139
pub dual_funding_context: DualFundingChannelContext,
91349140
/// The current interactive transaction construction session under negotiation.
91359141
pub interactive_tx_constructor: Option<InteractiveTxConstructor>,
9142+
/// The signing session created after `tx_complete` handling
9143+
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
91369144
}
91379145

91389146
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
@@ -9197,6 +9205,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
91979205
our_funding_inputs: funding_inputs,
91989206
},
91999207
interactive_tx_constructor: None,
9208+
interactive_tx_signing_session: None,
92009209
};
92019210
Ok(chan)
92029211
}
@@ -9373,6 +9382,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
93739382
context,
93749383
dual_funding_context,
93759384
interactive_tx_constructor,
9385+
interactive_tx_signing_session: None,
93769386
unfunded_context,
93779387
})
93789388
}
@@ -9450,6 +9460,24 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
94509460
pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
94519461
self.generate_accept_channel_v2_message()
94529462
}
9463+
9464+
pub fn into_funded_channel(self) -> Result<FundedChannel<SP>, (PendingV2Channel<SP>, ChannelError)> {
9465+
let holder_commitment_point = match self.unfunded_context.holder_commitment_point {
9466+
Some(point) => point,
9467+
None => {
9468+
let channel_id = self.context.channel_id();
9469+
return Err((self, ChannelError::close(
9470+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9471+
channel_id))));
9472+
}
9473+
};
9474+
Ok(FundedChannel {
9475+
context: self.context,
9476+
interactive_tx_signing_session: self.interactive_tx_signing_session,
9477+
holder_commitment_point,
9478+
is_v2_established: true,
9479+
})
9480+
}
94539481
}
94549482

94559483
// Unfunded channel utilities

lightning/src/ln/channelmanager.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8789,14 +8789,15 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
87898789
let peer_state = &mut *peer_state_lock;
87908790
match peer_state.channel_by_id.entry(msg.channel_id) {
87918791
hash_map::Entry::Occupied(mut chan_entry) => {
8792-
if let Some(chan) = chan_entry.get_mut().as_funded_mut() {
8793-
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8794-
let funding_txo = chan.context.get_funding_txo();
8795-
8796-
if chan.interactive_tx_signing_session.is_some() {
8797-
let monitor = try_channel_entry!(
8798-
self, peer_state, chan.commitment_signed_initial_v2(msg, best_block, &self.signer_provider, &&logger),
8799-
chan_entry);
8792+
let chan = chan_entry.get_mut();
8793+
let logger = WithChannelContext::from(&self.logger, &chan.context(), None);
8794+
let funding_txo = chan.context().get_funding_txo();
8795+
let (monitor_opt, monitor_update_opt) = try_channel_entry!(
8796+
self, peer_state, chan.commitment_signed(msg, best_block, &self.signer_provider, &&logger),
8797+
chan_entry);
8798+
8799+
if let Some(chan) = chan.as_funded_mut() {
8800+
if let Some(monitor) = monitor_opt {
88008801
let monitor_res = self.chain_monitor.watch_channel(monitor.channel_id(), monitor);
88018802
if let Ok(persist_state) = monitor_res {
88028803
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
@@ -8811,19 +8812,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
88118812
)
88128813
)), chan_entry)
88138814
}
8814-
} else {
8815-
let monitor_update_opt = try_channel_entry!(
8816-
self, peer_state, chan.commitment_signed(msg, &&logger), chan_entry);
8817-
if let Some(monitor_update) = monitor_update_opt {
8818-
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8819-
peer_state, per_peer_state, chan);
8820-
}
8815+
} else if let Some(monitor_update) = monitor_update_opt {
8816+
handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock,
8817+
peer_state, per_peer_state, chan);
88218818
}
8822-
Ok(())
8823-
} else {
8824-
return try_channel_entry!(self, peer_state, Err(ChannelError::close(
8825-
"Got a commitment_signed message for an unfunded channel!".into())), chan_entry);
88268819
}
8820+
Ok(())
88278821
},
88288822
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))
88298823
}

0 commit comments

Comments
 (0)