use crate::{ generic_aggregate_public_key::TAggregatePublicKey, generic_aggregate_signature::{GenericAggregateSignature, TAggregateSignature}, generic_public_key::{GenericPublicKey, TPublicKey}, generic_signature::{GenericSignature, TSignature}, Hash256, }; use std::borrow::Cow; use std::marker::PhantomData; /// A generic way to represent a `GenericSignature` or `GenericAggregateSignature`. pub struct WrappedSignature<'a, Pub, AggPub, Sig, AggSig> where Pub: TPublicKey + Clone, AggPub: Clone, Sig: Clone, AggSig: Clone, { aggregate: Cow<'a, GenericAggregateSignature>, } impl<'a, Pub, AggPub, Sig, AggSig> From<&'a GenericSignature> for WrappedSignature<'a, Pub, AggPub, Sig, AggSig> where Pub: TPublicKey + Clone, AggPub: Clone, Sig: TSignature + Clone, AggSig: TAggregateSignature + Clone, { fn from(sig: &'a GenericSignature) -> Self { let mut aggregate: GenericAggregateSignature = GenericAggregateSignature::infinity(); aggregate.add_assign(sig); WrappedSignature { aggregate: Cow::Owned(aggregate), } } } impl<'a, Pub, AggPub, Sig, AggSig> From<&'a GenericAggregateSignature> for WrappedSignature<'a, Pub, AggPub, Sig, AggSig> where Pub: TPublicKey + Clone, AggPub: Clone, Sig: Clone, AggSig: Clone, { fn from(aggregate: &'a GenericAggregateSignature) -> Self { WrappedSignature { aggregate: Cow::Borrowed(aggregate), } } } /// A generic way to represent a signature across a message by multiple public keys. /// /// This struct is primarily useful in a collection (e.g., `Vec`) so we can perform /// multiple-signature verification which is much faster than verifying each signature /// individually. #[derive(Clone)] pub struct GenericSignatureSet<'a, Pub, AggPub, Sig, AggSig> where Pub: TPublicKey + Clone, AggPub: Clone, Sig: Clone, AggSig: Clone, { pub signature: Cow<'a, GenericAggregateSignature>, pub(crate) signing_keys: Vec>>, pub(crate) message: Hash256, _phantom: PhantomData, } impl<'a, Pub, AggPub, Sig, AggSig> GenericSignatureSet<'a, Pub, AggPub, Sig, AggSig> where Pub: TPublicKey + Clone, AggPub: TAggregatePublicKey + Clone, Sig: TSignature + Clone, AggSig: TAggregateSignature + Clone, { /// Instantiate self where `signature` is only signed by a single public key. pub fn single_pubkey( signature: impl Into>, signing_key: Cow<'a, GenericPublicKey>, message: Hash256, ) -> Self { Self { signature: signature.into().aggregate, signing_keys: vec![signing_key], message, _phantom: PhantomData, } } /// Instantiate self where `signature` is signed by multiple public keys. pub fn multiple_pubkeys( signature: impl Into>, signing_keys: Vec>>, message: Hash256, ) -> Self { Self { signature: signature.into().aggregate, signing_keys, message, _phantom: PhantomData, } } /// Returns `true` if `self.signature` is a signature across `self.message` by /// `self.signing_keys`. pub fn verify(self) -> bool { let pubkeys = self .signing_keys .iter() .map(|pk| pk.as_ref()) .collect::>(); self.signature .fast_aggregate_verify(self.message, &pubkeys[..]) } }