@@ -269,9 +269,11 @@ enum HTLCUpdateAwaitingACK {
269
269
/// `ChannelReady` can then get all remaining flags set on it, until we finish shutdown, then we
270
270
/// move on to `ShutdownComplete`, at which point most calls into this channel are disallowed.
271
271
enum ChannelState {
272
- /// Implies we have (or are prepared to) send our open_channel/accept_channel message
272
+ /// Implies we have (or are prepared to) send our open_channel/accept_channel message or in the
273
+ /// case of V2 establishment, our open_channel2/accept_channel2 message
273
274
OurInitSent = 1 << 0,
274
- /// Implies we have received their `open_channel`/`accept_channel` message
275
+ /// Implies we have received their `open_channel`/`accept_channel` message or in the case of
276
+ /// V2 establishment, their `open_channel2`/`accept_channel2` message
275
277
TheirInitSent = 1 << 1,
276
278
/// We have sent `funding_created` and are awaiting a `funding_signed` to advance to `FundingSent`.
277
279
/// Note that this is nonsense for an inbound channel as we immediately generate `funding_signed`
@@ -2661,6 +2663,20 @@ pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channe
2661
2663
cmp::min(channel_value_satoshis, cmp::max(q, 1000))
2662
2664
}
2663
2665
2666
+ /// Returns a minimum channel reserve value each party needs to maintain, fixed in the spec to a
2667
+ /// default of 1% of the total channel value.
2668
+ ///
2669
+ /// Guaranteed to return a value no larger than channel_value_satoshis
2670
+ ///
2671
+ /// This is used both for outbound and inbound channels and has lower bound
2672
+ /// of `dust_limit_satoshis`.
2673
+ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satoshis: u64) -> u64 {
2674
+ let channel_reserve_proportional_millionths = 10_000; // Fixed at 1% in spec.
2675
+ let calculated_reserve =
2676
+ channel_value_satoshis.saturating_mul(channel_reserve_proportional_millionths) / 1_000_000;
2677
+ cmp::min(channel_value_satoshis, cmp::max(calculated_reserve, dust_limit_satoshis))
2678
+ }
2679
+
2664
2680
// Get the fee cost in SATS of a commitment tx with a given number of HTLC outputs.
2665
2681
// Note that num_htlcs should not include dust HTLCs.
2666
2682
#[inline]
@@ -2694,6 +2710,8 @@ pub(super) struct DualFundingChannelContext {
2694
2710
// Counterparty designates channel data owned by the another channel participant entity.
2695
2711
pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
2696
2712
pub context: ChannelContext<SP>,
2713
+ #[cfg(dual_funding)]
2714
+ pub dual_funding_channel_context: Option<DualFundingChannelContext>,
2697
2715
}
2698
2716
2699
2717
#[cfg(any(test, fuzzing))]
@@ -6636,6 +6654,8 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
6636
6654
6637
6655
let channel = Channel {
6638
6656
context: self.context,
6657
+ #[cfg(dual_funding)]
6658
+ dual_funding_channel_context: None,
6639
6659
};
6640
6660
6641
6661
Ok((channel, funding_created))
@@ -7107,6 +7127,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
7107
7127
// `ChannelMonitor`.
7108
7128
let mut channel = Channel {
7109
7129
context: self.context,
7130
+ #[cfg(dual_funding)]
7131
+ dual_funding_channel_context: None,
7110
7132
};
7111
7133
let need_channel_ready = channel.check_get_channel_ready(0).is_some();
7112
7134
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -7115,6 +7137,159 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
7115
7137
}
7116
7138
}
7117
7139
7140
+ // A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
7141
+ #[cfg(dual_funding)]
7142
+ pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
7143
+ pub context: ChannelContext<SP>,
7144
+ pub unfunded_context: UnfundedChannelContext,
7145
+ pub dual_funding_context: DualFundingChannelContext,
7146
+ }
7147
+
7148
+ #[cfg(dual_funding)]
7149
+ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
7150
+ /// Creates a new dual-funded channel from a remote side's request for one.
7151
+ /// Assumes chain_hash has already been checked and corresponds with what we expect!
7152
+ pub fn new<ES: Deref, F: Deref, L: Deref>(
7153
+ fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
7154
+ counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
7155
+ their_features: &InitFeatures, msg: &msgs::OpenChannelV2, funding_satoshis: u64, user_id: u128,
7156
+ config: &UserConfig, current_chain_height: u32, logger: &L,
7157
+ ) -> Result<InboundV2Channel<SP>, ChannelError>
7158
+ where ES::Target: EntropySource,
7159
+ F::Target: FeeEstimator,
7160
+ L::Target: Logger,
7161
+ {
7162
+ // TODO(dual_funding): Fix this
7163
+ let channel_value_satoshis = funding_satoshis * 1000 + msg.funding_satoshis;
7164
+ let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7165
+ channel_value_satoshis, msg.dust_limit_satoshis);
7166
+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7167
+ channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
7168
+
7169
+ let counterparty_pubkeys = ChannelPublicKeys {
7170
+ funding_pubkey: msg.funding_pubkey,
7171
+ revocation_basepoint: RevocationBasepoint(msg.revocation_basepoint),
7172
+ payment_point: msg.payment_basepoint,
7173
+ delayed_payment_basepoint: DelayedPaymentBasepoint(msg.delayed_payment_basepoint),
7174
+ htlc_basepoint: HtlcBasepoint(msg.htlc_basepoint)
7175
+ };
7176
+
7177
+ let mut context = ChannelContext::new_for_inbound_channel(
7178
+ fee_estimator,
7179
+ entropy_source,
7180
+ signer_provider,
7181
+ counterparty_node_id,
7182
+ our_supported_features,
7183
+ their_features,
7184
+ user_id,
7185
+ config,
7186
+ current_chain_height,
7187
+ logger,
7188
+ false,
7189
+
7190
+ funding_satoshis,
7191
+
7192
+ counterparty_pubkeys,
7193
+ msg.channel_flags,
7194
+ msg.channel_type.clone(),
7195
+ msg.funding_satoshis,
7196
+ msg.to_self_delay,
7197
+ holder_selected_channel_reserve_satoshis,
7198
+ counterparty_selected_channel_reserve_satoshis,
7199
+ 0 /* push_msat not used in dual-funding */,
7200
+ msg.dust_limit_satoshis,
7201
+ msg.htlc_minimum_msat,
7202
+ msg.commitment_feerate_sat_per_1000_weight,
7203
+ msg.max_accepted_htlcs,
7204
+ msg.shutdown_scriptpubkey.clone(),
7205
+ msg.max_htlc_value_in_flight_msat,
7206
+ msg.temporary_channel_id,
7207
+ msg.first_per_commitment_point,
7208
+ )?;
7209
+ let channel_id = ChannelId::v2_from_revocation_basepoints(
7210
+ &context.get_holder_pubkeys().revocation_basepoint,
7211
+ &context.get_counterparty_pubkeys().revocation_basepoint);
7212
+ context.channel_id = channel_id;
7213
+
7214
+ let chan = Self {
7215
+ context,
7216
+ unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
7217
+ dual_funding_context: DualFundingChannelContext {
7218
+ our_funding_satoshis: funding_satoshis,
7219
+ their_funding_satoshis: msg.funding_satoshis,
7220
+ funding_tx_locktime: msg.locktime,
7221
+ funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
7222
+ }
7223
+ };
7224
+
7225
+ Ok(chan)
7226
+ }
7227
+
7228
+ /// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannelV2`] message which
7229
+ /// should be sent back to the counterparty node.
7230
+ ///
7231
+ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7232
+ pub fn accept_inbound_dual_funded_channel(&mut self) -> msgs::AcceptChannelV2 {
7233
+ if self.context.is_outbound() {
7234
+ panic!("Tried to send accept_channel2 for an outbound channel?");
7235
+ }
7236
+ if self.context.channel_state != (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32) {
7237
+ panic!("Tried to send accept_channel2 after channel had moved forward");
7238
+ }
7239
+ if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
7240
+ panic!("Tried to send an accept_channel2 for a channel that has already advanced");
7241
+ }
7242
+
7243
+ self.generate_accept_channel_v2_message()
7244
+ }
7245
+
7246
+ /// This function is used to explicitly generate a [`msgs::AcceptChannel`] message for an
7247
+ /// inbound channel. If the intention is to accept an inbound channel, use
7248
+ /// [`InboundV1Channel::accept_inbound_channel`] instead.
7249
+ ///
7250
+ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7251
+ fn generate_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
7252
+ let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
7253
+ self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
7254
+ let second_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
7255
+ self.context.cur_holder_commitment_transaction_number - 1, &self.context.secp_ctx);
7256
+ let keys = self.context.get_holder_pubkeys();
7257
+
7258
+ msgs::AcceptChannelV2 {
7259
+ temporary_channel_id: self.context.temporary_channel_id.unwrap(),
7260
+ funding_satoshis: self.dual_funding_context.our_funding_satoshis,
7261
+ dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
7262
+ max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
7263
+ htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
7264
+ minimum_depth: self.context.minimum_depth.unwrap(),
7265
+ to_self_delay: self.context.get_holder_selected_contest_delay(),
7266
+ max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
7267
+ funding_pubkey: keys.funding_pubkey,
7268
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
7269
+ payment_basepoint: keys.payment_point,
7270
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
7271
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
7272
+ first_per_commitment_point,
7273
+ second_per_commitment_point,
7274
+ shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
7275
+ Some(script) => script.clone().into_inner(),
7276
+ None => Builder::new().into_script(),
7277
+ }),
7278
+ channel_type: Some(self.context.channel_type.clone()),
7279
+ require_confirmed_inputs: None,
7280
+ }
7281
+ }
7282
+
7283
+ /// Enables the possibility for tests to extract a [`msgs::AcceptChannelV2`] message for an
7284
+ /// inbound channel without accepting it.
7285
+ ///
7286
+ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
7287
+ #[cfg(test)]
7288
+ pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
7289
+ self.generate_accept_channel_v2_message()
7290
+ }
7291
+ }
7292
+
7118
7293
const SERIALIZATION_VERSION: u8 = 3;
7119
7294
const MIN_SERIALIZATION_VERSION: u8 = 3;
7120
7295
@@ -8011,7 +8186,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
8011
8186
channel_keys_id,
8012
8187
8013
8188
blocked_monitor_updates: blocked_monitor_updates.unwrap(),
8014
- }
8189
+ },
8190
+ #[cfg(dual_funding)]
8191
+ dual_funding_channel_context: None,
8015
8192
})
8016
8193
}
8017
8194
}
@@ -8569,7 +8746,11 @@ mod tests {
8569
8746
let config = UserConfig::default();
8570
8747
let features = channelmanager::provided_init_features(&config);
8571
8748
let outbound_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &features, 10000000, 100000, 42, &config, 0, 42, None).unwrap();
8572
- let mut chan = Channel { context: outbound_chan.context };
8749
+ let mut chan = Channel {
8750
+ context: outbound_chan.context,
8751
+ #[cfg(dual_funding)]
8752
+ dual_funding_channel_context: None,
8753
+ };
8573
8754
8574
8755
let dummy_htlc_source = HTLCSource::OutboundRoute {
8575
8756
path: Path {
0 commit comments