Skip to content

Commit e95d728

Browse files
committed
Properly handle funding key rotation during splices
When splicing, we're required by protocol to retain all the existing keys material except the funding key which we're allowed to rotate. In the original implementation we acknowledged that but figured we'd stick with a single `pubkey` method in the `ChannelSigner` anyway cause adding a specific method for it is annoying. Sadly, this was ultimately broken - in `FundingScope::for_splice`, we called the signer's `new_pubkeys` method (renamed from `pubkeys` after splicing initially landed), replacing all of the public keys the `Channel` would use rather than just the funding key. This can result in commitment signature mismatches if the signer changes any keys aside from the funding one. `InMemorySigner` did not do so, however, so we didn't notice the bug. Luckily-ish, in 189b8ac we started generating a fresh `remote_key` when splicing (at least when upgrading from 0.1 to 0.2 or when setting `KeysManager` to use v1 `remote_key` derivation). This breaks splicing cause we can't communicate the new `remote_key` to the counterparty during the splicing handshake. Ultimately this bug is because the API we had didn't communicate to the signer that we weren't allowed to change anything except the funding key, and allowed returning a `ChannelPublicKeys` which would break the channel. Here we fix this by renaming `new_pubkeys` `pubkeys` again (partially reverting 9d291e0 but keeping the changed requirements that `pubkeys` only be called once) and adding a new `ChannelSigner:new_funding_pubkey` method specifically for splicing. We also update `channel.rs` to correctly fetch the new funding pubkey before sending `splice_init`, storing it in the `PendingFunding` untl we build a `FundingScope`. Backport of e95ebf8
1 parent 941a3a1 commit e95d728

File tree

7 files changed

+112
-76
lines changed

7 files changed

+112
-76
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7115,7 +7115,7 @@ mod tests {
71157115
let funding_outpoint = OutPoint { txid: Txid::all_zeros(), index: u16::MAX };
71167116
let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint);
71177117
let channel_parameters = ChannelTransactionParameters {
7118-
holder_pubkeys: keys.new_pubkeys(None, &secp_ctx),
7118+
holder_pubkeys: keys.pubkeys(&secp_ctx),
71197119
holder_selected_contest_delay: 66,
71207120
is_outbound_from_holder: true,
71217121
counterparty_parameters: Some(CounterpartyChannelTransactionParameters {
@@ -7378,7 +7378,7 @@ mod tests {
73787378
let funding_outpoint = OutPoint { txid: Txid::all_zeros(), index: u16::MAX };
73797379
let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint);
73807380
let channel_parameters = ChannelTransactionParameters {
7381-
holder_pubkeys: keys.new_pubkeys(None, &secp_ctx),
7381+
holder_pubkeys: keys.pubkeys(&secp_ctx),
73827382
holder_selected_contest_delay: 66,
73837383
is_outbound_from_holder: true,
73847384
counterparty_parameters: Some(CounterpartyChannelTransactionParameters {

lightning/src/chain/onchaintx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,7 @@ mod tests {
13331333
// Use non-anchor channels so that HTLC-Timeouts are broadcast immediately instead of sent
13341334
// to the user for external funding.
13351335
let chan_params = ChannelTransactionParameters {
1336-
holder_pubkeys: signer.new_pubkeys(None, &secp_ctx),
1336+
holder_pubkeys: signer.pubkeys(&secp_ctx),
13371337
holder_selected_contest_delay: 66,
13381338
is_outbound_from_holder: true,
13391339
counterparty_parameters: Some(CounterpartyChannelTransactionParameters {

lightning/src/ln/chan_utils.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,11 +1058,11 @@ pub struct ChannelTransactionParameters {
10581058
/// If a channel was funded with transaction A, and later spliced with transaction B, this field
10591059
/// tracks the txid of transaction A.
10601060
///
1061-
/// See [`compute_funding_key_tweak`] and [`ChannelSigner::new_pubkeys`] for more context on how
1061+
/// See [`compute_funding_key_tweak`] and [`ChannelSigner::pubkeys`] for more context on how
10621062
/// this may be used.
10631063
///
10641064
/// [`compute_funding_key_tweak`]: crate::sign::compute_funding_key_tweak
1065-
/// [`ChannelSigner::new_pubkeys`]: crate::sign::ChannelSigner::new_pubkeys
1065+
/// [`ChannelSigner::pubkeys`]: crate::sign::ChannelSigner::pubkeys
10661066
pub splice_parent_funding_txid: Option<Txid>,
10671067
/// This channel's type, as negotiated during channel open. For old objects where this field
10681068
/// wasn't serialized, it will default to static_remote_key at deserialization.
@@ -2285,8 +2285,8 @@ mod tests {
22852285
let counterparty_signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(true, 1));
22862286
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
22872287
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
2288-
let holder_pubkeys = signer.new_pubkeys(None, &secp_ctx);
2289-
let counterparty_pubkeys = counterparty_signer.new_pubkeys(None, &secp_ctx).clone();
2288+
let holder_pubkeys = signer.pubkeys(&secp_ctx);
2289+
let counterparty_pubkeys = counterparty_signer.pubkeys(&secp_ctx).clone();
22902290
let channel_parameters = ChannelTransactionParameters {
22912291
holder_pubkeys: holder_pubkeys.clone(),
22922292
holder_selected_contest_delay: 0,

lightning/src/ln/channel.rs

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,6 +2469,7 @@ impl FundingScope {
24692469
fn for_splice<SP: Deref>(
24702470
prev_funding: &Self, context: &ChannelContext<SP>, our_funding_contribution: SignedAmount,
24712471
their_funding_contribution: SignedAmount, counterparty_funding_pubkey: PublicKey,
2472+
our_new_holder_keys: ChannelPublicKeys,
24722473
) -> Self
24732474
where
24742475
SP::Target: SignerProvider,
@@ -2488,19 +2489,15 @@ impl FundingScope {
24882489
debug_assert!(post_value_to_self_msat.is_some());
24892490
let post_value_to_self_msat = post_value_to_self_msat.unwrap();
24902491

2491-
// Rotate the pubkeys using the prev_funding_txid as a tweak
2492-
let prev_funding_txid = prev_funding.get_funding_txid();
2493-
let holder_pubkeys = context.new_holder_pubkeys(prev_funding_txid);
2494-
24952492
let channel_parameters = &prev_funding.channel_transaction_parameters;
24962493
let mut post_channel_transaction_parameters = ChannelTransactionParameters {
2497-
holder_pubkeys,
2494+
holder_pubkeys: our_new_holder_keys,
24982495
holder_selected_contest_delay: channel_parameters.holder_selected_contest_delay,
24992496
// The 'outbound' attribute doesn't change, even if the splice initiator is the other node
25002497
is_outbound_from_holder: channel_parameters.is_outbound_from_holder,
25012498
counterparty_parameters: channel_parameters.counterparty_parameters.clone(),
25022499
funding_outpoint: None, // filled later
2503-
splice_parent_funding_txid: prev_funding_txid,
2500+
splice_parent_funding_txid: prev_funding.get_funding_txid(),
25042501
channel_type_features: channel_parameters.channel_type_features.clone(),
25052502
channel_value_satoshis: post_channel_value,
25062503
};
@@ -2636,6 +2633,7 @@ impl_writeable_tlv_based!(PendingFunding, {
26362633
enum FundingNegotiation {
26372634
AwaitingAck {
26382635
context: FundingNegotiationContext,
2636+
new_holder_funding_key: PublicKey,
26392637
},
26402638
ConstructingTransaction {
26412639
funding: FundingScope,
@@ -2666,7 +2664,7 @@ impl FundingNegotiation {
26662664

26672665
fn is_initiator(&self) -> bool {
26682666
match self {
2669-
FundingNegotiation::AwaitingAck { context } => context.is_initiator,
2667+
FundingNegotiation::AwaitingAck { context, .. } => context.is_initiator,
26702668
FundingNegotiation::ConstructingTransaction { interactive_tx_constructor, .. } => {
26712669
interactive_tx_constructor.is_initiator()
26722670
},
@@ -3510,7 +3508,7 @@ where
35103508

35113509
// TODO(dual_funding): Checks for `funding_feerate_sat_per_1000_weight`?
35123510

3513-
let pubkeys = holder_signer.new_pubkeys(None, &secp_ctx);
3511+
let pubkeys = holder_signer.pubkeys(&secp_ctx);
35143512

35153513
let funding = FundingScope {
35163514
value_to_self_msat,
@@ -3748,7 +3746,7 @@ where
37483746
Err(_) => return Err(APIError::ChannelUnavailable { err: "Failed to get destination script".to_owned()}),
37493747
};
37503748

3751-
let pubkeys = holder_signer.new_pubkeys(None, &secp_ctx);
3749+
let pubkeys = holder_signer.pubkeys(&secp_ctx);
37523750
let temporary_channel_id = temporary_channel_id_fn.map(|f| f(&pubkeys))
37533751
.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
37543752

@@ -4111,16 +4109,6 @@ where
41114109
return &mut self.holder_signer;
41124110
}
41134111

4114-
/// Returns holder pubkeys to use for the channel.
4115-
fn new_holder_pubkeys(&self, prev_funding_txid: Option<Txid>) -> ChannelPublicKeys {
4116-
match &self.holder_signer {
4117-
ChannelSignerType::Ecdsa(ecdsa) => ecdsa.new_pubkeys(prev_funding_txid, &self.secp_ctx),
4118-
// TODO (taproot|arik)
4119-
#[cfg(taproot)]
4120-
_ => todo!(),
4121-
}
4122-
}
4123-
41244112
/// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
41254113
/// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases
41264114
/// or prior to any channel actions during `Channel` initialization.
@@ -6891,7 +6879,7 @@ macro_rules! maybe_create_splice_funding_failed {
68916879
.map(|funding| funding.get_channel_type().clone());
68926880

68936881
let (contributed_inputs, contributed_outputs) = match funding_negotiation {
6894-
FundingNegotiation::AwaitingAck { context } => {
6882+
FundingNegotiation::AwaitingAck { context, .. } => {
68956883
context.$contributed_inputs_and_outputs()
68966884
},
68976885
FundingNegotiation::ConstructingTransaction {
@@ -11962,17 +11950,29 @@ where
1196211950
change_script,
1196311951
};
1196411952

11953+
// Rotate the funding pubkey using the prev_funding_txid as a tweak
11954+
let prev_funding_txid = self.funding.get_funding_txid();
11955+
let funding_pubkey = match (prev_funding_txid, &self.context.holder_signer) {
11956+
(None, _) => {
11957+
debug_assert!(false);
11958+
self.funding.get_holder_pubkeys().funding_pubkey
11959+
},
11960+
(Some(prev_funding_txid), ChannelSignerType::Ecdsa(ecdsa)) => {
11961+
ecdsa.new_funding_pubkey(prev_funding_txid, &self.context.secp_ctx)
11962+
},
11963+
#[cfg(taproot)]
11964+
_ => todo!(),
11965+
};
11966+
11967+
let funding_negotiation =
11968+
FundingNegotiation::AwaitingAck { context, new_holder_funding_key: funding_pubkey };
1196511969
self.pending_splice = Some(PendingFunding {
11966-
funding_negotiation: Some(FundingNegotiation::AwaitingAck { context }),
11970+
funding_negotiation: Some(funding_negotiation),
1196711971
negotiated_candidates: vec![],
1196811972
sent_funding_txid: None,
1196911973
received_funding_txid: None,
1197011974
});
1197111975

11972-
// Rotate the pubkeys using the prev_funding_txid as a tweak
11973-
let prev_funding_txid = self.funding.get_funding_txid();
11974-
let funding_pubkey = self.context.new_holder_pubkeys(prev_funding_txid).funding_pubkey;
11975-
1197611976
msgs::SpliceInit {
1197711977
channel_id: self.context.channel_id,
1197811978
funding_contribution_satoshis: adjusted_funding_contribution.to_sat(),
@@ -12056,12 +12056,29 @@ where
1205612056
self.validate_splice_contributions(our_funding_contribution, their_funding_contribution)
1205712057
.map_err(|e| ChannelError::WarnAndDisconnect(e))?;
1205812058

12059+
// Rotate the pubkeys using the prev_funding_txid as a tweak
12060+
let prev_funding_txid = self.funding.get_funding_txid();
12061+
let funding_pubkey = match (prev_funding_txid, &self.context.holder_signer) {
12062+
(None, _) => {
12063+
debug_assert!(false);
12064+
self.funding.get_holder_pubkeys().funding_pubkey
12065+
},
12066+
(Some(prev_funding_txid), ChannelSignerType::Ecdsa(ecdsa)) => {
12067+
ecdsa.new_funding_pubkey(prev_funding_txid, &self.context.secp_ctx)
12068+
},
12069+
#[cfg(taproot)]
12070+
_ => todo!(),
12071+
};
12072+
let mut new_keys = self.funding.get_holder_pubkeys().clone();
12073+
new_keys.funding_pubkey = funding_pubkey;
12074+
1205912075
Ok(FundingScope::for_splice(
1206012076
&self.funding,
1206112077
&self.context,
1206212078
our_funding_contribution,
1206312079
their_funding_contribution,
1206412080
msg.funding_pubkey,
12081+
new_keys,
1206512082
))
1206612083
}
1206712084

@@ -12206,8 +12223,7 @@ where
1220612223
// optimization, but for often-offline nodes it may be, as we may connect and immediately
1220712224
// go into splicing from both sides.
1220812225

12209-
let funding_pubkey = splice_funding.get_holder_pubkeys().funding_pubkey;
12210-
12226+
let new_funding_pubkey = splice_funding.get_holder_pubkeys().funding_pubkey;
1221112227
self.pending_splice = Some(PendingFunding {
1221212228
funding_negotiation: Some(FundingNegotiation::ConstructingTransaction {
1221312229
funding: splice_funding,
@@ -12221,7 +12237,7 @@ where
1222112237
Ok(msgs::SpliceAck {
1222212238
channel_id: self.context.channel_id,
1222312239
funding_contribution_satoshis: our_funding_contribution.to_sat(),
12224-
funding_pubkey,
12240+
funding_pubkey: new_funding_pubkey,
1222512241
require_confirmed_inputs: None,
1222612242
})
1222712243
}
@@ -12247,13 +12263,14 @@ where
1224712263
let pending_splice =
1224812264
self.pending_splice.as_mut().expect("We should have returned an error earlier!");
1224912265
// TODO: Good candidate for a let else statement once MSRV >= 1.65
12250-
let funding_negotiation_context = if let Some(FundingNegotiation::AwaitingAck { context }) =
12251-
pending_splice.funding_negotiation.take()
12252-
{
12253-
context
12254-
} else {
12255-
panic!("We should have returned an error earlier!");
12256-
};
12266+
let funding_negotiation_context =
12267+
if let Some(FundingNegotiation::AwaitingAck { context, .. }) =
12268+
pending_splice.funding_negotiation.take()
12269+
{
12270+
context
12271+
} else {
12272+
panic!("We should have returned an error earlier!");
12273+
};
1225712274

1225812275
let mut interactive_tx_constructor = funding_negotiation_context
1225912276
.into_interactive_tx_constructor(
@@ -12284,13 +12301,17 @@ where
1228412301
fn validate_splice_ack(&self, msg: &msgs::SpliceAck) -> Result<FundingScope, ChannelError> {
1228512302
// TODO(splicing): Add check that we are the splice (quiescence) initiator
1228612303

12287-
let funding_negotiation_context = match &self
12304+
let pending_splice = self
1228812305
.pending_splice
1228912306
.as_ref()
12290-
.ok_or(ChannelError::Ignore("Channel is not in pending splice".to_owned()))?
12307+
.ok_or_else(|| ChannelError::Ignore("Channel is not in pending splice".to_owned()))?;
12308+
12309+
let (funding_negotiation_context, new_holder_funding_key) = match &pending_splice
1229112310
.funding_negotiation
1229212311
{
12293-
Some(FundingNegotiation::AwaitingAck { context }) => context,
12312+
Some(FundingNegotiation::AwaitingAck { context, new_holder_funding_key }) => {
12313+
(context, new_holder_funding_key)
12314+
},
1229412315
Some(FundingNegotiation::ConstructingTransaction { .. })
1229512316
| Some(FundingNegotiation::AwaitingSignatures { .. }) => {
1229612317
return Err(ChannelError::WarnAndDisconnect(
@@ -12309,12 +12330,16 @@ where
1230912330
self.validate_splice_contributions(our_funding_contribution, their_funding_contribution)
1231012331
.map_err(|e| ChannelError::WarnAndDisconnect(e))?;
1231112332

12333+
let mut new_keys = self.funding.get_holder_pubkeys().clone();
12334+
new_keys.funding_pubkey = *new_holder_funding_key;
12335+
1231212336
Ok(FundingScope::for_splice(
1231312337
&self.funding,
1231412338
&self.context,
1231512339
our_funding_contribution,
1231612340
their_funding_contribution,
1231712341
msg.funding_pubkey,
12342+
new_keys,
1231812343
))
1231912344
}
1232012345

@@ -16475,7 +16500,7 @@ mod tests {
1647516500
[0; 32],
1647616501
);
1647716502

16478-
let holder_pubkeys = signer.new_pubkeys(None, &secp_ctx);
16503+
let holder_pubkeys = signer.pubkeys(&secp_ctx);
1647916504
assert_eq!(holder_pubkeys.funding_pubkey.serialize()[..],
1648016505
<Vec<u8>>::from_hex("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
1648116506
let keys_provider = Keys { signer: signer.clone() };

lightning/src/sign/mod.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,12 @@ pub enum SpendableOutputDescriptor {
272272
/// To derive the delayed payment key which is used to sign this input, you must pass the
273273
/// holder [`InMemorySigner::delayed_payment_base_key`] (i.e., the private key which
274274
/// corresponds to the [`ChannelPublicKeys::delayed_payment_basepoint`] in
275-
/// [`ChannelSigner::new_pubkeys`]) and the provided
275+
/// [`ChannelSigner::pubkeys`]) and the provided
276276
/// [`DelayedPaymentOutputDescriptor::per_commitment_point`] to
277277
/// [`chan_utils::derive_private_key`]. The DelayedPaymentKey can be generated without the
278278
/// secret key using [`DelayedPaymentKey::from_basepoint`] and only the
279279
/// [`ChannelPublicKeys::delayed_payment_basepoint`] which appears in
280-
/// [`ChannelSigner::new_pubkeys`].
280+
/// [`ChannelSigner::pubkeys`].
281281
///
282282
/// To derive the [`DelayedPaymentOutputDescriptor::revocation_pubkey`] provided here (which is
283283
/// used in the witness script generation), you must pass the counterparty
@@ -292,7 +292,7 @@ pub enum SpendableOutputDescriptor {
292292
/// [`chan_utils::get_revokeable_redeemscript`].
293293
DelayedPaymentOutput(DelayedPaymentOutputDescriptor),
294294
/// An output spendable exclusively by our payment key (i.e., the private key that corresponds
295-
/// to the `payment_point` in [`ChannelSigner::new_pubkeys`]). The output type depends on the
295+
/// to the `payment_point` in [`ChannelSigner::pubkeys`]). The output type depends on the
296296
/// channel type negotiated.
297297
///
298298
/// On an anchor outputs channel, the witness in the spending input is:
@@ -792,19 +792,25 @@ pub trait ChannelSigner {
792792
/// and pause future signing operations until this validation completes.
793793
fn validate_counterparty_revocation(&self, idx: u64, secret: &SecretKey) -> Result<(), ()>;
794794

795-
/// Returns a *new* set of holder channel public keys and basepoints. They may be the same as a
796-
/// previous value, but are also allowed to change arbitrarily. Signing methods must still
797-
/// support signing for any keys which have ever been returned. This should only be called
798-
/// either for new channels or new splices.
795+
/// Returns the holder channel public keys and basepoints. This should only be called once
796+
/// during channel creation and as such implementations are allowed undefined behavior if
797+
/// called more than once.
799798
///
800-
/// `splice_parent_funding_txid` can be used to compute a tweak to rotate the funding key in the
801-
/// 2-of-2 multisig script during a splice. See [`compute_funding_key_tweak`] for an example
802-
/// tweak and more details.
799+
/// This method is *not* asynchronous. Instead, the value must be computed locally or in
800+
/// advance and cached.
801+
fn pubkeys(&self, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelPublicKeys;
802+
803+
/// Returns a new funding pubkey (i.e. our public which is used in a 2-of-2 with the
804+
/// counterparty's key to to lock the funds on-chain) for a spliced channel.
805+
///
806+
/// `splice_parent_funding_txid` can be used to compute a tweak with which to rotate the base
807+
/// key (which will then be available later in signing operations via
808+
/// [`ChannelTransactionParameters::splice_parent_funding_txid`]).
803809
///
804810
/// This method is *not* asynchronous. Instead, the value must be cached locally.
805-
fn new_pubkeys(
806-
&self, splice_parent_funding_txid: Option<Txid>, secp_ctx: &Secp256k1<secp256k1::All>,
807-
) -> ChannelPublicKeys;
811+
fn new_funding_pubkey(
812+
&self, splice_parent_funding_txid: Txid, secp_ctx: &Secp256k1<secp256k1::All>,
813+
) -> PublicKey;
808814

809815
/// Returns an arbitrary identifier describing the set of keys which are provided back to you in
810816
/// some [`SpendableOutputDescriptor`] types. This should be sufficient to identify this
@@ -1457,17 +1463,13 @@ impl ChannelSigner for InMemorySigner {
14571463
Ok(())
14581464
}
14591465

1460-
fn new_pubkeys(
1461-
&self, splice_parent_funding_txid: Option<Txid>, secp_ctx: &Secp256k1<secp256k1::All>,
1462-
) -> ChannelPublicKeys {
1466+
fn pubkeys(&self, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelPublicKeys {
14631467
// Because splices always break downgrades, we go ahead and always use the new derivation
14641468
// here as its just much better.
1465-
let use_v2_derivation =
1466-
self.v2_remote_key_derivation || splice_parent_funding_txid.is_some();
14671469
let payment_key =
1468-
if use_v2_derivation { &self.payment_key_v2 } else { &self.payment_key_v1 };
1470+
if self.v2_remote_key_derivation { &self.payment_key_v2 } else { &self.payment_key_v1 };
14691471
let from_secret = |s: &SecretKey| PublicKey::from_secret_key(secp_ctx, s);
1470-
let mut pubkeys = ChannelPublicKeys {
1472+
let pubkeys = ChannelPublicKeys {
14711473
funding_pubkey: from_secret(&self.funding_key.0),
14721474
revocation_basepoint: RevocationBasepoint::from(from_secret(&self.revocation_base_key)),
14731475
payment_point: from_secret(payment_key),
@@ -1477,13 +1479,15 @@ impl ChannelSigner for InMemorySigner {
14771479
htlc_basepoint: HtlcBasepoint::from(from_secret(&self.htlc_base_key)),
14781480
};
14791481

1480-
if splice_parent_funding_txid.is_some() {
1481-
pubkeys.funding_pubkey =
1482-
self.funding_key(splice_parent_funding_txid).public_key(secp_ctx);
1483-
}
14841482
pubkeys
14851483
}
14861484

1485+
fn new_funding_pubkey(
1486+
&self, splice_parent_funding_txid: Txid, secp_ctx: &Secp256k1<secp256k1::All>,
1487+
) -> PublicKey {
1488+
self.funding_key(Some(splice_parent_funding_txid)).public_key(secp_ctx)
1489+
}
1490+
14871491
fn channel_keys_id(&self) -> [u8; 32] {
14881492
self.channel_keys_id
14891493
}

0 commit comments

Comments
 (0)