Skip to content

Commit

Permalink
Add V2 ChannelPhase variants
Browse files Browse the repository at this point in the history
  • Loading branch information
dunxen committed Feb 20, 2024
1 parent e142e4a commit efec33f
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 10 deletions.
12 changes: 12 additions & 0 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,10 @@ impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
pub(super) enum ChannelPhase<SP: Deref> where SP::Target: SignerProvider {
UnfundedOutboundV1(OutboundV1Channel<SP>),
UnfundedInboundV1(InboundV1Channel<SP>),
#[cfg(dual_funding)]
UnfundedOutboundV2(OutboundV2Channel<SP>),
#[cfg(dual_funding)]
UnfundedInboundV2(InboundV2Channel<SP>),
Funded(Channel<SP>),
}

Expand All @@ -1173,6 +1177,10 @@ impl<'a, SP: Deref> ChannelPhase<SP> where
ChannelPhase::Funded(chan) => &chan.context,
ChannelPhase::UnfundedOutboundV1(chan) => &chan.context,
ChannelPhase::UnfundedInboundV1(chan) => &chan.context,
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(chan) => &chan.context,
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(chan) => &chan.context,
}
}

Expand All @@ -1181,6 +1189,10 @@ impl<'a, SP: Deref> ChannelPhase<SP> where
ChannelPhase::Funded(ref mut chan) => &mut chan.context,
ChannelPhase::UnfundedOutboundV1(ref mut chan) => &mut chan.context,
ChannelPhase::UnfundedInboundV1(ref mut chan) => &mut chan.context,
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(ref mut chan) => &mut chan.context,
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(ref mut chan) => &mut chan.context,
}
}
}
Expand Down
118 changes: 109 additions & 9 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,14 @@ impl <SP: Deref> PeerState<SP> where SP::Target: SignerProvider {
return false
}
!self.channel_by_id.iter().any(|(_, phase)|
matches!(phase, ChannelPhase::Funded(_) | ChannelPhase::UnfundedOutboundV1(_))
match phase {
ChannelPhase::Funded(_) | ChannelPhase::UnfundedOutboundV1(_) => true,
ChannelPhase::UnfundedInboundV1(_) => false,
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(_) => true,
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(_) => false,
}
)
&& self.monitor_update_blocked_actions.is_empty()
&& self.in_flight_monitor_updates.is_empty()
Expand Down Expand Up @@ -2092,6 +2099,14 @@ macro_rules! convert_chan_phase_err {
ChannelPhase::UnfundedInboundV1(channel) => {
convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL)
},
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(channel) => {
convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL)
},
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(channel) => {
convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL)
},
}
};
}
Expand Down Expand Up @@ -2958,6 +2973,13 @@ where
// Unfunded channel has no update
(None, chan_phase.context().get_counterparty_node_id())
},
// TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => {
self.finish_close_channel(chan_phase.context_mut().force_shutdown(false, closure_reason));
// Unfunded channel has no update
(None, chan_phase.context().get_counterparty_node_id())
},
}
} else if peer_state.inbound_channel_request_by_id.remove(channel_id).is_some() {
log_error!(logger, "Force-closing channel {}", &channel_id);
Expand Down Expand Up @@ -5031,6 +5053,16 @@ where
process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context,
pending_msg_events, counterparty_node_id)
},
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(chan) => {
process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context,
pending_msg_events, counterparty_node_id)
},
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(chan) => {
process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context,
pending_msg_events, counterparty_node_id)
},
}
});

Expand Down Expand Up @@ -6178,9 +6210,25 @@ where
num_unfunded_channels += 1;
}
},
// TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(chan) => {
// Only inbound V2 channels that are not 0conf and that we do not contribute to will be
// included in the unfunded count.
if chan.context.minimum_depth().unwrap_or(1) != 0 &&
chan.dual_funding_context.our_funding_satoshis == 0 {
num_unfunded_channels += 1;
}
},
ChannelPhase::UnfundedOutboundV1(_) => {
// Outbound channels don't contribute to the unfunded count in the DoS context.
continue;
},
// TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(_) => {
// Outbound channels don't contribute to the unfunded count in the DoS context.
continue;
}
}
}
Expand Down Expand Up @@ -6603,6 +6651,14 @@ where
let mut chan = remove_channel_phase!(self, chan_phase_entry);
finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel));
},
// TODO(dual_funding): Combine this match arm with above.
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(_) | ChannelPhase::UnfundedOutboundV2(_) => {
let context = phase.context_mut();
log_error!(self.logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id);
let mut chan = remove_channel_phase!(self, chan_phase_entry);
finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel));
},
}
} else {
return 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))
Expand Down Expand Up @@ -8470,6 +8526,9 @@ where
match phase {
// Retain unfunded channels.
ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => true,
// TODO(dual_funding): Combine this match arm with above.
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => true,
ChannelPhase::Funded(channel) => {
let res = f(channel);
if let Ok((channel_ready_opt, mut timed_out_pending_htlcs, announcement_sigs)) = res {
Expand Down Expand Up @@ -8939,6 +8998,14 @@ where
ChannelPhase::UnfundedInboundV1(chan) => {
&mut chan.context
},
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(chan) => {
&mut chan.context
},
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(chan) => {
&mut chan.context
},
};
// Clean up for removal.
update_maps_on_chan_removal!(self, &context);
Expand Down Expand Up @@ -9091,12 +9158,30 @@ where
});
}

// TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
#[cfg(dual_funding)]
ChannelPhase::UnfundedOutboundV2(chan) => {
pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 {
node_id: chan.context.get_counterparty_node_id(),
msg: chan.get_open_channel_v2(self.chain_hash),
});
},

ChannelPhase::UnfundedInboundV1(_) => {
// Since unfunded inbound channel maps are cleared upon disconnecting a peer,
// they are not persisted and won't be recovered after a crash.
// Therefore, they shouldn't exist at this point.
debug_assert!(false);
}

// TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
#[cfg(dual_funding)]
ChannelPhase::UnfundedInboundV2(channel) => {
// Since unfunded inbound channel maps are cleared upon disconnecting a peer,
// they are not persisted and won't be recovered after a crash.
// Therefore, they shouldn't exist at this point.
debug_assert!(false);
},
}
}
}
Expand Down Expand Up @@ -9174,14 +9259,29 @@ where
if peer_state_mutex_opt.is_none() { return; }
let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
let peer_state = &mut *peer_state_lock;
if let Some(ChannelPhase::UnfundedOutboundV1(chan)) = peer_state.channel_by_id.get_mut(&msg.channel_id) {
if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) {
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
node_id: *counterparty_node_id,
msg,
});
return;
}
match peer_state.channel_by_id.get_mut(&msg.channel_id) {
Some(ChannelPhase::UnfundedOutboundV1(ref mut chan)) => {
if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) {
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
node_id: *counterparty_node_id,
msg,
});
return;
}
},
#[cfg(dual_funding)]
Some(ChannelPhase::UnfundedOutboundV2(ref mut chan)) => {
if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) {
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 {
node_id: *counterparty_node_id,
msg,
});
return;
}
},
None | Some(ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::Funded(_)) => (),
#[cfg(dual_funding)]
Some(ChannelPhase::UnfundedInboundV2(_)) => (),
}
}

Expand Down
2 changes: 1 addition & 1 deletion lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) {
chan_context.holder_selected_channel_reserve_satoshis = 0;
chan_context.holder_max_htlc_value_in_flight_msat = 100_000_000;
},
ChannelPhase::Funded(_) => assert!(false),
_ => assert!(false),
}
}

Expand Down

0 comments on commit efec33f

Please sign in to comment.