From: Wilmer Paulino Date: Wed, 30 Nov 2022 22:05:02 +0000 (-0800) Subject: Extend BaseSign with HTLC output signing support for external claims X-Git-Tag: v0.0.113~12^2 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=ec1f3346c1642a693481172945b623b8198007e2;p=rust-lightning Extend BaseSign with HTLC output signing support for external claims --- diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 3ca66fcbc..f2d198bbf 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -34,7 +34,8 @@ use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness}; use crate::util::transaction_utils; use crate::util::crypto::{hkdf_extract_expand_twice, sign}; use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; - +#[cfg(anchors)] +use crate::util::events::HTLCDescriptor; use crate::chain::transaction::OutPoint; use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; use crate::ln::{chan_utils, PaymentPreimage}; @@ -325,6 +326,19 @@ pub trait BaseSign { /// (which is committed to in the BIP 143 signatures). fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result; + #[cfg(anchors)] + /// Computes the signature for a commitment transaction's HTLC output used as an input within + /// `htlc_tx`, which spends the commitment transaction, at index `input`. The signature returned + /// must be be computed using [`EcdsaSighashType::All`]. Note that this should only be used to + /// sign HTLC transactions from channels supporting anchor outputs after all additional + /// inputs/outputs have been added to the transaction. + /// + /// [`EcdsaSighashType::All`]: bitcoin::blockdata::transaction::EcdsaSighashType::All + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1 + ) -> Result; + /// Create a signature for a claiming transaction for a HTLC output on a counterparty's commitment /// transaction, either offered or received. /// @@ -682,7 +696,6 @@ impl InMemorySigner { witness.push(witness_script.clone().into_bytes()); Ok(witness) } - } impl BaseSign for InMemorySigner { @@ -779,6 +792,24 @@ impl BaseSign for InMemorySigner { return Ok(sign(secp_ctx, &sighash, &revocation_key)) } + #[cfg(anchors)] + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1 + ) -> Result { + let per_commitment_point = self.get_per_commitment_point( + htlc_descriptor.per_commitment_number, &secp_ctx + ); + let witness_script = htlc_descriptor.witness_script(&per_commitment_point, secp_ctx); + let sighash = &sighash::SighashCache::new(&*htlc_tx).segwit_signature_hash( + input, &witness_script, htlc_descriptor.htlc.amount_msat / 1000, EcdsaSighashType::All + ).map_err(|_| ())?; + let our_htlc_private_key = chan_utils::derive_private_key( + &secp_ctx, &per_commitment_point, &self.htlc_base_key + ); + Ok(sign(&secp_ctx, &hash_to_message!(sighash), &our_htlc_private_key)) + } + fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { 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); diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs index 21ef5d4b1..1a9038a2f 100644 --- a/lightning/src/util/enforcing_trait_impls.rs +++ b/lightning/src/util/enforcing_trait_impls.rs @@ -23,6 +23,8 @@ use bitcoin::util::sighash; use bitcoin::secp256k1; use bitcoin::secp256k1::{SecretKey, PublicKey}; use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; +#[cfg(anchors)] +use crate::util::events::HTLCDescriptor; use crate::util::ser::{Writeable, Writer}; use crate::io::Error; @@ -190,6 +192,17 @@ impl BaseSign for EnforcingSigner { Ok(self.inner.sign_justice_revoked_htlc(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap()) } + #[cfg(anchors)] + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1 + ) -> Result { + let per_commitment_point = self.get_per_commitment_point(htlc_descriptor.per_commitment_number, secp_ctx); + assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input()); + assert_eq!(htlc_tx.output[input], htlc_descriptor.tx_output(&per_commitment_point, secp_ctx)); + Ok(self.inner.sign_holder_htlc_transaction(htlc_tx, input, htlc_descriptor, secp_ctx).unwrap()) + } + fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { Ok(self.inner.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap()) }