use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
use crate::ln::{PaymentHash, PaymentPreimage};
use crate::ln::msgs::DecodeError;
-use crate::ln::chan_utils;
-use crate::ln::chan_utils::{CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys};
+use crate::ln::channel_keys::{DelayedPaymentKey, DelayedPaymentBasepoint, HtlcBasepoint, HtlcKey, RevocationKey, RevocationBasepoint};
+use crate::ln::chan_utils::{self,CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys};
use crate::ln::channelmanager::{HTLCSource, SentHTLCId};
use crate::chain;
use crate::chain::{BestBlock, WatchedOutput};
struct HolderSignedTx {
/// txid of the transaction in tx, just used to make comparison faster
txid: Txid,
- revocation_key: PublicKey,
- a_htlc_key: PublicKey,
- b_htlc_key: PublicKey,
- delayed_payment_key: PublicKey,
+ revocation_key: RevocationKey,
+ a_htlc_key: HtlcKey,
+ b_htlc_key: HtlcKey,
+ delayed_payment_key: DelayedPaymentKey,
per_commitment_point: PublicKey,
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
to_self_value_sat: u64,
/// justice or 2nd-stage preimage/timeout transactions.
#[derive(Clone, PartialEq, Eq)]
struct CounterpartyCommitmentParameters {
- counterparty_delayed_payment_base_key: PublicKey,
- counterparty_htlc_base_key: PublicKey,
+ counterparty_delayed_payment_base_key: DelayedPaymentBasepoint,
+ counterparty_htlc_base_key: HtlcBasepoint,
on_counterparty_tx_csv: u16,
}
commitment_transaction_number_obscure_factor: u64,
destination_script: ScriptBuf,
- broadcasted_holder_revokable_script: Option<(ScriptBuf, PublicKey, PublicKey)>,
+ broadcasted_holder_revokable_script: Option<(ScriptBuf, PublicKey, RevocationKey)>,
counterparty_payment_script: ScriptBuf,
shutdown_script: Option<ScriptBuf>,
channel_keys_id: [u8; 32],
- holder_revocation_basepoint: PublicKey,
+ holder_revocation_basepoint: RevocationBasepoint,
funding_info: (OutPoint, ScriptBuf),
current_counterparty_commitment_txid: Option<Txid>,
prev_counterparty_commitment_txid: Option<Txid>,
let their_per_commitment_point = PublicKey::from_secret_key(
&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
- let revocation_pubkey = chan_utils::derive_public_revocation_key(
- &self.onchain_tx_handler.secp_ctx, &their_per_commitment_point,
- &self.holder_revocation_basepoint);
- let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
- &their_per_commitment_point,
- &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+ let revocation_pubkey = RevocationKey::from_basepoint(&self.onchain_tx_handler.secp_ctx,
+ &self.holder_revocation_basepoint, &their_per_commitment_point);
+ let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx,
+ &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &their_per_commitment_point);
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
let secret = self.get_secret(commitment_number).unwrap();
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
- let revocation_pubkey = chan_utils::derive_public_revocation_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
- let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+ let revocation_pubkey = RevocationKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.holder_revocation_basepoint, &per_commitment_point,);
+ let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key));
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
} else { return (claimable_outpoints, to_counterparty_output_info); };
if let Some(transaction) = tx {
- let revocation_pubkey = chan_utils::derive_public_revocation_key(
- &self.onchain_tx_handler.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
- let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
- &per_commitment_point,
- &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+ let revocation_pubkey = RevocationKey::from_basepoint(
+ &self.onchain_tx_handler.secp_ctx, &self.holder_revocation_basepoint, &per_commitment_point);
+
+ let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &per_commitment_point);
+
let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
self.counterparty_commitment_params.on_counterparty_tx_csv,
&delayed_key).to_v0_p2wsh();
// Returns (1) `PackageTemplate`s that can be given to the OnchainTxHandler, so that the handler can
// broadcast transactions claiming holder HTLC commitment outputs and (2) a holder revokable
// script so we can detect whether a holder transaction has been seen on-chain.
- fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx, conf_height: u32) -> (Vec<PackageTemplate>, Option<(ScriptBuf, PublicKey, PublicKey)>) {
+ fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx, conf_height: u32) -> (Vec<PackageTemplate>, Option<(ScriptBuf, PublicKey, RevocationKey)>) {
let mut claim_requests = Vec::with_capacity(holder_tx.htlc_outputs.len());
let redeemscript = chan_utils::get_revokeable_redeemscript(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key);
per_commitment_point: broadcasted_holder_revokable_script.1,
to_self_delay: self.on_holder_tx_csv,
output: outp.clone(),
- revocation_pubkey: broadcasted_holder_revokable_script.2.clone(),
+ revocation_pubkey: broadcasted_holder_revokable_script.2,
channel_keys_id: self.channel_keys_id,
channel_value_satoshis: self.channel_value_satoshis,
}));
use crate::chain::transaction::OutPoint;
use crate::sign::InMemorySigner;
use crate::ln::{PaymentPreimage, PaymentHash};
- use crate::ln::chan_utils;
- use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
+ use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, RevocationBasepoint, RevocationKey};
+ use crate::ln::chan_utils::{self,HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
use crate::ln::channelmanager::{PaymentSendFailure, PaymentId, RecipientOnionFields};
use crate::ln::functional_test_utils::*;
use crate::ln::script::ShutdownScript;
let counterparty_pubkeys = ChannelPublicKeys {
funding_pubkey: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[44; 32]).unwrap()),
- revocation_basepoint: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()),
+ revocation_basepoint: RevocationBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap())),
payment_point: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap()),
- delayed_payment_basepoint: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[47; 32]).unwrap()),
- htlc_basepoint: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[48; 32]).unwrap())
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[47; 32]).unwrap())),
+ htlc_basepoint: HtlcBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[48; 32]).unwrap()))
};
let funding_outpoint = OutPoint { txid: Txid::all_zeros(), index: u16::max_value() };
let channel_parameters = ChannelTransactionParameters {
let privkey = SecretKey::from_slice(&<Vec<u8>>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
let pubkey = PublicKey::from_secret_key(&secp_ctx, &privkey);
+ use crate::ln::channel_keys::{HtlcKey, HtlcBasepoint};
macro_rules! sign_input {
($sighash_parts: expr, $idx: expr, $amount: expr, $weight: expr, $sum_actual_sigs: expr, $opt_anchors: expr) => {
let htlc = HTLCOutputInCommitment {
payment_hash: PaymentHash([1; 32]),
transaction_output_index: Some($idx as u32),
};
- let redeem_script = if *$weight == WEIGHT_REVOKED_OUTPUT { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, $opt_anchors, &pubkey, &pubkey, &pubkey) };
+ let redeem_script = if *$weight == WEIGHT_REVOKED_OUTPUT { chan_utils::get_revokeable_redeemscript(&RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(pubkey), &pubkey), 256, &DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(pubkey), &pubkey)) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, $opt_anchors, &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), &RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(pubkey), &pubkey)) };
let sighash = hash_to_message!(&$sighash_parts.segwit_signature_hash($idx, &redeem_script, $amount, EcdsaSighashType::All).unwrap()[..]);
let sig = secp_ctx.sign_ecdsa(&sighash, &privkey);
let mut ser_sig = sig.serialize_der().to_vec();
use bitcoin::sighash::EcdsaSighashType;
use crate::ln::PaymentPreimage;
-use crate::ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment};
-use crate::ln::chan_utils;
+use crate::ln::chan_utils::{self, TxCreationKeys, HTLCOutputInCommitment};
use crate::ln::features::ChannelTypeFeatures;
+use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint};
use crate::ln::msgs::DecodeError;
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT, compute_feerate_sat_per_1000_weight, FEERATE_FLOOR_SATS_PER_KW};
use crate::sign::WriteableEcdsaChannelSigner;
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct RevokedOutput {
per_commitment_point: PublicKey,
- counterparty_delayed_payment_base_key: PublicKey,
- counterparty_htlc_base_key: PublicKey,
+ counterparty_delayed_payment_base_key: DelayedPaymentBasepoint,
+ counterparty_htlc_base_key: HtlcBasepoint,
per_commitment_key: SecretKey,
weight: u64,
amount: u64,
}
impl RevokedOutput {
- pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, per_commitment_key: SecretKey, amount: u64, on_counterparty_tx_csv: u16, is_counterparty_balance_on_anchors: bool) -> Self {
+ pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, on_counterparty_tx_csv: u16, is_counterparty_balance_on_anchors: bool) -> Self {
RevokedOutput {
per_commitment_point,
counterparty_delayed_payment_base_key,
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct RevokedHTLCOutput {
per_commitment_point: PublicKey,
- counterparty_delayed_payment_base_key: PublicKey,
- counterparty_htlc_base_key: PublicKey,
+ counterparty_delayed_payment_base_key: DelayedPaymentBasepoint,
+ counterparty_htlc_base_key: HtlcBasepoint,
per_commitment_key: SecretKey,
weight: u64,
amount: u64,
}
impl RevokedHTLCOutput {
- pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, per_commitment_key: SecretKey, amount: u64, htlc: HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures) -> Self {
+ pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, htlc: HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures) -> Self {
let weight = if htlc.offered { weight_revoked_offered_htlc(channel_type_features) } else { weight_revoked_received_htlc(channel_type_features) };
RevokedHTLCOutput {
per_commitment_point,
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct CounterpartyOfferedHTLCOutput {
per_commitment_point: PublicKey,
- counterparty_delayed_payment_base_key: PublicKey,
- counterparty_htlc_base_key: PublicKey,
+ counterparty_delayed_payment_base_key: DelayedPaymentBasepoint,
+ counterparty_htlc_base_key: HtlcBasepoint,
preimage: PaymentPreimage,
htlc: HTLCOutputInCommitment,
channel_type_features: ChannelTypeFeatures,
}
impl CounterpartyOfferedHTLCOutput {
- pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, preimage: PaymentPreimage, htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures) -> Self {
+ pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, preimage: PaymentPreimage, htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures) -> Self {
CounterpartyOfferedHTLCOutput {
per_commitment_point,
counterparty_delayed_payment_base_key,
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct CounterpartyReceivedHTLCOutput {
per_commitment_point: PublicKey,
- counterparty_delayed_payment_base_key: PublicKey,
- counterparty_htlc_base_key: PublicKey,
+ counterparty_delayed_payment_base_key: DelayedPaymentBasepoint,
+ counterparty_htlc_base_key: HtlcBasepoint,
htlc: HTLCOutputInCommitment,
channel_type_features: ChannelTypeFeatures,
}
impl CounterpartyReceivedHTLCOutput {
- pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures) -> Self {
+ pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures) -> Self {
CounterpartyReceivedHTLCOutput {
per_commitment_point,
counterparty_delayed_payment_base_key,
let mut ser_sig = sig.serialize_der().to_vec();
ser_sig.push(EcdsaSighashType::All as u8);
bumped_tx.input[i].witness.push(ser_sig);
- bumped_tx.input[i].witness.push(chan_keys.revocation_key.clone().serialize().to_vec());
+ bumped_tx.input[i].witness.push(chan_keys.revocation_key.to_public_key().serialize().to_vec());
bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
} else { return false; }
},
use crate::chain::Txid;
use crate::ln::chan_utils::HTLCOutputInCommitment;
use crate::ln::{PaymentPreimage, PaymentHash};
+ use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint};
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::script::ScriptBuf;
{
let dumb_scalar = SecretKey::from_slice(&<Vec<u8>>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
let dumb_point = PublicKey::from_secret_key(&$secp_ctx, &dumb_scalar);
- PackageSolvingData::RevokedOutput(RevokedOutput::build(dumb_point, dumb_point, dumb_point, dumb_scalar, 0, 0, $is_counterparty_balance_on_anchors))
+ PackageSolvingData::RevokedOutput(RevokedOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), dumb_scalar, 0, 0, $is_counterparty_balance_on_anchors))
}
}
}
let dumb_point = PublicKey::from_secret_key(&$secp_ctx, &dumb_scalar);
let hash = PaymentHash([1; 32]);
let htlc = HTLCOutputInCommitment { offered: true, amount_msat: $amt, cltv_expiry: 0, payment_hash: hash, transaction_output_index: None };
- PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput::build(dumb_point, dumb_point, dumb_point, htlc, $opt_anchors))
+ PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), htlc, $opt_anchors))
}
}
}
let hash = PaymentHash([1; 32]);
let preimage = PaymentPreimage([2;32]);
let htlc = HTLCOutputInCommitment { offered: false, amount_msat: $amt, cltv_expiry: 1000, payment_hash: hash, transaction_output_index: None };
- PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build(dumb_point, dumb_point, dumb_point, preimage, htlc, $opt_anchors))
+ PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), preimage, htlc, $opt_anchors))
}
}
}
// You may not use this file except in accordance with one or both of these
// licenses.
-//! Various utilities for building scripts and deriving keys related to channels. These are
+//! Various utilities for building scripts related to channels. These are
//! largely of interest for those implementing the traits on [`crate::sign`] by hand.
use bitcoin::blockdata::script::{Script, ScriptBuf, Builder};
use crate::chain;
use crate::ln::features::ChannelTypeFeatures;
use crate::util::crypto::{sign, sign_with_aux_rand};
+use super::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint};
/// Maximum number of one-way in-flight HTLC (protocol-level value).
pub const MAX_HTLCS: u16 = 483;
.expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
}
-/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
-/// from the base point and the per_commitment_key. This is the public equivalent of
-/// derive_private_key - using only public keys to derive a public key instead of private keys.
-pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
- let mut sha = Sha256::engine();
- sha.input(&per_commitment_point.serialize());
- sha.input(&base_point.serialize());
- let res = Sha256::from_engine(sha).to_byte_array();
-
- let hashkey = PublicKey::from_secret_key(&secp_ctx,
- &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
- base_point.combine(&hashkey)
- .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
-}
-
/// Derives a per-commitment-transaction revocation key from its constituent parts.
///
/// Only the cheating participant owns a valid witness to propagate a revoked
.expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.")
}
-/// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
-/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
-/// public key instead of private keys.
-///
-/// Only the cheating participant owns a valid witness to propagate a revoked
-/// commitment transaction, thus per_commitment_point always come from cheater
-/// and revocation_base_point always come from punisher, which is the broadcaster
-/// of the transaction spending with this key knowledge.
-///
-/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
-/// generated (ie our own).
-pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>,
- per_commitment_point: &PublicKey, countersignatory_revocation_base_point: &PublicKey)
--> PublicKey {
- let rev_append_commit_hash_key = {
- let mut sha = Sha256::engine();
- sha.input(&countersignatory_revocation_base_point.serialize());
- sha.input(&per_commitment_point.serialize());
-
- Sha256::from_engine(sha).to_byte_array()
- };
- let commit_append_rev_hash_key = {
- let mut sha = Sha256::engine();
- sha.input(&per_commitment_point.serialize());
- sha.input(&countersignatory_revocation_base_point.serialize());
-
- Sha256::from_engine(sha).to_byte_array()
- };
-
- let countersignatory_contrib = countersignatory_revocation_base_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
- .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
- let broadcaster_contrib = per_commitment_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
- .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
- countersignatory_contrib.combine(&broadcaster_contrib)
- .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.")
-}
-
/// The set of public keys which are used in the creation of one commitment transaction.
/// These are derived from the channel base keys and per-commitment data.
///
/// The revocation key which is used to allow the broadcaster of the commitment
/// transaction to provide their counterparty the ability to punish them if they broadcast
/// an old state.
- pub revocation_key: PublicKey,
+ pub revocation_key: RevocationKey,
/// Broadcaster's HTLC Key
- pub broadcaster_htlc_key: PublicKey,
+ pub broadcaster_htlc_key: HtlcKey,
/// Countersignatory's HTLC Key
- pub countersignatory_htlc_key: PublicKey,
+ pub countersignatory_htlc_key: HtlcKey,
/// Broadcaster's Payment Key (which isn't allowed to be spent from for some delay)
- pub broadcaster_delayed_payment_key: PublicKey,
+ pub broadcaster_delayed_payment_key: DelayedPaymentKey,
}
impl_writeable_tlv_based!(TxCreationKeys, {
/// revocation keys. This is combined with the per-commitment-secret generated by the
/// counterparty to create a secret which the counterparty can reveal to revoke previous
/// states.
- pub revocation_basepoint: PublicKey,
+ pub revocation_basepoint: RevocationBasepoint,
/// The public key on which the non-broadcaster (ie the countersignatory) receives an immediately
/// spendable primary channel balance on the broadcaster's commitment transaction. This key is
/// static across every commitment transaction.
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives non-HTLC-encumbered funds which are only available for spending
/// after some delay (or can be claimed via the revocation path).
- pub delayed_payment_basepoint: PublicKey,
+ pub delayed_payment_basepoint: DelayedPaymentBasepoint,
/// The base point which is used (with derive_public_key) to derive a per-commitment public key
/// which is used to encumber HTLC-in-flight outputs.
- pub htlc_basepoint: PublicKey,
+ pub htlc_basepoint: HtlcBasepoint,
}
impl_writeable_tlv_based!(ChannelPublicKeys, {
impl TxCreationKeys {
/// Create per-state keys from channel base points and the per-commitment point.
/// Key set is asymmetric and can't be used as part of counter-signatory set of transactions.
- pub fn derive_new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &PublicKey, broadcaster_htlc_base: &PublicKey, countersignatory_revocation_base: &PublicKey, countersignatory_htlc_base: &PublicKey) -> TxCreationKeys {
+ pub fn derive_new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &DelayedPaymentBasepoint, broadcaster_htlc_base: &HtlcBasepoint, countersignatory_revocation_base: &RevocationBasepoint, countersignatory_htlc_base: &HtlcBasepoint) -> TxCreationKeys {
TxCreationKeys {
per_commitment_point: per_commitment_point.clone(),
- revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &countersignatory_revocation_base),
- broadcaster_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_htlc_base),
- countersignatory_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &countersignatory_htlc_base),
- broadcaster_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_delayed_payment_base),
+ revocation_key: RevocationKey::from_basepoint(&secp_ctx, &countersignatory_revocation_base, &per_commitment_point),
+ broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &broadcaster_htlc_base, &per_commitment_point),
+ countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &countersignatory_htlc_base, &per_commitment_point),
+ broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &broadcaster_delayed_payment_base, &per_commitment_point),
}
}
/// A script either spendable by the revocation
/// key or the broadcaster_delayed_payment_key and satisfying the relative-locktime OP_CSV constrain.
/// Encumbering a `to_holder` output on a commitment transaction or 2nd-stage HTLC transactions.
-pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, contest_delay: u16, broadcaster_delayed_payment_key: &PublicKey) -> ScriptBuf {
+pub fn get_revokeable_redeemscript(revocation_key: &RevocationKey, contest_delay: u16, broadcaster_delayed_payment_key: &DelayedPaymentKey) -> ScriptBuf {
let res = Builder::new().push_opcode(opcodes::all::OP_IF)
- .push_slice(&revocation_key.serialize())
+ .push_slice(&revocation_key.to_public_key().serialize())
.push_opcode(opcodes::all::OP_ELSE)
.push_int(contest_delay as i64)
.push_opcode(opcodes::all::OP_CSV)
.push_opcode(opcodes::all::OP_DROP)
- .push_slice(&broadcaster_delayed_payment_key.serialize())
+ .push_slice(&broadcaster_delayed_payment_key.to_public_key().serialize())
.push_opcode(opcodes::all::OP_ENDIF)
.push_opcode(opcodes::all::OP_CHECKSIG)
.into_script();
});
#[inline]
-pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_htlc_key: &PublicKey, countersignatory_htlc_key: &PublicKey, revocation_key: &PublicKey) -> ScriptBuf {
+pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_htlc_key: &HtlcKey, countersignatory_htlc_key: &HtlcKey, revocation_key: &RevocationKey) -> ScriptBuf {
let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).to_byte_array();
if htlc.offered {
let mut bldr = Builder::new().push_opcode(opcodes::all::OP_DUP)
.push_opcode(opcodes::all::OP_HASH160)
- .push_slice(PubkeyHash::hash(&revocation_key.serialize()))
+ .push_slice(PubkeyHash::hash(&revocation_key.to_public_key().serialize()))
.push_opcode(opcodes::all::OP_EQUAL)
.push_opcode(opcodes::all::OP_IF)
.push_opcode(opcodes::all::OP_CHECKSIG)
.push_opcode(opcodes::all::OP_ELSE)
- .push_slice(countersignatory_htlc_key.serialize())
+ .push_slice(&countersignatory_htlc_key.to_public_key().serialize())
.push_opcode(opcodes::all::OP_SWAP)
.push_opcode(opcodes::all::OP_SIZE)
.push_int(32)
.push_opcode(opcodes::all::OP_DROP)
.push_int(2)
.push_opcode(opcodes::all::OP_SWAP)
- .push_slice(broadcaster_htlc_key.serialize())
+ .push_slice(&broadcaster_htlc_key.to_public_key().serialize())
.push_int(2)
.push_opcode(opcodes::all::OP_CHECKMULTISIG)
.push_opcode(opcodes::all::OP_ELSE)
} else {
let mut bldr = Builder::new().push_opcode(opcodes::all::OP_DUP)
.push_opcode(opcodes::all::OP_HASH160)
- .push_slice(PubkeyHash::hash(&revocation_key.serialize()))
+ .push_slice(&PubkeyHash::hash(&revocation_key.to_public_key().serialize()))
.push_opcode(opcodes::all::OP_EQUAL)
.push_opcode(opcodes::all::OP_IF)
.push_opcode(opcodes::all::OP_CHECKSIG)
.push_opcode(opcodes::all::OP_ELSE)
- .push_slice(countersignatory_htlc_key.serialize())
+ .push_slice(&countersignatory_htlc_key.to_public_key().serialize())
.push_opcode(opcodes::all::OP_SWAP)
.push_opcode(opcodes::all::OP_SIZE)
.push_int(32)
.push_opcode(opcodes::all::OP_EQUALVERIFY)
.push_int(2)
.push_opcode(opcodes::all::OP_SWAP)
- .push_slice(broadcaster_htlc_key.serialize())
+ .push_slice(&broadcaster_htlc_key.to_public_key().serialize())
.push_int(2)
.push_opcode(opcodes::all::OP_CHECKMULTISIG)
.push_opcode(opcodes::all::OP_ELSE)
///
/// Panics if htlc.transaction_output_index.is_none() (as such HTLCs do not appear in the
/// commitment transaction).
-pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction {
+pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_delayed_payment_key: &DelayedPaymentKey, revocation_key: &RevocationKey) -> Transaction {
let mut txins: Vec<TxIn> = Vec::new();
txins.push(build_htlc_input(commitment_txid, htlc, channel_type_features));
}
pub(crate) fn build_htlc_output(
- feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey
+ feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_delayed_payment_key: &DelayedPaymentKey, revocation_key: &RevocationKey
) -> TxOut {
let weight = if htlc.offered {
htlc_timeout_tx_weight(channel_type_features)
let keys = TxCreationKeys {
per_commitment_point: dummy_key.clone(),
- revocation_key: dummy_key.clone(),
- broadcaster_htlc_key: dummy_key.clone(),
- countersignatory_htlc_key: dummy_key.clone(),
- broadcaster_delayed_payment_key: dummy_key.clone(),
+ revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
+ broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
+ countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
+ broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
};
let channel_pubkeys = ChannelPublicKeys {
funding_pubkey: dummy_key.clone(),
- revocation_basepoint: dummy_key.clone(),
+ revocation_basepoint: RevocationBasepoint::from(dummy_key),
payment_point: dummy_key.clone(),
- delayed_payment_basepoint: dummy_key.clone(),
- htlc_basepoint: dummy_key.clone()
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(dummy_key.clone()),
+ htlc_basepoint: HtlcBasepoint::from(dummy_key.clone())
};
let channel_parameters = ChannelTransactionParameters {
holder_pubkeys: channel_pubkeys.clone(),
use crate::sync::Mutex;
use crate::sign::type_resolver::ChannelSignerType;
+use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint};
+
#[cfg(test)]
pub struct ChannelValueStat {
pub value_to_self_msat: u64,
let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]);
log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
- log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.serialize()),
+ log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id());
- if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) {
+ if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) {
return Err(ChannelError::Close("Invalid HTLC tx signature from peer".to_owned()));
}
if !separate_nondust_htlc_sources {
log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}",
encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.context.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)),
encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &counterparty_keys)),
- log_bytes!(counterparty_keys.broadcaster_htlc_key.serialize()),
+ log_bytes!(counterparty_keys.broadcaster_htlc_key.to_public_key().serialize()),
log_bytes!(htlc_sig.serialize_compact()[..]), &self.context.channel_id());
}
}
to_self_delay: self.context.get_holder_selected_contest_delay(),
max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
funding_pubkey: keys.funding_pubkey,
- revocation_basepoint: keys.revocation_basepoint,
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
payment_point: keys.payment_point,
- delayed_payment_basepoint: keys.delayed_payment_basepoint,
- htlc_basepoint: keys.htlc_basepoint,
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
first_per_commitment_point,
channel_flags: if self.context.config.announced_channel {1} else {0},
shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
let counterparty_pubkeys = ChannelPublicKeys {
funding_pubkey: msg.funding_pubkey,
- revocation_basepoint: msg.revocation_basepoint,
+ revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint),
payment_point: msg.payment_point,
- delayed_payment_basepoint: msg.delayed_payment_basepoint,
- htlc_basepoint: msg.htlc_basepoint
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint),
+ htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint)
};
self.context.channel_transaction_parameters.counterparty_parameters = Some(CounterpartyChannelTransactionParameters {
let pubkeys = holder_signer.pubkeys().clone();
let counterparty_pubkeys = ChannelPublicKeys {
funding_pubkey: msg.funding_pubkey,
- revocation_basepoint: msg.revocation_basepoint,
+ revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint),
payment_point: msg.payment_point,
- delayed_payment_basepoint: msg.delayed_payment_basepoint,
- htlc_basepoint: msg.htlc_basepoint
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint),
+ htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint)
};
if config.channel_handshake_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
to_self_delay: self.context.get_holder_selected_contest_delay(),
max_accepted_htlcs: self.context.holder_max_accepted_htlcs,
funding_pubkey: keys.funding_pubkey,
- revocation_basepoint: keys.revocation_basepoint,
+ revocation_basepoint: keys.revocation_basepoint.to_public_key(),
payment_point: keys.payment_point,
- delayed_payment_basepoint: keys.delayed_payment_basepoint,
- htlc_basepoint: keys.htlc_basepoint,
+ delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(),
+ htlc_basepoint: keys.htlc_basepoint.to_public_key(),
first_per_commitment_point,
shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey {
Some(script) => script.clone().into_inner(),
use bitcoin::blockdata::opcodes;
use bitcoin::network::constants::Network;
use crate::ln::PaymentHash;
- use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
+ use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
+use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
use crate::ln::channel::InitFeatures;
use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat};
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
use crate::ln::features::ChannelTypeFeatures;
use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use crate::ln::script::ShutdownScript;
- use crate::ln::chan_utils;
- use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
+ use crate::ln::chan_utils::{self, htlc_success_tx_weight, htlc_timeout_tx_weight};
use crate::chain::BestBlock;
use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget};
use crate::sign::{ChannelSigner, InMemorySigner, EntropySource, SignerProvider};
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, EcdsaChannelSigner};
use crate::ln::PaymentPreimage;
use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys};
+ use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint};
use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
use crate::util::logger::Logger;
use crate::sync::Arc;
let counterparty_pubkeys = ChannelPublicKeys {
funding_pubkey: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"),
- revocation_basepoint: PublicKey::from_slice(&<Vec<u8>>::from_hex("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap(),
+ revocation_basepoint: RevocationBasepoint::from(PublicKey::from_slice(&<Vec<u8>>::from_hex("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap()),
payment_point: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444"),
- delayed_payment_basepoint: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"),
- htlc_basepoint: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444")
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13")),
+ htlc_basepoint: HtlcBasepoint::from(public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444"))
};
chan.context.channel_transaction_parameters.counterparty_parameters = Some(
CounterpartyChannelTransactionParameters {
assert_eq!(counterparty_pubkeys.funding_pubkey.serialize()[..],
<Vec<u8>>::from_hex("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]);
- assert_eq!(counterparty_pubkeys.htlc_basepoint.serialize()[..],
+ assert_eq!(counterparty_pubkeys.htlc_basepoint.to_public_key().serialize()[..],
<Vec<u8>>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
// We can't just use build_holder_transaction_keys here as the per_commitment_secret is not
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, $opt_anchors, &keys);
let htlc_sighashtype = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
let htlc_sighash = Message::from_slice(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]).unwrap();
- assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).is_ok(), "verify counterparty htlc sig");
+ assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key.to_public_key()).is_ok(), "verify counterparty htlc sig");
let mut preimage: Option<PaymentPreimage> = None;
if !htlc.offered {
assert_eq!(chan_utils::build_commitment_secret(&seed, 1),
<Vec<u8>>::from_hex("915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c").unwrap()[..]);
}
-
+
#[test]
fn test_key_derivation() {
// Test vectors from BOLT 3 Appendix E:
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
assert_eq!(per_commitment_point.serialize()[..], <Vec<u8>>::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
- assert_eq!(chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
- <Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
-
assert_eq!(chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret),
SecretKey::from_slice(&<Vec<u8>>::from_hex("cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f").unwrap()[..]).unwrap());
- assert_eq!(chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
+ assert_eq!(RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(base_point), &per_commitment_point).to_public_key().serialize()[..],
<Vec<u8>>::from_hex("02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0").unwrap()[..]);
assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret),
--- /dev/null
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Keys used to generate commitment transactions.
+//! See: <https://github.com/lightning/bolts/blob/master/03-transactions.md#keys>
+
+use bitcoin::hashes::Hash;
+use bitcoin::hashes::HashEngine;
+use bitcoin::secp256k1::Scalar;
+use bitcoin::secp256k1::SecretKey;
+use bitcoin::secp256k1::Secp256k1;
+use bitcoin::secp256k1;
+use crate::ln::msgs::DecodeError;
+use crate::util::ser::Readable;
+use crate::io;
+use crate::util::ser::Writer;
+use crate::util::ser::Writeable;
+use bitcoin::secp256k1::PublicKey;
+use bitcoin::hashes::sha256::Hash as Sha256;
+
+macro_rules! doc_comment {
+ ($x:expr, $($tt:tt)*) => {
+ #[doc = $x]
+ $($tt)*
+ };
+}
+macro_rules! basepoint_impl {
+ ($BasepointT:ty) => {
+ impl $BasepointT {
+ /// Get inner Public Key
+ pub fn to_public_key(&self) -> PublicKey {
+ self.0
+ }
+ }
+
+ impl From<PublicKey> for $BasepointT {
+ fn from(value: PublicKey) -> Self {
+ Self(value)
+ }
+ }
+
+ }
+}
+macro_rules! key_impl {
+ ($BasepointT:ty, $KeyName:expr) => {
+ doc_comment! {
+ concat!("Generate ", $KeyName, " using per_commitment_point"),
+ pub fn from_basepoint<T: secp256k1::Signing>(
+ secp_ctx: &Secp256k1<T>,
+ basepoint: &$BasepointT,
+ per_commitment_point: &PublicKey,
+ ) -> Self {
+ Self(derive_public_key(secp_ctx, per_commitment_point, &basepoint.0))
+ }
+ }
+
+ doc_comment! {
+ concat!("Generate ", $KeyName, " from privkey"),
+ pub fn from_secret_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, sk: &SecretKey) -> Self {
+ Self(PublicKey::from_secret_key(&secp_ctx, &sk))
+ }
+ }
+
+ /// Get inner Public Key
+ pub fn to_public_key(&self) -> PublicKey {
+ self.0
+ }
+ }
+}
+macro_rules! key_read_write {
+ ($SelfT:ty) => {
+ impl Writeable for $SelfT {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.0.serialize().write(w)
+ }
+ }
+
+ impl Readable for $SelfT {
+ fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let key: PublicKey = Readable::read(r)?;
+ Ok(Self(key))
+ }
+ }
+ }
+}
+
+
+
+/// Master key used in conjunction with per_commitment_point to generate [`local_delayedpubkey`](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
+/// A watcher can be given a [DelayedPaymentBasepoint] to generate per commitment [DelayedPaymentKey] to create justice transactions.
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
+pub struct DelayedPaymentBasepoint(pub PublicKey);
+basepoint_impl!(DelayedPaymentBasepoint);
+key_read_write!(DelayedPaymentBasepoint);
+
+/// [delayedpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
+/// To allow a counterparty to contest a channel state published by a node, Lightning protocol sets delays for some of the outputs, before can be spend.
+/// For example a commitment transaction has to_local output encumbered by a delay, negotiated at the channel establishment flow.
+/// To spend from such output a node has to generate a script using, among others, a local delayed payment key.
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct DelayedPaymentKey(pub PublicKey);
+
+impl DelayedPaymentKey {
+ key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
+}
+key_read_write!(DelayedPaymentKey);
+
+/// Master key used in conjunction with per_commitment_point to generate a [localpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
+/// Also used to generate a commitment number in a commitment transaction or as a Payment Key for a remote node (not us) in an anchor output if `option_static_remotekey` is enabled.
+/// Shared by both nodes in a channel establishment message flow.
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
+pub struct PaymentBasepoint(pub PublicKey);
+basepoint_impl!(PaymentBasepoint);
+key_read_write!(PaymentBasepoint);
+
+
+/// [localpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of a payment basepoint,
+/// that enables a secure hash-lock for off-chain payments without risk of funds getting stuck or stolen. A payment key is normally shared with a counterparty so that it can generate
+/// a commitment transaction's to_remote ouput, which our node can claim in case the counterparty force closes the channel.
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct PaymentKey(pub PublicKey);
+
+impl PaymentKey {
+ key_impl!(PaymentBasepoint, "localpubkey");
+}
+key_read_write!(PaymentKey);
+
+/// Master key used in conjunction with per_commitment_point to generate [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
+pub struct HtlcBasepoint(pub PublicKey);
+basepoint_impl!(HtlcBasepoint);
+key_read_write!(HtlcBasepoint);
+
+
+/// [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of an htlc basepoint,
+/// that enables secure routing of payments in onion scheme without a risk of them getting stuck or diverted. It is used to claim the funds in successful or timed out htlc outputs.
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct HtlcKey(pub PublicKey);
+
+impl HtlcKey {
+ key_impl!(HtlcBasepoint, "htlcpubkey");
+}
+key_read_write!(HtlcKey);
+
+/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
+/// from the base point and the per_commitment_key. This is the public equivalent of
+/// derive_private_key - using only public keys to derive a public key instead of private keys.
+fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
+ let mut sha = Sha256::engine();
+ sha.input(&per_commitment_point.serialize());
+ sha.input(&base_point.serialize());
+ let res = Sha256::from_engine(sha).to_byte_array();
+
+
+ let hashkey = PublicKey::from_secret_key(&secp_ctx,
+ &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
+ base_point.combine(&hashkey)
+ .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
+}
+
+/// Master key used in conjunction with per_commitment_point to generate [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
+/// A watcher can be given a [RevocationBasepoint] to generate per commitment [RevocationKey] to create justice transactions.
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
+pub struct RevocationBasepoint(pub PublicKey);
+basepoint_impl!(RevocationBasepoint);
+key_read_write!(RevocationBasepoint);
+
+
+/// [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of a revocation basepoint,
+/// that enables a node to create a justice transaction punishing a counterparty for an attempt to steal funds. Used to in generation of commitment and htlc outputs.
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
+pub struct RevocationKey(pub PublicKey);
+
+impl RevocationKey {
+ /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
+ /// the public equivalend of derive_private_revocation_key - using only public keys to derive a
+ /// public key instead of private keys.
+ ///
+ /// Only the cheating participant owns a valid witness to propagate a revoked
+ /// commitment transaction, thus per_commitment_point always come from cheater
+ /// and revocation_base_point always come from punisher, which is the broadcaster
+ /// of the transaction spending with this key knowledge.
+ ///
+ /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
+ /// generated (ie our own).
+ pub fn from_basepoint<T: secp256k1::Verification>(
+ secp_ctx: &Secp256k1<T>,
+ basepoint: &RevocationBasepoint,
+ per_commitment_point: &PublicKey,
+ ) -> Self {
+ let rev_append_commit_hash_key = {
+ let mut sha = Sha256::engine();
+ sha.input(&basepoint.to_public_key().serialize());
+ sha.input(&per_commitment_point.serialize());
+
+ Sha256::from_engine(sha).to_byte_array()
+ };
+ let commit_append_rev_hash_key = {
+ let mut sha = Sha256::engine();
+ sha.input(&per_commitment_point.serialize());
+ sha.input(&basepoint.to_public_key().serialize());
+
+ Sha256::from_engine(sha).to_byte_array()
+ };
+
+ let countersignatory_contrib = basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
+ .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
+ let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
+ .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
+ let pk = countersignatory_contrib.combine(&broadcaster_contrib)
+ .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
+ Self(pk)
+ }
+
+ /// Get inner Public Key
+ pub fn to_public_key(&self) -> PublicKey {
+ self.0
+ }
+}
+key_read_write!(RevocationKey);
+
+
+
+#[cfg(test)]
+mod test {
+ use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
+ use bitcoin::hashes::hex::FromHex;
+ use super::derive_public_key;
+
+ #[test]
+ fn test_key_derivation() {
+ // Test vectors from BOLT 3 Appendix E:
+ let secp_ctx = Secp256k1::new();
+
+ let base_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
+ let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
+
+ let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret);
+ assert_eq!(base_point.serialize()[..], <Vec<u8>>::from_hex("036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2").unwrap()[..]);
+
+ let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
+ assert_eq!(per_commitment_point.serialize()[..], <Vec<u8>>::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
+
+ assert_eq!(derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
+ <Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
+ }
+}
pub mod functional_test_utils;
pub mod channelmanager;
+pub mod channel_keys;
pub mod inbound_payment;
pub mod msgs;
pub mod peer_handler;
use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
use crate::ln::{chan_utils, PaymentPreimage};
use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction};
+use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint};
use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
use crate::ln::script::ShutdownScript;
use crate::offers::invoice::UnsignedBolt12Invoice;
pub output: TxOut,
/// The revocation point specific to the commitment transaction which was broadcast. Used to
/// derive the witnessScript for this output.
- pub revocation_pubkey: PublicKey,
+ pub revocation_pubkey: RevocationKey,
/// Arbitrary identification information returned by a call to [`ChannelSigner::channel_keys_id`].
/// This may be useful in re-deriving keys used in the channel to spend the output.
pub channel_keys_id: [u8; 32],
/// To derive the delayed payment key which is used to sign this input, you must pass the
/// holder [`InMemorySigner::delayed_payment_base_key`] (i.e., the private key which corresponds to the
/// [`ChannelPublicKeys::delayed_payment_basepoint`] in [`ChannelSigner::pubkeys`]) and the provided
- /// [`DelayedPaymentOutputDescriptor::per_commitment_point`] to [`chan_utils::derive_private_key`]. The public key can be
- /// generated without the secret key using [`chan_utils::derive_public_key`] and only the
+ /// [`DelayedPaymentOutputDescriptor::per_commitment_point`] to [`chan_utils::derive_private_key`]. The DelayedPaymentKey can be
+ /// generated without the secret key using [`DelayedPaymentKey::from_basepoint`] and only the
/// [`ChannelPublicKeys::delayed_payment_basepoint`] which appears in [`ChannelSigner::pubkeys`].
///
/// To derive the [`DelayedPaymentOutputDescriptor::revocation_pubkey`] provided here (which is
/// [`ChannelPublicKeys::revocation_basepoint`] (which appears in the call to
/// [`ChannelSigner::provide_channel_parameters`]) and the provided
/// [`DelayedPaymentOutputDescriptor::per_commitment_point`] to
- /// [`chan_utils::derive_public_revocation_key`].
+ /// [`RevocationKey`].
///
/// The witness script which is hashed and included in the output `script_pubkey` may be
/// regenerated by passing the [`DelayedPaymentOutputDescriptor::revocation_pubkey`] (derived
let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable();
let broadcaster_keys = channel_params.broadcaster_pubkeys();
let counterparty_keys = channel_params.countersignatory_pubkeys();
- let broadcaster_delayed_key = chan_utils::derive_public_key(
- secp, &self.per_commitment_point, &broadcaster_keys.delayed_payment_basepoint
- );
- let counterparty_revocation_key = chan_utils::derive_public_revocation_key(
- secp, &self.per_commitment_point, &counterparty_keys.revocation_basepoint
+ let broadcaster_delayed_key = DelayedPaymentKey::from_basepoint(
+ secp, &broadcaster_keys.delayed_payment_basepoint, &self.per_commitment_point
);
+ let counterparty_revocation_key = &RevocationKey::from_basepoint(&secp, &counterparty_keys.revocation_basepoint, &self.per_commitment_point);
chan_utils::build_htlc_output(
self.feerate_per_kw, channel_params.contest_delay(), &self.htlc,
channel_params.channel_type_features(), &broadcaster_delayed_key, &counterparty_revocation_key
let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable();
let broadcaster_keys = channel_params.broadcaster_pubkeys();
let counterparty_keys = channel_params.countersignatory_pubkeys();
- let broadcaster_htlc_key = chan_utils::derive_public_key(
- secp, &self.per_commitment_point, &broadcaster_keys.htlc_basepoint
- );
- let counterparty_htlc_key = chan_utils::derive_public_key(
- secp, &self.per_commitment_point, &counterparty_keys.htlc_basepoint
+ let broadcaster_htlc_key = HtlcKey::from_basepoint(
+ secp, &broadcaster_keys.htlc_basepoint, &self.per_commitment_point
);
- let counterparty_revocation_key = chan_utils::derive_public_revocation_key(
- secp, &self.per_commitment_point, &counterparty_keys.revocation_basepoint
+ let counterparty_htlc_key = HtlcKey::from_basepoint(
+ secp, &counterparty_keys.htlc_basepoint, &self.per_commitment_point,
);
+ let counterparty_revocation_key = &RevocationKey::from_basepoint(&secp, &counterparty_keys.revocation_basepoint, &self.per_commitment_point);
chan_utils::get_htlc_redeemscript_with_explicit_keys(
&self.htlc, channel_params.channel_type_features(), &broadcaster_htlc_key, &counterparty_htlc_key,
&counterparty_revocation_key,
let from_secret = |s: &SecretKey| PublicKey::from_secret_key(secp_ctx, s);
ChannelPublicKeys {
funding_pubkey: from_secret(&funding_key),
- revocation_basepoint: from_secret(&revocation_base_key),
+ revocation_basepoint: RevocationBasepoint::from(from_secret(&revocation_base_key)),
payment_point: from_secret(&payment_key),
- delayed_payment_basepoint: from_secret(&delayed_payment_base_key),
- htlc_basepoint: from_secret(&htlc_base_key),
+ delayed_payment_basepoint: DelayedPaymentBasepoint::from(from_secret(&delayed_payment_base_key)),
+ htlc_basepoint: HtlcBasepoint::from(from_secret(&htlc_base_key)),
}
}
if spend_tx.input[input_idx].sequence.0 != descriptor.to_self_delay as u32 { return Err(()); }
let delayed_payment_key = chan_utils::derive_private_key(&secp_ctx, &descriptor.per_commitment_point, &self.delayed_payment_base_key);
- let delayed_payment_pubkey = PublicKey::from_secret_key(&secp_ctx, &delayed_payment_key);
+ let delayed_payment_pubkey = DelayedPaymentKey::from_secret_key(&secp_ctx, &delayed_payment_key);
let witness_script = chan_utils::get_revokeable_redeemscript(&descriptor.revocation_pubkey, descriptor.to_self_delay, &delayed_payment_pubkey);
let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]);
let local_delayedsig = EcdsaSignature {
fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
let revocation_key = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key);
let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key);
- let revocation_pubkey = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint);
+ let revocation_pubkey = RevocationKey::from_basepoint(
+ &secp_ctx, &self.pubkeys().revocation_basepoint, &per_commitment_point,
+ );
let witness_script = {
let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR);
let holder_selected_contest_delay =
self.holder_selected_contest_delay().expect(MISSING_PARAMS_ERR);
- let counterparty_delayedpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &counterparty_keys.delayed_payment_basepoint);
+ let counterparty_delayedpubkey = DelayedPaymentKey::from_basepoint(&secp_ctx, &counterparty_keys.delayed_payment_basepoint, &per_commitment_point);
chan_utils::get_revokeable_redeemscript(&revocation_pubkey, holder_selected_contest_delay, &counterparty_delayedpubkey)
};
let mut sighash_parts = sighash::SighashCache::new(justice_tx);
fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
let revocation_key = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key);
let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key);
- let revocation_pubkey = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint);
+ let revocation_pubkey = RevocationKey::from_basepoint(
+ &secp_ctx, &self.pubkeys().revocation_basepoint, &per_commitment_point,
+ );
let witness_script = {
let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR);
- let counterparty_htlcpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &counterparty_keys.htlc_basepoint);
- let holder_htlcpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint);
+ let counterparty_htlcpubkey = HtlcKey::from_basepoint(
+ &secp_ctx, &counterparty_keys.htlc_basepoint, &per_commitment_point,
+ );
+ let holder_htlcpubkey = HtlcKey::from_basepoint(
+ &secp_ctx, &self.pubkeys().htlc_basepoint, &per_commitment_point,
+ );
let chan_type = self.channel_type_features().expect(MISSING_PARAMS_ERR);
chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, chan_type, &counterparty_htlcpubkey, &holder_htlcpubkey, &revocation_pubkey)
};
fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
let htlc_key = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.htlc_base_key);
- let revocation_pubkey = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint);
+ let revocation_pubkey = RevocationKey::from_basepoint(
+ &secp_ctx, &self.pubkeys().revocation_basepoint, &per_commitment_point,
+ );
let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR);
- let counterparty_htlcpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &counterparty_keys.htlc_basepoint);
- let htlcpubkey = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint);
+ let counterparty_htlcpubkey = HtlcKey::from_basepoint(
+ &secp_ctx, &counterparty_keys.htlc_basepoint, &per_commitment_point,
+ );
+ let htlcpubkey = HtlcKey::from_basepoint(&secp_ctx, &self.pubkeys().htlc_basepoint, &per_commitment_point);
let chan_type = self.channel_type_features().expect(MISSING_PARAMS_ERR);
let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, chan_type, &counterparty_htlcpubkey, &htlcpubkey, &revocation_pubkey);
let mut sighash_parts = sighash::SighashCache::new(htlc_tx);
use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSHIS};
use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction, ClosingTransaction};
-use crate::ln::{chan_utils, msgs, PaymentPreimage};
+use crate::ln::channel_keys::{HtlcKey};
+use crate::ln::{msgs, PaymentPreimage};
use crate::sign::{WriteableEcdsaChannelSigner, InMemorySigner, ChannelSigner, EcdsaChannelSigner};
use crate::prelude::*;
let sighash = &sighash::SighashCache::new(&*htlc_tx).segwit_signature_hash(
input, &witness_script, htlc_descriptor.htlc.amount_msat / 1000, sighash_type
).unwrap();
- let countersignatory_htlc_key = chan_utils::derive_public_key(
- &secp_ctx, &htlc_descriptor.per_commitment_point, &self.inner.counterparty_pubkeys().unwrap().htlc_basepoint
+ let countersignatory_htlc_key = HtlcKey::from_basepoint(
+ &secp_ctx, &self.inner.counterparty_pubkeys().unwrap().htlc_basepoint, &htlc_descriptor.per_commitment_point,
);
+
secp_ctx.verify_ecdsa(
- &hash_to_message!(sighash.as_byte_array()), &htlc_descriptor.counterparty_sig, &countersignatory_htlc_key
+ &hash_to_message!(sighash.as_byte_array()), &htlc_descriptor.counterparty_sig, &countersignatory_htlc_key.to_public_key()
).unwrap();
}
Ok(self.inner.sign_holder_htlc_transaction(htlc_tx, input, htlc_descriptor, secp_ctx).unwrap())