@@ -1616,7 +1616,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1616
1616
current_chain_height: u32,
1617
1617
outbound_scid_alias: u64,
1618
1618
temporary_channel_id: ChannelId,
1619
- channel_type: ChannelTypeFeatures,
1619
+ holder_selected_channel_reserve_satoshis: u64,
1620
+ channel_keys_id: [u8; 32],
1621
+ holder_signer: <SP::Target as SignerProvider>::EcdsaSigner,
1622
+ pubkeys: ChannelPublicKeys,
1620
1623
) -> Result<ChannelContext<SP>, APIError>
1621
1624
where
1622
1625
ES::Target: EntropySource,
@@ -1627,9 +1630,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1627
1630
let channel_value_satoshis = funding_satoshis;
1628
1631
1629
1632
let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay;
1630
- let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
1631
- let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
1632
- let pubkeys = holder_signer.pubkeys().clone();
1633
1633
1634
1634
if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO {
1635
1635
return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)});
@@ -1644,13 +1644,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1644
1644
if holder_selected_contest_delay < BREAKDOWN_TIMEOUT {
1645
1645
return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)});
1646
1646
}
1647
- let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config);
1648
- if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
1649
- // Protocol level safety check in place, although it should never happen because
1650
- // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
1651
- return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
1652
- }
1653
1647
1648
+ let channel_type = get_initial_channel_type(&config, their_features);
1654
1649
debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
1655
1650
1656
1651
let (commitment_conf_target, anchor_outputs_value_msat) = if channel_type.supports_anchors_zero_fee_htlc_tx() {
@@ -1706,6 +1701,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1706
1701
channel_state: ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT),
1707
1702
announcement_sigs_state: AnnouncementSigsState::NotSent,
1708
1703
secp_ctx,
1704
+ // We'll add our counterparty's `funding_satoshis` when we receive `accept_channel2`.
1709
1705
channel_value_satoshis,
1710
1706
1711
1707
latest_monitor_update_id: 0,
@@ -1739,6 +1735,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1739
1735
signer_pending_commitment_update: false,
1740
1736
signer_pending_funding: false,
1741
1737
1738
+ // We'll add our counterparty's `funding_satoshis` to these max commitment output assertions
1739
+ // when we receive `accept_channel2`.
1742
1740
#[cfg(debug_assertions)]
1743
1741
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
1744
1742
#[cfg(debug_assertions)]
@@ -1759,6 +1757,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1759
1757
counterparty_dust_limit_satoshis: 0,
1760
1758
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
1761
1759
counterparty_max_htlc_value_in_flight_msat: 0,
1760
+ // We'll adjust this to include our counterparty's `funding_satoshis` when we
1761
+ // receive `accept_channel2`.
1762
1762
holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.channel_handshake_config),
1763
1763
counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel
1764
1764
holder_selected_channel_reserve_satoshis,
@@ -6704,7 +6704,17 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6704
6704
F::Target: FeeEstimator
6705
6705
{
6706
6706
let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
6707
- let channel_type = Self::get_initial_channel_type(&config, their_features);
6707
+
6708
+ let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config);
6709
+ if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
6710
+ // Protocol level safety check in place, although it should never happen because
6711
+ // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
6712
+ return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
6713
+ }
6714
+
6715
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
6716
+ let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
6717
+ let pubkeys = holder_signer.pubkeys().clone();
6708
6718
6709
6719
let chan = Self {
6710
6720
context: ChannelContext::new_for_outbound_channel(
@@ -6720,7 +6730,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6720
6730
current_chain_height,
6721
6731
outbound_scid_alias,
6722
6732
temporary_channel_id,
6723
- channel_type,
6733
+ holder_selected_channel_reserve_satoshis,
6734
+ channel_keys_id,
6735
+ holder_signer,
6736
+ pubkeys,
6724
6737
)?,
6725
6738
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
6726
6739
};
@@ -6813,29 +6826,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6813
6826
Ok(funding_created)
6814
6827
}
6815
6828
6816
- fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
6817
- // The default channel type (ie the first one we try) depends on whether the channel is
6818
- // public - if it is, we just go with `only_static_remotekey` as it's the only option
6819
- // available. If it's private, we first try `scid_privacy` as it provides better privacy
6820
- // with no other changes, and fall back to `only_static_remotekey`.
6821
- let mut ret = ChannelTypeFeatures::only_static_remote_key();
6822
- if !config.channel_handshake_config.announced_channel &&
6823
- config.channel_handshake_config.negotiate_scid_privacy &&
6824
- their_features.supports_scid_privacy() {
6825
- ret.set_scid_privacy_required();
6826
- }
6827
-
6828
- // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
6829
- // set it now. If they don't understand it, we'll fall back to our default of
6830
- // `only_static_remotekey`.
6831
- if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
6832
- their_features.supports_anchors_zero_fee_htlc_tx() {
6833
- ret.set_anchors_zero_fee_htlc_tx_required();
6834
- }
6835
-
6836
- ret
6837
- }
6838
-
6839
6829
/// If we receive an error message, it may only be a rejection of the channel type we tried,
6840
6830
/// not of our ability to open any channel at all. Thus, on error, we should first call this
6841
6831
/// and see if we get a new `OpenChannel` message, otherwise the channel is failed.
@@ -7414,6 +7404,114 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
7414
7404
}
7415
7405
}
7416
7406
7407
+ // A not-yet-funded outbound (from holder) channel using V2 channel establishment.
7408
+ pub(super) struct OutboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
7409
+ pub context: ChannelContext<SP>,
7410
+ pub unfunded_context: UnfundedChannelContext,
7411
+ #[cfg(dual_funding)]
7412
+ pub dual_funding_context: DualFundingChannelContext,
7413
+ }
7414
+
7415
+ #[cfg(dual_funding)]
7416
+ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
7417
+ pub fn new<ES: Deref, F: Deref>(
7418
+ fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
7419
+ counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
7420
+ user_id: u128, config: &UserConfig, current_chain_height: u32, outbound_scid_alias: u64,
7421
+ funding_confirmation_target: ConfirmationTarget,
7422
+ ) -> Result<OutboundV2Channel<SP>, APIError>
7423
+ where ES::Target: EntropySource,
7424
+ F::Target: FeeEstimator,
7425
+ {
7426
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, funding_satoshis, user_id);
7427
+ let holder_signer = signer_provider.derive_channel_signer(funding_satoshis, channel_keys_id);
7428
+ let pubkeys = holder_signer.pubkeys().clone();
7429
+
7430
+ let temporary_channel_id = ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint);
7431
+
7432
+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7433
+ funding_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
7434
+
7435
+ let funding_feerate_sat_per_1000_weight = fee_estimator.bounded_sat_per_1000_weight(funding_confirmation_target);
7436
+ let funding_tx_locktime = current_chain_height;
7437
+
7438
+ let chan = Self {
7439
+ context: ChannelContext::new_for_outbound_channel(
7440
+ fee_estimator,
7441
+ entropy_source,
7442
+ signer_provider,
7443
+ counterparty_node_id,
7444
+ their_features,
7445
+ funding_satoshis,
7446
+ 0,
7447
+ user_id,
7448
+ config,
7449
+ current_chain_height,
7450
+ outbound_scid_alias,
7451
+ temporary_channel_id,
7452
+ holder_selected_channel_reserve_satoshis,
7453
+ channel_keys_id,
7454
+ holder_signer,
7455
+ pubkeys,
7456
+ )?,
7457
+ unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
7458
+ dual_funding_context: DualFundingChannelContext {
7459
+ our_funding_satoshis: funding_satoshis,
7460
+ their_funding_satoshis: 0,
7461
+ funding_tx_locktime,
7462
+ funding_feerate_sat_per_1000_weight,
7463
+ }
7464
+ };
7465
+ Ok(chan)
7466
+ }
7467
+
7468
+ pub fn get_open_channel_v2(&self, chain_hash: ChainHash) -> msgs::OpenChannelV2 {
7469
+ if self.context.channel_state != ChannelState::OurInitSent as u32 {
7470
+ panic!("Cannot generate an open_channel2 after we've moved forward");
7471
+ }
7472
+
7473
+ if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
7474
+ panic!("Tried to send an open_channel2 for a channel that has already advanced");
7475
+ }
7476
+
7477
+ let first_per_commitment_point = self.context.holder_signer.as_ref()
7478
+ .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number,
7479
+ &self.context.secp_ctx);
7480
+ let second_per_commitment_point = self.context.holder_signer.as_ref()
7481
+ .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number - 1,
7482
+ &self.context.secp_ctx);
7483
+ let keys = self.context.get_holder_pubkeys();
7484
+
7485
+ msgs::OpenChannelV2 {
7486
+ chain_hash,
7487
+ temporary_channel_id: self.context.temporary_channel_id.unwrap(),
7488
+ funding_satoshis: self.context.channel_value_satoshis,
7489
+ dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
7490
+ max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
7491
+ htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
7492
+ funding_feerate_sat_per_1000_weight: self.context.feerate_per_kw,
7493
+ commitment_feerate_sat_per_1000_weight: self.context.feerate_per_kw,
7494
+ to_self_delay: self.context.get_holder_selected_contest_delay(),
7495
+ max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
7496
+ funding_pubkey: keys.funding_pubkey,
7497
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
7498
+ payment_basepoint: keys.payment_point,
7499
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
7500
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
7501
+ first_per_commitment_point,
7502
+ second_per_commitment_point,
7503
+ channel_flags: if self.context.config.announced_channel {1} else {0},
7504
+ shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
7505
+ Some(script) => script.clone().into_inner(),
7506
+ None => Builder::new().into_script(),
7507
+ }),
7508
+ channel_type: Some(self.context.channel_type.clone()),
7509
+ locktime: self.dual_funding_context.funding_tx_locktime,
7510
+ require_confirmed_inputs: None,
7511
+ }
7512
+ }
7513
+ }
7514
+
7417
7515
// A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
7418
7516
#[cfg(dual_funding)]
7419
7517
pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
@@ -7567,6 +7665,31 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
7567
7665
}
7568
7666
}
7569
7667
7668
+ // Unfunded channel utilities
7669
+
7670
+ fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
7671
+ // The default channel type (ie the first one we try) depends on whether the channel is
7672
+ // public - if it is, we just go with `only_static_remotekey` as it's the only option
7673
+ // available. If it's private, we first try `scid_privacy` as it provides better privacy
7674
+ // with no other changes, and fall back to `only_static_remotekey`.
7675
+ let mut ret = ChannelTypeFeatures::only_static_remote_key();
7676
+ if !config.channel_handshake_config.announced_channel &&
7677
+ config.channel_handshake_config.negotiate_scid_privacy &&
7678
+ their_features.supports_scid_privacy() {
7679
+ ret.set_scid_privacy_required();
7680
+ }
7681
+
7682
+ // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
7683
+ // set it now. If they don't understand it, we'll fall back to our default of
7684
+ // `only_static_remotekey`.
7685
+ if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
7686
+ their_features.supports_anchors_zero_fee_htlc_tx() {
7687
+ ret.set_anchors_zero_fee_htlc_tx_required();
7688
+ }
7689
+
7690
+ ret
7691
+ }
7692
+
7570
7693
const SERIALIZATION_VERSION: u8 = 3;
7571
7694
const MIN_SERIALIZATION_VERSION: u8 = 3;
7572
7695
0 commit comments