use crate::{
fft::{EvaluationDomain, Polynomial},
proof_system::ProverKey,
};
use dusk_bls12_381::BlsScalar;
use dusk_bytes::{DeserializableSlice, Serializable};
use parity_scale_codec::{Decode, Encode};
#[allow(dead_code)]
pub(crate) struct Evaluations {
pub(crate) proof: ProofEvaluations,
pub(crate) quot_eval: BlsScalar,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Decode, Encode)]
pub(crate) struct ProofEvaluations {
pub(crate) a_eval: BlsScalar,
pub(crate) b_eval: BlsScalar,
pub(crate) c_eval: BlsScalar,
pub(crate) d_eval: BlsScalar,
pub(crate) a_next_eval: BlsScalar,
pub(crate) b_next_eval: BlsScalar,
pub(crate) d_next_eval: BlsScalar,
pub(crate) q_arith_eval: BlsScalar,
pub(crate) q_c_eval: BlsScalar,
pub(crate) q_l_eval: BlsScalar,
pub(crate) q_r_eval: BlsScalar,
pub(crate) q_lookup_eval: BlsScalar,
pub(crate) left_sigma_eval: BlsScalar,
pub(crate) right_sigma_eval: BlsScalar,
pub(crate) out_sigma_eval: BlsScalar,
pub(crate) lin_poly_eval: BlsScalar,
pub(crate) perm_eval: BlsScalar,
pub lookup_perm_eval: BlsScalar,
pub h_1_eval: BlsScalar,
pub h_1_next_eval: BlsScalar,
pub h_2_eval: BlsScalar,
pub f_eval: BlsScalar,
pub table_eval: BlsScalar,
pub table_next_eval: BlsScalar,
}
impl Serializable<{ 24 * BlsScalar::SIZE }> for ProofEvaluations {
type Error = dusk_bytes::Error;
#[allow(unused_must_use)]
fn to_bytes(&self) -> [u8; Self::SIZE] {
use dusk_bytes::Write;
let mut buf = [0u8; Self::SIZE];
let mut writer = &mut buf[..];
writer.write(&self.a_eval.to_bytes());
writer.write(&self.b_eval.to_bytes());
writer.write(&self.c_eval.to_bytes());
writer.write(&self.d_eval.to_bytes());
writer.write(&self.a_next_eval.to_bytes());
writer.write(&self.b_next_eval.to_bytes());
writer.write(&self.d_next_eval.to_bytes());
writer.write(&self.q_arith_eval.to_bytes());
writer.write(&self.q_c_eval.to_bytes());
writer.write(&self.q_l_eval.to_bytes());
writer.write(&self.q_r_eval.to_bytes());
writer.write(&self.q_lookup_eval.to_bytes());
writer.write(&self.left_sigma_eval.to_bytes());
writer.write(&self.right_sigma_eval.to_bytes());
writer.write(&self.out_sigma_eval.to_bytes());
writer.write(&self.lin_poly_eval.to_bytes());
writer.write(&self.perm_eval.to_bytes());
writer.write(&self.lookup_perm_eval.to_bytes());
writer.write(&self.h_1_eval.to_bytes());
writer.write(&self.h_1_next_eval.to_bytes());
writer.write(&self.h_2_eval.to_bytes());
writer.write(&self.f_eval.to_bytes());
writer.write(&self.table_eval.to_bytes());
writer.write(&self.table_next_eval.to_bytes());
buf
}
fn from_bytes(
buf: &[u8; Self::SIZE],
) -> Result<ProofEvaluations, Self::Error> {
let mut buffer = &buf[..];
let a_eval = BlsScalar::from_reader(&mut buffer)?;
let b_eval = BlsScalar::from_reader(&mut buffer)?;
let c_eval = BlsScalar::from_reader(&mut buffer)?;
let d_eval = BlsScalar::from_reader(&mut buffer)?;
let a_next_eval = BlsScalar::from_reader(&mut buffer)?;
let b_next_eval = BlsScalar::from_reader(&mut buffer)?;
let d_next_eval = BlsScalar::from_reader(&mut buffer)?;
let q_arith_eval = BlsScalar::from_reader(&mut buffer)?;
let q_c_eval = BlsScalar::from_reader(&mut buffer)?;
let q_l_eval = BlsScalar::from_reader(&mut buffer)?;
let q_r_eval = BlsScalar::from_reader(&mut buffer)?;
let q_lookup_eval = BlsScalar::from_reader(&mut buffer)?;
let left_sigma_eval = BlsScalar::from_reader(&mut buffer)?;
let right_sigma_eval = BlsScalar::from_reader(&mut buffer)?;
let out_sigma_eval = BlsScalar::from_reader(&mut buffer)?;
let lin_poly_eval = BlsScalar::from_reader(&mut buffer)?;
let perm_eval = BlsScalar::from_reader(&mut buffer)?;
let lookup_perm_eval = BlsScalar::from_reader(&mut buffer)?;
let h_1_eval = BlsScalar::from_reader(&mut buffer)?;
let h_1_next_eval = BlsScalar::from_reader(&mut buffer)?;
let h_2_eval = BlsScalar::from_reader(&mut buffer)?;
let f_eval = BlsScalar::from_reader(&mut buffer)?;
let table_eval = BlsScalar::from_reader(&mut buffer)?;
let table_next_eval = BlsScalar::from_reader(&mut buffer)?;
Ok(ProofEvaluations {
a_eval,
b_eval,
c_eval,
d_eval,
a_next_eval,
b_next_eval,
d_next_eval,
q_arith_eval,
q_c_eval,
q_l_eval,
q_r_eval,
q_lookup_eval,
left_sigma_eval,
right_sigma_eval,
out_sigma_eval,
lin_poly_eval,
perm_eval,
lookup_perm_eval,
h_1_eval,
h_1_next_eval,
h_2_eval,
f_eval,
table_eval,
table_next_eval,
})
}
}
#[allow(clippy::type_complexity)]
pub(crate) fn compute(
domain: &EvaluationDomain,
prover_key: &ProverKey,
(
alpha,
beta,
gamma,
delta,
epsilon,
zeta,
range_separation_challenge,
logic_separation_challenge,
fixed_base_separation_challenge,
var_base_separation_challenge,
lookup_separation_challenge,
z_challenge,
): &(
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
BlsScalar,
),
w_l_poly: &Polynomial,
w_r_poly: &Polynomial,
w_o_poly: &Polynomial,
w_4_poly: &Polynomial,
t_x_poly: &Polynomial,
z_poly: &Polynomial,
f_poly: &Polynomial,
h_1_poly: &Polynomial,
h_2_poly: &Polynomial,
table_poly: &Polynomial,
p_poly: &Polynomial,
) -> (Polynomial, Evaluations) {
let quot_eval = t_x_poly.evaluate(z_challenge);
let a_eval = w_l_poly.evaluate(z_challenge);
let b_eval = w_r_poly.evaluate(z_challenge);
let c_eval = w_o_poly.evaluate(z_challenge);
let d_eval = w_4_poly.evaluate(z_challenge);
let left_sigma_eval =
prover_key.permutation.left_sigma.0.evaluate(z_challenge);
let right_sigma_eval =
prover_key.permutation.right_sigma.0.evaluate(z_challenge);
let out_sigma_eval =
prover_key.permutation.out_sigma.0.evaluate(z_challenge);
let q_arith_eval = prover_key.arithmetic.q_arith.0.evaluate(z_challenge);
let q_c_eval = prover_key.logic.q_c.0.evaluate(z_challenge);
let q_l_eval = prover_key.fixed_base.q_l.0.evaluate(z_challenge);
let q_r_eval = prover_key.fixed_base.q_r.0.evaluate(z_challenge);
let q_lookup_eval = prover_key.lookup.q_lookup.0.evaluate(z_challenge);
let f_eval = f_poly.evaluate(z_challenge);
let h_1_eval = h_1_poly.evaluate(z_challenge);
let h_2_eval = h_2_poly.evaluate(z_challenge);
let table_eval = table_poly.evaluate(z_challenge);
let a_next_eval = w_l_poly.evaluate(&(z_challenge * domain.group_gen));
let b_next_eval = w_r_poly.evaluate(&(z_challenge * domain.group_gen));
let d_next_eval = w_4_poly.evaluate(&(z_challenge * domain.group_gen));
let perm_eval = z_poly.evaluate(&(z_challenge * domain.group_gen));
let lookup_perm_eval = p_poly.evaluate(&(z_challenge * domain.group_gen));
let h_1_next_eval = h_1_poly.evaluate(&(z_challenge * domain.group_gen));
let table_next_eval =
table_poly.evaluate(&(z_challenge * domain.group_gen));
let l_coeffs = domain.evaluate_all_lagrange_coefficients(*z_challenge);
let l1_eval = l_coeffs[0];
let f_1 = compute_circuit_satisfiability(
(
range_separation_challenge,
logic_separation_challenge,
fixed_base_separation_challenge,
var_base_separation_challenge,
lookup_separation_challenge,
),
&a_eval,
&b_eval,
&c_eval,
&d_eval,
&a_next_eval,
&b_next_eval,
&d_next_eval,
&q_arith_eval,
&f_eval,
&table_eval,
&table_next_eval,
&h_1_eval,
&h_2_eval,
&lookup_perm_eval,
&l1_eval,
p_poly,
h_2_poly,
(delta, epsilon),
zeta,
&q_c_eval,
&q_l_eval,
&q_r_eval,
prover_key,
);
let f_2 = prover_key.permutation.compute_linearisation(
z_challenge,
(alpha, beta, gamma),
(&a_eval, &b_eval, &c_eval, &d_eval),
(&left_sigma_eval, &right_sigma_eval, &out_sigma_eval),
&perm_eval,
z_poly,
);
let lin_poly = &f_1 + &f_2;
let lin_poly_eval = lin_poly.evaluate(z_challenge);
(
lin_poly,
Evaluations {
proof: ProofEvaluations {
a_eval,
b_eval,
c_eval,
d_eval,
a_next_eval,
b_next_eval,
d_next_eval,
q_arith_eval,
q_c_eval,
q_l_eval,
q_r_eval,
q_lookup_eval,
left_sigma_eval,
right_sigma_eval,
out_sigma_eval,
lin_poly_eval,
perm_eval,
lookup_perm_eval,
h_1_eval,
h_1_next_eval,
h_2_eval,
f_eval,
table_eval,
table_next_eval,
},
quot_eval,
},
)
}
fn compute_circuit_satisfiability(
(
range_separation_challenge,
logic_separation_challenge,
fixed_base_separation_challenge,
var_base_separation_challenge,
lookup_separation_challenge,
): (&BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar),
a_eval: &BlsScalar,
b_eval: &BlsScalar,
c_eval: &BlsScalar,
d_eval: &BlsScalar,
a_next_eval: &BlsScalar,
b_next_eval: &BlsScalar,
d_next_eval: &BlsScalar,
q_arith_eval: &BlsScalar,
f_eval: &BlsScalar,
table_eval: &BlsScalar,
table_next_eval: &BlsScalar,
h_1_eval: &BlsScalar,
h_2_eval: &BlsScalar,
p_next_eval: &BlsScalar,
l1_eval: &BlsScalar,
p_poly: &Polynomial,
h_2_poly: &Polynomial,
(delta, epsilon): (&BlsScalar, &BlsScalar),
zeta: &BlsScalar,
q_c_eval: &BlsScalar,
q_l_eval: &BlsScalar,
q_r_eval: &BlsScalar,
prover_key: &ProverKey,
) -> Polynomial {
let a = prover_key.arithmetic.compute_linearisation(
a_eval,
b_eval,
c_eval,
d_eval,
q_arith_eval,
);
let b = prover_key.range.compute_linearisation(
range_separation_challenge,
a_eval,
b_eval,
c_eval,
d_eval,
d_next_eval,
);
let c = prover_key.logic.compute_linearisation(
logic_separation_challenge,
a_eval,
a_next_eval,
b_eval,
b_next_eval,
c_eval,
d_eval,
d_next_eval,
q_c_eval,
);
let d = prover_key.fixed_base.compute_linearisation(
fixed_base_separation_challenge,
a_eval,
a_next_eval,
b_eval,
b_next_eval,
c_eval,
d_eval,
d_next_eval,
q_l_eval,
q_r_eval,
q_c_eval,
);
let e = prover_key.variable_base.compute_linearisation(
var_base_separation_challenge,
a_eval,
a_next_eval,
b_eval,
b_next_eval,
c_eval,
d_eval,
d_next_eval,
);
let f = prover_key.lookup.compute_linearisation(
a_eval,
b_eval,
c_eval,
d_eval,
f_eval,
table_eval,
table_next_eval,
h_1_eval,
h_2_eval,
p_next_eval,
l1_eval,
p_poly,
h_2_poly,
(delta, epsilon),
zeta,
lookup_separation_challenge,
);
let mut linearisation_poly = &a + &b;
linearisation_poly += &c;
linearisation_poly += &d;
linearisation_poly += &e;
linearisation_poly += &f;
linearisation_poly
}
#[cfg(test)]
mod evaluations_tests {
use super::*;
#[test]
fn proof_evaluations_dusk_bytes_serde() {
let proof_evals = ProofEvaluations::default();
let bytes = proof_evals.to_bytes();
let obtained_evals = ProofEvaluations::from_slice(&bytes)
.expect("Deserialization error");
assert_eq!(proof_evals.to_bytes(), obtained_evals.to_bytes())
}
}