mirror of
https://github.com/arnaucube/Nova.git
synced 2026-02-01 08:46:39 +01:00
hash of public parameters in the transcript (#168)
This commit is contained in:
73
src/lib.rs
73
src/lib.rs
@@ -36,10 +36,12 @@ use constants::{BN_LIMB_WIDTH, BN_N_LIMBS, NUM_FE_WITHOUT_IO_FOR_CRHF, NUM_HASH_
|
||||
use core::marker::PhantomData;
|
||||
use errors::NovaError;
|
||||
use ff::Field;
|
||||
use flate2::{write::ZlibEncoder, Compression};
|
||||
use gadgets::utils::scalar_as_base;
|
||||
use nifs::NIFS;
|
||||
use r1cs::{R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha3::{Digest, Sha3_256};
|
||||
use traits::{
|
||||
circuit::StepCircuit,
|
||||
commitment::{CommitmentEngineTrait, CommitmentTrait},
|
||||
@@ -69,6 +71,7 @@ where
|
||||
r1cs_shape_secondary: R1CSShape<G2>,
|
||||
augmented_circuit_params_primary: NovaAugmentedCircuitParams,
|
||||
augmented_circuit_params_secondary: NovaAugmentedCircuitParams,
|
||||
digest: G1::Scalar, // digest of everything else with this field set to G1::Scalar::ZERO
|
||||
_p_c1: PhantomData<C1>,
|
||||
_p_c2: PhantomData<C2>,
|
||||
}
|
||||
@@ -119,7 +122,7 @@ where
|
||||
let _ = circuit_secondary.synthesize(&mut cs);
|
||||
let (r1cs_shape_secondary, ck_secondary) = cs.r1cs_shape();
|
||||
|
||||
Self {
|
||||
let mut pp = Self {
|
||||
F_arity_primary,
|
||||
F_arity_secondary,
|
||||
ro_consts_primary,
|
||||
@@ -132,9 +135,15 @@ where
|
||||
r1cs_shape_secondary,
|
||||
augmented_circuit_params_primary,
|
||||
augmented_circuit_params_secondary,
|
||||
digest: G1::Scalar::ZERO,
|
||||
_p_c1: Default::default(),
|
||||
_p_c2: Default::default(),
|
||||
}
|
||||
};
|
||||
|
||||
// set the digest in pp
|
||||
pp.digest = compute_digest::<G1, PublicParams<G1, G2, C1, C2>>(&pp);
|
||||
|
||||
pp
|
||||
}
|
||||
|
||||
/// Returns the number of constraints in the primary and secondary circuits
|
||||
@@ -205,7 +214,7 @@ where
|
||||
// base case for the primary
|
||||
let mut cs_primary: SatisfyingAssignment<G1> = SatisfyingAssignment::new();
|
||||
let inputs_primary: NovaAugmentedCircuitInputs<G2> = NovaAugmentedCircuitInputs::new(
|
||||
pp.r1cs_shape_secondary.get_digest(),
|
||||
scalar_as_base::<G1>(pp.digest),
|
||||
G1::Scalar::ZERO,
|
||||
z0_primary.clone(),
|
||||
None,
|
||||
@@ -228,7 +237,7 @@ where
|
||||
// base case for the secondary
|
||||
let mut cs_secondary: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
|
||||
let inputs_secondary: NovaAugmentedCircuitInputs<G1> = NovaAugmentedCircuitInputs::new(
|
||||
pp.r1cs_shape_primary.get_digest(),
|
||||
pp.digest,
|
||||
G2::Scalar::ZERO,
|
||||
z0_secondary.clone(),
|
||||
None,
|
||||
@@ -294,6 +303,7 @@ where
|
||||
let (nifs_secondary, (r_U_secondary, r_W_secondary)) = NIFS::prove(
|
||||
&pp.ck_secondary,
|
||||
&pp.ro_consts_secondary,
|
||||
&scalar_as_base::<G1>(pp.digest),
|
||||
&pp.r1cs_shape_secondary,
|
||||
&r_snark.r_U_secondary,
|
||||
&r_snark.r_W_secondary,
|
||||
@@ -303,7 +313,7 @@ where
|
||||
|
||||
let mut cs_primary: SatisfyingAssignment<G1> = SatisfyingAssignment::new();
|
||||
let inputs_primary: NovaAugmentedCircuitInputs<G2> = NovaAugmentedCircuitInputs::new(
|
||||
pp.r1cs_shape_secondary.get_digest(),
|
||||
scalar_as_base::<G1>(pp.digest),
|
||||
G1::Scalar::from(r_snark.i as u64),
|
||||
z0_primary,
|
||||
Some(r_snark.zi_primary.clone()),
|
||||
@@ -328,6 +338,7 @@ where
|
||||
let (nifs_primary, (r_U_primary, r_W_primary)) = NIFS::prove(
|
||||
&pp.ck_primary,
|
||||
&pp.ro_consts_primary,
|
||||
&pp.digest,
|
||||
&pp.r1cs_shape_primary,
|
||||
&r_snark.r_U_primary,
|
||||
&r_snark.r_W_primary,
|
||||
@@ -337,7 +348,7 @@ where
|
||||
|
||||
let mut cs_secondary: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
|
||||
let inputs_secondary: NovaAugmentedCircuitInputs<G1> = NovaAugmentedCircuitInputs::new(
|
||||
pp.r1cs_shape_primary.get_digest(),
|
||||
pp.digest,
|
||||
G2::Scalar::from(r_snark.i as u64),
|
||||
z0_secondary,
|
||||
Some(r_snark.zi_secondary.clone()),
|
||||
@@ -414,7 +425,7 @@ where
|
||||
pp.ro_consts_secondary.clone(),
|
||||
NUM_FE_WITHOUT_IO_FOR_CRHF + 2 * pp.F_arity_primary,
|
||||
);
|
||||
hasher.absorb(scalar_as_base::<G2>(pp.r1cs_shape_secondary.get_digest()));
|
||||
hasher.absorb(pp.digest);
|
||||
hasher.absorb(G1::Scalar::from(num_steps as u64));
|
||||
for e in &z0_primary {
|
||||
hasher.absorb(*e);
|
||||
@@ -428,7 +439,7 @@ where
|
||||
pp.ro_consts_primary.clone(),
|
||||
NUM_FE_WITHOUT_IO_FOR_CRHF + 2 * pp.F_arity_secondary,
|
||||
);
|
||||
hasher2.absorb(scalar_as_base::<G1>(pp.r1cs_shape_primary.get_digest()));
|
||||
hasher2.absorb(scalar_as_base::<G1>(pp.digest));
|
||||
hasher2.absorb(G2::Scalar::from(num_steps as u64));
|
||||
for e in &z0_secondary {
|
||||
hasher2.absorb(*e);
|
||||
@@ -531,8 +542,7 @@ where
|
||||
F_arity_secondary: usize,
|
||||
ro_consts_primary: ROConstants<G1>,
|
||||
ro_consts_secondary: ROConstants<G2>,
|
||||
r1cs_shape_primary_digest: G1::Scalar,
|
||||
r1cs_shape_secondary_digest: G2::Scalar,
|
||||
digest: G1::Scalar,
|
||||
vk_primary: S1::VerifierKey,
|
||||
vk_secondary: S2::VerifierKey,
|
||||
_p_c1: PhantomData<C1>,
|
||||
@@ -602,8 +612,7 @@ where
|
||||
F_arity_secondary: pp.F_arity_secondary,
|
||||
ro_consts_primary: pp.ro_consts_primary.clone(),
|
||||
ro_consts_secondary: pp.ro_consts_secondary.clone(),
|
||||
r1cs_shape_primary_digest: pp.r1cs_shape_primary.get_digest(),
|
||||
r1cs_shape_secondary_digest: pp.r1cs_shape_secondary.get_digest(),
|
||||
digest: pp.digest,
|
||||
vk_primary,
|
||||
vk_secondary,
|
||||
_p_c1: Default::default(),
|
||||
@@ -625,6 +634,7 @@ where
|
||||
NIFS::prove(
|
||||
&pp.ck_primary,
|
||||
&pp.ro_consts_primary,
|
||||
&pp.digest,
|
||||
&pp.r1cs_shape_primary,
|
||||
&recursive_snark.r_U_primary,
|
||||
&recursive_snark.r_W_primary,
|
||||
@@ -637,6 +647,7 @@ where
|
||||
NIFS::prove(
|
||||
&pp.ck_secondary,
|
||||
&pp.ro_consts_secondary,
|
||||
&scalar_as_base::<G1>(pp.digest),
|
||||
&pp.r1cs_shape_secondary,
|
||||
&recursive_snark.r_U_secondary,
|
||||
&recursive_snark.r_W_secondary,
|
||||
@@ -709,7 +720,7 @@ where
|
||||
vk.ro_consts_secondary.clone(),
|
||||
NUM_FE_WITHOUT_IO_FOR_CRHF + 2 * vk.F_arity_primary,
|
||||
);
|
||||
hasher.absorb(scalar_as_base::<G2>(vk.r1cs_shape_secondary_digest));
|
||||
hasher.absorb(vk.digest);
|
||||
hasher.absorb(G1::Scalar::from(num_steps as u64));
|
||||
for e in z0_primary {
|
||||
hasher.absorb(e);
|
||||
@@ -723,7 +734,7 @@ where
|
||||
vk.ro_consts_primary.clone(),
|
||||
NUM_FE_WITHOUT_IO_FOR_CRHF + 2 * vk.F_arity_secondary,
|
||||
);
|
||||
hasher2.absorb(scalar_as_base::<G1>(vk.r1cs_shape_primary_digest));
|
||||
hasher2.absorb(scalar_as_base::<G1>(vk.digest));
|
||||
hasher2.absorb(G2::Scalar::from(num_steps as u64));
|
||||
for e in z0_secondary {
|
||||
hasher2.absorb(e);
|
||||
@@ -748,13 +759,13 @@ where
|
||||
// fold the running instance and last instance to get a folded instance
|
||||
let f_U_primary = self.nifs_primary.verify(
|
||||
&vk.ro_consts_primary,
|
||||
&vk.r1cs_shape_primary_digest,
|
||||
&vk.digest,
|
||||
&self.r_U_primary,
|
||||
&self.l_u_primary,
|
||||
)?;
|
||||
let f_U_secondary = self.nifs_secondary.verify(
|
||||
&vk.ro_consts_secondary,
|
||||
&vk.r1cs_shape_secondary_digest,
|
||||
&scalar_as_base::<G1>(vk.digest),
|
||||
&self.r_U_secondary,
|
||||
&self.l_u_secondary,
|
||||
)?;
|
||||
@@ -781,6 +792,36 @@ type Commitment<G> = <<G as Group>::CE as CommitmentEngineTrait<G>>::Commitment;
|
||||
type CompressedCommitment<G> = <<<G as Group>::CE as CommitmentEngineTrait<G>>::Commitment as CommitmentTrait<G>>::CompressedCommitment;
|
||||
type CE<G> = <G as Group>::CE;
|
||||
|
||||
fn compute_digest<G: Group, T: Serialize>(o: &T) -> G::Scalar {
|
||||
// obtain a vector of bytes representing public parameters
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
bincode::serialize_into(&mut encoder, o).unwrap();
|
||||
let pp_bytes = encoder.finish().unwrap();
|
||||
|
||||
// convert pp_bytes into a short digest
|
||||
let mut hasher = Sha3_256::new();
|
||||
hasher.input(&pp_bytes);
|
||||
let digest = hasher.result();
|
||||
|
||||
// truncate the digest to NUM_HASH_BITS bits
|
||||
let bv = (0..NUM_HASH_BITS).map(|i| {
|
||||
let (byte_pos, bit_pos) = (i / 8, i % 8);
|
||||
let bit = (digest[byte_pos] >> bit_pos) & 1;
|
||||
bit == 1
|
||||
});
|
||||
|
||||
// turn the bit vector into a scalar
|
||||
let mut digest = G::Scalar::ZERO;
|
||||
let mut coeff = G::Scalar::ONE;
|
||||
for bit in bv {
|
||||
if bit {
|
||||
digest += coeff;
|
||||
}
|
||||
coeff += coeff;
|
||||
}
|
||||
digest
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user