Skip to content
This repository has been archived by the owner on Aug 15, 2024. It is now read-only.

Commit

Permalink
debugging FRI
Browse files Browse the repository at this point in the history
  • Loading branch information
Konstantce committed Apr 15, 2020
1 parent 364fdf0 commit 44f9c82
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 102 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ gm17 = []
redshift = ["lazy_static", "tiny-keccak", "blake2s_simd", "blake2s_const"]
wasm = ["web-sys"]
nightly = ["prefetch"]
derive_serde = ["pairing/derive_serde"]
derive_serde = ["pairing/derive_serde"]
25 changes: 14 additions & 11 deletions src/redshift/IOP/FRI/coset_combining_fri/coset_combiner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ impl CosetCombiner {
pub fn get_coset_idx_for_natural_index(
natural_index: usize,
domain_size: usize,
log_domain_size: usize,
collapsing_factor: usize) -> Range<usize>
log_domain_size: u32,
collapsing_factor: u32) -> Range<usize>
{
assert!(natural_index < domain_size, "asking for index {} for domain size {}", natural_index, domain_size);
assert_eq!(1 << log_domain_size, domain_size);

let mut mask = (1 << collapsing_factor) - 1;
let mut mask = 1 << collapsing_factor - 1;

This comment has been minimized.

Copy link
@hedgar2017

hedgar2017 Apr 15, 2020

Removing the parenthesis is a bad idea.
Many people don't remember the precedence table perfectly, and it is extremely ambiguous.

mask = !(mask << (log_domain_size - collapsing_factor));

let start_idx = (natural_index & mask) << collapsing_factor;
Expand All @@ -35,8 +35,8 @@ impl CosetCombiner {
pub fn get_coset_idx_for_natural_index_extended(
natural_index: usize,
domain_size: usize,
log_domain_size: usize,
collapsing_factor: usize) -> (Range<usize>, usize)
log_domain_size: u32,
collapsing_factor: u32) -> (Range<usize>, usize)
{
assert!(natural_index < domain_size, "asking for index {} for domain size {}", natural_index, domain_size);
assert_eq!(1 << log_domain_size, domain_size);
Expand All @@ -56,16 +56,19 @@ impl CosetCombiner {
pub fn get_natural_idx_for_coset_index(
coset_index: usize,
domain_size: usize,
log_domain_size: usize,
collapsing_factor: usize) -> usize
log_domain_size: u32,
collapsing_factor: u32) -> usize
{
assert!(coset_index < domain_size, "asking for index {} for domain size {}", coset_index, domain_size);
assert_eq!(1 << log_domain_size, domain_size);

let start_idx = coset_index >> collapsing_factor;
let mask = (1 << collapsing_factor) - 1;
let shift = bitreverse(coset_index & mask, log_domain_size as usize);
mask + shift
let shift = bitreverse(coset_index & mask, collapsing_factor as usize);

let mut res = shift.checked_shl((log_domain_size - collapsing_factor) as u32).unwrap();
res += coset_index >> collapsing_factor;

res
}
}

Expand All @@ -88,7 +91,7 @@ mod test {
let coset_index = 23;
let natural_idx = CosetCombiner::get_natural_idx_for_coset_index(
coset_index, domain_size, log_domain_size, collapsing_factor);
assert_eq!(coset_idx, CosetCombiner::get_coset_idx_for_natural_index_extended(
assert_eq!(coset_index, CosetCombiner::get_coset_idx_for_natural_index_extended(
natural_idx, domain_size, log_domain_size, collapsing_factor).1);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/redshift/IOP/FRI/coset_combining_fri/fri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
)
}

fn prototype_into_proof<'a>(
pub fn prototype_into_proof<'a>(
prototype: FriProofPrototype<F, O>,
upper_layer_oracles: &'a BatchedOracle<F, O>,
upper_layer_values: Vec<&[F]>,
Expand Down
2 changes: 1 addition & 1 deletion src/redshift/IOP/FRI/coset_combining_fri/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub trait FriPrecomputations<F: PrimeField> {
pub struct FriParams {
//it measures how much nearby levels of FRI differ in size (nu in the paper)
// it is 1 for 2 -> 1 mapping, 2 for 4 -> 1 mapping, etc.
pub collapsing_factor : usize,
pub collapsing_factor : u32,
//number of iterations done during FRI query phase
pub R : usize,
// should be mutable as initial degree is set by generator
Expand Down
4 changes: 2 additions & 2 deletions src/redshift/IOP/FRI/coset_combining_fri/query_producer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<F: PrimeField, I: Oracle<F>> FriProofPrototype<F, I>

let mut rounds = vec![];
let initial_domain_size = params.initial_degree_plus_one.get() * params.lde_factor;
let log_initial_domain_size = log2_floor(initial_domain_size) as usize;
let log_initial_domain_size = log2_floor(initial_domain_size);
let collapsing_factor = params.collapsing_factor;
let coset_size = 1 << collapsing_factor;
let mut upper_layer_queries = vec![];
Expand All @@ -41,7 +41,7 @@ impl<F: PrimeField, I: Oracle<F>> FriProofPrototype<F, I>

let mut queries = vec![];
let mut domain_size = initial_domain_size >> collapsing_factor;
let mut log_domain_size = initial_domain_size - collapsing_factor;
let mut log_domain_size = log_initial_domain_size - collapsing_factor;
let mut elem_index = (natural_first_element_index << collapsing_factor) % domain_size;

for (oracle, leaf_values) in self.oracles.iter().zip(&self.intermediate_values) {
Expand Down
97 changes: 89 additions & 8 deletions src/redshift/IOP/FRI/coset_combining_fri/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
let collapsing_factor = params.collapsing_factor;
let coset_size = 1 << collapsing_factor;
let initial_domain_size = domain.size as usize;
let log_initial_domain_size = log2_floor(initial_domain_size) as usize;
let log_initial_domain_size = log2_floor(initial_domain_size);

if natural_element_indexes.len() != params.R || proof.final_coefficients.len() > params.final_degree_plus_one {
return Ok(false);
Expand Down Expand Up @@ -96,8 +96,8 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
fri_challenges: &[F],
_num_steps: usize,
initial_domain_size: usize,
log_initial_domain_size: usize,
collapsing_factor: usize,
log_initial_domain_size: u32,
collapsing_factor: u32,
coset_size: usize,
oracle_params: &O::Params,
omega: &F,
Expand Down Expand Up @@ -130,7 +130,7 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
let mut domain_size = initial_domain_size;
let mut log_domain_size = log_initial_domain_size;
let mut elem_index = (natural_first_element_index << collapsing_factor) % domain_size;
// TODO: here is a bug - omega inverse should also be cloned
// TODO: here is a bug - omega inverse should also be doubled
let mut omega_inv = omega_inv.clone();
let mut previous_layer_element = FriIop::<F, O, C>::coset_interpolant_value(
&values[..],
Expand Down Expand Up @@ -200,10 +200,10 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
values: &[F],
challenge: &F,
coset_idx_range: Range<usize>,
collapsing_factor: usize,
collapsing_factor: u32,
coset_size: usize,
domain_size: &mut usize,
log_domain_size: &mut usize,
log_domain_size: &mut u32,
elem_index: &mut usize,
omega_inv: &mut F,
two_inv: &F,
Expand All @@ -213,7 +213,7 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
let mut this_level_values = Vec::with_capacity(coset_size/2);
let mut next_level_values = vec![F::zero(); coset_size / 2];

let base_omega_idx = bitreverse(coset_idx_range.start, *log_domain_size);
let base_omega_idx = bitreverse(coset_idx_range.start, *log_domain_size as usize);

for wrapping_step in 0..collapsing_factor {
let inputs = if wrapping_step == 0 {
Expand All @@ -224,7 +224,7 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
for (pair_idx, (pair, o)) in inputs.chunks(2).zip(next_level_values.iter_mut()).enumerate()
{

let idx = bitreverse(base_omega_idx + 2 * pair_idx, *log_domain_size);
let idx = bitreverse(base_omega_idx + 2 * pair_idx, *log_domain_size as usize);
let divisor = omega_inv.pow([idx as u64]);
let f_at_omega = pair[0];
let f_at_minus_omega = pair[1];
Expand Down Expand Up @@ -260,3 +260,84 @@ impl<F: PrimeField, O: Oracle<F>, C: Channel<F, Input = O::Commitment>> FriIop<F
}


#[cfg(test)]
mod test {

#[test]
fn fri_queries() {

use crate::ff::{Field, PrimeField};
use rand::{XorShiftRng, SeedableRng, Rand, Rng};

use crate::redshift::polynomials::*;
use crate::multicore::*;
use crate::redshift::fft::cooley_tukey_ntt::{CTPrecomputations, BitReversedOmegas};

use crate::redshift::IOP::FRI::coset_combining_fri::precomputation::*;
use crate::redshift::IOP::FRI::coset_combining_fri::FriPrecomputations;
use crate::redshift::IOP::FRI::coset_combining_fri::fri;
use crate::redshift::IOP::FRI::coset_combining_fri::{FriParams, FriIop};

use crate::redshift::IOP::channel::blake_channel::*;
use crate::redshift::IOP::channel::*;

use crate::redshift::IOP::oracle::coset_combining_blake2s_tree::*;
use crate::redshift::IOP::oracle::{Oracle, BatchedOracle};

use crate::pairing::bn256::Fr as Fr;

const SIZE: usize = 1024;
let worker = Worker::new_with_cpus(1);
let mut channel = Blake2sChannel::new(&());

let params = FriParams {
collapsing_factor: 1,
R: 80,
initial_degree_plus_one: std::cell::Cell::new(1024),
lde_factor: 16,
final_degree_plus_one: 2,
};

let oracle_params = FriSpecificBlake2sTreeParams {
values_per_leaf: 1 << params.collapsing_factor
};

let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let coeffs = (0..SIZE).map(|_| Fr::rand(rng)).collect::<Vec<_>>();

let poly = Polynomial::<Fr, _>::from_coeffs(coeffs).unwrap();
let precomp = BitReversedOmegas::<Fr>::new_for_domain_size(poly.size());

let coset_factor = Fr::multiplicative_generator();
let eval_result = poly.bitreversed_lde_using_bitreversed_ntt(&worker, 16, &precomp, &coset_factor).unwrap();

// construct upper layer oracle from eval_result

let upper_layer_oracle = FriSpecificBlake2sTree::create(eval_result.as_ref(), &oracle_params);
let batched_oracle = BatchedOracle::create(vec![("starting oracle", &upper_layer_oracle)]);

let fri_precomp = <OmegasInvBitreversed::<Fr> as FriPrecomputations<Fr>>::new_for_domain_size(eval_result.size());

let fri_proto = FriIop::<Fr, FriSpecificBlake2sTree<Fr>, Blake2sChannel<Fr>>::proof_from_lde(
eval_result.clone(),
&fri_precomp,
&worker,
&mut channel,
&params,
&oracle_params,
).expect("FRI must succeed");

// upper layer combiner is trivial in our case

let proof = FriIop::<Fr, FriSpecificBlake2sTree<Fr>, Blake2sChannel<Fr>>::prototype_into_proof(
fri_proto,
&batched_oracle,
vec![eval_result.as_ref()],
vec![0],
&params,
&oracle_params,
).expect("Fri Proof must be constrcuted");
}
}


21 changes: 20 additions & 1 deletion src/redshift/IOP/hashes/rescue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fn rescue_f<F: PrimeField, Params: RescueParams<F>>(
let RESCUE_M = params.t();
let RESCUE_ROUNDS = params.get_num_rescue_rounds();
let constants = params.get_constants();


for i in 0..RESCUE_M {
state[i].add_assign(&constants[0][i]);
Expand Down Expand Up @@ -116,7 +117,7 @@ fn rescue_duplex<F: PrimeField, Params: RescueParams<F>>(

let mut output = vec![];
for i in 0..OUTPUT_RATE {
output[i] = Some(state[i]);
output.push(Some(state[i]));
}
output
}
Expand Down Expand Up @@ -205,4 +206,22 @@ impl<F: PrimeField, RP: RescueParams<F>> Rescue<F, RP> {
}
}
}
}


#[test]
fn test_rescue() {
use crate::ff::Field;
use crate::pairing::bn256::Fr as Fr;
use bn256_rescue_params::BN256Rescue;

let bn256_params = BN256Rescue::default();

let mut elem = Fr::one();

let mut rescue = Rescue::new(&bn256_params);
rescue.absorb(elem.clone(), &bn256_params);
elem.double();
rescue.absorb(elem, &bn256_params);
rescue.squeeze(&bn256_params);
}
37 changes: 2 additions & 35 deletions src/redshift/IOP/oracle/coset_combining_blake2s_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ impl<F: PrimeField> Oracle<F> for FriSpecificBlake2sTree<F> {
// we never expect that query is mis-alligned, so check it
debug_assert!(indexes.start % self.params.values_per_leaf == 0);
debug_assert!(indexes.len() == self.params.values_per_leaf);
debug_assert!(indexes.end < self.size());
debug_assert!(indexes.end < values.len());
debug_assert!(indexes.end <= self.size());
debug_assert!(indexes.end <= values.len());

let query_values = Vec::from(&values[indexes.start..indexes.end]);

Expand Down Expand Up @@ -298,36 +298,3 @@ fn make_small_iop() {
assert!(valid, "invalid query for leaf index {}", i);
}
}


#[test]
fn test_bench_large_fri_specific_iop() {
use crate::ff::Field;
use crate::redshift::partial_reduction_field::Fr;

const SIZE: usize = 1 << (20 + 4);
const VALUES_PER_LEAF: usize = 8;

let params = FriSpecificBlake2sTreeParams {
values_per_leaf: VALUES_PER_LEAF
};

let mut inputs = vec![];
let mut f = Fr::one();
for _ in 0..SIZE {
inputs.push(f);
f.double();
}

let iop = FriSpecificBlake2sTree::create(&inputs, &params);
let commitment = iop.get_commitment();
let tree_size = iop.size();
assert!(tree_size == SIZE);
assert!(iop.nodes.len() == (SIZE / VALUES_PER_LEAF));
for i in 0..128 {
let indexes = (i*VALUES_PER_LEAF)..(VALUES_PER_LEAF + i*VALUES_PER_LEAF);
let query = iop.produce_query(indexes, &inputs, &params);
let valid = FriSpecificBlake2sTree::verify_query(&commitment, &query, &params);
assert!(valid, "invalid query for leaf index {}", i);
}
}
Loading

0 comments on commit 44f9c82

Please sign in to comment.