use core::borrow::Borrow;
#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(feature = "std")]
use ark_ec::AffineRepr;
#[cfg(feature = "std")]
use ark_ff::field_hashers::{DefaultFieldHasher, HashToField};
#[cfg(feature = "std")]
use ark_serialize::CanonicalSerialize;
#[cfg(feature = "std")]
use digest::DynDigest;
#[cfg(feature = "std")]
use digest::FixedOutputReset;
use ark_ec::CurveGroup;
use alloc::vec::Vec;
use super::*;
pub type PublicKeyProjective<E> = <E as EngineBLS>::PublicKeyGroup;
pub type PublicKeyAffine<E> = <<E as EngineBLS>::PublicKeyGroup as CurveGroup>::Affine;
pub type SignatureProjective<E> = <E as EngineBLS>::SignatureGroup;
pub type SignatureAffine<E> = <<E as EngineBLS>::SignatureGroup as CurveGroup>::Affine;
pub fn verify_unoptimized<S: Signed>(s: S) -> bool {
let signature = S::E::prepare_signature(s.signature().0);
let prepared = s
.messages_and_publickeys()
.map(|(message, public_key)| {
(
S::E::prepare_public_key(public_key.borrow().0),
S::E::prepare_signature(message.borrow().hash_to_signature_curve::<S::E>()),
)
})
.collect::<Vec<(_, _)>>();
S::E::verify_prepared(signature, prepared.iter())
}
pub fn verify_simple<S: Signed>(s: S) -> bool {
let signature = s.signature().0;
let itr = s.messages_and_publickeys();
let l = {
let (lower, upper) = itr.size_hint();
upper.unwrap_or(lower)
};
let mut gpk = Vec::with_capacity(l);
let mut gms = Vec::with_capacity(l + 1);
for (message, publickey) in itr {
gpk.push(publickey.borrow().0.clone());
gms.push(message.borrow().hash_to_signature_curve::<S::E>());
}
let gpk = <<S as Signed>::E as EngineBLS>::PublicKeyGroup::normalize_batch(gpk.as_mut_slice());
gms.push(signature);
let mut gms =
<<S as Signed>::E as EngineBLS>::SignatureGroup::normalize_batch(gms.as_mut_slice());
let signature = <<S as Signed>::E as EngineBLS>::prepare_signature(gms.pop().unwrap());
let prepared = gpk
.iter()
.zip(gms)
.map(|(pk, m)| {
(
<<S as Signed>::E as EngineBLS>::prepare_public_key(*pk),
<<S as Signed>::E as EngineBLS>::prepare_signature(m),
)
})
.collect::<Vec<(_, _)>>();
S::E::verify_prepared(signature, prepared.iter())
}
#[cfg(feature = "std")]
pub fn verify_with_distinct_messages<S: Signed>(signed: S, normalize_public_keys: bool) -> bool {
let signature = signed.signature().0;
let itr = signed.messages_and_publickeys();
let l = {
let (lower, upper) = itr.size_hint();
upper.unwrap_or(lower)
};
let mut publickeys = Vec::with_capacity(l);
let mut messages = Vec::with_capacity(l + 1);
for (m, pk) in itr {
publickeys.push(pk.borrow().0.clone());
messages.push(m.borrow().hash_to_signature_curve::<S::E>());
}
let mut affine_publickeys = if normalize_public_keys {
<<S as Signed>::E as EngineBLS>::PublicKeyGroup::normalize_batch(&publickeys)
} else {
publickeys
.iter()
.map(|pk| pk.into_affine())
.collect::<Vec<_>>()
};
type AA<E> = (PublicKeyAffine<E>, SignatureProjective<E>);
let mut pks_n_ms = HashMap::with_capacity(l);
for (pk, m) in affine_publickeys.drain(..).zip(messages.drain(..)) {
let mut pk_uncompressed = vec![0; pk.uncompressed_size()];
pk.serialize_uncompressed(&mut pk_uncompressed[..]).unwrap();
pks_n_ms
.entry(pk_uncompressed)
.and_modify(|(_pk0, m0): &mut AA<S::E>| {
*m0 += m;
})
.or_insert((pk, m));
}
let mut publickeys = Vec::with_capacity(l);
for (_, (pk, m)) in pks_n_ms.drain() {
messages.push(m);
publickeys.push(pk.clone());
}
messages.push(signature);
let mut affine_messages =
<<S as Signed>::E as EngineBLS>::SignatureGroup::normalize_batch(messages.as_mut_slice());
let signature =
<<S as Signed>::E as EngineBLS>::prepare_signature(affine_messages.pop().unwrap());
let prepared = publickeys
.iter()
.zip(messages)
.map(|(pk, m)| {
(
<<S as Signed>::E as EngineBLS>::prepare_public_key(*pk),
<<S as Signed>::E as EngineBLS>::prepare_signature(m),
)
})
.collect::<Vec<(_, _)>>();
S::E::verify_prepared(signature, prepared.iter())
}
#[cfg(feature = "std")]
pub fn verify_using_aggregated_auxiliary_public_keys<
E: EngineBLS,
H: DynDigest + FixedOutputReset + Default + Clone,
>(
signed: &single_pop_aggregator::SignatureAggregatorAssumingPoP<E>,
normalize_public_keys: bool,
aggregated_aux_pub_key: <E as EngineBLS>::SignatureGroup,
) -> bool {
let signature = Signed::signature(&signed).0;
let mut signature_as_bytes = vec![0; signature.compressed_size()];
signature
.serialize_compressed(&mut signature_as_bytes[..])
.expect("compressed size has been alocated");
let itr = signed.messages_and_publickeys();
let l = {
let (lower, upper) = itr.size_hint();
upper.unwrap_or(lower)
};
let (first_message, first_public_key) = match signed.messages_and_publickeys().next() {
Some((first_message, first_public_key)) => (first_message, first_public_key),
None => return false,
};
let mut first_public_key_as_bytes = vec![0; first_public_key.compressed_size()];
first_public_key
.serialize_compressed(&mut first_public_key_as_bytes[..])
.expect("compressed size has been alocated");
let first_message_point = first_message.hash_to_signature_curve::<E>();
let first_message_point_as_bytes = E::signature_point_to_byte(&first_message_point);
let mut aggregated_aux_pub_key_as_bytes = vec![0; aggregated_aux_pub_key.compressed_size()];
aggregated_aux_pub_key
.serialize_compressed(&mut aggregated_aux_pub_key_as_bytes[..])
.expect("compressed size has been alocated");
let pseudo_random_scalar_seed = [
first_message_point_as_bytes,
first_public_key_as_bytes,
aggregated_aux_pub_key_as_bytes,
signature_as_bytes,
]
.concat();
let hasher = <DefaultFieldHasher<H> as HashToField<E::Scalar>>::new(&[]);
let pseudo_random_scalar: E::Scalar =
hasher.hash_to_field::<1>(&pseudo_random_scalar_seed[..])[0];
let signature = signature + aggregated_aux_pub_key * pseudo_random_scalar;
let mut publickeys = Vec::with_capacity(l);
let mut messages = Vec::with_capacity(l + 1);
for (m, pk) in itr {
publickeys.push(pk.0.clone());
messages.push(
m.hash_to_signature_curve::<E>()
+ E::SignatureGroupAffine::generator() * pseudo_random_scalar,
);
}
let mut affine_publickeys = if normalize_public_keys {
<E as EngineBLS>::PublicKeyGroup::normalize_batch(&publickeys)
} else {
publickeys
.iter()
.map(|pk| pk.into_affine())
.collect::<Vec<_>>()
};
type AA<E> = (PublicKeyAffine<E>, SignatureProjective<E>);
let mut pks_n_ms = HashMap::with_capacity(l);
for (pk, m) in affine_publickeys.drain(..).zip(messages.drain(..)) {
let mut pk_uncompressed = vec![0; pk.uncompressed_size()];
pk.serialize_uncompressed(&mut pk_uncompressed[..]).unwrap();
pks_n_ms
.entry(pk_uncompressed)
.and_modify(|(_pk0, m0): &mut AA<E>| {
*m0 += m;
})
.or_insert((pk, m));
}
let mut publickeys = Vec::with_capacity(l);
for (_, (pk, m)) in pks_n_ms.drain() {
messages.push(m);
publickeys.push(pk.clone());
}
messages.push(signature);
let mut affine_messages =
<E as EngineBLS>::SignatureGroup::normalize_batch(messages.as_mut_slice());
let signature = <E as EngineBLS>::prepare_signature(affine_messages.pop().unwrap());
let prepared = publickeys
.iter()
.zip(messages)
.map(|(pk, m)| {
(
<E as EngineBLS>::prepare_public_key(*pk),
<E as EngineBLS>::prepare_signature(m),
)
})
.collect::<Vec<(_, _)>>();
E::verify_prepared(signature, prepared.iter())
}