mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-03-13 14:52:21 +01:00
Introduce DynSigner, a dynamically dispatched signer
DynSigner provides an abstraction for specifying an external signer for functional tests.
This commit is contained in:
parent
60222d07cf
commit
17cd6e39fc
6 changed files with 425 additions and 31 deletions
|
@ -84,7 +84,7 @@ pub trait EcdsaChannelSigner: ChannelSigner {
|
|||
/// only ever get called once.
|
||||
///
|
||||
/// This method is *not* async as it is intended only for testing purposes.
|
||||
#[cfg(any(test, feature = "unsafe_revoked_tx_signing"))]
|
||||
#[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
|
||||
fn unsafe_sign_holder_commitment(
|
||||
&self, channel_parameters: &ChannelTransactionParameters,
|
||||
commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
|
|
|
@ -31,7 +31,6 @@ use bitcoin::hashes::{Hash, HashEngine};
|
|||
use bitcoin::secp256k1::ecdh::SharedSecret;
|
||||
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
|
||||
use bitcoin::secp256k1::schnorr;
|
||||
#[cfg(taproot)]
|
||||
use bitcoin::secp256k1::All;
|
||||
use bitcoin::secp256k1::{Keypair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
|
||||
use bitcoin::{secp256k1, Psbt, Sequence, Txid, WPubkeyHash, Witness};
|
||||
|
@ -898,10 +897,10 @@ pub trait OutputSpender {
|
|||
/// Returns `Err(())` if the output value is greater than the input value minus required fee,
|
||||
/// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
|
||||
/// does not match the one we can spend.
|
||||
fn spend_spendable_outputs<C: Signing>(
|
||||
fn spend_spendable_outputs(
|
||||
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
|
||||
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<All>,
|
||||
) -> Result<Transaction, ()>;
|
||||
}
|
||||
|
||||
|
@ -1351,7 +1350,7 @@ impl EcdsaChannelSigner for InMemorySigner {
|
|||
))
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "unsafe_revoked_tx_signing"))]
|
||||
#[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
|
||||
fn unsafe_sign_holder_commitment(
|
||||
&self, channel_parameters: &ChannelTransactionParameters,
|
||||
commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
|
@ -2044,10 +2043,10 @@ impl OutputSpender for KeysManager {
|
|||
///
|
||||
/// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
|
||||
/// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
|
||||
fn spend_spendable_outputs<C: Signing>(
|
||||
fn spend_spendable_outputs(
|
||||
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
|
||||
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<All>,
|
||||
) -> Result<Transaction, ()> {
|
||||
let (mut psbt, expected_max_weight) =
|
||||
SpendableOutputDescriptor::create_spendable_outputs_psbt(
|
||||
|
@ -2194,10 +2193,10 @@ impl NodeSigner for PhantomKeysManager {
|
|||
impl OutputSpender for PhantomKeysManager {
|
||||
/// See [`OutputSpender::spend_spendable_outputs`] and [`KeysManager::spend_spendable_outputs`]
|
||||
/// for documentation on this method.
|
||||
fn spend_spendable_outputs<C: Signing>(
|
||||
fn spend_spendable_outputs(
|
||||
&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
|
||||
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<C>,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<All>,
|
||||
) -> Result<Transaction, ()> {
|
||||
self.inner.spend_spendable_outputs(
|
||||
descriptors,
|
||||
|
|
330
lightning/src/util/dyn_signer.rs
Normal file
330
lightning/src/util/dyn_signer.rs
Normal file
|
@ -0,0 +1,330 @@
|
|||
//! A dynamically dispatched signer
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use core::any::Any;
|
||||
|
||||
use crate::ln::chan_utils::{
|
||||
ChannelPublicKeys, ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction,
|
||||
HTLCOutputInCommitment, HolderCommitmentTransaction,
|
||||
};
|
||||
use crate::ln::inbound_payment::ExpandedKey;
|
||||
use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
|
||||
use crate::ln::script::ShutdownScript;
|
||||
use crate::sign::ecdsa::EcdsaChannelSigner;
|
||||
#[cfg(taproot)]
|
||||
use crate::sign::taproot::TaprootChannelSigner;
|
||||
use crate::sign::ChannelSigner;
|
||||
use crate::sign::InMemorySigner;
|
||||
use crate::sign::{EntropySource, HTLCDescriptor, OutputSpender, PhantomKeysManager};
|
||||
use crate::sign::{NodeSigner, Recipient, SignerProvider, SpendableOutputDescriptor};
|
||||
use bitcoin;
|
||||
use bitcoin::absolute::LockTime;
|
||||
use bitcoin::secp256k1::All;
|
||||
use bitcoin::{secp256k1, ScriptBuf, Transaction, TxOut};
|
||||
use lightning_invoice::RawBolt11Invoice;
|
||||
#[cfg(taproot)]
|
||||
use musig2::types::{PartialSignature, PublicNonce};
|
||||
use secp256k1::ecdsa::RecoverableSignature;
|
||||
use secp256k1::{ecdh::SharedSecret, ecdsa::Signature, PublicKey, Scalar, Secp256k1, SecretKey};
|
||||
use types::payment::PaymentPreimage;
|
||||
|
||||
#[cfg(not(taproot))]
|
||||
/// A super-trait for all the traits that a dyn signer backing implements
|
||||
pub trait DynSignerTrait: EcdsaChannelSigner + Send + Sync {}
|
||||
|
||||
#[cfg(taproot)]
|
||||
/// A super-trait for all the traits that a dyn signer backing implements
|
||||
pub trait DynSignerTrait: EcdsaChannelSigner + TaprootChannelSigner + Send + Sync {}
|
||||
|
||||
/// Helper to allow DynSigner to clone itself
|
||||
pub trait InnerSign: DynSignerTrait {
|
||||
/// Clone into a Box
|
||||
fn box_clone(&self) -> Box<dyn InnerSign>;
|
||||
/// Cast to Any for runtime type checking
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
/// A ChannelSigner derived struct allowing run-time selection of a signer
|
||||
pub struct DynSigner {
|
||||
/// The inner signer
|
||||
pub inner: Box<dyn InnerSign>,
|
||||
}
|
||||
|
||||
impl DynSigner {
|
||||
/// Create a new DynSigner
|
||||
pub fn new<S: InnerSign + 'static>(inner: S) -> Self {
|
||||
DynSigner { inner: Box::new(inner) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(taproot)]
|
||||
#[allow(unused_variables)]
|
||||
impl TaprootChannelSigner for DynSigner {
|
||||
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,
|
||||
inbound_htlc_preimages: Vec<PaymentPreimage>,
|
||||
outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<All>,
|
||||
) -> Result<(crate::ln::msgs::PartialSignatureWithNonce, Vec<secp256k1::schnorr::Signature>), ()>
|
||||
{
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn finalize_holder_commitment(
|
||||
&self, commitment_tx: &HolderCommitmentTransaction,
|
||||
counterparty_partial_signature: crate::ln::msgs::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 Clone for DynSigner {
|
||||
fn clone(&self) -> Self {
|
||||
DynSigner { inner: self.inner.box_clone() }
|
||||
}
|
||||
}
|
||||
|
||||
delegate!(DynSigner, EcdsaChannelSigner, inner,
|
||||
fn sign_holder_commitment(, channel_parameters: &ChannelTransactionParameters,
|
||||
commitment_tx: &HolderCommitmentTransaction,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
#[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
|
||||
fn unsafe_sign_holder_commitment(, channel_parameters: &ChannelTransactionParameters,
|
||||
commitment_tx: &HolderCommitmentTransaction,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_counterparty_commitment(, channel_parameters: &ChannelTransactionParameters,
|
||||
commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec<PaymentPreimage>,
|
||||
outbound_htlc_preimages: Vec<PaymentPreimage>,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()>,
|
||||
fn sign_justice_revoked_output(, channel_parameters: &ChannelTransactionParameters,
|
||||
justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_justice_revoked_htlc(, channel_parameters: &ChannelTransactionParameters,
|
||||
justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey,
|
||||
htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_counterparty_htlc_transaction(, channel_parameters: &ChannelTransactionParameters,
|
||||
htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey,
|
||||
htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_closing_transaction(, channel_parameters: &ChannelTransactionParameters,
|
||||
closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_channel_announcement_with_funding_key(, msg: &UnsignedChannelAnnouncement,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_holder_anchor_input(, channel_parameters: &ChannelTransactionParameters,
|
||||
anchor_tx: &Transaction, input: usize,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>) -> Result<Signature, ()>,
|
||||
fn sign_holder_htlc_transaction(, htlc_tx: &Transaction, input: usize,
|
||||
htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1<All>) -> Result<Signature, ()>,
|
||||
fn sign_splicing_funding_input(, channel_parameters: &ChannelTransactionParameters,
|
||||
tx: &Transaction, input_index: usize, input_value: u64,
|
||||
secp_ctx: &Secp256k1<All>) -> Result<Signature, ()>
|
||||
);
|
||||
|
||||
delegate!(DynSigner, ChannelSigner,
|
||||
inner,
|
||||
fn get_per_commitment_point(,
|
||||
idx: u64,
|
||||
secp_ctx: &Secp256k1<secp256k1::All>
|
||||
) -> Result<PublicKey, ()>,
|
||||
fn release_commitment_secret(, idx: u64) -> Result<[u8; 32], ()>,
|
||||
fn validate_holder_commitment(,
|
||||
holder_tx: &HolderCommitmentTransaction,
|
||||
preimages: Vec<PaymentPreimage>
|
||||
) -> Result<(), ()>,
|
||||
fn pubkeys(,) -> &ChannelPublicKeys,
|
||||
fn channel_keys_id(,) -> [u8; 32],
|
||||
fn validate_counterparty_revocation(, idx: u64, secret: &SecretKey) -> Result<(), ()>
|
||||
);
|
||||
|
||||
impl DynSignerTrait for InMemorySigner {}
|
||||
|
||||
impl InnerSign for InMemorySigner {
|
||||
fn box_clone(&self) -> Box<dyn InnerSign> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience wrapper for DynKeysInterfaceTrait
|
||||
pub struct DynKeysInterface {
|
||||
/// The inner dyn keys interface
|
||||
pub inner: Box<dyn DynKeysInterfaceTrait>,
|
||||
}
|
||||
|
||||
impl DynKeysInterface {
|
||||
/// Create a new DynKeysInterface
|
||||
pub fn new(inner: Box<dyn DynKeysInterfaceTrait>) -> Self {
|
||||
DynKeysInterface { inner }
|
||||
}
|
||||
}
|
||||
|
||||
delegate!(DynKeysInterface, NodeSigner,
|
||||
inner,
|
||||
fn get_node_id(, recipient: Recipient) -> Result<PublicKey, ()>,
|
||||
fn sign_gossip_message(, msg: UnsignedGossipMessage) -> Result<Signature, ()>,
|
||||
fn ecdh(, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>,
|
||||
fn sign_invoice(, invoice: &RawBolt11Invoice, recipient: Recipient) -> Result<RecoverableSignature, ()>,
|
||||
fn sign_bolt12_invoice(,
|
||||
invoice: &crate::offers::invoice::UnsignedBolt12Invoice
|
||||
) -> Result<secp256k1::schnorr::Signature, ()>,
|
||||
fn get_inbound_payment_key(,) -> ExpandedKey
|
||||
);
|
||||
|
||||
delegate!(DynKeysInterface, SignerProvider,
|
||||
inner,
|
||||
fn get_destination_script(, channel_keys_id: [u8; 32]) -> Result<ScriptBuf, ()>,
|
||||
fn get_shutdown_scriptpubkey(,) -> Result<ShutdownScript, ()>,
|
||||
fn generate_channel_keys_id(, _inbound: bool, _user_channel_id: u128) -> [u8; 32],
|
||||
fn derive_channel_signer(, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner;
|
||||
type EcdsaSigner = DynSigner,
|
||||
#[cfg(taproot)]
|
||||
type TaprootSigner = DynSigner
|
||||
);
|
||||
|
||||
delegate!(DynKeysInterface, EntropySource, inner,
|
||||
fn get_secure_random_bytes(,) -> [u8; 32]
|
||||
);
|
||||
|
||||
delegate!(DynKeysInterface, OutputSpender, inner,
|
||||
fn spend_spendable_outputs(,
|
||||
descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
|
||||
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<All>
|
||||
) -> Result<Transaction, ()>
|
||||
);
|
||||
#[cfg(not(taproot))]
|
||||
/// A supertrait for all the traits that a keys interface implements
|
||||
pub trait DynKeysInterfaceTrait:
|
||||
NodeSigner + OutputSpender + SignerProvider<EcdsaSigner = DynSigner> + EntropySource + Send + Sync
|
||||
{
|
||||
#[cfg(test)]
|
||||
fn set_counter(&self, _count: u64) {}
|
||||
}
|
||||
|
||||
#[cfg(taproot)]
|
||||
/// A supertrait for all the traits that a keys interface implements
|
||||
pub trait DynKeysInterfaceTrait:
|
||||
NodeSigner
|
||||
+ OutputSpender
|
||||
+ SignerProvider<EcdsaSigner = DynSigner, TaprootSigner = DynSigner>
|
||||
+ EntropySource
|
||||
+ Send
|
||||
+ Sync
|
||||
{
|
||||
#[cfg(test)]
|
||||
fn set_counter(&self, _count: u64) {}
|
||||
}
|
||||
|
||||
/// A dyn wrapper for PhantomKeysManager
|
||||
pub struct DynPhantomKeysInterface {
|
||||
inner: Box<PhantomKeysManager>,
|
||||
}
|
||||
|
||||
impl DynPhantomKeysInterface {
|
||||
/// Create a new DynPhantomKeysInterface
|
||||
pub fn new(inner: PhantomKeysManager) -> Self {
|
||||
DynPhantomKeysInterface { inner: Box::new(inner) }
|
||||
}
|
||||
}
|
||||
|
||||
delegate!(DynPhantomKeysInterface, NodeSigner,
|
||||
inner,
|
||||
fn get_node_id(, recipient: Recipient) -> Result<PublicKey, ()>,
|
||||
fn sign_gossip_message(, msg: UnsignedGossipMessage) -> Result<Signature, ()>,
|
||||
fn ecdh(, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>,
|
||||
fn sign_invoice(, invoice: &RawBolt11Invoice, recipient: Recipient) -> Result<RecoverableSignature, ()>,
|
||||
fn sign_bolt12_invoice(, invoice: &crate::offers::invoice::UnsignedBolt12Invoice
|
||||
) -> Result<secp256k1::schnorr::Signature, ()>,
|
||||
fn get_inbound_payment_key(,) -> ExpandedKey
|
||||
);
|
||||
|
||||
impl SignerProvider for DynPhantomKeysInterface {
|
||||
type EcdsaSigner = DynSigner;
|
||||
#[cfg(taproot)]
|
||||
type TaprootSigner = DynSigner;
|
||||
|
||||
fn get_destination_script(&self, channel_keys_id: [u8; 32]) -> Result<ScriptBuf, ()> {
|
||||
self.inner.get_destination_script(channel_keys_id)
|
||||
}
|
||||
|
||||
fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> {
|
||||
self.inner.get_shutdown_scriptpubkey()
|
||||
}
|
||||
|
||||
fn generate_channel_keys_id(&self, _inbound: bool, _user_channel_id: u128) -> [u8; 32] {
|
||||
self.inner.generate_channel_keys_id(_inbound, _user_channel_id)
|
||||
}
|
||||
|
||||
fn derive_channel_signer(&self, channel_keys_id: [u8; 32]) -> Self::EcdsaSigner {
|
||||
let inner = self.inner.derive_channel_signer(channel_keys_id);
|
||||
DynSigner::new(inner)
|
||||
}
|
||||
}
|
||||
|
||||
delegate!(DynPhantomKeysInterface, EntropySource, inner,
|
||||
fn get_secure_random_bytes(,) -> [u8; 32]
|
||||
);
|
||||
|
||||
delegate!(DynPhantomKeysInterface, OutputSpender, inner,
|
||||
fn spend_spendable_outputs(,
|
||||
descriptors: &[&SpendableOutputDescriptor], outputs: Vec<TxOut>,
|
||||
change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32,
|
||||
locktime: Option<LockTime>, secp_ctx: &Secp256k1<All>
|
||||
) -> Result<Transaction, ()>
|
||||
);
|
||||
|
||||
impl DynKeysInterfaceTrait for DynPhantomKeysInterface {
|
||||
#[cfg(test)]
|
||||
fn set_counter(&self, count: u64) {
|
||||
self.inner.inner.entropy_source.set_counter(count);
|
||||
}
|
||||
}
|
|
@ -67,3 +67,48 @@ pub mod string {
|
|||
//! [`lightning::types::string`]: crate::types::string
|
||||
pub use lightning_types::string::{PrintableString, UntrustedString};
|
||||
}
|
||||
|
||||
/// A macro to delegate trait implementations to a field of a struct.
|
||||
///
|
||||
/// For example:
|
||||
/// ```ignore
|
||||
/// use lightning::delegate;
|
||||
/// delegate!(A, T, inner,
|
||||
/// fn b(, c: u64) -> u64,
|
||||
/// fn m(mut, d: u64) -> (),
|
||||
/// fn o(, ) -> u64,
|
||||
/// #[cfg(debug_assertions)]
|
||||
/// fn t(,) -> (),
|
||||
/// ;
|
||||
/// type O = u64,
|
||||
/// #[cfg(debug_assertions)]
|
||||
/// type T = (),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// where T is the trait to be implemented, A is the struct
|
||||
/// to implement the trait for, and inner is the field of A
|
||||
/// to delegate the trait implementation to.
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
macro_rules! delegate {
|
||||
($N: ident, $T: ident, $ref: ident,
|
||||
$($(#[$fpat: meta])? fn $f: ident($($mu: ident)?, $($n: ident: $t: ty),*) -> $r: ty),* $(,)?
|
||||
$(;$($(#[$tpat: meta])? type $TN: ident = $TT: ty),*)? $(,)?
|
||||
) => {
|
||||
impl $T for $N {
|
||||
$(
|
||||
$(#[$fpat])?
|
||||
fn $f(&$($mu)? self, $($n: $t),*) -> $r {
|
||||
$T::$f(&$($mu)? *self.$ref, $($n),*)
|
||||
}
|
||||
)*
|
||||
$($(
|
||||
$(#[$tpat])?
|
||||
type $TN = $TT;
|
||||
)*)?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
pub mod dyn_signer;
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::types::payment::PaymentPreimage;
|
|||
#[allow(unused_imports)]
|
||||
use crate::prelude::*;
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
use crate::sync::MutexGuard;
|
||||
use crate::sync::{Arc, Mutex};
|
||||
use core::cmp;
|
||||
|
@ -136,17 +136,17 @@ impl TestChannelSigner {
|
|||
Self { inner, state, disable_revocation_policy_check }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
pub fn get_enforcement_state(&self) -> MutexGuard<EnforcementState> {
|
||||
self.state.lock().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
pub fn enable_op(&self, signer_op: SignerOp) {
|
||||
self.get_enforcement_state().disabled_signer_ops.remove(&signer_op);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
pub fn disable_op(&self, signer_op: SignerOp) {
|
||||
self.get_enforcement_state().disabled_signer_ops.insert(signer_op);
|
||||
}
|
||||
|
@ -284,13 +284,13 @@ impl EcdsaChannelSigner for TestChannelSigner {
|
|||
{
|
||||
if !self.disable_revocation_policy_check {
|
||||
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
|
||||
state.last_holder_revoked_commitment, commitment_number, self.inner.commitment_seed[0])
|
||||
state.last_holder_revoked_commitment, commitment_number, self.inner.channel_keys_id()[0])
|
||||
}
|
||||
}
|
||||
Ok(self.inner.sign_holder_commitment(channel_parameters, commitment_tx, secp_ctx).unwrap())
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "unsafe_revoked_tx_signing"))]
|
||||
#[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))]
|
||||
fn unsafe_sign_holder_commitment(
|
||||
&self, channel_parameters: &ChannelTransactionParameters,
|
||||
commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>,
|
||||
|
@ -358,7 +358,7 @@ impl EcdsaChannelSigner for TestChannelSigner {
|
|||
{
|
||||
if !self.disable_revocation_policy_check {
|
||||
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
|
||||
state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.commitment_seed[0])
|
||||
state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.channel_keys_id()[0])
|
||||
}
|
||||
}
|
||||
assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input());
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::blinded_path::payment::{BlindedPaymentPath, ReceiveTlvs};
|
|||
use crate::chain;
|
||||
use crate::chain::chaininterface;
|
||||
use crate::chain::chaininterface::ConfirmationTarget;
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW;
|
||||
use crate::chain::chainmonitor::{ChainMonitor, Persist};
|
||||
use crate::chain::channelmonitor::{
|
||||
|
@ -23,7 +23,7 @@ use crate::chain::transaction::OutPoint;
|
|||
use crate::chain::WatchedOutput;
|
||||
use crate::events;
|
||||
use crate::events::bump_transaction::{Utxo, WalletSource};
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
use crate::ln::chan_utils::CommitmentTransaction;
|
||||
use crate::ln::channel_state::ChannelDetails;
|
||||
use crate::ln::channelmanager;
|
||||
|
@ -46,13 +46,17 @@ use crate::routing::router::{
|
|||
use crate::routing::scoring::{ChannelUsage, ScoreLookUp, ScoreUpdate};
|
||||
use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult};
|
||||
use crate::sign;
|
||||
use crate::sign::ChannelSigner;
|
||||
use crate::sync::RwLock;
|
||||
use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures};
|
||||
use crate::util::config::UserConfig;
|
||||
use crate::util::logger::{Logger, Record};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::util::mut_global::MutGlobal;
|
||||
use crate::util::persist::{KVStore, MonitorName};
|
||||
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
||||
use crate::util::test_channel_signer::{EnforcementState, TestChannelSigner};
|
||||
use crate::util::dyn_signer::{DynPhantomKeysInterface, DynSigner, DynKeysInterfaceTrait};
|
||||
|
||||
use bitcoin::amount::Amount;
|
||||
use bitcoin::block::Block;
|
||||
|
@ -505,14 +509,14 @@ impl<'a> chain::Watch<TestChannelSigner> for TestChainMonitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
struct JusticeTxData {
|
||||
justice_tx: Transaction,
|
||||
value: Amount,
|
||||
commitment_number: u64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
pub(crate) struct WatchtowerPersister {
|
||||
persister: TestPersister,
|
||||
/// Upon a new commitment_signed, we'll get a
|
||||
|
@ -526,9 +530,8 @@ pub(crate) struct WatchtowerPersister {
|
|||
destination_script: ScriptBuf,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
impl WatchtowerPersister {
|
||||
#[cfg(test)]
|
||||
pub(crate) fn new(destination_script: ScriptBuf) -> Self {
|
||||
let unsigned_justice_tx_data = Mutex::new(new_hash_map());
|
||||
let watchtower_state = Mutex::new(new_hash_map());
|
||||
|
@ -540,7 +543,6 @@ impl WatchtowerPersister {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn justice_tx(
|
||||
&self, channel_id: ChannelId, commitment_txid: &Txid,
|
||||
) -> Option<Transaction> {
|
||||
|
@ -571,7 +573,7 @@ impl WatchtowerPersister {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "_test_utils"))]
|
||||
impl<Signer: sign::ecdsa::EcdsaChannelSigner> Persist<Signer> for WatchtowerPersister {
|
||||
fn persist_new_channel(
|
||||
&self, monitor_name: MonitorName, data: &ChannelMonitor<Signer>,
|
||||
|
@ -1547,7 +1549,7 @@ impl SignerProvider for TestKeysInterface {
|
|||
|
||||
fn derive_channel_signer(&self, channel_keys_id: [u8; 32]) -> TestChannelSigner {
|
||||
let keys = self.backing.derive_channel_signer(channel_keys_id);
|
||||
let state = self.make_enforcement_state_cell(keys.commitment_seed);
|
||||
let state = self.make_enforcement_state_cell(keys.channel_keys_id());
|
||||
let signer =
|
||||
TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check);
|
||||
#[cfg(test)]
|
||||
|
@ -1578,6 +1580,26 @@ impl SignerProvider for TestKeysInterface {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub static SIGNER_FACTORY: MutGlobal<Arc<dyn TestSignerFactory>> = MutGlobal::new(|| { Arc::new(DefaultSignerFactory()) });
|
||||
|
||||
pub trait TestSignerFactory: Send + Sync {
|
||||
/// Make a dynamic signer
|
||||
fn make_signer(&self, seed: &[u8; 32], now: Duration) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner=DynSigner>>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct DefaultSignerFactory();
|
||||
|
||||
impl TestSignerFactory for DefaultSignerFactory {
|
||||
fn make_signer(&self, seed: &[u8; 32], now: Duration) -> Box<dyn DynKeysInterfaceTrait<EcdsaSigner=DynSigner>> {
|
||||
let phantom = sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed);
|
||||
let dphantom = DynPhantomKeysInterface::new(phantom);
|
||||
let backing = Box::new(dphantom) as Box<dyn DynKeysInterfaceTrait<EcdsaSigner=DynSigner>>;
|
||||
backing
|
||||
}
|
||||
}
|
||||
|
||||
impl TestKeysInterface {
|
||||
pub fn new(seed: &[u8; 32], network: Network) -> Self {
|
||||
let now = Duration::from_secs(genesis_block(network).header.time as u64);
|
||||
|
@ -1607,15 +1629,13 @@ impl TestKeysInterface {
|
|||
self.derive_channel_signer(*id)
|
||||
}
|
||||
|
||||
fn make_enforcement_state_cell(
|
||||
&self, commitment_seed: [u8; 32],
|
||||
) -> Arc<Mutex<EnforcementState>> {
|
||||
fn make_enforcement_state_cell(&self, keys_id: [u8; 32]) -> Arc<Mutex<EnforcementState>> {
|
||||
let mut states = self.enforcement_states.lock().unwrap();
|
||||
if !states.contains_key(&commitment_seed) {
|
||||
if !states.contains_key(&keys_id) {
|
||||
let state = EnforcementState::new();
|
||||
states.insert(commitment_seed, Arc::new(Mutex::new(state)));
|
||||
states.insert(keys_id, Arc::new(Mutex::new(state)));
|
||||
}
|
||||
let cell = states.get(&commitment_seed).unwrap();
|
||||
let cell = states.get(&keys_id).unwrap();
|
||||
Arc::clone(cell)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue