Skip to content

Commit 937f31c

Browse files
committed
Add InboundV2Channel struct
1 parent 85dceee commit 937f31c

File tree

2 files changed

+185
-8
lines changed

2 files changed

+185
-8
lines changed

lightning/src/ln/channel.rs

Lines changed: 184 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,6 +3191,19 @@ pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channe
31913191
cmp::min(channel_value_satoshis, cmp::max(q, 1000))
31923192
}
31933193

3194+
/// Returns a minimum channel reserve value each party needs to maintain, fixed in the spec to a
3195+
/// default of 1% of the total channel value.
3196+
///
3197+
/// Guaranteed to return a value no larger than channel_value_satoshis
3198+
///
3199+
/// This is used both for outbound and inbound channels and has lower bound
3200+
/// of `dust_limit_satoshis`.
3201+
fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satoshis: u64) -> u64 {
3202+
// Fixed at 1% of channel value by spec.
3203+
let (q, _) = channel_value_satoshis.overflowing_div(100);
3204+
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
3205+
}
3206+
31943207
// Get the fee cost in SATS of a commitment tx with a given number of HTLC outputs.
31953208
// Note that num_htlcs should not include dust HTLCs.
31963209
#[inline]
@@ -3224,6 +3237,8 @@ pub(super) struct DualFundingChannelContext {
32243237
// Counterparty designates channel data owned by the another channel participant entity.
32253238
pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
32263239
pub context: ChannelContext<SP>,
3240+
#[cfg(dual_funding)]
3241+
pub dual_funding_channel_context: Option<DualFundingChannelContext>,
32273242
}
32283243

32293244
#[cfg(any(test, fuzzing))]
@@ -7554,7 +7569,11 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
75547569

75557570
log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id());
75567571

7557-
let mut channel = Channel { context: self.context };
7572+
let mut channel = Channel {
7573+
context: self.context,
7574+
#[cfg(dual_funding)]
7575+
dual_funding_channel_context: None,
7576+
};
75587577

75597578
let need_channel_ready = channel.check_get_channel_ready(0).is_some();
75607579
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -7579,12 +7598,12 @@ pub(super) struct InboundV1Channel<SP: Deref> where SP::Target: SignerProvider {
75797598
}
75807599

75817600
/// Fetches the [`ChannelTypeFeatures`] that will be used for a channel built from a given
7582-
/// [`msgs::OpenChannel`].
7601+
/// [`msgs::CommonOpenChannelFields`].
75837602
pub(super) fn channel_type_from_open_channel(
7584-
msg: &msgs::OpenChannel, their_features: &InitFeatures,
7603+
common_fields: &msgs::CommonOpenChannelFields, their_features: &InitFeatures,
75857604
our_supported_features: &ChannelTypeFeatures
75867605
) -> Result<ChannelTypeFeatures, ChannelError> {
7587-
if let Some(channel_type) = &msg.common_fields.channel_type {
7606+
if let Some(channel_type) = &common_fields.channel_type {
75887607
if channel_type.supports_any_optional_bits() {
75897608
return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
75907609
}
@@ -7599,7 +7618,7 @@ pub(super) fn channel_type_from_open_channel(
75997618
if !channel_type.is_subset(our_supported_features) {
76007619
return Err(ChannelError::Close("Channel Type contains unsupported features".to_owned()));
76017620
}
7602-
let announced_channel = if (msg.common_fields.channel_flags & 1) == 1 { true } else { false };
7621+
let announced_channel = if (common_fields.channel_flags & 1) == 1 { true } else { false };
76037622
if channel_type.requires_scid_privacy() && announced_channel {
76047623
return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
76057624
}
@@ -7630,7 +7649,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
76307649

76317650
// First check the channel type is known, failing before we do anything else if we don't
76327651
// support this channel type.
7633-
let channel_type = channel_type_from_open_channel(msg, their_features, our_supported_features)?;
7652+
let channel_type = channel_type_from_open_channel(&msg.common_fields, their_features, our_supported_features)?;
76347653

76357654
let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.common_fields.funding_satoshis, config);
76367655
let counterparty_pubkeys = ChannelPublicKeys {
@@ -7842,6 +7861,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
78427861
// `ChannelMonitor`.
78437862
let mut channel = Channel {
78447863
context: self.context,
7864+
#[cfg(dual_funding)]
7865+
dual_funding_channel_context: None,
78457866
};
78467867
let need_channel_ready = channel.check_get_channel_ready(0).is_some();
78477868
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -7850,6 +7871,160 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
78507871
}
78517872
}
78527873

7874+
// A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
7875+
#[cfg(dual_funding)]
7876+
pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
7877+
pub context: ChannelContext<SP>,
7878+
pub unfunded_context: UnfundedChannelContext,
7879+
pub dual_funding_context: DualFundingChannelContext,
7880+
}
7881+
7882+
#[cfg(dual_funding)]
7883+
impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
7884+
/// Creates a new dual-funded channel from a remote side's request for one.
7885+
/// Assumes chain_hash has already been checked and corresponds with what we expect!
7886+
pub fn new<ES: Deref, F: Deref, L: Deref>(
7887+
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
7888+
counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
7889+
their_features: &InitFeatures, msg: &msgs::OpenChannelV2, funding_satoshis: u64, user_id: u128,
7890+
config: &UserConfig, current_chain_height: u32, logger: &L,
7891+
) -> Result<InboundV2Channel<SP>, ChannelError>
7892+
where ES::Target: EntropySource,
7893+
F::Target: FeeEstimator,
7894+
L::Target: Logger,
7895+
{
7896+
let channel_value_satoshis = funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
7897+
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7898+
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
7899+
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7900+
channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
7901+
7902+
// First check the channel type is known, failing before we do anything else if we don't
7903+
// support this channel type.
7904+
if msg.common_fields.channel_type.is_none() {
7905+
return Err(ChannelError::Close(format!("Rejecting V2 channel {} missing channel_type",
7906+
msg.common_fields.temporary_channel_id)))
7907+
}
7908+
let channel_type = channel_type_from_open_channel(&msg.common_fields, their_features, our_supported_features)?;
7909+
7910+
let counterparty_pubkeys = ChannelPublicKeys {
7911+
funding_pubkey: msg.common_fields.funding_pubkey,
7912+
revocation_basepoint: RevocationBasepoint(msg.common_fields.revocation_basepoint),
7913+
payment_point: msg.common_fields.payment_basepoint,
7914+
delayed_payment_basepoint: DelayedPaymentBasepoint(msg.common_fields.delayed_payment_basepoint),
7915+
htlc_basepoint: HtlcBasepoint(msg.common_fields.htlc_basepoint)
7916+
};
7917+
7918+
let mut context = ChannelContext::new_for_inbound_channel(
7919+
fee_estimator,
7920+
entropy_source,
7921+
signer_provider,
7922+
counterparty_node_id,
7923+
their_features,
7924+
user_id,
7925+
config,
7926+
current_chain_height,
7927+
logger,
7928+
false,
7929+
7930+
funding_satoshis,
7931+
7932+
counterparty_pubkeys,
7933+
channel_type,
7934+
holder_selected_channel_reserve_satoshis,
7935+
counterparty_selected_channel_reserve_satoshis,
7936+
0 /* push_msat not used in dual-funding */,
7937+
msg.common_fields.clone(),
7938+
)?;
7939+
let channel_id = ChannelId::v2_from_revocation_basepoints(
7940+
&context.get_holder_pubkeys().revocation_basepoint,
7941+
&context.get_counterparty_pubkeys().revocation_basepoint);
7942+
context.channel_id = channel_id;
7943+
7944+
let chan = Self {
7945+
context,
7946+
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
7947+
dual_funding_context: DualFundingChannelContext {
7948+
our_funding_satoshis: funding_satoshis,
7949+
their_funding_satoshis: msg.common_fields.funding_satoshis,
7950+
funding_tx_locktime: msg.locktime,
7951+
funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
7952+
}
7953+
};
7954+
7955+
Ok(chan)
7956+
}
7957+
7958+
/// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannelV2`] message which
7959+
/// should be sent back to the counterparty node.
7960+
///
7961+
/// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7962+
pub fn accept_inbound_dual_funded_channel(&mut self) -> msgs::AcceptChannelV2 {
7963+
if self.context.is_outbound() {
7964+
debug_assert!(false, "Tried to send accept_channel for an outbound channel?");
7965+
}
7966+
if !matches!(
7967+
self.context.channel_state, ChannelState::NegotiatingFunding(flags)
7968+
if flags == (NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT)
7969+
) {
7970+
debug_assert!(false, "Tried to send accept_channel2 after channel had moved forward");
7971+
}
7972+
if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
7973+
debug_assert!(false, "Tried to send an accept_channel2 for a channel that has already advanced");
7974+
}
7975+
7976+
self.generate_accept_channel_v2_message()
7977+
}
7978+
7979+
/// This function is used to explicitly generate a [`msgs::AcceptChannel`] message for an
7980+
/// inbound channel. If the intention is to accept an inbound channel, use
7981+
/// [`InboundV1Channel::accept_inbound_channel`] instead.
7982+
///
7983+
/// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7984+
fn generate_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
7985+
let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
7986+
self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
7987+
let second_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
7988+
self.context.cur_holder_commitment_transaction_number - 1, &self.context.secp_ctx);
7989+
let keys = self.context.get_holder_pubkeys();
7990+
7991+
msgs::AcceptChannelV2 {
7992+
common_fields: msgs::CommonAcceptChannelFields {
7993+
temporary_channel_id: self.context.temporary_channel_id.unwrap(),
7994+
dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
7995+
max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
7996+
htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
7997+
minimum_depth: self.context.minimum_depth.unwrap(),
7998+
to_self_delay: self.context.get_holder_selected_contest_delay(),
7999+
max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
8000+
funding_pubkey: keys.funding_pubkey,
8001+
revocation_basepoint: keys.revocation_basepoint.to_public_key(),
8002+
payment_basepoint: keys.payment_point,
8003+
delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
8004+
htlc_basepoint: keys.htlc_basepoint.to_public_key(),
8005+
first_per_commitment_point,
8006+
shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
8007+
Some(script) => script.clone().into_inner(),
8008+
None => Builder::new().into_script(),
8009+
}),
8010+
channel_type: Some(self.context.channel_type.clone()),
8011+
},
8012+
funding_satoshis: self.dual_funding_context.our_funding_satoshis,
8013+
second_per_commitment_point,
8014+
require_confirmed_inputs: None,
8015+
}
8016+
}
8017+
8018+
/// Enables the possibility for tests to extract a [`msgs::AcceptChannelV2`] message for an
8019+
/// inbound channel without accepting it.
8020+
///
8021+
/// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
8022+
#[cfg(test)]
8023+
pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
8024+
self.generate_accept_channel_v2_message()
8025+
}
8026+
}
8027+
78538028
const SERIALIZATION_VERSION: u8 = 3;
78548029
const MIN_SERIALIZATION_VERSION: u8 = 3;
78558030

@@ -8793,7 +8968,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
87938968
local_initiated_shutdown,
87948969

87958970
blocked_monitor_updates: blocked_monitor_updates.unwrap(),
8796-
}
8971+
},
8972+
#[cfg(dual_funding)]
8973+
dual_funding_channel_context: None,
87978974
})
87988975
}
87998976
}

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6251,7 +6251,7 @@ where
62516251
// If we're doing manual acceptance checks on the channel, then defer creation until we're sure we want to accept.
62526252
if self.default_configuration.manually_accept_inbound_channels {
62536253
let channel_type = channel::channel_type_from_open_channel(
6254-
&msg, &peer_state.latest_features, &self.channel_type_features()
6254+
&msg.common_fields, &peer_state.latest_features, &self.channel_type_features()
62556255
).map_err(|e|
62566256
MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id)
62576257
)?;

0 commit comments

Comments
 (0)