Skip to content

Commit 8f769b3

Browse files
committed
Add OutboundV2Channel struct
1 parent c465f6a commit 8f769b3

File tree

1 file changed

+158
-36
lines changed

1 file changed

+158
-36
lines changed

lightning/src/ln/channel.rs

Lines changed: 158 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
13891389
entropy_source: &'a ES,
13901390
signer_provider: &'a SP,
13911391
counterparty_node_id: PublicKey,
1392-
// our_supported_features: &'a ChannelTypeFeatures,
13931392
their_features: &'a InitFeatures,
13941393
funding_satoshis: u64,
13951394
push_msat: u64,
@@ -1398,7 +1397,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
13981397
current_chain_height: u32,
13991398
outbound_scid_alias: u64,
14001399
temporary_channel_id: ChannelId,
1401-
channel_type: ChannelTypeFeatures,
1400+
holder_selected_channel_reserve_satoshis: u64,
1401+
channel_keys_id: [u8; 32],
1402+
holder_signer: <SP::Target as SignerProvider>::EcdsaSigner,
1403+
pubkeys: ChannelPublicKeys,
14021404
) -> Result<ChannelContext<SP>, APIError>
14031405
where
14041406
ES::Target: EntropySource,
@@ -1409,9 +1411,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14091411
let channel_value_satoshis = funding_satoshis;
14101412

14111413
let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay;
1412-
let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
1413-
let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
1414-
let pubkeys = holder_signer.pubkeys().clone();
14151414

14161415
if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO {
14171416
return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)});
@@ -1426,13 +1425,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14261425
if holder_selected_contest_delay < BREAKDOWN_TIMEOUT {
14271426
return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)});
14281427
}
1429-
let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config);
1430-
if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
1431-
// Protocol level safety check in place, although it should never happen because
1432-
// of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
1433-
return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
1434-
}
14351428

1429+
let channel_type = get_initial_channel_type(&config, their_features);
14361430
debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
14371431

14381432
let (commitment_conf_target, anchor_outputs_value_msat) = if channel_type.supports_anchors_zero_fee_htlc_tx() {
@@ -1488,6 +1482,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
14881482
channel_state: ChannelState::OurInitSent as u32,
14891483
announcement_sigs_state: AnnouncementSigsState::NotSent,
14901484
secp_ctx,
1485+
// We'll add our counterparty's `funding_satoshis` when we receive `accept_channel2`.
14911486
channel_value_satoshis,
14921487

14931488
latest_monitor_update_id: 0,
@@ -1521,6 +1516,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
15211516
signer_pending_commitment_update: false,
15221517
signer_pending_funding: false,
15231518

1519+
// We'll add our counterparty's `funding_satoshis` to these max commitment output assertions
1520+
// when we receive `accept_channel2`.
15241521
#[cfg(debug_assertions)]
15251522
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
15261523
#[cfg(debug_assertions)]
@@ -1541,6 +1538,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
15411538
counterparty_dust_limit_satoshis: 0,
15421539
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
15431540
counterparty_max_htlc_value_in_flight_msat: 0,
1541+
// We'll adjust this to include our counterparty's `funding_satoshis` when we
1542+
// receive `accept_channel2`.
15441543
holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.channel_handshake_config),
15451544
counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel
15461545
holder_selected_channel_reserve_satoshis,
@@ -6605,7 +6604,17 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
66056604
F::Target: FeeEstimator
66066605
{
66076606
let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
6608-
let channel_type = Self::get_initial_channel_type(&config, their_features);
6607+
6608+
let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config);
6609+
if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
6610+
// Protocol level safety check in place, although it should never happen because
6611+
// of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`
6612+
return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
6613+
}
6614+
6615+
let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id);
6616+
let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
6617+
let pubkeys = holder_signer.pubkeys().clone();
66096618

66106619
let chan = Self {
66116620
context: ChannelContext::new_for_outbound_channel(
@@ -6621,7 +6630,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
66216630
current_chain_height,
66226631
outbound_scid_alias,
66236632
temporary_channel_id,
6624-
channel_type,
6633+
holder_selected_channel_reserve_satoshis,
6634+
channel_keys_id,
6635+
holder_signer,
6636+
pubkeys,
66256637
)?,
66266638
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
66276639
};
@@ -6685,29 +6697,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
66856697
Ok((channel, funding_created))
66866698
}
66876699

6688-
fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
6689-
// The default channel type (ie the first one we try) depends on whether the channel is
6690-
// public - if it is, we just go with `only_static_remotekey` as it's the only option
6691-
// available. If it's private, we first try `scid_privacy` as it provides better privacy
6692-
// with no other changes, and fall back to `only_static_remotekey`.
6693-
let mut ret = ChannelTypeFeatures::only_static_remote_key();
6694-
if !config.channel_handshake_config.announced_channel &&
6695-
config.channel_handshake_config.negotiate_scid_privacy &&
6696-
their_features.supports_scid_privacy() {
6697-
ret.set_scid_privacy_required();
6698-
}
6699-
6700-
// Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
6701-
// set it now. If they don't understand it, we'll fall back to our default of
6702-
// `only_static_remotekey`.
6703-
if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
6704-
their_features.supports_anchors_zero_fee_htlc_tx() {
6705-
ret.set_anchors_zero_fee_htlc_tx_required();
6706-
}
6707-
6708-
ret
6709-
}
6710-
67116700
/// If we receive an error message, it may only be a rejection of the channel type we tried,
67126701
/// not of our ability to open any channel at all. Thus, on error, we should first call this
67136702
/// and see if we get a new `OpenChannel` message, otherwise the channel is failed.
@@ -7162,6 +7151,114 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
71627151
}
71637152
}
71647153

7154+
// A not-yet-funded outbound (from holder) channel using V2 channel establishment.
7155+
pub(super) struct OutboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
7156+
pub context: ChannelContext<SP>,
7157+
pub unfunded_context: UnfundedChannelContext,
7158+
#[cfg(dual_funding)]
7159+
pub dual_funding_context: DualFundingChannelContext,
7160+
}
7161+
7162+
#[cfg(dual_funding)]
7163+
impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
7164+
pub fn new<ES: Deref, F: Deref>(
7165+
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
7166+
counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
7167+
user_id: u128, config: &UserConfig, current_chain_height: u32, outbound_scid_alias: u64,
7168+
funding_confirmation_target: ConfirmationTarget,
7169+
) -> Result<OutboundV2Channel<SP>, APIError>
7170+
where ES::Target: EntropySource,
7171+
F::Target: FeeEstimator,
7172+
{
7173+
let channel_keys_id = signer_provider.generate_channel_keys_id(false, funding_satoshis, user_id);
7174+
let holder_signer = signer_provider.derive_channel_signer(funding_satoshis, channel_keys_id);
7175+
let pubkeys = holder_signer.pubkeys().clone();
7176+
7177+
let temporary_channel_id = ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint);
7178+
7179+
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
7180+
funding_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
7181+
7182+
let funding_feerate_sat_per_1000_weight = fee_estimator.bounded_sat_per_1000_weight(funding_confirmation_target);
7183+
let funding_tx_locktime = current_chain_height;
7184+
7185+
let chan = Self {
7186+
context: ChannelContext::new_for_outbound_channel(
7187+
fee_estimator,
7188+
entropy_source,
7189+
signer_provider,
7190+
counterparty_node_id,
7191+
their_features,
7192+
funding_satoshis,
7193+
0,
7194+
user_id,
7195+
config,
7196+
current_chain_height,
7197+
outbound_scid_alias,
7198+
temporary_channel_id,
7199+
holder_selected_channel_reserve_satoshis,
7200+
channel_keys_id,
7201+
holder_signer,
7202+
pubkeys,
7203+
)?,
7204+
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
7205+
dual_funding_context: DualFundingChannelContext {
7206+
our_funding_satoshis: funding_satoshis,
7207+
their_funding_satoshis: 0,
7208+
funding_tx_locktime,
7209+
funding_feerate_sat_per_1000_weight,
7210+
}
7211+
};
7212+
Ok(chan)
7213+
}
7214+
7215+
pub fn get_open_channel_v2(&self, chain_hash: ChainHash) -> msgs::OpenChannelV2 {
7216+
if self.context.channel_state != ChannelState::OurInitSent as u32 {
7217+
panic!("Cannot generate an open_channel2 after we've moved forward");
7218+
}
7219+
7220+
if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
7221+
panic!("Tried to send an open_channel2 for a channel that has already advanced");
7222+
}
7223+
7224+
let first_per_commitment_point = self.context.holder_signer.as_ref()
7225+
.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number,
7226+
&self.context.secp_ctx);
7227+
let second_per_commitment_point = self.context.holder_signer.as_ref()
7228+
.get_per_commitment_point(self.context.cur_holder_commitment_transaction_number - 1,
7229+
&self.context.secp_ctx);
7230+
let keys = self.context.get_holder_pubkeys();
7231+
7232+
msgs::OpenChannelV2 {
7233+
chain_hash,
7234+
temporary_channel_id: self.context.temporary_channel_id.unwrap(),
7235+
funding_satoshis: self.context.channel_value_satoshis,
7236+
dust_limit_satoshis: self.context.holder_dust_limit_satoshis,
7237+
max_htlc_value_in_flight_msat: self.context.holder_max_htlc_value_in_flight_msat,
7238+
htlc_minimum_msat: self.context.holder_htlc_minimum_msat,
7239+
funding_feerate_sat_per_1000_weight: self.context.feerate_per_kw,
7240+
commitment_feerate_sat_per_1000_weight: self.context.feerate_per_kw,
7241+
to_self_delay: self.context.get_holder_selected_contest_delay(),
7242+
max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
7243+
funding_pubkey: keys.funding_pubkey,
7244+
revocation_basepoint: keys.revocation_basepoint.to_public_key(),
7245+
payment_basepoint: keys.payment_point,
7246+
delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
7247+
htlc_basepoint: keys.htlc_basepoint.to_public_key(),
7248+
first_per_commitment_point,
7249+
second_per_commitment_point,
7250+
channel_flags: if self.context.config.announced_channel {1} else {0},
7251+
shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
7252+
Some(script) => script.clone().into_inner(),
7253+
None => Builder::new().into_script(),
7254+
}),
7255+
channel_type: Some(self.context.channel_type.clone()),
7256+
locktime: self.dual_funding_context.funding_tx_locktime,
7257+
require_confirmed_inputs: None,
7258+
}
7259+
}
7260+
}
7261+
71657262
// A not-yet-funded inbound (from counterparty) channel using V2 channel establishment.
71667263
#[cfg(dual_funding)]
71677264
pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
@@ -7315,6 +7412,31 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
73157412
}
73167413
}
73177414

7415+
// Unfunded channel utilities
7416+
7417+
fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
7418+
// The default channel type (ie the first one we try) depends on whether the channel is
7419+
// public - if it is, we just go with `only_static_remotekey` as it's the only option
7420+
// available. If it's private, we first try `scid_privacy` as it provides better privacy
7421+
// with no other changes, and fall back to `only_static_remotekey`.
7422+
let mut ret = ChannelTypeFeatures::only_static_remote_key();
7423+
if !config.channel_handshake_config.announced_channel &&
7424+
config.channel_handshake_config.negotiate_scid_privacy &&
7425+
their_features.supports_scid_privacy() {
7426+
ret.set_scid_privacy_required();
7427+
}
7428+
7429+
// Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
7430+
// set it now. If they don't understand it, we'll fall back to our default of
7431+
// `only_static_remotekey`.
7432+
if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
7433+
their_features.supports_anchors_zero_fee_htlc_tx() {
7434+
ret.set_anchors_zero_fee_htlc_tx_required();
7435+
}
7436+
7437+
ret
7438+
}
7439+
73187440
const SERIALIZATION_VERSION: u8 = 3;
73197441
const MIN_SERIALIZATION_VERSION: u8 = 3;
73207442

0 commit comments

Comments
 (0)