mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-03-13 14:52:21 +01:00
Merge pull request #3624 from wpaulino/funding-key-tweak
Support scalar tweak to rotate holder funding key during splicing
This commit is contained in:
commit
f25709cc79
11 changed files with 241 additions and 63 deletions
|
@ -1359,8 +1359,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
|
|||
) -> ChannelMonitor<Signer> {
|
||||
|
||||
assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
|
||||
let holder_pubkeys = &channel_parameters.holder_pubkeys;
|
||||
let counterparty_payment_script = chan_utils::get_counterparty_payment_script(
|
||||
&channel_parameters.channel_type_features, &keys.pubkeys().payment_point
|
||||
&channel_parameters.channel_type_features, &holder_pubkeys.payment_point
|
||||
);
|
||||
|
||||
let counterparty_channel_parameters = channel_parameters.counterparty_parameters.as_ref().unwrap();
|
||||
|
@ -1369,7 +1370,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
|
|||
let counterparty_commitment_params = CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key, counterparty_htlc_base_key, on_counterparty_tx_csv };
|
||||
|
||||
let channel_keys_id = keys.channel_keys_id();
|
||||
let holder_revocation_basepoint = keys.pubkeys().revocation_basepoint;
|
||||
let holder_revocation_basepoint = holder_pubkeys.revocation_basepoint;
|
||||
|
||||
// block for Rust 1.34 compat
|
||||
let (holder_commitment_tx, current_holder_commitment_number) = {
|
||||
|
@ -5417,6 +5418,7 @@ mod tests {
|
|||
selected_contest_delay: 67,
|
||||
}),
|
||||
funding_outpoint: Some(funding_outpoint),
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
|
||||
channel_value_satoshis: 0,
|
||||
};
|
||||
|
@ -5669,6 +5671,7 @@ mod tests {
|
|||
selected_contest_delay: 67,
|
||||
}),
|
||||
funding_outpoint: Some(funding_outpoint),
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
|
||||
channel_value_satoshis: 0,
|
||||
};
|
||||
|
|
|
@ -1352,6 +1352,7 @@ mod tests {
|
|||
selected_contest_delay: 67,
|
||||
}),
|
||||
funding_outpoint: Some(funding_outpoint),
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
|
||||
channel_value_satoshis: 0,
|
||||
};
|
||||
|
|
|
@ -605,7 +605,20 @@ impl PackageSolvingData {
|
|||
let channel_parameters = &onchain_handler.channel_transaction_parameters;
|
||||
match self {
|
||||
PackageSolvingData::RevokedOutput(ref outp) => {
|
||||
let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
|
||||
let directed_parameters =
|
||||
&onchain_handler.channel_transaction_parameters.as_counterparty_broadcastable();
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint,
|
||||
outp.counterparty_delayed_payment_base_key,
|
||||
);
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().htlc_basepoint,
|
||||
outp.counterparty_htlc_base_key,
|
||||
);
|
||||
let chan_keys = TxCreationKeys::from_channel_static_keys(
|
||||
&outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(),
|
||||
directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx,
|
||||
);
|
||||
let witness_script = chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key);
|
||||
//TODO: should we panic on signer failure ?
|
||||
if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output(channel_parameters, &bumped_tx, i, outp.amount.to_sat(), &outp.per_commitment_key, &onchain_handler.secp_ctx) {
|
||||
|
@ -617,7 +630,20 @@ impl PackageSolvingData {
|
|||
} else { return false; }
|
||||
},
|
||||
PackageSolvingData::RevokedHTLCOutput(ref outp) => {
|
||||
let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
|
||||
let directed_parameters =
|
||||
&onchain_handler.channel_transaction_parameters.as_counterparty_broadcastable();
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint,
|
||||
outp.counterparty_delayed_payment_base_key,
|
||||
);
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().htlc_basepoint,
|
||||
outp.counterparty_htlc_base_key,
|
||||
);
|
||||
let chan_keys = TxCreationKeys::from_channel_static_keys(
|
||||
&outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(),
|
||||
directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx,
|
||||
);
|
||||
let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &onchain_handler.channel_type_features(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
|
||||
//TODO: should we panic on signer failure ?
|
||||
if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_htlc(channel_parameters, &bumped_tx, i, outp.amount, &outp.per_commitment_key, &outp.htlc, &onchain_handler.secp_ctx) {
|
||||
|
@ -629,7 +655,20 @@ impl PackageSolvingData {
|
|||
} else { return false; }
|
||||
},
|
||||
PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => {
|
||||
let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
|
||||
let directed_parameters =
|
||||
&onchain_handler.channel_transaction_parameters.as_counterparty_broadcastable();
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint,
|
||||
outp.counterparty_delayed_payment_base_key,
|
||||
);
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().htlc_basepoint,
|
||||
outp.counterparty_htlc_base_key,
|
||||
);
|
||||
let chan_keys = TxCreationKeys::from_channel_static_keys(
|
||||
&outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(),
|
||||
directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx,
|
||||
);
|
||||
let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &onchain_handler.channel_type_features(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
|
||||
|
||||
if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(channel_parameters, &bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) {
|
||||
|
@ -641,7 +680,20 @@ impl PackageSolvingData {
|
|||
}
|
||||
},
|
||||
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => {
|
||||
let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint);
|
||||
let directed_parameters =
|
||||
&onchain_handler.channel_transaction_parameters.as_counterparty_broadcastable();
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint,
|
||||
outp.counterparty_delayed_payment_base_key,
|
||||
);
|
||||
debug_assert_eq!(
|
||||
directed_parameters.broadcaster_pubkeys().htlc_basepoint,
|
||||
outp.counterparty_htlc_base_key,
|
||||
);
|
||||
let chan_keys = TxCreationKeys::from_channel_static_keys(
|
||||
&outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(),
|
||||
directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx,
|
||||
);
|
||||
let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &onchain_handler.channel_type_features(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
|
||||
|
||||
if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(channel_parameters, &bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) {
|
||||
|
|
|
@ -880,6 +880,17 @@ pub struct ChannelTransactionParameters {
|
|||
pub counterparty_parameters: Option<CounterpartyChannelTransactionParameters>,
|
||||
/// The late-bound funding outpoint
|
||||
pub funding_outpoint: Option<chain::transaction::OutPoint>,
|
||||
/// The parent funding txid for a channel that has been spliced.
|
||||
///
|
||||
/// If a channel was funded with transaction A, and later spliced with transaction B, this field
|
||||
/// tracks the txid of transaction A.
|
||||
///
|
||||
/// See [`compute_funding_key_tweak`] and [`ChannelSigner::pubkeys`] for more context on how
|
||||
/// this may be used.
|
||||
///
|
||||
/// [`compute_funding_key_tweak`]: crate::sign::compute_funding_key_tweak
|
||||
/// [`ChannelSigner::pubkeys`]: crate::sign::ChannelSigner::pubkeys
|
||||
pub splice_parent_funding_txid: Option<Txid>,
|
||||
/// This channel's type, as negotiated during channel open. For old objects where this field
|
||||
/// wasn't serialized, it will default to static_remote_key at deserialization.
|
||||
pub channel_type_features: ChannelTypeFeatures,
|
||||
|
@ -963,6 +974,7 @@ impl ChannelTransactionParameters {
|
|||
funding_outpoint: Some(chain::transaction::OutPoint {
|
||||
txid: Txid::from_byte_array([42; 32]), index: 0
|
||||
}),
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: ChannelTypeFeatures::empty(),
|
||||
channel_value_satoshis,
|
||||
}
|
||||
|
@ -985,6 +997,7 @@ impl Writeable for ChannelTransactionParameters {
|
|||
(8, self.funding_outpoint, option),
|
||||
(10, legacy_deserialization_prevention_marker, option),
|
||||
(11, self.channel_type_features, required),
|
||||
(12, self.splice_parent_funding_txid, option),
|
||||
(13, self.channel_value_satoshis, required),
|
||||
});
|
||||
Ok(())
|
||||
|
@ -998,6 +1011,7 @@ impl ReadableArgs<u64> for ChannelTransactionParameters {
|
|||
let mut is_outbound_from_holder = RequiredWrapper(None);
|
||||
let mut counterparty_parameters = None;
|
||||
let mut funding_outpoint = None;
|
||||
let mut splice_parent_funding_txid = None;
|
||||
let mut _legacy_deserialization_prevention_marker: Option<()> = None;
|
||||
let mut channel_type_features = None;
|
||||
let mut channel_value_satoshis = None;
|
||||
|
@ -1010,6 +1024,7 @@ impl ReadableArgs<u64> for ChannelTransactionParameters {
|
|||
(8, funding_outpoint, option),
|
||||
(10, _legacy_deserialization_prevention_marker, option),
|
||||
(11, channel_type_features, option),
|
||||
(12, splice_parent_funding_txid, option),
|
||||
(13, channel_value_satoshis, option),
|
||||
});
|
||||
|
||||
|
@ -1028,6 +1043,7 @@ impl ReadableArgs<u64> for ChannelTransactionParameters {
|
|||
is_outbound_from_holder: is_outbound_from_holder.0.unwrap(),
|
||||
counterparty_parameters,
|
||||
funding_outpoint,
|
||||
splice_parent_funding_txid,
|
||||
channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key()),
|
||||
channel_value_satoshis,
|
||||
})
|
||||
|
@ -1154,6 +1170,7 @@ impl HolderCommitmentTransaction {
|
|||
is_outbound_from_holder: false,
|
||||
counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: channel_pubkeys.clone(), selected_contest_delay: 0 }),
|
||||
funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }),
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
|
||||
channel_value_satoshis,
|
||||
};
|
||||
|
@ -1953,22 +1970,25 @@ mod tests {
|
|||
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
|
||||
let signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(false, 0));
|
||||
let counterparty_signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(true, 1));
|
||||
let delayed_payment_base = &signer.pubkeys().delayed_payment_basepoint;
|
||||
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
|
||||
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
|
||||
let htlc_basepoint = &signer.pubkeys().htlc_basepoint;
|
||||
let holder_pubkeys = signer.pubkeys();
|
||||
let counterparty_pubkeys = counterparty_signer.pubkeys().clone();
|
||||
let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint);
|
||||
let holder_pubkeys = signer.pubkeys(None, &secp_ctx);
|
||||
let counterparty_pubkeys = counterparty_signer.pubkeys(None, &secp_ctx).clone();
|
||||
let channel_parameters = ChannelTransactionParameters {
|
||||
holder_pubkeys: holder_pubkeys.clone(),
|
||||
holder_selected_contest_delay: 0,
|
||||
is_outbound_from_holder: false,
|
||||
counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), selected_contest_delay: 0 }),
|
||||
funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }),
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
|
||||
channel_value_satoshis: 3000,
|
||||
};
|
||||
let directed_parameters = channel_parameters.as_holder_broadcastable();
|
||||
let keys = TxCreationKeys::from_channel_static_keys(
|
||||
&per_commitment_point, directed_parameters.broadcaster_pubkeys(),
|
||||
directed_parameters.countersignatory_pubkeys(), &secp_ctx,
|
||||
);
|
||||
let htlcs_with_aux = Vec::new();
|
||||
|
||||
Self {
|
||||
|
|
|
@ -2411,7 +2411,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
|
||||
let channel_keys_id = signer_provider.generate_channel_keys_id(true, user_id);
|
||||
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
|
||||
let pubkeys = holder_signer.pubkeys().clone();
|
||||
|
||||
if config.channel_handshake_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
|
||||
return Err(ChannelError::close(format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks. It must be greater than {}", config.channel_handshake_config.our_to_self_delay, BREAKDOWN_TIMEOUT)));
|
||||
|
@ -2571,6 +2570,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
|
||||
// TODO(dual_funding): Checks for `funding_feerate_sat_per_1000_weight`?
|
||||
|
||||
let pubkeys = holder_signer.pubkeys(None, &secp_ctx);
|
||||
|
||||
let funding = FundingScope {
|
||||
value_to_self_msat,
|
||||
counterparty_selected_channel_reserve_satoshis: Some(msg_channel_reserve_satoshis),
|
||||
|
@ -2595,6 +2596,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
pubkeys: counterparty_pubkeys,
|
||||
}),
|
||||
funding_outpoint: None,
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: channel_type.clone(),
|
||||
channel_value_satoshis,
|
||||
},
|
||||
|
@ -2734,11 +2736,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
config: &'a UserConfig,
|
||||
current_chain_height: u32,
|
||||
outbound_scid_alias: u64,
|
||||
temporary_channel_id: Option<ChannelId>,
|
||||
temporary_channel_id_fn: Option<impl Fn(&ChannelPublicKeys) -> ChannelId>,
|
||||
holder_selected_channel_reserve_satoshis: u64,
|
||||
channel_keys_id: [u8; 32],
|
||||
holder_signer: <SP::Target as SignerProvider>::EcdsaSigner,
|
||||
pubkeys: ChannelPublicKeys,
|
||||
_logger: L,
|
||||
) -> Result<(FundingScope, ChannelContext<SP>), APIError>
|
||||
where
|
||||
|
@ -2804,7 +2805,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
Err(_) => return Err(APIError::ChannelUnavailable { err: "Failed to get destination script".to_owned()}),
|
||||
};
|
||||
|
||||
let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
|
||||
let pubkeys = holder_signer.pubkeys(None, &secp_ctx);
|
||||
let temporary_channel_id = temporary_channel_id_fn.map(|f| f(&pubkeys))
|
||||
.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
|
||||
|
||||
let funding = FundingScope {
|
||||
value_to_self_msat,
|
||||
|
@ -2829,6 +2832,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
|
|||
is_outbound_from_holder: true,
|
||||
counterparty_parameters: None,
|
||||
funding_outpoint: None,
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features: channel_type.clone(),
|
||||
// We'll add our counterparty's `funding_satoshis` when we receive `accept_channel2`.
|
||||
channel_value_satoshis,
|
||||
|
@ -8161,7 +8165,9 @@ impl<SP: Deref> FundedChannel<SP> where
|
|||
};
|
||||
match &self.context.holder_signer {
|
||||
ChannelSignerType::Ecdsa(ecdsa) => {
|
||||
let our_bitcoin_sig = match ecdsa.sign_channel_announcement_with_funding_key(&announcement, &self.context.secp_ctx) {
|
||||
let our_bitcoin_sig = match ecdsa.sign_channel_announcement_with_funding_key(
|
||||
&self.funding.channel_transaction_parameters, &announcement, &self.context.secp_ctx,
|
||||
) {
|
||||
Err(_) => {
|
||||
log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!");
|
||||
return None;
|
||||
|
@ -8202,7 +8208,9 @@ impl<SP: Deref> FundedChannel<SP> where
|
|||
.map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?;
|
||||
match &self.context.holder_signer {
|
||||
ChannelSignerType::Ecdsa(ecdsa) => {
|
||||
let our_bitcoin_sig = ecdsa.sign_channel_announcement_with_funding_key(&announcement, &self.context.secp_ctx)
|
||||
let our_bitcoin_sig = ecdsa.sign_channel_announcement_with_funding_key(
|
||||
&self.funding.channel_transaction_parameters, &announcement, &self.context.secp_ctx,
|
||||
)
|
||||
.map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?;
|
||||
Ok(msgs::ChannelAnnouncement {
|
||||
node_signature_1: if were_node_one { our_node_sig } else { their_node_sig },
|
||||
|
@ -9008,7 +9016,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
|
|||
|
||||
let channel_keys_id = signer_provider.generate_channel_keys_id(false, user_id);
|
||||
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
|
||||
let pubkeys = holder_signer.pubkeys().clone();
|
||||
|
||||
let temporary_channel_id_fn = temporary_channel_id.map(|id| {
|
||||
move |_: &ChannelPublicKeys| id
|
||||
});
|
||||
|
||||
let (funding, context) = ChannelContext::new_for_outbound_channel(
|
||||
fee_estimator,
|
||||
|
@ -9022,11 +9033,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
|
|||
config,
|
||||
current_chain_height,
|
||||
outbound_scid_alias,
|
||||
temporary_channel_id,
|
||||
temporary_channel_id_fn,
|
||||
holder_selected_channel_reserve_satoshis,
|
||||
channel_keys_id,
|
||||
holder_signer,
|
||||
pubkeys,
|
||||
logger,
|
||||
)?;
|
||||
let unfunded_context = UnfundedChannelContext {
|
||||
|
@ -9565,9 +9575,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
|
|||
{
|
||||
let channel_keys_id = signer_provider.generate_channel_keys_id(false, user_id);
|
||||
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
|
||||
let pubkeys = holder_signer.pubkeys().clone();
|
||||
|
||||
let temporary_channel_id = Some(ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint));
|
||||
let temporary_channel_id_fn = Some(|pubkeys: &ChannelPublicKeys| {
|
||||
ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint)
|
||||
});
|
||||
|
||||
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
|
||||
funding_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
|
||||
|
@ -9591,11 +9602,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
|
|||
config,
|
||||
current_chain_height,
|
||||
outbound_scid_alias,
|
||||
temporary_channel_id,
|
||||
temporary_channel_id_fn,
|
||||
holder_selected_channel_reserve_satoshis,
|
||||
channel_keys_id,
|
||||
holder_signer,
|
||||
pubkeys,
|
||||
logger,
|
||||
)?;
|
||||
let unfunded_context = UnfundedChannelContext {
|
||||
|
@ -11597,7 +11607,8 @@ mod tests {
|
|||
[0; 32],
|
||||
);
|
||||
|
||||
assert_eq!(signer.pubkeys().funding_pubkey.serialize()[..],
|
||||
let holder_pubkeys = signer.pubkeys(None, &secp_ctx);
|
||||
assert_eq!(holder_pubkeys.funding_pubkey.serialize()[..],
|
||||
<Vec<u8>>::from_hex("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
|
||||
let keys_provider = Keys { signer: signer.clone() };
|
||||
|
||||
|
@ -11636,11 +11647,13 @@ mod tests {
|
|||
// We can't just use build_holder_transaction_keys here as the per_commitment_secret is not
|
||||
// derived from a commitment_seed, so instead we copy it here and call
|
||||
// build_commitment_transaction.
|
||||
let delayed_payment_base = &chan.context.holder_signer.as_ref().pubkeys().delayed_payment_basepoint;
|
||||
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
|
||||
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
|
||||
let htlc_basepoint = &chan.context.holder_signer.as_ref().pubkeys().htlc_basepoint;
|
||||
let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint);
|
||||
let directed_params = chan.funding.channel_transaction_parameters.as_holder_broadcastable();
|
||||
let keys = TxCreationKeys::from_channel_static_keys(
|
||||
&per_commitment_point, directed_params.broadcaster_pubkeys(),
|
||||
directed_params.countersignatory_pubkeys(), &secp_ctx,
|
||||
);
|
||||
|
||||
macro_rules! test_commitment {
|
||||
( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $($remain:tt)* ) => {
|
||||
|
@ -11691,7 +11704,7 @@ mod tests {
|
|||
commitment_tx.clone(),
|
||||
counterparty_signature,
|
||||
counterparty_htlc_sigs,
|
||||
&chan.context.holder_signer.as_ref().pubkeys().funding_pubkey,
|
||||
&holder_pubkeys.funding_pubkey,
|
||||
chan.funding.counterparty_funding_pubkey()
|
||||
);
|
||||
let holder_sig = signer.sign_holder_commitment(&chan.funding.channel_transaction_parameters, &holder_commitment_tx, &secp_ctx).unwrap();
|
||||
|
|
|
@ -169,6 +169,7 @@ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession)
|
|||
holder_selected_contest_delay: open_channel_v2_msg.common_fields.to_self_delay,
|
||||
is_outbound_from_holder: true,
|
||||
funding_outpoint,
|
||||
splice_parent_funding_txid: None,
|
||||
channel_type_features,
|
||||
channel_value_satoshis: funding_satoshis,
|
||||
};
|
||||
|
|
|
@ -737,7 +737,7 @@ pub fn test_update_fee_that_funder_cannot_afford() {
|
|||
let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
|
||||
let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
|
||||
let chan_signer = local_chan.get_signer();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
|
||||
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
|
||||
pubkeys.funding_pubkey)
|
||||
};
|
||||
|
@ -746,7 +746,7 @@ pub fn test_update_fee_that_funder_cannot_afford() {
|
|||
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
|
||||
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
|
||||
let chan_signer = remote_chan.get_signer();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
|
||||
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
|
||||
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap(),
|
||||
pubkeys.funding_pubkey)
|
||||
|
@ -1468,21 +1468,21 @@ pub fn test_fee_spike_violation_fails_htlc() {
|
|||
// Make the signer believe we validated another commitment, so we can release the secret
|
||||
chan_signer.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1;
|
||||
|
||||
let pubkeys = chan_signer.as_ref().pubkeys();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
|
||||
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
|
||||
chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
|
||||
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap(),
|
||||
chan_signer.as_ref().pubkeys().funding_pubkey)
|
||||
chan_signer.as_ref().pubkeys(None, &secp_ctx).funding_pubkey)
|
||||
};
|
||||
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point, remote_funding) = {
|
||||
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
|
||||
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
|
||||
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
|
||||
let chan_signer = remote_chan.get_signer();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys();
|
||||
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
|
||||
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
|
||||
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap(),
|
||||
chan_signer.as_ref().pubkeys().funding_pubkey)
|
||||
chan_signer.as_ref().pubkeys(None, &secp_ctx).funding_pubkey)
|
||||
};
|
||||
|
||||
// Assemble the set of keys we can use for signatures for our commitment_signed message.
|
||||
|
|
|
@ -238,7 +238,8 @@ pub trait EcdsaChannelSigner: ChannelSigner {
|
|||
///
|
||||
/// [`NodeSigner::sign_gossip_message`]: crate::sign::NodeSigner::sign_gossip_message
|
||||
fn sign_channel_announcement_with_funding_key(
|
||||
&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
&self, channel_parameters: &ChannelTransactionParameters,
|
||||
msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
) -> Result<Signature, ()>;
|
||||
|
||||
/// Signs the input of a splicing funding transaction with our funding key.
|
||||
|
|
|
@ -774,8 +774,14 @@ pub trait ChannelSigner {
|
|||
|
||||
/// Returns the holder's channel public keys and basepoints.
|
||||
///
|
||||
/// `splice_parent_funding_txid` can be used to compute a tweak to rotate the funding key in the
|
||||
/// 2-of-2 multisig script during a splice. See [`compute_funding_key_tweak`] for an example
|
||||
/// tweak and more details.
|
||||
///
|
||||
/// This method is *not* asynchronous. Instead, the value must be cached locally.
|
||||
fn pubkeys(&self) -> &ChannelPublicKeys;
|
||||
fn pubkeys(
|
||||
&self, splice_parent_funding_txid: Option<Txid>, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
) -> ChannelPublicKeys;
|
||||
|
||||
/// Returns an arbitrary identifier describing the set of keys which are provided back to you in
|
||||
/// some [`SpendableOutputDescriptor`] types. This should be sufficient to identify this
|
||||
|
@ -977,6 +983,56 @@ pub trait ChangeDestinationSource {
|
|||
fn get_change_destination_script(&self) -> Result<ScriptBuf, ()>;
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
use bitcoin::secp256k1::{Scalar, SecretKey};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct MaybeTweakedSecretKey(SecretKey);
|
||||
|
||||
impl From<SecretKey> for MaybeTweakedSecretKey {
|
||||
fn from(value: SecretKey) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl MaybeTweakedSecretKey {
|
||||
pub fn with_tweak(&self, tweak: Option<Scalar>) -> SecretKey {
|
||||
tweak
|
||||
.map(|tweak| {
|
||||
self.0
|
||||
.add_tweak(&tweak)
|
||||
.expect("Addition only fails if the tweak is the inverse of the key")
|
||||
})
|
||||
.unwrap_or(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the tweak to apply to the base funding key of a channel.
|
||||
///
|
||||
/// The tweak is computed similar to existing tweaks used in
|
||||
/// [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation):
|
||||
///
|
||||
/// 1. We use the txid of the funding transaction the splice transaction is spending instead of the
|
||||
/// `per_commitment_point` to guarantee uniqueness.
|
||||
/// 2. We include the private key instead of the public key to guarantee only those with knowledge
|
||||
/// of it can re-derive the new funding key.
|
||||
///
|
||||
/// tweak = SHA256(splice_parent_funding_txid || base_funding_secret_key)
|
||||
/// tweaked_funding_key = base_funding_key + tweak
|
||||
///
|
||||
/// While the use of this tweak is not required (signers may choose to compute a tweak of their
|
||||
/// choice), signers must ensure their tweak guarantees the two properties mentioned above:
|
||||
/// uniqueness and derivable only by one or both of the channel participants.
|
||||
pub fn compute_funding_key_tweak(
|
||||
base_funding_secret_key: &SecretKey, splice_parent_funding_txid: &Txid,
|
||||
) -> Scalar {
|
||||
let mut sha = Sha256::engine();
|
||||
sha.input(splice_parent_funding_txid.as_byte_array());
|
||||
sha.input(&base_funding_secret_key.secret_bytes());
|
||||
Scalar::from_be_bytes(Sha256::from_engine(sha).to_byte_array()).unwrap()
|
||||
}
|
||||
|
||||
/// A simple implementation of [`EcdsaChannelSigner`] that just keeps the private keys in memory.
|
||||
///
|
||||
/// This implementation performs no policy checks and is insufficient by itself as
|
||||
|
@ -984,7 +1040,7 @@ pub trait ChangeDestinationSource {
|
|||
pub struct InMemorySigner {
|
||||
/// Holder secret key in the 2-of-2 multisig script of a channel. This key also backs the
|
||||
/// holder's anchor output in a commitment transaction, if one is present.
|
||||
pub funding_key: SecretKey,
|
||||
funding_key: sealed::MaybeTweakedSecretKey,
|
||||
/// Holder secret key for blinded revocation pubkey.
|
||||
pub revocation_base_key: SecretKey,
|
||||
/// Holder secret key used for our balance in counterparty-broadcasted commitment transactions.
|
||||
|
@ -1048,7 +1104,7 @@ impl InMemorySigner {
|
|||
&htlc_base_key,
|
||||
);
|
||||
InMemorySigner {
|
||||
funding_key,
|
||||
funding_key: sealed::MaybeTweakedSecretKey::from(funding_key),
|
||||
revocation_base_key,
|
||||
payment_key,
|
||||
delayed_payment_base_key,
|
||||
|
@ -1060,6 +1116,14 @@ impl InMemorySigner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Holder secret key in the 2-of-2 multisig script of a channel. This key also backs the
|
||||
/// holder's anchor output in a commitment transaction, if one is present.
|
||||
pub fn funding_key(&self, splice_parent_funding_txid: Option<Txid>) -> SecretKey {
|
||||
let tweak = splice_parent_funding_txid
|
||||
.map(|txid| compute_funding_key_tweak(&self.funding_key.with_tweak(None), &txid));
|
||||
self.funding_key.with_tweak(tweak)
|
||||
}
|
||||
|
||||
fn make_holder_keys<C: Signing>(
|
||||
secp_ctx: &Secp256k1<C>, funding_key: &SecretKey, revocation_base_key: &SecretKey,
|
||||
payment_key: &SecretKey, delayed_payment_base_key: &SecretKey, htlc_base_key: &SecretKey,
|
||||
|
@ -1103,7 +1167,7 @@ impl InMemorySigner {
|
|||
return Err(());
|
||||
}
|
||||
|
||||
let remotepubkey = bitcoin::PublicKey::new(self.pubkeys().payment_point);
|
||||
let remotepubkey = bitcoin::PublicKey::new(self.holder_channel_pubkeys.payment_point);
|
||||
let supports_anchors_zero_fee_htlc_tx = descriptor
|
||||
.channel_transaction_parameters
|
||||
.as_ref()
|
||||
|
@ -1251,8 +1315,15 @@ impl ChannelSigner for InMemorySigner {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn pubkeys(&self) -> &ChannelPublicKeys {
|
||||
&self.holder_channel_pubkeys
|
||||
fn pubkeys(
|
||||
&self, splice_parent_funding_txid: Option<Txid>, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
) -> ChannelPublicKeys {
|
||||
let mut pubkeys = self.holder_channel_pubkeys.clone();
|
||||
if splice_parent_funding_txid.is_some() {
|
||||
pubkeys.funding_pubkey =
|
||||
self.funding_key(splice_parent_funding_txid).public_key(secp_ctx);
|
||||
}
|
||||
pubkeys
|
||||
}
|
||||
|
||||
fn channel_keys_id(&self) -> [u8; 32] {
|
||||
|
@ -1274,7 +1345,8 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
let trusted_tx = commitment_tx.trust();
|
||||
let keys = trusted_tx.keys();
|
||||
|
||||
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
let funding_pubkey = funding_key.public_key(secp_ctx);
|
||||
let counterparty_keys =
|
||||
channel_parameters.counterparty_pubkeys().expect(MISSING_PARAMS_ERR);
|
||||
let channel_funding_redeemscript =
|
||||
|
@ -1282,7 +1354,7 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
|
||||
let built_tx = trusted_tx.built_transaction();
|
||||
let commitment_sig = built_tx.sign_counterparty_commitment(
|
||||
&self.funding_key,
|
||||
&funding_key,
|
||||
&channel_funding_redeemscript,
|
||||
channel_parameters.channel_value_satoshis,
|
||||
secp_ctx,
|
||||
|
@ -1335,14 +1407,15 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
) -> Result<Signature, ()> {
|
||||
assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
|
||||
|
||||
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
let funding_pubkey = funding_key.public_key(secp_ctx);
|
||||
let counterparty_keys =
|
||||
channel_parameters.counterparty_pubkeys().expect(MISSING_PARAMS_ERR);
|
||||
let funding_redeemscript =
|
||||
make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey);
|
||||
let trusted_tx = commitment_tx.trust();
|
||||
Ok(trusted_tx.built_transaction().sign_holder_commitment(
|
||||
&self.funding_key,
|
||||
&funding_key,
|
||||
&funding_redeemscript,
|
||||
channel_parameters.channel_value_satoshis,
|
||||
&self,
|
||||
|
@ -1357,14 +1430,15 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
) -> Result<Signature, ()> {
|
||||
assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
|
||||
|
||||
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
let funding_pubkey = funding_key.public_key(secp_ctx);
|
||||
let counterparty_keys =
|
||||
channel_parameters.counterparty_pubkeys().expect(MISSING_PARAMS_ERR);
|
||||
let funding_redeemscript =
|
||||
make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey);
|
||||
let trusted_tx = commitment_tx.trust();
|
||||
Ok(trusted_tx.built_transaction().sign_holder_commitment(
|
||||
&self.funding_key,
|
||||
&funding_key,
|
||||
&funding_redeemscript,
|
||||
channel_parameters.channel_value_satoshis,
|
||||
&self,
|
||||
|
@ -1549,13 +1623,14 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
) -> Result<Signature, ()> {
|
||||
assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
|
||||
|
||||
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
let funding_pubkey = funding_key.public_key(secp_ctx);
|
||||
let counterparty_funding_key =
|
||||
&channel_parameters.counterparty_pubkeys().expect(MISSING_PARAMS_ERR).funding_pubkey;
|
||||
let channel_funding_redeemscript =
|
||||
make_funding_redeemscript(&funding_pubkey, counterparty_funding_key);
|
||||
Ok(closing_tx.trust().sign(
|
||||
&self.funding_key,
|
||||
&funding_key,
|
||||
&channel_funding_redeemscript,
|
||||
channel_parameters.channel_value_satoshis,
|
||||
secp_ctx,
|
||||
|
@ -1578,14 +1653,17 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
EcdsaSighashType::All,
|
||||
)
|
||||
.unwrap();
|
||||
Ok(sign_with_aux_rand(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key, &self))
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
Ok(sign_with_aux_rand(secp_ctx, &hash_to_message!(&sighash[..]), &funding_key, &self))
|
||||
}
|
||||
|
||||
fn sign_channel_announcement_with_funding_key(
|
||||
&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
&self, channel_parameters: &ChannelTransactionParameters,
|
||||
msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
) -> Result<Signature, ()> {
|
||||
let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
|
||||
Ok(secp_ctx.sign_ecdsa(&msghash, &self.funding_key))
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
Ok(secp_ctx.sign_ecdsa(&msghash, &funding_key))
|
||||
}
|
||||
|
||||
fn sign_splicing_funding_input(
|
||||
|
@ -1594,7 +1672,8 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
) -> Result<Signature, ()> {
|
||||
assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
|
||||
|
||||
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
|
||||
let funding_key = self.funding_key(channel_parameters.splice_parent_funding_txid);
|
||||
let funding_pubkey = funding_key.public_key(secp_ctx);
|
||||
let counterparty_funding_key =
|
||||
&channel_parameters.counterparty_pubkeys().expect(MISSING_PARAMS_ERR).funding_pubkey;
|
||||
let funding_redeemscript =
|
||||
|
@ -1608,7 +1687,7 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
)
|
||||
.unwrap()[..];
|
||||
let msg = hash_to_message!(sighash);
|
||||
Ok(sign(secp_ctx, &msg, &self.funding_key))
|
||||
Ok(sign(secp_ctx, &msg, &funding_key))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::sign::{NodeSigner, Recipient, SignerProvider, SpendableOutputDescript
|
|||
use bitcoin;
|
||||
use bitcoin::absolute::LockTime;
|
||||
use bitcoin::secp256k1::All;
|
||||
use bitcoin::{secp256k1, ScriptBuf, Transaction, TxOut};
|
||||
use bitcoin::{secp256k1, ScriptBuf, Transaction, TxOut, Txid};
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
#[cfg(taproot)]
|
||||
use musig2::types::{PartialSignature, PublicNonce};
|
||||
|
@ -154,8 +154,10 @@ delegate!(DynSigner, EcdsaChannelSigner, inner,
|
|||
htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_closing_transaction(, channel_parameters: &ChannelTransactionParameters,
|
||||
closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_channel_announcement_with_funding_key(, msg: &UnsignedChannelAnnouncement,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_channel_announcement_with_funding_key(,
|
||||
channel_parameters: &ChannelTransactionParameters, msg: &UnsignedChannelAnnouncement,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>
|
||||
) -> Result<Signature, ()>,
|
||||
fn sign_holder_anchor_input(, channel_parameters: &ChannelTransactionParameters,
|
||||
anchor_tx: &Transaction, input: usize,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
|
@ -177,7 +179,9 @@ delegate!(DynSigner, ChannelSigner,
|
|||
holder_tx: &HolderCommitmentTransaction,
|
||||
preimages: Vec<PaymentPreimage>
|
||||
) -> Result<(), ()>,
|
||||
fn pubkeys(,) -> &ChannelPublicKeys,
|
||||
fn pubkeys(,
|
||||
splice_parent_funding_txid: Option<Txid>, secp_ctx: &Secp256k1<secp256k1::All>
|
||||
) -> ChannelPublicKeys,
|
||||
fn channel_keys_id(,) -> [u8; 32],
|
||||
fn validate_counterparty_revocation(, idx: u64, secret: &SecretKey) -> Result<(), ()>
|
||||
);
|
||||
|
|
|
@ -30,6 +30,7 @@ use bitcoin::hashes::Hash;
|
|||
use bitcoin::sighash;
|
||||
use bitcoin::sighash::EcdsaSighashType;
|
||||
use bitcoin::transaction::Transaction;
|
||||
use bitcoin::Txid;
|
||||
|
||||
#[cfg(taproot)]
|
||||
use crate::ln::msgs::PartialSignatureWithNonce;
|
||||
|
@ -210,8 +211,10 @@ impl ChannelSigner for TestChannelSigner {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn pubkeys(&self) -> &ChannelPublicKeys {
|
||||
self.inner.pubkeys()
|
||||
fn pubkeys(
|
||||
&self, splice_parent_funding_txid: Option<Txid>, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
) -> ChannelPublicKeys {
|
||||
self.inner.pubkeys(splice_parent_funding_txid, secp_ctx)
|
||||
}
|
||||
|
||||
fn channel_keys_id(&self) -> [u8; 32] {
|
||||
|
@ -467,9 +470,10 @@ impl EcdsaChannelSigner for TestChannelSigner {
|
|||
}
|
||||
|
||||
fn sign_channel_announcement_with_funding_key(
|
||||
&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
&self, channel_parameters: &ChannelTransactionParameters,
|
||||
msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
) -> Result<Signature, ()> {
|
||||
self.inner.sign_channel_announcement_with_funding_key(msg, secp_ctx)
|
||||
self.inner.sign_channel_announcement_with_funding_key(channel_parameters, msg, secp_ctx)
|
||||
}
|
||||
|
||||
fn sign_splicing_funding_input(
|
||||
|
|
Loading…
Add table
Reference in a new issue