use alloc::vec::Vec;
use itertools::Itertools;
use core::{borrow::Borrow, iter::once};
use ark_ec::{pairing::Pairing, CurveGroup};
use ark_serialize::*;
use ark_std::rand::RngCore;
use schnorr_pok::{error::SchnorrError, SchnorrCommitment};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use utils::serde_utils::ArkObjectBytes;
use crate::helpers::{rand, OwnedPairs, Pairs, WithSchnorrAndBlindings, WithSchnorrResponse};
#[serde_as]
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
CanonicalSerialize,
CanonicalDeserialize,
Serialize,
Deserialize,
)]
pub struct MultiMessageCommitment<E: Pairing>(#[serde_as(as = "ArkObjectBytes")] E::G1Affine);
utils::impl_deref! { MultiMessageCommitment<E: Pairing>(E::G1Affine) }
impl<E: Pairing> MultiMessageCommitment<E> {
pub fn new(
h_m_pairs: Pairs<impl Borrow<E::G1Affine>, impl Borrow<E::ScalarField>>,
g: &E::G1Affine,
o: &E::ScalarField,
) -> Self {
let bases_exps: OwnedPairs<_, _> = Self::bases_exps(g, o, h_m_pairs).collect();
Self(bases_exps.msm().into_affine())
}
pub fn exps(
&o: &E::ScalarField,
m: impl IntoIterator<Item = impl Borrow<E::ScalarField>>,
) -> impl Iterator<Item = E::ScalarField> {
once(o).chain(m.into_iter().map(|v| *v.borrow()))
}
pub fn bases(
&g: &E::G1Affine,
h: impl IntoIterator<Item = impl Borrow<E::G1Affine>>,
) -> impl Iterator<Item = E::G1Affine> {
once(g).chain(h.into_iter().map(|v| *v.borrow()))
}
pub fn bases_exps<'a>(
g: &E::G1Affine,
o: &E::ScalarField,
h_m_pairs: Pairs<'a, 'a, impl Borrow<E::G1Affine>, impl Borrow<E::ScalarField>>,
) -> impl Iterator<Item = (E::G1Affine, E::ScalarField)> + 'a {
let (h, m) = h_m_pairs.split();
let bases = Self::bases(g, h.iter().map(Borrow::borrow));
let exps = Self::exps(o, m.iter().map(Borrow::borrow));
bases.zip(exps)
}
}
impl<E: Pairing> WithSchnorrAndBlindings<E::G1Affine, MultiMessageCommitment<E>> {
pub fn response(
&self,
o: &E::ScalarField,
m: impl IntoIterator<Item = impl Borrow<E::ScalarField>>,
challenge: &E::ScalarField,
) -> Result<WithSchnorrResponse<E::G1Affine, MultiMessageCommitment<E>>, SchnorrError> {
let witnesses = MultiMessageCommitment::<E>::exps(o, m).collect_vec();
self.schnorr
.response(&witnesses, challenge)
.map(|response| {
let msg_end = response.0.len();
WithSchnorrResponse::new(response, self, 1..msg_end)
})
}
}
impl<E> WithSchnorrResponse<E::G1Affine, MultiMessageCommitment<E>>
where
E: Pairing,
{
pub fn verify_challenge(
&self,
challenge: &E::ScalarField,
g: &E::G1Affine,
committed_h: impl IntoIterator<Item = impl Borrow<E::G1Affine>>,
) -> Result<(), SchnorrError> {
let Self {
response,
value: com,
commitment: t,
..
} = self;
let bases = MultiMessageCommitment::<E>::bases(g, committed_h).collect_vec();
response.is_valid(&bases, com, t, challenge)
}
}
pub(crate) struct MultiMessageCommitmentRandomness<'a, E: Pairing> {
o: E::ScalarField,
h_blindings_pairs: Pairs<'a, 'a, &'a E::G1Affine, E::ScalarField>,
g: &'a E::G1Affine,
}
impl<'a, E: Pairing> MultiMessageCommitmentRandomness<'a, E> {
pub fn init<R: RngCore>(
rng: &mut R,
h_blindings_pairs: Pairs<'a, 'a, &'a E::G1Affine, E::ScalarField>,
g: &'a E::G1Affine,
) -> Self {
let o = rand(rng);
Self {
o,
h_blindings_pairs,
g,
}
}
pub fn commit(&self) -> SchnorrCommitment<E::G1Affine> {
let Self {
o,
g,
h_blindings_pairs,
} = self;
let (bases, exps): (Vec<_>, _) =
MultiMessageCommitment::<E>::bases_exps(g, o, *h_blindings_pairs).unzip();
SchnorrCommitment::new(&bases, exps)
}
}