chore(zk): refactor hashes to reuse code between proof and verify

This commit is contained in:
Nicolas Sarlin
2025-06-16 09:59:33 +02:00
committed by Nicolas Sarlin
parent 58f7457660
commit ce7c15585e
2 changed files with 876 additions and 615 deletions

View File

@@ -0,0 +1,773 @@
/// Scalar generation using the hash random oracle
use crate::{
curve_api::{Curve, FieldOps},
proofs::pke_v2::{compute_crs_params, inf_norm_bound_to_euclidean_squared},
};
use super::{PKEv2DomainSeparators, PublicCommit, PublicParams};
// The scalar used for the proof are generated using sha3 as a random oracle. The inputs of the hash
// that generates a given scalar are reused for the subsequent hashes. We use the typestate pattern
// to propagate the inputs from one hash to the next.
struct RInputs<'a> {
ds: &'a PKEv2DomainSeparators,
sid_bytes: Box<[u8]>,
metadata: &'a [u8],
x_bytes: Box<[u8]>,
C_hat_e_bytes: &'a [u8],
C_e_bytes: &'a [u8],
C_r_tilde_bytes: &'a [u8],
D: usize,
m: usize,
n: usize,
k: usize,
d: usize,
}
pub(super) struct RHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
}
impl<'a> RHash<'a> {
pub(super) fn new<G: Curve>(
public: (&'a PublicParams<G>, &PublicCommit<G>),
metadata: &'a [u8],
C_hat_e_bytes: &'a [u8],
C_e_bytes: &'a [u8],
C_r_tilde_bytes: &'a [u8],
) -> (Box<[i8]>, Self) {
let (
&PublicParams {
g_lists: _,
D: _,
n,
d,
k: _,
B_bound_squared: _,
B_inf,
q,
t: t_input,
msbs_zero_padding_bit_count,
bound_type,
sid,
domain_separators: ref ds,
},
PublicCommit { a, b, c1, c2, .. },
) = public;
let k = c2.len();
let B_squared = inf_norm_bound_to_euclidean_squared(B_inf, d + k);
let (_, D, _, m) = compute_crs_params(
d,
k,
B_squared,
t_input,
msbs_zero_padding_bit_count,
bound_type,
);
let x_bytes = [
q.to_le_bytes().as_slice(),
(d as u64).to_le_bytes().as_slice(),
B_squared.to_le_bytes().as_slice(),
t_input.to_le_bytes().as_slice(),
msbs_zero_padding_bit_count.to_le_bytes().as_slice(),
&*a.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*b.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*c1.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*c2.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
]
.iter()
.copied()
.flatten()
.copied()
.collect::<Box<[_]>>();
let sid_bytes = Box::from(sid.to_le_bytes().as_slice());
// make R_bar a random number generator from the given bytes
use sha3::digest::{ExtendableOutput, Update, XofReader};
let mut hasher = sha3::Shake256::default();
for &data in &[
ds.hash_R(),
&sid_bytes,
metadata,
&x_bytes,
C_hat_e_bytes,
C_e_bytes,
C_r_tilde_bytes,
] {
hasher.update(data);
}
let mut R_bar = hasher.finalize_xof();
let R = (0..128 * (2 * (d + k) + 4))
.map(|_| {
let mut byte = 0u8;
R_bar.read(core::slice::from_mut(&mut byte));
// take two bits
match byte & 0b11 {
// probability 1/2
0 | 1 => 0,
// probability 1/4
2 => 1,
// probability 1/4
3 => -1,
_ => unreachable!(),
}
})
.collect::<Box<[i8]>>();
let R_coeffs = |i: usize, j: usize| R[i + j * 128];
let R_bytes = (0..128)
.flat_map(|i| (0..(2 * (d + k) + 4)).map(move |j| R_coeffs(i, j) as u8))
.collect();
(
R,
Self {
R_inputs: RInputs {
ds,
sid_bytes,
metadata,
x_bytes,
C_hat_e_bytes,
C_e_bytes,
C_r_tilde_bytes,
D,
m,
n,
k,
d,
},
R_bytes,
},
)
}
pub(super) fn gen_phi<Zp: FieldOps>(self, C_R_bytes: &'a [u8]) -> ([Zp; 128], PhiHash<'a>) {
let Self { R_inputs, R_bytes } = self;
let mut phi = [Zp::ZERO; 128];
Zp::hash(
&mut phi,
&[
R_inputs.ds.hash_phi(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&R_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
C_R_bytes,
R_inputs.C_r_tilde_bytes,
],
);
let phi_bytes = phi
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
phi,
PhiHash {
R_inputs,
phi_inputs: PhiInputs { C_R_bytes },
R_bytes,
phi_bytes,
},
)
}
}
struct PhiInputs<'a> {
C_R_bytes: &'a [u8],
}
pub(super) struct PhiHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
}
impl<'a> PhiHash<'a> {
pub(super) fn gen_xi<Zp: FieldOps>(self, C_hat_bin_bytes: &'a [u8]) -> ([Zp; 128], XiHash<'a>) {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
} = self;
let mut xi = [Zp::ZERO; 128];
Zp::hash(
&mut xi,
&[
R_inputs.ds.hash_xi(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
&phi_bytes,
phi_inputs.C_R_bytes,
C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
],
);
let xi_bytes = xi
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
xi,
XiHash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs: XiInputs { C_hat_bin_bytes },
xi_bytes,
},
)
}
}
struct XiInputs<'a> {
C_hat_bin_bytes: &'a [u8],
}
pub(super) struct XiHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
}
impl<'a> XiHash<'a> {
pub(super) fn gen_y<Zp: FieldOps>(self) -> (Vec<Zp>, YHash<'a>) {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
} = self;
let mut y = vec![Zp::ZERO; R_inputs.D + 128 * R_inputs.m];
Zp::hash(
&mut y,
&[
R_inputs.ds.hash(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&R_bytes,
&phi_bytes,
&xi_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
],
);
let y_bytes = y
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
y,
YHash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
},
)
}
}
pub(super) struct YHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
y_bytes: Box<[u8]>,
}
impl<'a> YHash<'a> {
pub(super) fn gen_t<Zp: FieldOps>(self, C_y_bytes: &'a [u8]) -> (Vec<Zp>, THash<'a>) {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
} = self;
let mut t = vec![Zp::ZERO; R_inputs.n];
Zp::hash_128bit(
&mut t,
&[
R_inputs.ds.hash_t(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&y_bytes,
&phi_bytes,
&xi_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
C_y_bytes,
],
);
let t_bytes = t
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
t,
THash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs: TInputs { C_y_bytes },
t_bytes,
},
)
}
}
struct TInputs<'a> {
C_y_bytes: &'a [u8],
}
pub(super) struct THash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
y_bytes: Box<[u8]>,
t_inputs: TInputs<'a>,
t_bytes: Box<[u8]>,
}
impl<'a> THash<'a> {
pub(super) fn gen_theta<Zp: FieldOps>(self) -> (Vec<Zp>, ThetaHash<'a>) {
let Self {
R_inputs,
phi_inputs,
xi_inputs,
t_inputs,
t_bytes,
R_bytes,
phi_bytes,
xi_bytes,
y_bytes,
} = self;
let mut theta = vec![Zp::ZERO; R_inputs.d + R_inputs.k];
Zp::hash(
&mut theta,
&[
R_inputs.ds.hash_lmap(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&y_bytes,
&t_bytes,
&phi_bytes,
&xi_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
t_inputs.C_y_bytes,
],
);
let theta_bytes = theta
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
theta,
ThetaHash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
},
)
}
}
pub(super) struct ThetaHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
y_bytes: Box<[u8]>,
t_inputs: TInputs<'a>,
t_bytes: Box<[u8]>,
theta_bytes: Box<[u8]>,
}
impl<'a> ThetaHash<'a> {
pub(super) fn gen_omega<Zp: FieldOps>(self) -> (Vec<Zp>, OmegaHash<'a>) {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
} = self;
let mut omega = vec![Zp::ZERO; R_inputs.n];
Zp::hash_128bit(
&mut omega,
&[
R_inputs.ds.hash_w(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&y_bytes,
&t_bytes,
&phi_bytes,
&xi_bytes,
&theta_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
t_inputs.C_y_bytes,
],
);
let omega_bytes = omega
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
omega,
OmegaHash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
omega_bytes,
},
)
}
}
pub(super) struct OmegaHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
y_bytes: Box<[u8]>,
t_inputs: TInputs<'a>,
t_bytes: Box<[u8]>,
theta_bytes: Box<[u8]>,
omega_bytes: Box<[u8]>,
}
impl<'a> OmegaHash<'a> {
pub(super) fn gen_delta<Zp: FieldOps>(self) -> ([Zp; 7], DeltaHash<'a>) {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
omega_bytes,
} = self;
let mut delta = [Zp::ZERO; 7];
Zp::hash(
&mut delta,
&[
R_inputs.ds.hash_agg(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&y_bytes,
&t_bytes,
&phi_bytes,
&xi_bytes,
&theta_bytes,
&omega_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
t_inputs.C_y_bytes,
],
);
let delta_bytes = delta
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
(
delta,
DeltaHash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
delta_bytes,
},
)
}
}
pub(super) struct DeltaHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
y_bytes: Box<[u8]>,
t_inputs: TInputs<'a>,
t_bytes: Box<[u8]>,
theta_bytes: Box<[u8]>,
delta_bytes: Box<[u8]>,
}
impl<'a> DeltaHash<'a> {
pub(super) fn gen_z<Zp: FieldOps>(
self,
C_h1_bytes: &'a [u8],
C_h2_bytes: &'a [u8],
C_hat_t_bytes: &'a [u8],
C_hat_h3_bytes: &'a [u8],
C_hat_omega_bytes: &'a [u8],
) -> (Zp, ZHash<'a>) {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
delta_bytes,
} = self;
let mut z = Zp::ZERO;
Zp::hash(
core::slice::from_mut(&mut z),
&[
R_inputs.ds.hash_z(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&y_bytes,
&t_bytes,
&phi_bytes,
&R_inputs.x_bytes, // x is duplicated but we have to keep it for backward compat
&theta_bytes,
&delta_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
t_inputs.C_y_bytes,
C_h1_bytes,
C_h2_bytes,
C_hat_t_bytes,
C_hat_h3_bytes,
C_hat_omega_bytes,
],
);
(
z,
ZHash {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
delta_bytes,
z_inputs: ZInputs {
C_h1_bytes,
C_h2_bytes,
C_hat_t_bytes,
C_hat_h3_bytes,
C_hat_omega_bytes,
},
z_bytes: Box::from(z.to_le_bytes().as_ref()),
},
)
}
}
struct ZInputs<'a> {
C_h1_bytes: &'a [u8],
C_h2_bytes: &'a [u8],
C_hat_t_bytes: &'a [u8],
C_hat_h3_bytes: &'a [u8],
C_hat_omega_bytes: &'a [u8],
}
pub(super) struct ZHash<'a> {
R_inputs: RInputs<'a>,
R_bytes: Box<[u8]>,
phi_inputs: PhiInputs<'a>,
phi_bytes: Box<[u8]>,
xi_inputs: XiInputs<'a>,
xi_bytes: Box<[u8]>,
y_bytes: Box<[u8]>,
t_inputs: TInputs<'a>,
t_bytes: Box<[u8]>,
theta_bytes: Box<[u8]>,
delta_bytes: Box<[u8]>,
z_inputs: ZInputs<'a>,
z_bytes: Box<[u8]>,
}
impl<'a> ZHash<'a> {
pub(super) fn gen_chi<Zp: FieldOps>(self, p_h1: Zp, p_h2: Zp, p_t: Zp) -> Zp {
let Self {
R_inputs,
R_bytes,
phi_inputs,
phi_bytes,
xi_inputs,
xi_bytes,
y_bytes,
t_inputs,
t_bytes,
theta_bytes,
delta_bytes,
z_inputs,
z_bytes,
} = self;
let mut chi = Zp::ZERO;
Zp::hash(
core::slice::from_mut(&mut chi),
&[
R_inputs.ds.hash_chi(),
&R_inputs.sid_bytes,
R_inputs.metadata,
&R_inputs.x_bytes,
&y_bytes,
&t_bytes,
&phi_bytes,
&xi_bytes,
&theta_bytes,
&delta_bytes,
R_inputs.C_hat_e_bytes,
R_inputs.C_e_bytes,
&R_bytes,
phi_inputs.C_R_bytes,
xi_inputs.C_hat_bin_bytes,
R_inputs.C_r_tilde_bytes,
t_inputs.C_y_bytes,
z_inputs.C_h1_bytes,
z_inputs.C_h2_bytes,
z_inputs.C_hat_t_bytes,
z_inputs.C_hat_h3_bytes,
z_inputs.C_hat_omega_bytes,
&z_bytes,
p_h1.to_le_bytes().as_ref(),
p_h2.to_le_bytes().as_ref(),
p_t.to_le_bytes().as_ref(),
],
);
chi
}
}

View File

@@ -15,6 +15,10 @@ use core::marker::PhantomData;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
mod hashes;
use hashes::RHash;
fn bit_iter(x: u64, nbits: u32) -> impl Iterator<Item = bool> {
(0..nbits).map(move |idx| ((x >> idx) & 1) != 0)
}
@@ -416,6 +420,19 @@ pub(crate) struct ComputeLoadProofFields<G: Curve> {
pub(crate) C_hat_w: G::G2,
}
impl<G: Curve> ComputeLoadProofFields<G> {
fn to_le_bytes(fields: &Option<Self>) -> (Box<[u8]>, Box<[u8]>) {
if let Some(ComputeLoadProofFields { C_hat_h3, C_hat_w }) = fields.as_ref() {
(
Box::from(G::G2::to_le_bytes(*C_hat_h3).as_ref()),
Box::from(G::G2::to_le_bytes(*C_hat_w).as_ref()),
)
} else {
(Box::from([]), Box::from([]))
}
}
}
#[derive(Serialize, Deserialize, Versionize)]
#[serde(bound(
deserialize = "G: Curve, CompressedG1<G>: serde::Deserialize<'de>, CompressedG2<G>: serde::Deserialize<'de>",
@@ -821,7 +838,7 @@ fn prove_impl<G: Curve>(
t: t_input,
msbs_zero_padding_bit_count,
bound_type,
sid,
sid: _,
domain_separators: ref ds,
},
PublicCommit { a, b, c1, c2, .. },
@@ -939,69 +956,18 @@ fn prove_impl<G: Curve>(
},
);
let x_bytes = &*[
q.to_le_bytes().as_slice(),
(d as u64).to_le_bytes().as_slice(),
B_squared.to_le_bytes().as_slice(),
t_input.to_le_bytes().as_slice(),
msbs_zero_padding_bit_count.to_le_bytes().as_slice(),
&*a.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*b.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*c1.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*c2.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
]
.iter()
.copied()
.flatten()
.copied()
.collect::<Box<[_]>>();
let C_hat_e_bytes = C_hat_e.to_le_bytes();
let C_e_bytes = C_e.to_le_bytes();
let C_r_tilde_bytes = C_r_tilde.to_le_bytes();
// make R_bar a random number generator from the given bytes
use sha3::digest::{ExtendableOutput, Update, XofReader};
let mut hasher = sha3::Shake256::default();
for &data in &[
ds.hash_R(),
sid.to_le_bytes().as_slice(),
let (R, R_hash) = RHash::new(
public,
metadata,
x_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
] {
hasher.update(data);
}
let mut R_bar = hasher.finalize_xof();
let R = (0..128 * (2 * (d + k) + 4))
.map(|_| {
let mut byte = 0u8;
R_bar.read(core::slice::from_mut(&mut byte));
// take two bits
match byte & 0b11 {
// probability 1/2
0 | 1 => 0,
// probability 1/4
2 => 1,
// probability 1/4
3 => -1,
_ => unreachable!(),
}
})
.collect::<Box<[i8]>>();
C_hat_e_bytes.as_ref(),
C_e_bytes.as_ref(),
C_r_tilde_bytes.as_ref(),
);
let R = |i: usize, j: usize| R[i + j * 128];
let R_bytes = &*(0..128)
.flat_map(|i| (0..(2 * (d + k) + 4)).map(move |j| R(i, j) as u8))
.collect::<Box<[u8]>>();
let w_R = (0..128)
.map(|i| {
@@ -1041,25 +1007,8 @@ fn prove_impl<G: Curve>(
.collect::<Box<[_]>>(),
);
let mut phi = vec![G::Zp::ZERO; 128];
G::Zp::hash(
&mut phi,
&[
ds.hash_phi(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
R_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
C_R.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
],
);
let phi_bytes = &*phi
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let C_R_bytes = C_R.to_le_bytes();
let (phi, phi_hash) = R_hash.gen_phi(C_R_bytes.as_ref());
let m = m_bound;
@@ -1082,51 +1031,10 @@ fn prove_impl<G: Curve>(
.map(G::G2::projective)
.sum::<G::G2>();
let mut xi = vec![G::Zp::ZERO; 128];
G::Zp::hash(
&mut xi,
&[
ds.hash_xi(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
phi_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
],
);
let C_hat_bin_bytes = C_hat_bin.to_le_bytes();
let (xi, xi_hash) = phi_hash.gen_xi::<G::Zp>(C_hat_bin_bytes.as_ref());
let xi_bytes = &*xi
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let mut y = vec![G::Zp::ZERO; D + 128 * m];
G::Zp::hash(
&mut y,
&[
ds.hash(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
R_bytes,
phi_bytes,
xi_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
],
);
let y_bytes = &*y
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let (y, y_hash) = xi_hash.gen_y();
if sanity_check_mode == ProofSanityCheckMode::Panic {
assert_eq!(y.len(), w_bin.len());
@@ -1140,56 +1048,10 @@ fn prove_impl<G: Curve>(
let C_y =
g.mul_scalar(gamma_y) + G::G1::multi_mul_scalar(&g_list[n - (D + 128 * m)..n], &scalars);
let mut t = vec![G::Zp::ZERO; n];
G::Zp::hash_128bit(
&mut t,
&[
ds.hash_t(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
phi_bytes,
xi_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let t_bytes = &*t
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let C_y_bytes = C_y.to_le_bytes();
let (t, t_hash) = y_hash.gen_t(C_y_bytes.as_ref());
let mut theta = vec![G::Zp::ZERO; d + k];
G::Zp::hash(
&mut theta,
&[
ds.hash_lmap(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let theta_bytes = &*theta
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let (theta, theta_hash) = t_hash.gen_theta();
let mut a_theta = vec![G::Zp::ZERO; D];
compute_a_theta::<G>(&mut a_theta, &theta, a, k, b, effective_cleartext_t, delta);
@@ -1201,61 +1063,10 @@ fn prove_impl<G: Curve>(
.map(|(x, y)| x * y)
.sum::<G::Zp>();
let mut w = vec![G::Zp::ZERO; n];
G::Zp::hash_128bit(
&mut w,
&[
ds.hash_w(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
theta_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let w_bytes = &*w
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let (omega, omega_hash) = theta_hash.gen_omega();
let mut delta = [G::Zp::ZERO; 7];
G::Zp::hash(
&mut delta,
&[
ds.hash_agg(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
theta_bytes,
w_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let (delta, delta_hash) = omega_hash.gen_delta::<G::Zp>();
let [delta_r, delta_dec, delta_eq, delta_y, delta_theta, delta_e, delta_l] = delta;
let delta_bytes = &*delta
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let mut poly_0_lhs = vec![G::Zp::ZERO; 1 + n];
let mut poly_0_rhs = vec![G::Zp::ZERO; 1 + D + 128 * m];
@@ -1270,7 +1081,7 @@ fn prove_impl<G: Curve>(
let mut poly_5_lhs = vec![G::Zp::ZERO; 1 + n];
let mut poly_5_rhs = vec![G::Zp::ZERO; 1 + n];
let mut xi_scaled = xi.clone();
let mut xi_scaled = xi;
poly_0_lhs[0] = delta_y * gamma_y;
for j in 0..D + 128 * m {
let p = &mut poly_0_lhs[n - j];
@@ -1326,7 +1137,7 @@ fn prove_impl<G: Curve>(
for j in 0..n {
let p = &mut poly_1_lhs[n - j];
let mut acc = delta_e * w[j];
let mut acc = delta_e * omega[j];
if j < d + k {
acc += delta_theta * theta[j];
}
@@ -1413,7 +1224,7 @@ fn prove_impl<G: Curve>(
for j in 0..d + k + 4 {
let p = &mut poly_4_rhs[1 + j];
*p = w[j];
*p = omega[j];
}
poly_5_lhs[0] = delta_eq * gamma_y;
@@ -1507,7 +1318,7 @@ fn prove_impl<G: Curve>(
g.mul_scalar(P_pi[0]) + G::G1::multi_mul_scalar(&g_list[..P_pi.len() - 1], &P_pi[1..])
};
let mut xi_scaled = xi.clone();
let mut xi_scaled = xi;
let mut scalars = (0..D + 128 * m)
.map(|j| {
let mut acc = G::Zp::ZERO;
@@ -1545,7 +1356,7 @@ fn prove_impl<G: Curve>(
acc += delta_theta * theta[j];
}
acc += delta_e * w[j];
acc += delta_e * omega[j];
if j < d + k + 4 {
let mut acc2 = G::Zp::ZERO;
@@ -1587,7 +1398,7 @@ fn prove_impl<G: Curve>(
.collect::<Box<[_]>>(),
)
},
|| G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &w[..d + k + 4]),
|| G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &omega[..d + k + 4]),
);
Some(ComputeLoadProofFields { C_hat_h3, C_hat_w })
@@ -1595,49 +1406,21 @@ fn prove_impl<G: Curve>(
ComputeLoad::Verify => None,
};
let byte_generators =
if let Some(ComputeLoadProofFields { C_hat_h3, C_hat_w }) = compute_load_proof_fields {
Some((G::G2::to_le_bytes(C_hat_h3), G::G2::to_le_bytes(C_hat_w)))
} else {
None
};
let (C_hat_h3_bytes, C_hat_w_bytes): (&[u8], &[u8]) =
if let Some((C_hat_h3_bytes_owner, C_hat_w_bytes_owner)) = byte_generators.as_ref() {
(C_hat_h3_bytes_owner.as_ref(), C_hat_w_bytes_owner.as_ref())
} else {
(&[], &[])
};
let C_hat_t = G::G2::multi_mul_scalar(g_hat_list, &t);
let mut z = G::Zp::ZERO;
G::Zp::hash(
core::slice::from_mut(&mut z),
&[
ds.hash_z(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
x_bytes,
theta_bytes,
delta_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
C_h1.to_le_bytes().as_ref(),
C_h2.to_le_bytes().as_ref(),
C_hat_t.to_le_bytes().as_ref(),
C_hat_h3_bytes,
C_hat_w_bytes,
],
let (C_hat_h3_bytes, C_hat_w_bytes) =
ComputeLoadProofFields::to_le_bytes(&compute_load_proof_fields);
let C_h1_bytes = C_h1.to_le_bytes();
let C_h2_bytes = C_h2.to_le_bytes();
let C_hat_t_bytes = C_hat_t.to_le_bytes();
let (z, z_hash) = delta_hash.gen_z(
C_h1_bytes.as_ref(),
C_h2_bytes.as_ref(),
C_hat_t_bytes.as_ref(),
&C_hat_h3_bytes,
&C_hat_w_bytes,
);
let mut P_h1 = vec![G::Zp::ZERO; 1 + n];
@@ -1652,7 +1435,7 @@ fn prove_impl<G: Curve>(
ComputeLoad::Verify => vec![],
};
let mut xi_scaled = xi.clone();
let mut xi_scaled = xi;
for j in 0..D + 128 * m {
let p = &mut P_h1[n - j];
if j < D {
@@ -1684,7 +1467,7 @@ fn prove_impl<G: Curve>(
*p += delta_theta * theta[j];
}
*p += delta_e * w[j];
*p += delta_e * omega[j];
if j < d + k + 4 {
let mut acc = G::Zp::ZERO;
@@ -1720,7 +1503,7 @@ fn prove_impl<G: Curve>(
}
if !P_w.is_empty() {
P_w[1..].copy_from_slice(&w[..d + k + 4]);
P_w[1..].copy_from_slice(&omega[..d + k + 4]);
}
let mut p_h1 = G::Zp::ZERO;
@@ -1745,38 +1528,7 @@ fn prove_impl<G: Curve>(
pow = pow * z;
}
let mut chi = G::Zp::ZERO;
G::Zp::hash(
core::slice::from_mut(&mut chi),
&[
ds.hash_chi(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
theta_bytes,
delta_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
C_h1.to_le_bytes().as_ref(),
C_h2.to_le_bytes().as_ref(),
C_hat_t.to_le_bytes().as_ref(),
C_hat_h3_bytes,
C_hat_w_bytes,
z.to_le_bytes().as_ref(),
p_h1.to_le_bytes().as_ref(),
p_h2.to_le_bytes().as_ref(),
p_t.to_le_bytes().as_ref(),
],
);
let chi = z_hash.gen_chi(p_h1, p_h2, p_t);
let mut Q_kzg = vec![G::Zp::ZERO; 1 + n];
let chi2 = chi * chi;
@@ -1967,8 +1719,8 @@ pub fn verify_impl<G: Curve>(
t: t_input,
msbs_zero_padding_bit_count,
bound_type,
sid,
domain_separators: ref ds,
sid: _,
domain_separators: _,
} = public.0;
let g_list = &*g_lists.g_list.0;
let g_hat_list = &*g_lists.g_hat_list.0;
@@ -2004,227 +1756,31 @@ pub fn verify_impl<G: Curve>(
return Err(());
}
let byte_generators = if let Some(&ComputeLoadProofFields { C_hat_h3, C_hat_w }) =
compute_load_proof_fields.as_ref()
{
Some((G::G2::to_le_bytes(C_hat_h3), G::G2::to_le_bytes(C_hat_w)))
} else {
None
};
let C_hat_e_bytes = C_hat_e.to_le_bytes();
let C_e_bytes = C_e.to_le_bytes();
let C_r_tilde_bytes = C_r_tilde.to_le_bytes();
let (C_hat_h3_bytes, C_hat_w_bytes): (&[u8], &[u8]) =
if let Some((C_hat_h3_bytes_owner, C_hat_w_bytes_owner)) = byte_generators.as_ref() {
(C_hat_h3_bytes_owner.as_ref(), C_hat_w_bytes_owner.as_ref())
} else {
(&[], &[])
};
let x_bytes = &*[
q.to_le_bytes().as_slice(),
(d as u64).to_le_bytes().as_slice(),
B_squared.to_le_bytes().as_slice(),
t_input.to_le_bytes().as_slice(),
msbs_zero_padding_bit_count.to_le_bytes().as_slice(),
&*a.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*b.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*c1.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
&*c2.iter()
.flat_map(|&x| x.to_le_bytes())
.collect::<Box<[_]>>(),
]
.iter()
.copied()
.flatten()
.copied()
.collect::<Box<[_]>>();
// make R_bar a random number generator from the given bytes
use sha3::digest::{ExtendableOutput, Update, XofReader};
let mut hasher = sha3::Shake256::default();
for &data in &[
ds.hash_R(),
sid.to_le_bytes().as_slice(),
let (R, R_hash) = RHash::new(
public,
metadata,
x_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
] {
hasher.update(data);
}
let mut R_bar = hasher.finalize_xof();
let R = (0..128 * (2 * (d + k) + 4))
.map(|_| {
let mut byte = 0u8;
R_bar.read(core::slice::from_mut(&mut byte));
// take two bits
match byte & 0b11 {
// probability 1/2
0 | 1 => 0,
// probability 1/4
2 => 1,
// probability 1/4
3 => -1,
_ => unreachable!(),
}
})
.collect::<Box<[i8]>>();
C_hat_e_bytes.as_ref(),
C_e_bytes.as_ref(),
C_r_tilde_bytes.as_ref(),
);
let R = |i: usize, j: usize| R[i + j * 128];
let R_bytes = &*(0..128)
.flat_map(|i| (0..(2 * (d + k) + 4)).map(move |j| R(i, j) as u8))
.collect::<Box<[u8]>>();
let mut phi = vec![G::Zp::ZERO; 128];
G::Zp::hash(
&mut phi,
&[
ds.hash_phi(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
R_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
C_R.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
],
);
let phi_bytes = &*phi
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let C_R_bytes = C_R.to_le_bytes();
let (phi, phi_hash) = R_hash.gen_phi(C_R_bytes.as_ref());
let mut xi = vec![G::Zp::ZERO; 128];
G::Zp::hash(
&mut xi,
&[
ds.hash_xi(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
phi_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
],
);
let xi_bytes = &*xi
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let C_hat_bin_bytes = C_hat_bin.to_le_bytes();
let (xi, xi_hash) = phi_hash.gen_xi::<G::Zp>(C_hat_bin_bytes.as_ref());
let mut y = vec![G::Zp::ZERO; D + 128 * m];
G::Zp::hash(
&mut y,
&[
ds.hash(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
R_bytes,
phi_bytes,
xi_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
],
);
let y_bytes = &*y
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let (y, y_hash) = xi_hash.gen_y();
let mut t = vec![G::Zp::ZERO; n];
G::Zp::hash_128bit(
&mut t,
&[
ds.hash_t(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
phi_bytes,
xi_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let t_bytes = &*t
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let C_y_bytes = C_y.to_le_bytes();
let (t, t_hash) = y_hash.gen_t(C_y_bytes.as_ref());
let mut theta = vec![G::Zp::ZERO; d + k];
G::Zp::hash(
&mut theta,
&[
ds.hash_lmap(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let theta_bytes = &*theta
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let mut w = vec![G::Zp::ZERO; n];
G::Zp::hash_128bit(
&mut w,
&[
ds.hash_w(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
theta_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let w_bytes = &*w
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let (theta, theta_hash) = t_hash.gen_theta();
let mut a_theta = vec![G::Zp::ZERO; D];
compute_a_theta::<G>(&mut a_theta, &theta, a, k, b, effective_cleartext_t, delta);
@@ -2236,34 +1792,10 @@ pub fn verify_impl<G: Curve>(
.map(|(x, y)| x * y)
.sum::<G::Zp>();
let mut delta = [G::Zp::ZERO; 7];
G::Zp::hash(
&mut delta,
&[
ds.hash_agg(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
theta_bytes,
w_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
],
);
let (omega, omega_hash) = theta_hash.gen_omega();
let (delta, delta_hash) = omega_hash.gen_delta();
let [delta_r, delta_dec, delta_eq, delta_y, delta_theta, delta_e, delta_l] = delta;
let delta_bytes = &*delta
.iter()
.flat_map(|x| x.to_le_bytes().as_ref().to_vec())
.collect::<Box<[_]>>();
let g = G::G1::GENERATOR;
let g_hat = G::G2::GENERATOR;
@@ -2319,7 +1851,7 @@ pub fn verify_impl<G: Curve>(
C_hat_h3: _,
C_hat_w,
}) => C_hat_w,
None => G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &w[..d + k + 4]),
None => G::G2::multi_mul_scalar(&g_hat_list[..d + k + 4], &omega[..d + k + 4]),
},
);
let lhs5 = pairing(C_y.mul_scalar(delta_eq), C_hat_t);
@@ -2336,41 +1868,27 @@ pub fn verify_impl<G: Curve>(
return Err(());
}
let mut z = G::Zp::ZERO;
G::Zp::hash(
core::slice::from_mut(&mut z),
&[
ds.hash_z(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
x_bytes,
theta_bytes,
delta_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
C_h1.to_le_bytes().as_ref(),
C_h2.to_le_bytes().as_ref(),
C_hat_t.to_le_bytes().as_ref(),
C_hat_h3_bytes,
C_hat_w_bytes,
],
);
let load = if compute_load_proof_fields.is_some() {
ComputeLoad::Proof
} else {
ComputeLoad::Verify
};
let (C_hat_h3_bytes, C_hat_w_bytes) =
ComputeLoadProofFields::to_le_bytes(compute_load_proof_fields);
let C_h1_bytes = C_h1.to_le_bytes();
let C_h2_bytes = C_h2.to_le_bytes();
let C_hat_t_bytes = C_hat_t.to_le_bytes();
let (z, z_hash) = delta_hash.gen_z(
C_h1_bytes.as_ref(),
C_h2_bytes.as_ref(),
C_hat_t_bytes.as_ref(),
&C_hat_h3_bytes,
&C_hat_w_bytes,
);
let mut P_h1 = vec![G::Zp::ZERO; 1 + n];
let mut P_h2 = vec![G::Zp::ZERO; 1 + n];
let mut P_t = vec![G::Zp::ZERO; 1 + n];
@@ -2383,7 +1901,7 @@ pub fn verify_impl<G: Curve>(
ComputeLoad::Verify => vec![],
};
let mut xi_scaled = xi.clone();
let mut xi_scaled = xi;
for j in 0..D + 128 * m {
let p = &mut P_h1[n - j];
if j < D {
@@ -2415,7 +1933,7 @@ pub fn verify_impl<G: Curve>(
*p += delta_theta * theta[j];
}
*p += delta_e * w[j];
*p += delta_e * omega[j];
if j < d + k + 4 {
let mut acc = G::Zp::ZERO;
@@ -2451,7 +1969,7 @@ pub fn verify_impl<G: Curve>(
}
if !P_w.is_empty() {
P_w[1..].copy_from_slice(&w[..d + k + 4]);
P_w[1..].copy_from_slice(&omega[..d + k + 4]);
}
let mut p_h1 = G::Zp::ZERO;
@@ -2476,38 +1994,8 @@ pub fn verify_impl<G: Curve>(
pow = pow * z;
}
let mut chi = G::Zp::ZERO;
G::Zp::hash(
core::slice::from_mut(&mut chi),
&[
ds.hash_chi(),
sid.to_le_bytes().as_slice(),
metadata,
x_bytes,
y_bytes,
t_bytes,
phi_bytes,
xi_bytes,
theta_bytes,
delta_bytes,
C_hat_e.to_le_bytes().as_ref(),
C_e.to_le_bytes().as_ref(),
R_bytes,
C_R.to_le_bytes().as_ref(),
C_hat_bin.to_le_bytes().as_ref(),
C_r_tilde.to_le_bytes().as_ref(),
C_y.to_le_bytes().as_ref(),
C_h1.to_le_bytes().as_ref(),
C_h2.to_le_bytes().as_ref(),
C_hat_t.to_le_bytes().as_ref(),
C_hat_h3_bytes,
C_hat_w_bytes,
z.to_le_bytes().as_ref(),
p_h1.to_le_bytes().as_ref(),
p_h2.to_le_bytes().as_ref(),
p_t.to_le_bytes().as_ref(),
],
);
let chi = z_hash.gen_chi(p_h1, p_h2, p_t);
let chi2 = chi * chi;
let chi3 = chi2 * chi;
let chi4 = chi3 * chi;