Skip to content

Commit 65c84e4

Browse files
committed
Move funding_signed phase transition to Channel
Now that ChannelPhase is encapsulated in Channel, phase transitions can be moved from ChannelManager to Channel. Update the funding_signed phase transition accordingly. This allows for simpler logic in ChannelManager since the channel does not need to removed and then readded into the channel_by_id map.
1 parent adcaf99 commit 65c84e4

File tree

3 files changed

+83
-51
lines changed

3 files changed

+83
-51
lines changed

lightning/src/ln/channel.rs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,10 +1211,6 @@ impl<SP: Deref> Channel<SP> where
12111211
matches!(self.phase, ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_))
12121212
}
12131213

1214-
pub fn is_unfunded_outbound_v1(&self) -> bool {
1215-
matches!(self.phase, ChannelPhase::UnfundedOutboundV1(_))
1216-
}
1217-
12181214
pub fn into_unfunded_outbound_v1(self) -> Result<OutboundV1Channel<SP>, Self> {
12191215
if let ChannelPhase::UnfundedOutboundV1(channel) = self.phase {
12201216
Ok(channel)
@@ -1378,6 +1374,57 @@ impl<SP: Deref> Channel<SP> where
13781374
},
13791375
}
13801376
}
1377+
1378+
pub fn funding_signed<L: Deref>(
1379+
&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
1380+
) -> Result<(&mut FundedChannel<SP>, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), ChannelError>
1381+
where
1382+
L::Target: Logger
1383+
{
1384+
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1385+
let result = if let ChannelPhase::UnfundedOutboundV1(chan) = phase {
1386+
let logger = WithChannelContext::from(logger, &chan.context, None);
1387+
match chan.funding_signed(msg, best_block, signer_provider, &&logger) {
1388+
Ok((chan, monitor)) => {
1389+
self.phase = ChannelPhase::Funded(chan);
1390+
Ok(monitor)
1391+
},
1392+
Err((chan, e)) => {
1393+
self.phase = ChannelPhase::UnfundedOutboundV1(chan);
1394+
Err(e)
1395+
},
1396+
}
1397+
} else {
1398+
self.phase = phase;
1399+
Err(ChannelError::SendError("Failed to find corresponding UnfundedOutboundV1 channel".to_owned()))
1400+
};
1401+
1402+
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1403+
result.map(|monitor| (self.as_funded_mut().expect("Channel should be funded"), monitor))
1404+
}
1405+
1406+
pub fn unset_funding_info(&mut self) {
1407+
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1408+
if let ChannelPhase::Funded(mut funded_chan) = phase {
1409+
funded_chan.unset_funding_info();
1410+
1411+
let context = funded_chan.context;
1412+
let unfunded_context = UnfundedChannelContext {
1413+
unfunded_channel_age_ticks: 0,
1414+
holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
1415+
};
1416+
let unfunded_chan = OutboundV1Channel {
1417+
context,
1418+
unfunded_context,
1419+
signer_pending_open_channel: false,
1420+
};
1421+
self.phase = ChannelPhase::UnfundedOutboundV1(unfunded_chan);
1422+
} else {
1423+
self.phase = phase;
1424+
};
1425+
1426+
debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1427+
}
13811428
}
13821429

13831430
impl<SP: Deref> From<OutboundV1Channel<SP>> for Channel<SP>
@@ -4952,12 +4999,15 @@ impl<SP: Deref> FundedChannel<SP> where
49524999
///
49535000
/// Further, the channel must be immediately shut down after this with a call to
49545001
/// [`ChannelContext::force_shutdown`].
4955-
pub fn unset_funding_info(&mut self, temporary_channel_id: ChannelId) {
5002+
pub fn unset_funding_info(&mut self) {
49565003
debug_assert!(matches!(
49575004
self.context.channel_state, ChannelState::AwaitingChannelReady(_)
49585005
));
49595006
self.context.channel_transaction_parameters.funding_outpoint = None;
4960-
self.context.channel_id = temporary_channel_id;
5007+
self.context.channel_id = self.context.temporary_channel_id.expect(
5008+
"temporary_channel_id should be set since unset_funding_info is only called on funded \
5009+
channels that were unfunded immediately beforehand"
5010+
);
49615011
}
49625012

49635013
/// Handles a channel_ready message from our peer. If we've already sent our channel_ready

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8096,7 +8096,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
80968096
// `locked_close_channel`), we'll remove the existing channel from `outpoint_to_peer`.
80978097
// Thus, we must first unset the funding outpoint on the channel.
80988098
let err = ChannelError::close($err.to_owned());
8099-
chan.unset_funding_info(msg.temporary_channel_id);
8099+
chan.unset_funding_info();
81008100
return Err(convert_channel_err!(self, peer_state, err, chan.context, &funded_channel_id, UNFUNDED_CHANNEL).1);
81018101
} } }
81028102

@@ -8157,49 +8157,31 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
81578157
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
81588158
let peer_state = &mut *peer_state_lock;
81598159
match peer_state.channel_by_id.entry(msg.channel_id) {
8160-
hash_map::Entry::Occupied(chan_entry) => {
8161-
if chan_entry.get().is_unfunded_outbound_v1() {
8162-
let chan = if let Ok(chan) = chan_entry.remove().into_unfunded_outbound_v1() { chan } else { unreachable!() };
8163-
let logger = WithContext::from(
8164-
&self.logger,
8165-
Some(chan.context.get_counterparty_node_id()),
8166-
Some(chan.context.channel_id()),
8167-
None
8168-
);
8169-
let res =
8170-
chan.funding_signed(&msg, best_block, &self.signer_provider, &&logger);
8171-
match res {
8172-
Ok((mut chan, monitor)) => {
8173-
if let Ok(persist_status) = self.chain_monitor.watch_channel(chan.context.get_funding_txo().unwrap(), monitor) {
8174-
// We really should be able to insert here without doing a second
8175-
// lookup, but sadly rust stdlib doesn't currently allow keeping
8176-
// the original Entry around with the value removed.
8177-
let chan = peer_state.channel_by_id.entry(msg.channel_id).or_insert(Channel::from(chan));
8178-
if let Some(funded_chan) = chan.as_funded_mut() {
8179-
handle_new_monitor_update!(self, persist_status, peer_state_lock, peer_state, per_peer_state, funded_chan, INITIAL_MONITOR);
8180-
} else { unreachable!(); }
8181-
Ok(())
8182-
} else {
8183-
let e = ChannelError::close("Channel funding outpoint was a duplicate".to_owned());
8184-
// We weren't able to watch the channel to begin with, so no
8185-
// updates should be made on it. Previously, full_stack_target
8186-
// found an (unreachable) panic when the monitor update contained
8187-
// within `shutdown_finish` was applied.
8188-
chan.unset_funding_info(msg.channel_id);
8189-
return Err(convert_channel_err!(self, peer_state, e, chan, &msg.channel_id, FUNDED_CHANNEL).1);
8190-
}
8191-
},
8192-
Err((mut chan, e)) => {
8193-
debug_assert!(matches!(e, ChannelError::Close(_)),
8194-
"We don't have a channel anymore, so the error better have expected close");
8195-
// We've already removed this outbound channel from the map in
8196-
// `PeerState` above so at this point we just need to clean up any
8197-
// lingering entries concerning this channel as it is safe to do so.
8198-
return Err(convert_channel_err!(self, peer_state, e, chan.context, &msg.channel_id, UNFUNDED_CHANNEL).1);
8199-
}
8200-
}
8201-
} else {
8202-
return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id));
8160+
hash_map::Entry::Occupied(mut chan_entry) => {
8161+
let chan = chan_entry.get_mut();
8162+
match chan
8163+
.funding_signed(&msg, best_block, &self.signer_provider, &self.logger)
8164+
.and_then(|(funded_chan, monitor)| {
8165+
self.chain_monitor
8166+
.watch_channel(funded_chan.context.get_funding_txo().unwrap(), monitor)
8167+
.map(|persist_status| (funded_chan, persist_status))
8168+
.map_err(|()| {
8169+
ChannelError::close("Channel funding outpoint was a duplicate".to_owned())
8170+
})
8171+
})
8172+
{
8173+
Ok((funded_chan, persist_status)) => {
8174+
handle_new_monitor_update!(self, persist_status, peer_state_lock, peer_state, per_peer_state, funded_chan, INITIAL_MONITOR);
8175+
Ok(())
8176+
},
8177+
Err(e) => {
8178+
// We weren't able to watch the channel to begin with, so no
8179+
// updates should be made on it. Previously, full_stack_target
8180+
// found an (unreachable) panic when the monitor update contained
8181+
// within `shutdown_finish` was applied.
8182+
chan.unset_funding_info();
8183+
try_channel_entry!(self, peer_state, Err(e), chan_entry)
8184+
},
82038185
}
82048186
},
82058187
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9069,7 +9069,7 @@ fn test_duplicate_conflicting_funding_from_second_peer() {
90699069
check_added_monitors!(nodes[0], 1);
90709070
get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id());
90719071
let err_reason = ClosureReason::ProcessingError { err: "Channel funding outpoint was a duplicate".to_owned() };
9072-
check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(funding_signed_msg.channel_id, true, err_reason)]);
9072+
check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(temp_chan_id, true, err_reason)]);
90739073
}
90749074

90759075
#[test]

0 commit comments

Comments
 (0)