Skip to content

Commit

Permalink
add additional prop test that asserts we can extend the OG data withi…
Browse files Browse the repository at this point in the history
…n the chunk size limit
  • Loading branch information
martyall committed Feb 10, 2025
1 parent 4eca4ce commit 82bbc48
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 18 deletions.
41 changes: 23 additions & 18 deletions saffron/src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl<F: PrimeField> Diff<F> {
}

#[instrument(skip_all, level = "debug")]
pub fn as_evaulations(
pub fn as_evaluations(
&self,
domain: &Radix2EvaluationDomain<F>,
) -> Vec<Evaluations<F, Radix2EvaluationDomain<F>>> {
Expand All @@ -76,7 +76,7 @@ impl<F: PrimeField> Diff<F> {
#[cfg(test)]
pub mod tests {
use super::*;
use crate::utils::{min_encoding_chunks, test_utils::UserData};
use crate::utils::{chunk_size_in_bytes, min_encoding_chunks, test_utils::UserData};
use ark_ff::Zero;
use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
use mina_curves::pasta::Fp;
Expand All @@ -87,12 +87,9 @@ pub mod tests {
static DOMAIN: Lazy<Radix2EvaluationDomain<Fp>> =
Lazy::new(|| Radix2EvaluationDomain::new(1 << 16).unwrap());

// Take a prefix of the data and randomly modify it according to the threshold
pub fn random_legal_perturbation(threshold: f64, prefix_len: usize, data: &[u8]) -> Vec<u8> {
assert!(prefix_len <= data.len());
pub fn randomize_data(threshold: f64, data: &[u8]) -> Vec<u8> {
let mut rng = rand::thread_rng();
data.iter()
.take(prefix_len)
.map(|b| {
let n = rng.gen::<f64>();
if n < threshold {
Expand All @@ -104,6 +101,19 @@ pub mod tests {
.collect()
}

pub fn random_diff(UserData(xs): UserData) -> BoxedStrategy<(UserData, UserData)> {
let n_chunks = min_encoding_chunks(&*DOMAIN, &xs);
let max_byte_len = n_chunks * chunk_size_in_bytes(&*DOMAIN);
(0.0..=1.0, 0..=max_byte_len)
.prop_flat_map(move |(threshold, n)| {
let mut ys = randomize_data(threshold, &xs);
// NOTE: n could be less than xs.len(), in which case this is just truncation
ys.resize_with(n, rand::random);
Just((UserData(xs.clone()), UserData(ys)))
})
.boxed()
}

fn add(mut evals: Vec<Vec<Fp>>, diff: &Diff<Fp>) -> Vec<Vec<Fp>> {
evals
.par_iter_mut()
Expand All @@ -117,20 +127,15 @@ pub mod tests {
}

proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#![proptest_config(ProptestConfig::with_cases(20))]
#[test]

// Adding a diff to the original data should give the new data, including possible truncation scenario
fn test_add_diff((threshold, (UserData(data), n)) in
(0.0..1.0, UserData::arbitrary().prop_flat_map(|d| {
let len = d.len();
(Just(d), 0..len)
}))
fn test_allow_legal_updates((UserData(xs), UserData(ys)) in
(UserData::arbitrary().prop_flat_map(random_diff))
) {
let ys = random_legal_perturbation(threshold, n, &data);
let diff = Diff::<Fp>::create(&*DOMAIN, &data, &ys);
let diff = Diff::<Fp>::create(&*DOMAIN, &xs, &ys);
prop_assert!(diff.is_ok());
let xs_elems = encode_for_domain(&*DOMAIN, &data);
let xs_elems = encode_for_domain(&*DOMAIN, &xs);
let ys_elems = {
let pad = vec![Fp::zero(); DOMAIN.size()];
let mut elems = encode_for_domain(&*DOMAIN, &ys);
Expand All @@ -142,7 +147,7 @@ pub mod tests {
}
}

// Check that we can't construct a diff that requires more polynomial chunks than the original data
// Check that we CAN'T construct a diff that requires more polynomial chunks than the original data
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
Expand All @@ -167,7 +172,7 @@ pub mod tests {
})
)
) {
let mut ys = random_legal_perturbation(threshold, data.len(), &data);
let mut ys = randomize_data(threshold, &data);
ys.append(&mut extra);
let diff = Diff::<Fp>::create(&*DOMAIN, &data, &ys);
prop_assert!(diff.is_err());
Expand Down
5 changes: 5 additions & 0 deletions saffron/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ pub fn min_encoding_chunks<F: PrimeField, D: EvaluationDomain<F>>(domain: &D, xs
(num_field_elems + domain.size() - 1) / domain.size()
}

pub fn chunk_size_in_bytes<F: PrimeField, D: EvaluationDomain<F>>(domain: &D) -> usize {
let m = F::MODULUS_BIT_SIZE as usize / 8;
domain.size() * m
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 82bbc48

Please sign in to comment.