Add TaprootSigner variant to SignerProvider.

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.
This commit is contained in:
Arik Sosman 2023-11-05 21:36:59 -08:00
parent f862aa9f5f
commit c6bcf75848
No known key found for this signature in database
GPG key ID: F4FB5A3366C4D92E
7 changed files with 118 additions and 5 deletions

View 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;

View 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;

View 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!() }

View 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()

View 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)

View 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`

View 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)