@@ -2849,6 +2849,20 @@ pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channe
2849
2849
cmp::min(channel_value_satoshis, cmp::max(q, 1000))
2850
2850
}
2851
2851
2852
+ /// Returns a minimum channel reserve value each party needs to maintain, fixed in the spec to a
2853
+ /// default of 1% of the total channel value.
2854
+ ///
2855
+ /// Guaranteed to return a value no larger than channel_value_satoshis
2856
+ ///
2857
+ /// This is used both for outbound and inbound channels and has lower bound
2858
+ /// of `dust_limit_satoshis`.
2859
+ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satoshis: u64) -> u64 {
2860
+ let channel_reserve_proportional_millionths = 10_000; // Fixed at 1% in spec.
2861
+ let calculated_reserve =
2862
+ channel_value_satoshis.saturating_mul(channel_reserve_proportional_millionths) / 1_000_000;
2863
+ cmp::min(channel_value_satoshis, cmp::max(calculated_reserve, dust_limit_satoshis))
2864
+ }
2865
+
2852
2866
// Get the fee cost in SATS of a commitment tx with a given number of HTLC outputs.
2853
2867
// Note that num_htlcs should not include dust HTLCs.
2854
2868
#[inline]
@@ -2882,6 +2896,8 @@ pub(super) struct DualFundingChannelContext {
2882
2896
// Counterparty designates channel data owned by the another channel participant entity.
2883
2897
pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
2884
2898
pub context: ChannelContext<SP>,
2899
+ #[cfg(dual_funding)]
2900
+ pub dual_funding_channel_context: Option<DualFundingChannelContext>,
2885
2901
}
2886
2902
2887
2903
#[cfg(any(test, fuzzing))]
@@ -7190,7 +7206,11 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
7190
7206
7191
7207
log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id());
7192
7208
7193
- let mut channel = Channel { context: self.context };
7209
+ let mut channel = Channel {
7210
+ context: self.context,
7211
+ #[cfg(dual_funding)]
7212
+ dual_funding_channel_context: None,
7213
+ };
7194
7214
7195
7215
let need_channel_ready = channel.check_get_channel_ready(0).is_some();
7196
7216
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -7220,7 +7240,23 @@ pub(super) fn channel_type_from_open_channel(
7220
7240
msg: &msgs::OpenChannel, their_features: &InitFeatures,
7221
7241
our_supported_features: &ChannelTypeFeatures
7222
7242
) -> Result<ChannelTypeFeatures, ChannelError> {
7223
- if let Some(channel_type) = &msg.channel_type {
7243
+ channel_type_from_type_and_flags(&msg.channel_type, msg.channel_flags, their_features, our_supported_features)
7244
+ }
7245
+
7246
+ /// Fetches the [`ChannelTypeFeatures`] that will be used for a channel built from a given
7247
+ /// [`msgs::OpenChannelV2`].
7248
+ #[cfg(dual_funding)]
7249
+ pub(super) fn channel_type_from_open_channel_v2(
7250
+ msg: &msgs::OpenChannelV2, their_features: &InitFeatures,
7251
+ our_supported_features: &ChannelTypeFeatures
7252
+ ) -> Result<ChannelTypeFeatures, ChannelError> {
7253
+ channel_type_from_type_and_flags(&msg.channel_type, msg.channel_flags, their_features, our_supported_features)
7254
+ }
7255
+
7256
+ fn channel_type_from_type_and_flags(msg_channel_type: &Option<ChannelTypeFeatures>,
7257
+ msg_channel_flags: u8, their_features: &InitFeatures, our_supported_features: &ChannelTypeFeatures
7258
+ ) -> Result<ChannelTypeFeatures, ChannelError> {
7259
+ if let Some(channel_type) = &msg_channel_type {
7224
7260
if channel_type.supports_any_optional_bits() {
7225
7261
return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned()));
7226
7262
}
@@ -7235,7 +7271,7 @@ pub(super) fn channel_type_from_open_channel(
7235
7271
if !channel_type.is_subset(our_supported_features) {
7236
7272
return Err(ChannelError::Close("Channel Type contains unsupported features".to_owned()));
7237
7273
}
7238
- let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
7274
+ let announced_channel = if (msg_channel_flags & 1) == 1 { true } else { false };
7239
7275
if channel_type.requires_scid_privacy() && announced_channel {
7240
7276
return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned()));
7241
7277
}
@@ -7486,6 +7522,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
7486
7522
// `ChannelMonitor`.
7487
7523
let mut channel = Channel {
7488
7524
context: self.context,
7525
+ #[cfg(dual_funding)]
7526
+ dual_funding_channel_context: None,
7489
7527
};
7490
7528
let need_channel_ready = channel.check_get_channel_ready(0).is_some();
7491
7529
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -7494,6 +7532,165 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
7494
7532
}
7495
7533
}
7496
7534
7535
+ // A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
7536
+ #[cfg(dual_funding)]
7537
+ pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
7538
+ pub context: ChannelContext<SP>,
7539
+ pub unfunded_context: UnfundedChannelContext,
7540
+ pub dual_funding_context: DualFundingChannelContext,
7541
+ }
7542
+
7543
+ #[cfg(dual_funding)]
7544
+ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
7545
+ /// Creates a new dual-funded channel from a remote side's request for one.
7546
+ /// Assumes chain_hash has already been checked and corresponds with what we expect!
7547
+ pub fn new<ES: Deref, F: Deref, L: Deref>(
7548
+ fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
7549
+ counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
7550
+ their_features: &InitFeatures, msg: &msgs::OpenChannelV2, funding_satoshis: u64, user_id: u128,
7551
+ config: &UserConfig, current_chain_height: u32, logger: &L,
7552
+ ) -> Result<InboundV2Channel<SP>, ChannelError>
7553
+ where ES::Target: EntropySource,
7554
+ F::Target: FeeEstimator,
7555
+ L::Target: Logger,
7556
+ {
7557
+ // TODO(dual_funding): Fix this
7558
+ let channel_value_satoshis = funding_satoshis * 1000 + msg.funding_satoshis;
7559
+ let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7560
+ channel_value_satoshis, msg.dust_limit_satoshis);
7561
+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7562
+ channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
7563
+
7564
+ // First check the channel type is known, failing before we do anything else if we don't
7565
+ // support this channel type.
7566
+ let channel_type = channel_type_from_open_channel_v2(msg, their_features, our_supported_features)?;
7567
+
7568
+ let counterparty_pubkeys = ChannelPublicKeys {
7569
+ funding_pubkey: msg.funding_pubkey,
7570
+ revocation_basepoint: RevocationBasepoint(msg.revocation_basepoint),
7571
+ payment_point: msg.payment_basepoint,
7572
+ delayed_payment_basepoint: DelayedPaymentBasepoint(msg.delayed_payment_basepoint),
7573
+ htlc_basepoint: HtlcBasepoint(msg.htlc_basepoint)
7574
+ };
7575
+
7576
+ let mut context = ChannelContext::new_for_inbound_channel(
7577
+ fee_estimator,
7578
+ entropy_source,
7579
+ signer_provider,
7580
+ counterparty_node_id,
7581
+ their_features,
7582
+ user_id,
7583
+ config,
7584
+ current_chain_height,
7585
+ logger,
7586
+ false,
7587
+
7588
+ funding_satoshis,
7589
+
7590
+ counterparty_pubkeys,
7591
+ msg.channel_flags,
7592
+ channel_type,
7593
+ msg.funding_satoshis,
7594
+ msg.to_self_delay,
7595
+ holder_selected_channel_reserve_satoshis,
7596
+ counterparty_selected_channel_reserve_satoshis,
7597
+ 0 /* push_msat not used in dual-funding */,
7598
+ msg.dust_limit_satoshis,
7599
+ msg.htlc_minimum_msat,
7600
+ msg.commitment_feerate_sat_per_1000_weight,
7601
+ msg.max_accepted_htlcs,
7602
+ msg.shutdown_scriptpubkey.clone(),
7603
+ msg.max_htlc_value_in_flight_msat,
7604
+ msg.temporary_channel_id,
7605
+ msg.first_per_commitment_point,
7606
+ )?;
7607
+ let channel_id = ChannelId::v2_from_revocation_basepoints(
7608
+ &context.get_holder_pubkeys().revocation_basepoint,
7609
+ &context.get_counterparty_pubkeys().revocation_basepoint);
7610
+ context.channel_id = channel_id;
7611
+
7612
+ let chan = Self {
7613
+ context,
7614
+ unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
7615
+ dual_funding_context: DualFundingChannelContext {
7616
+ our_funding_satoshis: funding_satoshis,
7617
+ their_funding_satoshis: msg.funding_satoshis,
7618
+ funding_tx_locktime: msg.locktime,
7619
+ funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
7620
+ }
7621
+ };
7622
+
7623
+ Ok(chan)
7624
+ }
7625
+
7626
+ /// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannelV2`] message which
7627
+ /// should be sent back to the counterparty node.
7628
+ ///
7629
+ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7630
+ pub fn accept_inbound_dual_funded_channel(&mut self) -> msgs::AcceptChannelV2 {
7631
+ if self.context.is_outbound() {
7632
+ panic!("Tried to send accept_channel for an outbound channel?");
7633
+ }
7634
+ if !matches!(
7635
+ self.context.channel_state, ChannelState::NegotiatingFunding(flags)
7636
+ if flags == (NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT)
7637
+ ) {
7638
+ panic!("Tried to send accept_channel2 after channel had moved forward");
7639
+ }
7640
+ if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
7641
+ panic!("Tried to send an accept_channel2 for a channel that has already advanced");
7642
+ }
7643
+
7644
+ self.generate_accept_channel_v2_message()
7645
+ }
7646
+
7647
+ /// This function is used to explicitly generate a [`msgs::AcceptChannel`] message for an
7648
+ /// inbound channel. If the intention is to accept an inbound channel, use
7649
+ /// [`InboundV1Channel::accept_inbound_channel`] instead.
7650
+ ///
7651
+ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7652
+ fn generate_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
7653
+ let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
7654
+ self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
7655
+ let second_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
7656
+ self.context.cur_holder_commitment_transaction_number - 1, &self.context.secp_ctx);
7657
+ let keys = self.context.get_holder_pubkeys();
7658
+
7659
+ msgs::AcceptChannelV2 {
7660
+ temporary_channel_id: self.context.temporary_channel_id.unwrap(),
7661
+ funding_satoshis: self.dual_funding_context.our_funding_satoshis,
7662
+ dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
7663
+ max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
7664
+ htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
7665
+ minimum_depth: self.context.minimum_depth.unwrap(),
7666
+ to_self_delay: self.context.get_holder_selected_contest_delay(),
7667
+ max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
7668
+ funding_pubkey: keys.funding_pubkey,
7669
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
7670
+ payment_basepoint: keys.payment_point,
7671
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
7672
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
7673
+ first_per_commitment_point,
7674
+ second_per_commitment_point,
7675
+ shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
7676
+ Some(script) => script.clone().into_inner(),
7677
+ None => Builder::new().into_script(),
7678
+ }),
7679
+ channel_type: Some(self.context.channel_type.clone()),
7680
+ require_confirmed_inputs: None,
7681
+ }
7682
+ }
7683
+
7684
+ /// Enables the possibility for tests to extract a [`msgs::AcceptChannelV2`] message for an
7685
+ /// inbound channel without accepting it.
7686
+ ///
7687
+ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7688
+ #[cfg(test)]
7689
+ pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
7690
+ self.generate_accept_channel_v2_message()
7691
+ }
7692
+ }
7693
+
7497
7694
const SERIALIZATION_VERSION: u8 = 3;
7498
7695
const MIN_SERIALIZATION_VERSION: u8 = 3;
7499
7696
@@ -8429,7 +8626,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
8429
8626
channel_keys_id,
8430
8627
8431
8628
blocked_monitor_updates: blocked_monitor_updates.unwrap(),
8432
- }
8629
+ },
8630
+ #[cfg(dual_funding)]
8631
+ dual_funding_channel_context: None,
8433
8632
})
8434
8633
}
8435
8634
}
@@ -8992,7 +9191,11 @@ mod tests {
8992
9191
let config = UserConfig::default();
8993
9192
let features = channelmanager::provided_init_features(&config);
8994
9193
let outbound_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &features, 10000000, 100000, 42, &config, 0, 42, None).unwrap();
8995
- let mut chan = Channel { context: outbound_chan.context };
9194
+ let mut chan = Channel {
9195
+ context: outbound_chan.context,
9196
+ #[cfg(dual_funding)]
9197
+ dual_funding_channel_context: None,
9198
+ };
8996
9199
8997
9200
let dummy_htlc_source = HTLCSource::OutboundRoute {
8998
9201
path: Path {
0 commit comments