use alloc::vec::Vec;
use ark_ec::pairing::Pairing;
use ark_serialize::*;
use serde::{Deserialize, Serialize};
use utils::{
join, misc::seq_pairs_satisfy, randomized_pairing_check::RandomizedPairingChecker,
try_iter::InvalidPair,
};
use crate::{
helpers::{pluck_missed, take_while_satisfy, SendIfParallel, WithSchnorrResponse},
setup::{PreparedPublicKey, PreparedSignatureParams},
};
use super::*;
#[derive(
Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
)]
#[serde(bound = "")]
pub struct SignaturePoK<E: Pairing> {
pub(super) k: WithSchnorrResponse<E::G2Affine, K<E>>,
pub(super) randomized_sig: RandomizedSignature<E>,
}
impl<E: Pairing> SignaturePoK<E> {
pub fn verify<'a, I>(
&self,
challenge: &E::ScalarField,
indexed_revealed_messages_sorted_by_index: I,
pk: &PublicKey<E>,
params: &SignatureParams<E>,
) -> Result<()>
where
I: IntoIterator<Item = (usize, &'a E::ScalarField)>,
I::IntoIter: Clone + SendIfParallel,
{
let revealed_messages = indexed_revealed_messages_sorted_by_index.into_iter();
let revealed_indices = revealed_messages.clone().map(|(idx, _)| idx);
let (sig_res, proof_res) = join!(
self.randomized_sig
.verify(revealed_messages, &self.k.value, pk, params)
.map_err(SignaturePoKError::SignatureError),
self.verify_response(challenge, revealed_indices, pk, params)
);
proof_res.and(sig_res)
}
pub fn challenge_contribution<W: Write>(
&self,
mut writer: W,
PublicKey { beta_tilde, .. }: &PublicKey<E>,
SignatureParams { g, .. }: &SignatureParams<E>,
) -> Result<(), SchnorrError> {
beta_tilde
.serialize_compressed(&mut writer)
.map_err(SchnorrError::Serialization)?;
g.serialize_compressed(&mut writer)
.map_err(SchnorrError::Serialization)?;
self.k.challenge_contribution(&mut writer)
}
pub fn response_for_message<I>(
&self,
msg_idx: usize,
unique_sorted_revealed_msg_ids: I,
) -> Result<&E::ScalarField>
where
I: IntoIterator<Item = usize>,
{
let mut invalid_idx_pair = None;
let unique_sorted_msg_ids = take_while_satisfy(
unique_sorted_revealed_msg_ids,
seq_pairs_satisfy(|a, b| a < b),
&mut invalid_idx_pair,
);
let res = self
.k
.response_for_message(msg_idx, unique_sorted_msg_ids)
.map_err(schnorr_error)
.map_err(SignaturePoKError::SchnorrError);
if let Some(InvalidPair(previous, current)) = invalid_idx_pair {
Err(SignaturePoKError::RevealedIndicesMustBeUniqueAndSorted { previous, current })
} else {
res
}
}
pub fn verify_with_randomized_pairing_checker<'a, MI>(
&self,
challenge: &E::ScalarField,
indexed_revealed_messages_sorted_by_index: MI,
pk: &PreparedPublicKey<E>,
params: &PreparedSignatureParams<E>,
pairing_checker: &mut RandomizedPairingChecker<E>,
) -> Result<()>
where
MI: IntoIterator<Item = (usize, &'a E::ScalarField)>,
MI::IntoIter: Clone + SendIfParallel,
{
let revealed_messages = indexed_revealed_messages_sorted_by_index.into_iter();
let revealed_indices = revealed_messages.clone().map(|(idx, _)| idx);
let (resp_res, pairing_res) = join!(
self.verify_response(challenge, revealed_indices, pk, params),
RandomizedSignature::<E>::prepare_pairing_values(
revealed_messages,
&self.k.value,
pk,
params,
)
.map_err(SignaturePoKError::SignatureError)
);
let (p1, p2) = resp_res.and(pairing_res)?;
let (sigma_1, sigma_2) = self.randomized_sig.split();
pairing_checker.add_sources(&sigma_1, p1, &sigma_2, p2);
Ok(())
}
fn verify_response<I>(
&self,
challenge: &E::ScalarField,
sorted_unique_revealed_indices: I,
pk: &PublicKey<E>,
params: &SignatureParams<E>,
) -> Result<()>
where
I: IntoIterator<Item = usize>,
{
let mut invalid_idx_pair = None;
let committed_beta_tilde = pluck_missed(
take_while_satisfy(
sorted_unique_revealed_indices,
seq_pairs_satisfy(|a, b| a < b),
&mut invalid_idx_pair,
),
&pk.beta_tilde,
);
let verification_res = self
.k
.verify_challenge(challenge, committed_beta_tilde, ¶ms.g_tilde)
.map_err(schnorr_error)
.map_err(SignaturePoKError::SchnorrError);
if let Some(InvalidPair(previous, current)) = invalid_idx_pair {
Err(SignaturePoKError::RevealedIndicesMustBeUniqueAndSorted { previous, current })
} else {
verification_res
}
}
}