]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Add TaprootSigner variant to SignerProvider.
authorArik Sosman <git@arik.io>
Mon, 6 Nov 2023 05:36:59 +0000 (21:36 -0800)
committerArik Sosman <git@arik.io>
Tue, 28 Nov 2023 00:27:21 +0000 (16:27 -0800)
Previously, SignerProvider was not laid out to support multiple signer
types. However, with the distinction between ECDSA and Taproot signers,
we now need to account for SignerProviders needing to support both.

This approach does mean that if ever we introduced another signer type
in the future, all implementers of SignerProvider would need to add it
as an associated type, and would also need to write a set of dummy
implementations for any Signer trait they do not wish to support.

For the time being, the TaprootSigner associated type is cfg-gated.

fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/onion_message.rs
lightning/src/ln/channel.rs
lightning/src/sign/mod.rs
lightning/src/util/test_channel_signer.rs
lightning/src/util/test_utils.rs

index 22491bdf0b70bc1e3e98a3b34ca26f36cf132dc3..f654908771f0fec964b40384ce6178bd0b267c71 100644 (file)
@@ -231,6 +231,8 @@ impl NodeSigner for KeyProvider {
 
 impl SignerProvider for KeyProvider {
        type EcdsaSigner = TestChannelSigner;
+       #[cfg(taproot)]
+       type TaprootSigner = TestChannelSigner;
 
        fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
                let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed) as u8;
index 49d67650681a3de7dea33c2c7ed098625529da35..57c78e76d6bcd675f41cb437613981129dc6469c 100644 (file)
@@ -341,6 +341,8 @@ impl NodeSigner for KeyProvider {
 
 impl SignerProvider for KeyProvider {
        type EcdsaSigner = TestChannelSigner;
+       #[cfg(taproot)]
+       type TaprootSigner = TestChannelSigner;
 
        fn generate_channel_keys_id(&self, inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
                let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8;
index 6ddee84c085a7dd7ae6e899b3142d5c99cf9d0e6..13de5005cf8be1e2fee35f9fc501366bd4e46434 100644 (file)
@@ -190,6 +190,8 @@ impl NodeSigner for KeyProvider {
 
 impl SignerProvider for KeyProvider {
        type EcdsaSigner = TestChannelSigner;
+       #[cfg(taproot)]
+       type TaprootSigner = TestChannelSigner;
 
        fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!() }
 
index cf543b32d227ea720b35c365ca467b3793383ede..157103fea2692f0c54e98629d5fc3d0d464c36e8 100644 (file)
@@ -7863,6 +7863,8 @@ use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
 
        impl SignerProvider for Keys {
                type EcdsaSigner = InMemorySigner;
+               #[cfg(taproot)]
+               type TaprootSigner = InMemorySigner;
 
                fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
                        self.signer.channel_keys_id()
index a21a68f19c7772c4e950ad1be34ebff7e2126002..a2740bc35581f257a21bc11a96bfd88018d4a31a 100644 (file)
@@ -29,6 +29,8 @@ use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hash_types::WPubkeyHash;
 
+#[cfg(taproot)]
+use bitcoin::secp256k1::All;
 use bitcoin::secp256k1::{KeyPair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
 use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
@@ -44,6 +46,8 @@ 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};
+#[cfg(taproot)]
+use crate::ln::msgs::PartialSignatureWithNonce;
 use crate::ln::script::ShutdownScript;
 use crate::offers::invoice::UnsignedBolt12Invoice;
 use crate::offers::invoice_request::UnsignedInvoiceRequest;
@@ -52,9 +56,13 @@ use crate::prelude::*;
 use core::convert::TryInto;
 use core::ops::Deref;
 use core::sync::atomic::{AtomicUsize, Ordering};
+#[cfg(taproot)]
+use musig2::types::{PartialSignature, PublicNonce, SecretNonce};
 use crate::io::{self, Error};
 use crate::ln::features::ChannelTypeFeatures;
 use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
+#[cfg(taproot)]
+use crate::sign::taproot::TaprootChannelSigner;
 use crate::util::atomic_counter::AtomicCounter;
 use crate::util::chacha20::ChaCha20;
 use crate::util::invoice::construct_invoice_preimage;
@@ -869,6 +877,9 @@ pub trait NodeSigner {
 pub trait SignerProvider {
        /// A type which implements [`WriteableEcdsaChannelSigner`] which will be returned by [`Self::derive_channel_signer`].
        type EcdsaSigner: WriteableEcdsaChannelSigner;
+       #[cfg(taproot)]
+       /// A type which implements [`TaprootChannelSigner`]
+       type TaprootSigner: TaprootChannelSigner;
 
        /// Generates a unique `channel_keys_id` that can be used to obtain a [`Self::EcdsaSigner`] through
        /// [`SignerProvider::derive_channel_signer`]. The `user_channel_id` is provided to allow
@@ -1380,6 +1391,45 @@ impl EcdsaChannelSigner for InMemorySigner {
        }
 }
 
+#[cfg(taproot)]
+impl TaprootChannelSigner for InMemorySigner {
+       fn generate_local_nonce_pair(&self, commitment_number: u64, secp_ctx: &Secp256k1<All>) -> PublicNonce {
+               todo!()
+       }
+
+       fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>) -> Result<(PartialSignatureWithNonce, Vec<schnorr::Signature>), ()> {
+               todo!()
+       }
+
+       fn finalize_holder_commitment(&self, commitment_number: u64, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1<All>) -> Result<PartialSignature, ()> {
+               todo!()
+       }
+
+       fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<All>) -> Result<schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<All>) -> Result<schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1<All>) -> Result<schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<All>) -> Result<schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn partially_sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1<All>) -> Result<PartialSignature, ()> {
+               todo!()
+       }
+
+       fn sign_holder_anchor_input(&self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1<All>) -> Result<schnorr::Signature, ()> {
+               todo!()
+       }
+}
+
 const SERIALIZATION_VERSION: u8 = 1;
 
 const MIN_SERIALIZATION_VERSION: u8 = 1;
@@ -1783,6 +1833,8 @@ impl NodeSigner for KeysManager {
 
 impl SignerProvider for KeysManager {
        type EcdsaSigner = InMemorySigner;
+       #[cfg(taproot)]
+       type TaprootSigner = InMemorySigner;
 
        fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] {
                let child_idx = self.channel_child_index.fetch_add(1, Ordering::AcqRel);
@@ -1902,6 +1954,8 @@ impl NodeSigner for PhantomKeysManager {
 
 impl SignerProvider for PhantomKeysManager {
        type EcdsaSigner = InMemorySigner;
+       #[cfg(taproot)]
+       type TaprootSigner = InMemorySigner;
 
        fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] {
                self.inner.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id)
index 9c6a1e30224a14b21eff915b3bc3666f96e7b2d5..3e0ca970e1202d6f1132e4755111781805281b23 100644 (file)
@@ -24,12 +24,20 @@ use bitcoin::sighash;
 use bitcoin::sighash::EcdsaSighashType;
 
 use bitcoin::secp256k1;
+#[cfg(taproot)]
+use bitcoin::secp256k1::All;
 use bitcoin::secp256k1::{SecretKey, PublicKey};
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
+#[cfg(taproot)]
+use musig2::types::{PartialSignature, PublicNonce, SecretNonce};
 use crate::sign::HTLCDescriptor;
 use crate::util::ser::{Writeable, Writer};
 use crate::io::Error;
 use crate::ln::features::ChannelTypeFeatures;
+#[cfg(taproot)]
+use crate::ln::msgs::PartialSignatureWithNonce;
+#[cfg(taproot)]
+use crate::sign::taproot::TaprootChannelSigner;
 
 /// Initial value for revoked commitment downward counter
 pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48;
@@ -201,11 +209,11 @@ impl EcdsaChannelSigner for TestChannelSigner {
        }
 
        fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
-               Ok(self.inner.sign_justice_revoked_output(justice_tx, input, amount, per_commitment_key, secp_ctx).unwrap())
+               Ok(EcdsaChannelSigner::sign_justice_revoked_output(&self.inner, justice_tx, input, amount, per_commitment_key, secp_ctx).unwrap())
        }
 
        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, ()> {
-               Ok(self.inner.sign_justice_revoked_htlc(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap())
+               Ok(EcdsaChannelSigner::sign_justice_revoked_htlc(&self.inner, justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap())
        }
 
        fn sign_holder_htlc_transaction(
@@ -241,11 +249,11 @@ impl EcdsaChannelSigner for TestChannelSigner {
                                &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())
+               Ok(EcdsaChannelSigner::sign_holder_htlc_transaction(&self.inner, 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<secp256k1::All>) -> Result<Signature, ()> {
-               Ok(self.inner.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap())
+               Ok(EcdsaChannelSigner::sign_counterparty_htlc_transaction(&self.inner, htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap())
        }
 
        fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()> {
@@ -261,7 +269,7 @@ impl EcdsaChannelSigner for TestChannelSigner {
                // As long as our minimum dust limit is enforced and is greater than our anchor output
                // value, an anchor output can only have an index within [0, 1].
                assert!(anchor_tx.input[input].previous_output.vout == 0 || anchor_tx.input[input].previous_output.vout == 1);
-               self.inner.sign_holder_anchor_input(anchor_tx, input, secp_ctx)
+               EcdsaChannelSigner::sign_holder_anchor_input(&self.inner, anchor_tx, input, secp_ctx)
        }
 
        fn sign_channel_announcement_with_funding_key(
@@ -273,6 +281,45 @@ impl EcdsaChannelSigner for TestChannelSigner {
 
 impl WriteableEcdsaChannelSigner for TestChannelSigner {}
 
+#[cfg(taproot)]
+impl TaprootChannelSigner for TestChannelSigner {
+       fn generate_local_nonce_pair(&self, commitment_number: u64, secp_ctx: &Secp256k1<All>) -> PublicNonce {
+               todo!()
+       }
+
+       fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>) -> Result<(PartialSignatureWithNonce, Vec<secp256k1::schnorr::Signature>), ()> {
+               todo!()
+       }
+
+       fn finalize_holder_commitment(&self, commitment_number: u64, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1<All>) -> Result<PartialSignature, ()> {
+               todo!()
+       }
+
+       fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1<All>) -> Result<secp256k1::schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<All>) -> Result<secp256k1::schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1<All>) -> Result<secp256k1::schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<All>) -> Result<secp256k1::schnorr::Signature, ()> {
+               todo!()
+       }
+
+       fn partially_sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1<All>) -> Result<PartialSignature, ()> {
+               todo!()
+       }
+
+       fn sign_holder_anchor_input(&self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1<All>) -> Result<secp256k1::schnorr::Signature, ()> {
+               todo!()
+       }
+}
+
 impl Writeable for TestChannelSigner {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
                // TestChannelSigner has two fields - `inner` ([`InMemorySigner`]) and `state`
index b46f14681d8e8869e147c5ab14d8b4f8da1b297f..c9563f42f0e94165d03cf6cd36557dd9c57b8055 100644 (file)
@@ -176,6 +176,8 @@ impl EntropySource for OnlyReadsKeysInterface {
 
 impl SignerProvider for OnlyReadsKeysInterface {
        type EcdsaSigner = TestChannelSigner;
+       #[cfg(taproot)]
+       type TaprootSigner = TestChannelSigner;
 
        fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!(); }
 
@@ -1097,6 +1099,8 @@ impl NodeSigner for TestKeysInterface {
 
 impl SignerProvider for TestKeysInterface {
        type EcdsaSigner = TestChannelSigner;
+       #[cfg(taproot)]
+       type TaprootSigner = TestChannelSigner;
 
        fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] {
                self.backing.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id)