@@ -1596,7 +1596,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1596
1596
current_chain_height: u32,
1597
1597
outbound_scid_alias: u64,
1598
1598
temporary_channel_id: ChannelId,
1599
- channel_type: ChannelTypeFeatures,
1599
+ holder_selected_channel_reserve_satoshis: u64,
1600
+ channel_keys_id: [u8; 32],
1601
+ holder_signer: <SP::Target as SignerProvider>::EcdsaSigner,
1602
+ pubkeys: ChannelPublicKeys,
1600
1603
) -> Result<ChannelContext<SP>, APIError>
1601
1604
where
1602
1605
ES::Target: EntropySource,
@@ -1607,9 +1610,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1607
1610
let channel_value_satoshis = funding_satoshis;
1608
1611
1609
1612
let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay;
1610
- let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
1611
- let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
1612
- let pubkeys = holder_signer.pubkeys().clone();
1613
1613
1614
1614
if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO {
1615
1615
return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)});
@@ -1624,13 +1624,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1624
1624
if holder_selected_contest_delay < BREAKDOWN_TIMEOUT {
1625
1625
return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)});
1626
1626
}
1627
- let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config);
1628
- if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
1629
- // Protocol level safety check in place, although it should never happen because
1630
- // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
1631
- return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
1632
- }
1633
1627
1628
+ let channel_type = get_initial_channel_type(&config, their_features);
1634
1629
debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
1635
1630
1636
1631
let (commitment_conf_target, anchor_outputs_value_msat) = if channel_type.supports_anchors_zero_fee_htlc_tx() {
@@ -1686,6 +1681,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1686
1681
channel_state: ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT),
1687
1682
announcement_sigs_state: AnnouncementSigsState::NotSent,
1688
1683
secp_ctx,
1684
+ // We'll add our counterparty's `funding_satoshis` when we receive `accept_channel2`.
1689
1685
channel_value_satoshis,
1690
1686
1691
1687
latest_monitor_update_id: 0,
@@ -1719,6 +1715,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1719
1715
signer_pending_commitment_update: false,
1720
1716
signer_pending_funding: false,
1721
1717
1718
+ // We'll add our counterparty's `funding_satoshis` to these max commitment output assertions
1719
+ // when we receive `accept_channel2`.
1722
1720
#[cfg(debug_assertions)]
1723
1721
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
1724
1722
#[cfg(debug_assertions)]
@@ -1739,6 +1737,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1739
1737
counterparty_dust_limit_satoshis: 0,
1740
1738
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
1741
1739
counterparty_max_htlc_value_in_flight_msat: 0,
1740
+ // We'll adjust this to include our counterparty's `funding_satoshis` when we
1741
+ // receive `accept_channel2`.
1742
1742
holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.channel_handshake_config),
1743
1743
counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel
1744
1744
holder_selected_channel_reserve_satoshis,
@@ -6804,7 +6804,17 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6804
6804
F::Target: FeeEstimator
6805
6805
{
6806
6806
let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
6807
- let channel_type = Self::get_initial_channel_type(&config, their_features);
6807
+
6808
+ let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config);
6809
+ if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
6810
+ // Protocol level safety check in place, although it should never happen because
6811
+ // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
6812
+ return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
6813
+ }
6814
+
6815
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
6816
+ let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
6817
+ let pubkeys = holder_signer.pubkeys().clone();
6808
6818
6809
6819
let chan = Self {
6810
6820
context: ChannelContext::new_for_outbound_channel(
@@ -6820,7 +6830,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6820
6830
current_chain_height,
6821
6831
outbound_scid_alias,
6822
6832
temporary_channel_id,
6823
- channel_type,
6833
+ holder_selected_channel_reserve_satoshis,
6834
+ channel_keys_id,
6835
+ holder_signer,
6836
+ pubkeys,
6824
6837
)?,
6825
6838
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
6826
6839
};
@@ -6918,29 +6931,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6918
6931
Ok(funding_created)
6919
6932
}
6920
6933
6921
- fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
6922
- // The default channel type (ie the first one we try) depends on whether the channel is
6923
- // public - if it is, we just go with `only_static_remotekey` as it's the only option
6924
- // available. If it's private, we first try `scid_privacy` as it provides better privacy
6925
- // with no other changes, and fall back to `only_static_remotekey`.
6926
- let mut ret = ChannelTypeFeatures::only_static_remote_key();
6927
- if !config.channel_handshake_config.announced_channel &&
6928
- config.channel_handshake_config.negotiate_scid_privacy &&
6929
- their_features.supports_scid_privacy() {
6930
- ret.set_scid_privacy_required();
6931
- }
6932
-
6933
- // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
6934
- // set it now. If they don't understand it, we'll fall back to our default of
6935
- // `only_static_remotekey`.
6936
- if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
6937
- their_features.supports_anchors_zero_fee_htlc_tx() {
6938
- ret.set_anchors_zero_fee_htlc_tx_required();
6939
- }
6940
-
6941
- ret
6942
- }
6943
-
6944
6934
/// If we receive an error message, it may only be a rejection of the channel type we tried,
6945
6935
/// not of our ability to open any channel at all. Thus, on error, we should first call this
6946
6936
/// and see if we get a new `OpenChannel` message, otherwise the channel is failed.
@@ -7574,6 +7564,114 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
7574
7564
}
7575
7565
}
7576
7566
7567
+ // A not-yet-funded outbound (from holder) channel using V2 channel establishment.
7568
+ pub(super) struct OutboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
7569
+ pub context: ChannelContext<SP>,
7570
+ pub unfunded_context: UnfundedChannelContext,
7571
+ #[cfg(dual_funding)]
7572
+ pub dual_funding_context: DualFundingChannelContext,
7573
+ }
7574
+
7575
+ #[cfg(dual_funding)]
7576
+ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
7577
+ pub fn new<ES: Deref, F: Deref>(
7578
+ fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
7579
+ counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
7580
+ user_id: u128, config: &UserConfig, current_chain_height: u32, outbound_scid_alias: u64,
7581
+ funding_confirmation_target: ConfirmationTarget,
7582
+ ) -> Result<OutboundV2Channel<SP>, APIError>
7583
+ where ES::Target: EntropySource,
7584
+ F::Target: FeeEstimator,
7585
+ {
7586
+ let channel_keys_id = signer_provider.generate_channel_keys_id(false, funding_satoshis, user_id);
7587
+ let holder_signer = signer_provider.derive_channel_signer(funding_satoshis, channel_keys_id);
7588
+ let pubkeys = holder_signer.pubkeys().clone();
7589
+
7590
+ let temporary_channel_id = ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint);
7591
+
7592
+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7593
+ funding_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
7594
+
7595
+ let funding_feerate_sat_per_1000_weight = fee_estimator.bounded_sat_per_1000_weight(funding_confirmation_target);
7596
+ let funding_tx_locktime = current_chain_height;
7597
+
7598
+ let chan = Self {
7599
+ context: ChannelContext::new_for_outbound_channel(
7600
+ fee_estimator,
7601
+ entropy_source,
7602
+ signer_provider,
7603
+ counterparty_node_id,
7604
+ their_features,
7605
+ funding_satoshis,
7606
+ 0,
7607
+ user_id,
7608
+ config,
7609
+ current_chain_height,
7610
+ outbound_scid_alias,
7611
+ temporary_channel_id,
7612
+ holder_selected_channel_reserve_satoshis,
7613
+ channel_keys_id,
7614
+ holder_signer,
7615
+ pubkeys,
7616
+ )?,
7617
+ unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
7618
+ dual_funding_context: DualFundingChannelContext {
7619
+ our_funding_satoshis: funding_satoshis,
7620
+ their_funding_satoshis: 0,
7621
+ funding_tx_locktime,
7622
+ funding_feerate_sat_per_1000_weight,
7623
+ }
7624
+ };
7625
+ Ok(chan)
7626
+ }
7627
+
7628
+ pub fn get_open_channel_v2(&self, chain_hash: ChainHash) -> msgs::OpenChannelV2 {
7629
+ if self.context.have_received_message() {
7630
+ panic!("Cannot generate an open_channel2 after we've moved forward");
7631
+ }
7632
+
7633
+ if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
7634
+ panic!("Tried to send an open_channel2 for a channel that has already advanced");
7635
+ }
7636
+
7637
+ let first_per_commitment_point = self.context.holder_signer.as_ref()
7638
+ .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number,
7639
+ &self.context.secp_ctx);
7640
+ let second_per_commitment_point = self.context.holder_signer.as_ref()
7641
+ .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number - 1,
7642
+ &self.context.secp_ctx);
7643
+ let keys = self.context.get_holder_pubkeys();
7644
+
7645
+ msgs::OpenChannelV2 {
7646
+ chain_hash,
7647
+ temporary_channel_id: self.context.temporary_channel_id.unwrap(),
7648
+ funding_satoshis: self.context.channel_value_satoshis,
7649
+ dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
7650
+ max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
7651
+ htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
7652
+ funding_feerate_sat_per_1000_weight: self.context.feerate_per_kw,
7653
+ commitment_feerate_sat_per_1000_weight: self.context.feerate_per_kw,
7654
+ to_self_delay: self.context.get_holder_selected_contest_delay(),
7655
+ max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
7656
+ funding_pubkey: keys.funding_pubkey,
7657
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
7658
+ payment_basepoint: keys.payment_point,
7659
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
7660
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
7661
+ first_per_commitment_point,
7662
+ second_per_commitment_point,
7663
+ channel_flags: if self.context.config.announced_channel {1} else {0},
7664
+ shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
7665
+ Some(script) => script.clone().into_inner(),
7666
+ None => Builder::new().into_script(),
7667
+ }),
7668
+ channel_type: Some(self.context.channel_type.clone()),
7669
+ locktime: self.dual_funding_context.funding_tx_locktime,
7670
+ require_confirmed_inputs: None,
7671
+ }
7672
+ }
7673
+ }
7674
+
7577
7675
// A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
7578
7676
#[cfg(dual_funding)]
7579
7677
pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
@@ -7733,6 +7831,31 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
7733
7831
}
7734
7832
}
7735
7833
7834
+ // Unfunded channel utilities
7835
+
7836
+ fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
7837
+ // The default channel type (ie the first one we try) depends on whether the channel is
7838
+ // public - if it is, we just go with `only_static_remotekey` as it's the only option
7839
+ // available. If it's private, we first try `scid_privacy` as it provides better privacy
7840
+ // with no other changes, and fall back to `only_static_remotekey`.
7841
+ let mut ret = ChannelTypeFeatures::only_static_remote_key();
7842
+ if !config.channel_handshake_config.announced_channel &&
7843
+ config.channel_handshake_config.negotiate_scid_privacy &&
7844
+ their_features.supports_scid_privacy() {
7845
+ ret.set_scid_privacy_required();
7846
+ }
7847
+
7848
+ // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
7849
+ // set it now. If they don't understand it, we'll fall back to our default of
7850
+ // `only_static_remotekey`.
7851
+ if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
7852
+ their_features.supports_anchors_zero_fee_htlc_tx() {
7853
+ ret.set_anchors_zero_fee_htlc_tx_required();
7854
+ }
7855
+
7856
+ ret
7857
+ }
7858
+
7736
7859
const SERIALIZATION_VERSION: u8 = 3;
7737
7860
const MIN_SERIALIZATION_VERSION: u8 = 3;
7738
7861
0 commit comments