use crate::zisklib::{
is_on_subgroup_bls12_381,
lib::utils::{eq, is_one, lt},
};
use super::{
constants::{G1_GENERATOR, G1_IDENTITY, G2_GENERATOR, G2_IDENTITY, R, TRUSTED_SETUP_TAU_G2},
curve::{decompress_bls12_381, scalar_mul_bls12_381, sub_complete_bls12_381},
pairing::pairing_batch_bls12_381,
twist::{neg_twist_bls12_381, scalar_mul_twist_bls12_381, sub_complete_twist_bls12_381},
};
pub fn verify_kzg_proof(
z_bytes: &[u8; 32],
y_bytes: &[u8; 32],
commitment_bytes: &[u8; 48],
proof_bytes: &[u8; 48],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> bool {
let (commitment, commitment_is_inf) = match decompress_bls12_381(
commitment_bytes,
#[cfg(feature = "hints")]
hints,
) {
Ok((result, is_infinity)) => (result, is_infinity),
Err(_) => return false,
};
if !commitment_is_inf
&& !is_on_subgroup_bls12_381(
&commitment,
#[cfg(feature = "hints")]
hints,
)
{
return false;
}
let (proof, proof_is_inf) = match decompress_bls12_381(
proof_bytes,
#[cfg(feature = "hints")]
hints,
) {
Ok((result, is_infinity)) => (result, is_infinity),
Err(_) => return false,
};
if !proof_is_inf
&& !is_on_subgroup_bls12_381(
&proof,
#[cfg(feature = "hints")]
hints,
)
{
return false;
}
let z = match scalar_bytes_be_to_u64_le_canonical(z_bytes) {
Some(s) => s,
None => return false,
};
let y = match scalar_bytes_be_to_u64_le_canonical(y_bytes) {
Some(s) => s,
None => return false,
};
let tau_g2 = TRUSTED_SETUP_TAU_G2;
let g1 = G1_GENERATOR;
let g2 = G2_GENERATOR;
let y_g1 = scalar_mul_bls12_381(
&g1,
&y,
#[cfg(feature = "hints")]
hints,
);
let c_minus_y = sub_complete_bls12_381(
&commitment,
&y_g1,
#[cfg(feature = "hints")]
hints,
);
let z_g2 = scalar_mul_twist_bls12_381(
&g2,
&z,
#[cfg(feature = "hints")]
hints,
);
let t_minus_z = sub_complete_twist_bls12_381(
&tau_g2,
&z_g2,
#[cfg(feature = "hints")]
hints,
);
let c_minus_y_is_inf = eq(&c_minus_y, &G1_IDENTITY);
let proof_is_inf = eq(&proof, &G1_IDENTITY);
let t_minus_z_is_inf = eq(&t_minus_z, &G2_IDENTITY);
if c_minus_y_is_inf {
return proof_is_inf || t_minus_z_is_inf;
}
if proof_is_inf || t_minus_z_is_inf {
return false;
}
let neg_g2 = neg_twist_bls12_381(
&g2,
#[cfg(feature = "hints")]
hints,
);
let g1_points = [c_minus_y, proof];
let g2_points = [neg_g2, t_minus_z];
is_one(&pairing_batch_bls12_381(
&g1_points,
&g2_points,
#[cfg(feature = "hints")]
hints,
))
}
#[allow(dead_code)]
#[inline]
pub(crate) unsafe fn verify_kzg_proof_c(
z: *const u8,
y: *const u8,
commitment: *const u8,
proof: *const u8,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> bool {
let z_bytes: &[u8; 32] = &*(z as *const [u8; 32]);
let y_bytes: &[u8; 32] = &*(y as *const [u8; 32]);
let commitment_bytes: &[u8; 48] = &*(commitment as *const [u8; 48]);
let proof_bytes: &[u8; 48] = &*(proof as *const [u8; 48]);
verify_kzg_proof(
z_bytes,
y_bytes,
commitment_bytes,
proof_bytes,
#[cfg(feature = "hints")]
hints,
)
}
fn scalar_bytes_be_to_u64_le_canonical(bytes: &[u8; 32]) -> Option<[u64; 4]> {
let mut scalar = [0u64; 4];
for i in 0..4 {
for j in 0..8 {
scalar[3 - i] |= (bytes[i * 8 + j] as u64) << (8 * (7 - j));
}
}
if !lt(&scalar, &R) {
return None;
}
Some(scalar)
}