mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-11 16:41:28 +01:00
Truncate digest bits (#50)
* apply a hash function before adding to transcript * truncate shape_digest into 250 bits * add missing file * fix clippy * cargo fmt
This commit is contained in:
2
src/constants.rs
Normal file
2
src/constants.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub(crate) const NUM_CHALLENGE_BITS: usize = 128;
|
||||
pub(crate) const NUM_HASH_BITS: usize = 250;
|
||||
@@ -3,10 +3,10 @@
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
mod commitments;
|
||||
|
||||
pub mod bellperson;
|
||||
mod circuit;
|
||||
mod commitments;
|
||||
mod constants;
|
||||
pub mod errors;
|
||||
pub mod gadgets;
|
||||
pub mod pasta;
|
||||
@@ -14,14 +14,13 @@ mod poseidon;
|
||||
pub mod r1cs;
|
||||
pub mod traits;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use commitments::CompressedCommitment;
|
||||
use errors::NovaError;
|
||||
use merlin::Transcript;
|
||||
use r1cs::{
|
||||
R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use traits::{AppendToTranscriptTrait, ChallengeTrait, Group};
|
||||
|
||||
/// A SNARK that holds the proof of a step of an incremental computation
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
//! Poseidon Constants and Poseidon-based RO used in Nova
|
||||
use crate::traits::{HashFuncConstantsTrait, HashFuncTrait};
|
||||
use super::{
|
||||
constants::{NUM_CHALLENGE_BITS, NUM_HASH_BITS},
|
||||
traits::{HashFuncConstantsTrait, HashFuncTrait},
|
||||
};
|
||||
use bellperson::{
|
||||
gadgets::{
|
||||
boolean::{AllocatedBit, Boolean},
|
||||
@@ -102,11 +105,11 @@ where
|
||||
#[allow(dead_code)]
|
||||
fn get_challenge(&self) -> Scalar {
|
||||
let hash = self.hash_inner();
|
||||
// Only keep 128 bits
|
||||
// Only keep NUM_CHALLENGE_BITS bits
|
||||
let bits = hash.to_le_bits();
|
||||
let mut res = Scalar::zero();
|
||||
let mut coeff = Scalar::one();
|
||||
for bit in bits[0..128].into_iter() {
|
||||
for bit in bits[0..NUM_CHALLENGE_BITS].into_iter() {
|
||||
if *bit {
|
||||
res += coeff;
|
||||
}
|
||||
@@ -118,11 +121,11 @@ where
|
||||
#[allow(dead_code)]
|
||||
fn get_hash(&self) -> Scalar {
|
||||
let hash = self.hash_inner();
|
||||
// Only keep 250 bits
|
||||
// Only keep NUM_HASH_BITS bits
|
||||
let bits = hash.to_le_bits();
|
||||
let mut res = Scalar::zero();
|
||||
let mut coeff = Scalar::one();
|
||||
for bit in bits[0..250].into_iter() {
|
||||
for bit in bits[0..NUM_HASH_BITS].into_iter() {
|
||||
if *bit {
|
||||
res += coeff;
|
||||
}
|
||||
@@ -204,8 +207,7 @@ where
|
||||
CS: ConstraintSystem<Scalar>,
|
||||
{
|
||||
let bits = self.hash_inner(cs.namespace(|| "hash"))?;
|
||||
// Only keep 128 bits
|
||||
Ok(bits[..128].into())
|
||||
Ok(bits[..NUM_CHALLENGE_BITS].into())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -214,8 +216,7 @@ where
|
||||
CS: ConstraintSystem<Scalar>,
|
||||
{
|
||||
let bits = self.hash_inner(cs.namespace(|| "hash"))?;
|
||||
// Only keep 250 bits
|
||||
Ok(bits[..250].into())
|
||||
Ok(bits[..NUM_HASH_BITS].into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
31
src/r1cs.rs
31
src/r1cs.rs
@@ -2,6 +2,7 @@
|
||||
#![allow(clippy::type_complexity)]
|
||||
use super::{
|
||||
commitments::{CommitGens, CommitTrait, Commitment, CompressedCommitment},
|
||||
constants::NUM_HASH_BITS,
|
||||
errors::NovaError,
|
||||
traits::{AppendToTranscriptTrait, Group},
|
||||
};
|
||||
@@ -11,6 +12,7 @@ use itertools::concat;
|
||||
use merlin::Transcript;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha3::{Digest, Sha3_256};
|
||||
|
||||
/// Public parameters for a given R1CS
|
||||
pub struct R1CSGens<G: Group> {
|
||||
@@ -328,10 +330,37 @@ impl<G: Group> AppendToTranscriptTrait for R1CSShape<G> {
|
||||
.collect(),
|
||||
};
|
||||
|
||||
// obtain a vector of bytes representing the R1CS shape
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
bincode::serialize_into(&mut encoder, &shape_serialized).unwrap();
|
||||
let shape_bytes = encoder.finish().unwrap();
|
||||
transcript.append_message(b"R1CSShape", &shape_bytes);
|
||||
|
||||
// convert shape_bytes into a short digest
|
||||
let mut hasher = Sha3_256::new();
|
||||
hasher.input(&shape_bytes);
|
||||
let shape_digest = hasher.result();
|
||||
|
||||
let shape_digest_trun = {
|
||||
// truncate the digest to 250 bits
|
||||
let bv = (0..NUM_HASH_BITS).map(|i| {
|
||||
let (byte_pos, bit_pos) = (i / 8, i % 8);
|
||||
let bit = (shape_digest[byte_pos] >> bit_pos) & 1;
|
||||
bit == 1
|
||||
});
|
||||
|
||||
// turn the bit vector into a scalar
|
||||
let mut res = G::Scalar::zero();
|
||||
let mut coeff = G::Scalar::one();
|
||||
for bit in bv {
|
||||
if bit {
|
||||
res += coeff;
|
||||
}
|
||||
coeff += coeff;
|
||||
}
|
||||
res
|
||||
};
|
||||
|
||||
shape_digest_trun.append_to_transcript(b"R1CSShape", transcript);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user