extern crate alloc;
use alloc::vec::Vec;
use blstrs::{G1Projective, Scalar};
use core::iter;
use group::{ff::Field, Group};
use crate::generators::{BulletproofGens, PedersenGens};
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
pub struct BitCommitment {
pub(super) V_j: G1Projective,
pub(super) A_j: G1Projective,
pub(super) S_j: G1Projective,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
pub struct BitChallenge {
pub(super) y: Scalar,
pub(super) z: Scalar,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
pub struct PolyCommitment {
pub(super) T_1_j: G1Projective,
pub(super) T_2_j: G1Projective,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
pub struct PolyChallenge {
pub(super) x: Scalar,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ProofShare {
pub(super) t_x: Scalar,
pub(super) t_x_blinding: Scalar,
pub(super) e_blinding: Scalar,
pub(super) l_vec: Vec<Scalar>,
pub(super) r_vec: Vec<Scalar>,
}
impl ProofShare {
pub(super) fn check_size(
&self,
expected_n: usize,
bp_gens: &BulletproofGens,
j: usize,
) -> Result<(), ()> {
if self.l_vec.len() != expected_n {
return Err(());
}
if self.r_vec.len() != expected_n {
return Err(());
}
if expected_n > bp_gens.gens_capacity {
return Err(());
}
if j >= bp_gens.party_capacity {
return Err(());
}
Ok(())
}
pub(super) fn audit_share(
&self,
bp_gens: &BulletproofGens,
pc_gens: &PedersenGens,
j: usize,
bit_commitment: &BitCommitment,
bit_challenge: &BitChallenge,
poly_commitment: &PolyCommitment,
poly_challenge: &PolyChallenge,
) -> Result<(), ()> {
use crate::inner_product_proof::inner_product;
use crate::util;
let n = self.l_vec.len();
self.check_size(n, bp_gens, j)?;
let (y, z) = (&bit_challenge.y, &bit_challenge.z);
let x = &poly_challenge.x;
let zz = z * z;
let minus_z = -z;
let z_j = util::scalar_exp_vartime(z, j as u64); let y_jn = util::scalar_exp_vartime(y, (j * n) as u64); let y_jn_inv: Scalar = Option::from(y_jn.invert()).ok_or(())?; let y_inv = Option::from(y.invert()).ok_or(())?;
if self.t_x != inner_product(&self.l_vec, &self.r_vec) {
return Err(());
}
let g = self.l_vec.iter().map(|l_i| minus_z - l_i);
let h = self
.r_vec
.iter()
.zip(util::exp_iter(Scalar::from(2u64)))
.zip(util::exp_iter(y_inv))
.map(|((r_i, exp_2), exp_y_inv)| {
z + exp_y_inv * y_jn_inv * (-r_i) + exp_y_inv * y_jn_inv * (zz * z_j * exp_2)
});
let P_check: G1Projective = iter::once(Scalar::one())
.chain(iter::once(*x))
.chain(iter::once(-self.e_blinding))
.chain(g)
.chain(h)
.zip(
iter::once(&bit_commitment.A_j)
.chain(iter::once(&bit_commitment.S_j))
.chain(iter::once(&pc_gens.B_blinding))
.chain(bp_gens.share(j).G(n))
.chain(bp_gens.share(j).H(n)),
)
.map(|(s, P)| P * s)
.sum();
if !bool::from(P_check.is_identity()) {
return Err(());
}
let sum_of_powers_y = util::sum_of_powers(&y, n);
let sum_of_powers_2 = util::sum_of_powers(&Scalar::from(2u64), n);
let delta = (z - zz) * sum_of_powers_y * y_jn - z * zz * sum_of_powers_2 * z_j;
let t_check: G1Projective = iter::once(zz * z_j)
.chain(iter::once(*x))
.chain(iter::once(x * x))
.chain(iter::once(delta - self.t_x))
.chain(iter::once(-self.t_x_blinding))
.zip(
iter::once(&bit_commitment.V_j)
.chain(iter::once(&poly_commitment.T_1_j))
.chain(iter::once(&poly_commitment.T_2_j))
.chain(iter::once(&pc_gens.B))
.chain(iter::once(&pc_gens.B_blinding)),
)
.map(|(s, P)| P * s)
.sum();
if bool::from(t_check.is_identity()) {
Ok(())
} else {
Err(())
}
}
}