Skip to content

Commit

Permalink
temp: debug constraint synthesis
Browse files Browse the repository at this point in the history
  • Loading branch information
redshiftzero committed Jun 8, 2023
1 parent 3280081 commit 524faf7
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 159 deletions.
100 changes: 53 additions & 47 deletions poseidon-permutation/src/r1cs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(non_snake_case)]
use ark_ff::PrimeField;
use ark_std::{vec, vec::Vec};
use ark_std::{dbg, vec, vec::Vec};

use ark_r1cs_std::{fields::fp::FpVar, prelude::*};
use ark_relations::r1cs::ConstraintSystemRef;
Expand All @@ -24,59 +24,34 @@ impl<F> InstanceVar<F>
where
F: PrimeField,
{
/// Initialize a new Poseidon instance.
pub fn new(parameters: PoseidonParameters<F>, cs: ConstraintSystemRef<F>) -> Self {
let zero = FpVar::<F>::zero();
/// Fixed width hash from n:1. Outputs a F given `t` input words.
pub fn n_to_1_fixed_hash(
parameters: PoseidonParameters<F>,
cs: ConstraintSystemRef<F>,
input_words: Vec<FpVar<F>>,
) -> FpVar<F> {
// Check input words are `t` elements long
if input_words.len() != parameters.t {
panic!("err: input words must be t elements long")
}

// t = rate + capacity
let state_words = vec![zero; parameters.t];
let M00_var = FpVar::<F>::new_constant(cs.clone(), parameters.optimized_mds.M_00)
.expect("can create constant");

Self {
let mut instance = InstanceVar {
parameters,
cs,
state_words,
state_words: input_words,
M00_var,
}
}

/// Fixed width hash from n:1. Outputs a F given `t` input words.
pub fn n_to_1_fixed_hash(&mut self, input_words: Vec<FpVar<F>>) -> FpVar<F> {
// Check input words are `t` elements long
if input_words.len() != self.parameters.t {
panic!("err: input words must be t elements long")
}

// Set internal state words.
for (i, input_word) in input_words.into_iter().enumerate() {
self.state_words[i] = input_word
}
};

// Apply Poseidon permutation.
//self.unoptimized_permute();
self.permute();
instance.permute();

// Emit a single element since this is a n:1 hash.
self.state_words[1].clone()
}

/// Fixed width hash from n:1. Outputs a F given `t` input words.
pub fn unoptimized_n_to_1_fixed_hash(&mut self, input_words: Vec<FpVar<F>>) -> FpVar<F> {
// Check input words are `t` elements long
if input_words.len() != self.parameters.t {
panic!("err: input words must be t elements long")
}

// Set internal state words.
for (i, input_word) in input_words.into_iter().enumerate() {
self.state_words[i] = input_word
}

// Apply Poseidon permutation.
self.unoptimized_permute();

// Emit a single element since this is a n:1 hash.
self.state_words[1].clone()
instance.state_words[1].clone()
}

/// Unoptimized Poseidon permutation.
Expand All @@ -87,6 +62,7 @@ where
let t = self.parameters.t;
let round_constants = self.parameters.arc.elements().clone();

dbg!("before R_f rounds", self.cs.num_constraints());
// First full rounds
for _ in 0..R_f {
// Apply `AddRoundConstants` layer
Expand All @@ -97,6 +73,7 @@ where
self.full_sub_words();
self.mix_layer_mds();
}
dbg!("after R_f rounds", self.cs.num_constraints());

// Partial rounds
for _ in 0..R_P {
Expand All @@ -108,6 +85,7 @@ where
self.partial_sub_words();
self.mix_layer_mds();
}
dbg!("after R_P rounds", self.cs.num_constraints());

// Final full rounds
for _ in 0..R_f {
Expand All @@ -119,6 +97,7 @@ where
self.full_sub_words();
self.mix_layer_mds();
}
dbg!("after final R_f rounds", self.cs.num_constraints());
}

/// Permutes the internal state.
Expand All @@ -131,38 +110,64 @@ where
let round_constants = self.parameters.optimized_arc.0.clone();
let t = self.parameters.t;

dbg!(self.state_words.len());
dbg!("before R_f rounds", self.cs.num_constraints());
dbg!(R_f);
// First chunk of full rounds
for r in 0..R_f {
dbg!("start of round: ", self.cs.num_constraints());
// Apply `AddRoundConstants` layer
for i in 0..t {
self.state_words[i] += round_constants.get_element(r, i);
}
dbg!("after adding constants: ", self.cs.num_constraints());
self.full_sub_words();
dbg!("after x^a: ", self.cs.num_constraints());
self.mix_layer_mds();
dbg!("after linear layer: ", self.cs.num_constraints());
}
let mut round_constants_counter = R_f;
dbg!("after R_f rounds", self.cs.num_constraints());

// Partial rounds
// First part of `AddRoundConstants` layer
dbg!(R_P);
for i in 0..t {
self.state_words[i] += round_constants.get_element(round_constants_counter, i);
}
dbg!("after adding constants: ", self.cs.num_constraints());
// First full matrix multiplication.
self.mix_layer_mi();
dbg!("after Mi mult", self.cs.num_constraints());

for r in 0..R_P - 1 {
dbg!("start of round: ", self.cs.num_constraints());
self.partial_sub_words();
dbg!("after x^a: ", self.cs.num_constraints());
// Rest of `AddRoundConstants` layer, moved to after the S-box layer
round_constants_counter += 1;
self.state_words[0] += round_constants.get_element(round_constants_counter, 0);
dbg!("after x^a: ", self.cs.num_constraints());
self.sparse_mat_mul(R_P - r - 1);
dbg!(
"after sparse matrix linear layer: ",
self.cs.num_constraints()
);
}
dbg!("after R_P - 1 rounds", self.cs.num_constraints());

// Last partial round
self.partial_sub_words();
dbg!("after x^a: ", self.cs.num_constraints());
self.sparse_mat_mul(0);
dbg!(
"after sparse matrix linear layer: ",
self.cs.num_constraints()
);
round_constants_counter += 1;
dbg!("after R_P rounds", self.cs.num_constraints());

dbg!(R_f);
// Final full rounds
for _ in 0..R_f {
// Apply `AddRoundConstants` layer
Expand All @@ -173,6 +178,7 @@ where
self.mix_layer_mds();
round_constants_counter += 1;
}
dbg!("after final R_f rounds", self.cs.num_constraints());
}

/// Applies the partial `SubWords` layer.
Expand All @@ -191,11 +197,11 @@ where
fn full_sub_words(&mut self) {
match self.parameters.alpha {
Alpha::Exponent(exp) => {
self.state_words = self
.state_words
.iter()
.map(|x| x.pow_by_constant([exp as u64]).expect("can compute pow"))
.collect()
for i in 0..self.parameters.t {
self.state_words[i] = (self.state_words[i])
.pow_by_constant([exp as u64])
.expect("can compute pow")
}
}
Alpha::Inverse => {
unimplemented!("err: inverse alpha not implemented")
Expand Down
103 changes: 59 additions & 44 deletions poseidon377/src/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,90 +9,105 @@ pub fn hash_1(
domain_separator: &FqVar,
value: FqVar,
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_1_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![domain_separator.clone(), value]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_1_PARAMS.clone(),
cs.clone(),
vec![domain_separator.clone(), value],
))
}

pub fn hash_2(
cs: ConstraintSystemRef<Fq>,
domain_separator: &FqVar,
value: (FqVar, FqVar),
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_2_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![domain_separator.clone(), value.0, value.1]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_2_PARAMS.clone(),
cs.clone(),
vec![domain_separator.clone(), value.0, value.1],
))
}

pub fn hash_3(
cs: ConstraintSystemRef<Fq>,
domain_separator: &FqVar,
value: (FqVar, FqVar, FqVar),
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_3_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![domain_separator.clone(), value.0, value.1, value.2]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_3_PARAMS.clone(),
cs.clone(),
vec![domain_separator.clone(), value.0, value.1, value.2],
))
}

pub fn hash_4(
cs: ConstraintSystemRef<Fq>,
domain_separator: &FqVar,
value: (FqVar, FqVar, FqVar, FqVar),
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_4_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_4_PARAMS.clone(),
cs.clone(),
vec![domain_separator.clone(), value.0, value.1, value.2, value.3],
))
}

pub fn hash_5(
cs: ConstraintSystemRef<Fq>,
domain_separator: &FqVar,
value: (FqVar, FqVar, FqVar, FqVar, FqVar),
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_5_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
value.4,
]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_5_PARAMS.clone(),
cs.clone(),
vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
value.4,
],
))
}

pub fn hash_6(
cs: ConstraintSystemRef<Fq>,
domain_separator: &FqVar,
value: (FqVar, FqVar, FqVar, FqVar, FqVar, FqVar),
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_6_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
value.4,
value.5,
]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_6_PARAMS.clone(),
cs.clone(),
vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
value.4,
value.5,
],
))
}

pub fn hash_7(
cs: ConstraintSystemRef<Fq>,
domain_separator: &FqVar,
value: (FqVar, FqVar, FqVar, FqVar, FqVar, FqVar, FqVar),
) -> Result<FqVar, SynthesisError> {
let mut state = InstanceVar::new(crate::RATE_7_PARAMS.clone(), cs.clone());
Ok(state.n_to_1_fixed_hash(vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
value.4,
value.5,
value.6,
]))
Ok(InstanceVar::n_to_1_fixed_hash(
crate::RATE_7_PARAMS.clone(),
cs.clone(),
vec![
domain_separator.clone(),
value.0,
value.1,
value.2,
value.3,
value.4,
value.5,
value.6,
],
))
}
Loading

0 comments on commit 524faf7

Please sign in to comment.