From 51a4592e35b7139bb381931feb3978061ccc91fa Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 16:03:18 +0200 Subject: [PATCH 01/13] run tests with $n = 5$ --- src/fec.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index f1a9e7cb..506ab4c0 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -337,11 +337,11 @@ mod tests { fn end_to_end() { let bytes = bytes(); - for k in [3, 5] { - for rho in [0.5, 0.33] { - let n = (k as f64 / rho) as usize; - end_to_end_template::<Fr>(&bytes, k, n); - } + let ks = [3, 5]; + let n = 5; + + for k in ks { + end_to_end_template::<Fr>(&bytes, k, n); } } @@ -349,11 +349,11 @@ mod tests { fn end_to_end_with_recoding() { let bytes = bytes(); - for k in [3, 5] { - for rho in [0.50, 0.33] { - let n = (k as f64 / rho) as usize; - end_to_end_with_recoding_template::<Fr>(&bytes, k, n); - } + let ks = [3, 5]; + let n = 5; + + for k in ks { + end_to_end_with_recoding_template::<Fr>(&bytes, k, n); } } -- GitLab From 5f30af3d2404a0fd167b612f35eebf199497cf07 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 16:09:16 +0200 Subject: [PATCH 02/13] move "recoding steps" and "should not decode" to arguments --- src/fec.rs | 56 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index 506ab4c0..013bb8b0 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -292,34 +292,19 @@ mod tests { try_all_decoding_combinations(data, &shards, k, &test_case, None, vec![]); } - fn end_to_end_with_recoding_template<F: PrimeField>(data: &[u8], k: usize, n: usize) { - assert!(n >= 5, "n should be at least 5, found {}", n); - + fn end_to_end_with_recoding_template<F: PrimeField>( + data: &[u8], + k: usize, + n: usize, + recoding_steps: Vec<Vec<usize>>, + should_not_be_decodable: Vec<Vec<usize>>, + ) { let mut rng = ark_std::test_rng(); let test_case = format!("TEST | data: {} bytes, k: {}, n: {}", data.len(), k, n); let mut shards = encode::<F>(data, &Matrix::random(k, n, &mut rng)) .unwrap_or_else(|_| panic!("could not encode {test_case}")); - let recoding_steps = [ - vec![2, 4], // = n - vec![1, 3], // = (n + 1) - vec![n, (n + 1)], // = (n + 2) = ((2, 4), (1, 3)) - vec![0], // = (n + 3) = (0) - vec![(n + 3)], // = (n + 4) = (0) - ]; - let should_not_be_decodable = vec![ - vec![2, 4, n], - vec![1, 3, (n + 1)], - vec![n, (n + 1), (n + 2)], - vec![1, 3, n, (n + 2)], - vec![2, 4, (n + 1), (n + 2)], - vec![1, 2, 3, 4, (n + 2)], - vec![0, (n + 3)], - vec![0, (n + 4)], - vec![(n + 3), (n + 4)], - ]; - for step in recoding_steps { let shards_to_recode: Vec<_> = shards .iter() @@ -352,8 +337,33 @@ mod tests { let ks = [3, 5]; let n = 5; + let recoding_steps = vec![ + vec![2, 4], // = n + vec![1, 3], // = (n + 1) + vec![n, (n + 1)], // = (n + 2) = ((2, 4), (1, 3)) + vec![0], // = (n + 3) = (0) + vec![(n + 3)], // = (n + 4) = (0) + ]; + let should_not_be_decodable = vec![ + vec![2, 4, n], + vec![1, 3, (n + 1)], + vec![n, (n + 1), (n + 2)], + vec![1, 3, n, (n + 2)], + vec![2, 4, (n + 1), (n + 2)], + vec![1, 2, 3, 4, (n + 2)], + vec![0, (n + 3)], + vec![0, (n + 4)], + vec![(n + 3), (n + 4)], + ]; + for k in ks { - end_to_end_with_recoding_template::<Fr>(&bytes, k, n); + end_to_end_with_recoding_template::<Fr>( + &bytes, + k, + n, + recoding_steps.clone(), + should_not_be_decodable.clone(), + ); } } -- GitLab From 73705efdff40e68cc748eac62966333529d37896 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 16:25:49 +0200 Subject: [PATCH 03/13] don't try to decode when recoding this has already been tested in the plain "end to end" test. --- src/fec.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index 013bb8b0..bfb9d709 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -246,6 +246,7 @@ mod tests { data: &[u8], shards: &[Shard<F>], k: usize, + n: usize, test_case: &str, limit: Option<usize>, should_not_be_decodable: Vec<Vec<usize>>, @@ -257,10 +258,12 @@ mod tests { .combinations(k) .take(limit.unwrap_or(usize::MAX)) { - let s = c.iter().map(|(_, s)| s).cloned().collect(); - let is: Vec<usize> = c.iter().map(|(i, _)| i).cloned().collect(); + let is: Vec<usize> = c.iter().map(|(i, _)| *i).collect(); + if shards.len() > n && *is.iter().max().unwrap() <= n - 1 { + continue; + } - let actual = decode::<F>(s); + let actual = decode::<F>(c.iter().map(|(_, s)| s).cloned().collect()); if contains_one_of(&is, &should_not_be_decodable) { assert!( @@ -289,7 +292,7 @@ mod tests { let shards = encode::<F>(data, &Matrix::random(k, n, &mut rng)) .unwrap_or_else(|_| panic!("could not encode {test_case}")); - try_all_decoding_combinations(data, &shards, k, &test_case, None, vec![]); + try_all_decoding_combinations(data, &shards, k, n, &test_case, None, vec![]); } fn end_to_end_with_recoding_template<F: PrimeField>( @@ -315,7 +318,15 @@ mod tests { shards.push(recode_random(&shards_to_recode, &mut rng).unwrap().unwrap()); } - try_all_decoding_combinations(data, &shards, k, &test_case, None, should_not_be_decodable); + try_all_decoding_combinations( + data, + &shards, + k, + n, + &test_case, + None, + should_not_be_decodable, + ); } #[test] -- GitLab From fe3efe75cbcfaab31e4f8c45987f3a6bf1901905 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 16:29:11 +0200 Subject: [PATCH 04/13] better names --- src/fec.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index bfb9d709..8c311528 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -251,6 +251,8 @@ mod tests { limit: Option<usize>, should_not_be_decodable: Vec<Vec<usize>>, ) { + let there_are_recoded_shards = shards.len() > n; + for c in shards .iter() .cloned() @@ -259,8 +261,11 @@ mod tests { .take(limit.unwrap_or(usize::MAX)) { let is: Vec<usize> = c.iter().map(|(i, _)| *i).collect(); - if shards.len() > n && *is.iter().max().unwrap() <= n - 1 { - continue; + if there_are_recoded_shards { + let contains_recoded_shards = *is.iter().max().unwrap() <= n - 1; + if contains_recoded_shards { + continue; + } } let actual = decode::<F>(c.iter().map(|(_, s)| s).cloned().collect()); -- GitLab From 5ab8f27b2355348bbf5bf74432ca755b179809c2 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 16:32:57 +0200 Subject: [PATCH 05/13] split scenarii --- src/fec.rs | 68 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index 8c311528..aebe7d96 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -306,9 +306,16 @@ mod tests { n: usize, recoding_steps: Vec<Vec<usize>>, should_not_be_decodable: Vec<Vec<usize>>, + name: &str, ) { let mut rng = ark_std::test_rng(); - let test_case = format!("TEST | data: {} bytes, k: {}, n: {}", data.len(), k, n); + let test_case = format!( + "TEST | data: {} bytes, k: {}, n: {}, scenario: {}", + data.len(), + k, + n, + name + ); let mut shards = encode::<F>(data, &Matrix::random(k, n, &mut rng)) .unwrap_or_else(|_| panic!("could not encode {test_case}")); @@ -353,33 +360,44 @@ mod tests { let ks = [3, 5]; let n = 5; - let recoding_steps = vec![ - vec![2, 4], // = n - vec![1, 3], // = (n + 1) - vec![n, (n + 1)], // = (n + 2) = ((2, 4), (1, 3)) - vec![0], // = (n + 3) = (0) - vec![(n + 3)], // = (n + 4) = (0) - ]; - let should_not_be_decodable = vec![ - vec![2, 4, n], - vec![1, 3, (n + 1)], - vec![n, (n + 1), (n + 2)], - vec![1, 3, n, (n + 2)], - vec![2, 4, (n + 1), (n + 2)], - vec![1, 2, 3, 4, (n + 2)], - vec![0, (n + 3)], - vec![0, (n + 4)], - vec![(n + 3), (n + 4)], + let scenarii = [ + ( + "simple", + vec![ + vec![2, 4], // = n + vec![1, 3], // = (n + 1) + vec![n, (n + 1)], // = (n + 2) = ((2, 4), (1, 3)) + ], + vec![ + vec![2, 4, n], + vec![1, 3, (n + 1)], + vec![n, (n + 1), (n + 2)], + vec![1, 3, n, (n + 2)], + vec![2, 4, (n + 1), (n + 2)], + vec![1, 2, 3, 4, (n + 2)], + ], + ), + ( + "chain", + vec![ + vec![0], // = (n) = (0) + vec![(n)], // = (n + 1) = (0) + ], + vec![vec![0, (n)], vec![0, (n + 1)], vec![(n), (n + 1)]], + ), ]; for k in ks { - end_to_end_with_recoding_template::<Fr>( - &bytes, - k, - n, - recoding_steps.clone(), - should_not_be_decodable.clone(), - ); + for (name, steps, should_not_decode) in scenarii.clone() { + end_to_end_with_recoding_template::<Fr>( + &bytes, + k, + n, + steps, + should_not_decode, + name, + ); + } } } -- GitLab From 7c358a2b8901f4c08256a78ab43f50dbaccb7818 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 16:40:04 +0200 Subject: [PATCH 06/13] add mermaid graphs --- src/fec.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/fec.rs b/src/fec.rs index aebe7d96..a3174422 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -361,6 +361,15 @@ mod tests { let n = 5; let scenarii = [ + // ```mermaid + // graph TD; + // a[n+1]; b[n+2]; c[n+3]; + // + // 1; + // 3-->a; 5-->a; + // 2-->b; 4-->b; + // a-->c; b-->c; + // ``` ( "simple", vec![ @@ -377,6 +386,13 @@ mod tests { vec![1, 2, 3, 4, (n + 2)], ], ), + // ```mermaid + // graph TD; + // a[n+1]; b[n+2]; + // + // 1-->a; a-->b; + // 2; 3; 4; 5; + // ``` ( "chain", vec![ -- GitLab From 342da7492b7c2fcc50bc2a0b908fb5398e68f9cb Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Thu, 6 Jun 2024 17:32:09 +0200 Subject: [PATCH 07/13] pretty print the is --- src/fec.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index a3174422..0bb2146d 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -268,24 +268,43 @@ mod tests { } } + let pretty_is = is + .iter() + .map(|&i| { + if i == n { + "(n)".into() + } else if i > n { + format!("(n + {})", i - n) + } else { + format!("{}", i) + } + }) + .collect::<Vec<_>>() + .join(", "); + let pretty_is = format!("[{pretty_is}]"); + let actual = decode::<F>(c.iter().map(|(_, s)| s).cloned().collect()); if contains_one_of(&is, &should_not_be_decodable) { assert!( actual.is_err(), - "should not decode with {:?} {test_case}", - is + "should not decode with {} {test_case}", + pretty_is ); continue; } - assert!(actual.is_ok(), "could not decode with {:?} {test_case}", is); + assert!( + actual.is_ok(), + "could not decode with {} {test_case}", + pretty_is + ); assert_eq!( data, actual.unwrap(), - "bad decoded data with {:?} {test_case}", - is, + "bad decoded data with {} {test_case}", + pretty_is, ); } } -- GitLab From 5344c6d4f1419994aefc1bc4d22ca1602378614a Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 7 Jun 2024 10:44:02 +0200 Subject: [PATCH 08/13] new containment test --- src/fec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fec.rs b/src/fec.rs index 0bb2146d..bdc2e363 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -240,6 +240,7 @@ mod tests { &[3, 6, 8, 9, 10], &[vec![2, 4, 6], vec![1, 3, 7], vec![6, 7, 8], vec![3, 6, 8]], )); + assert!(contains_one_of(&[0, 4, 5], &[vec![2, 3, 5], vec![4, 5]])); } fn try_all_decoding_combinations<F: PrimeField>( -- GitLab From 04cefd41a5cf7b27299a0ea46f2dab109ba121d9 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 7 Jun 2024 10:44:19 +0200 Subject: [PATCH 09/13] don't format the `scenarii` --- src/fec.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fec.rs b/src/fec.rs index bdc2e363..b10ede1e 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -380,6 +380,7 @@ mod tests { let ks = [3, 5]; let n = 5; + #[rustfmt::skip] let scenarii = [ // ```mermaid // graph TD; @@ -399,7 +400,9 @@ mod tests { ], vec![ vec![2, 4, n], + vec![1, 3, (n + 1)], + vec![n, (n + 1), (n + 2)], vec![1, 3, n, (n + 2)], vec![2, 4, (n + 1), (n + 2)], -- GitLab From 3638550d42eba91d5dcbdb7882524edd3b64be58 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 7 Jun 2024 11:12:30 +0200 Subject: [PATCH 10/13] generate scenarii from n --- src/fec.rs | 99 ++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index b10ede1e..a7789c82 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -377,64 +377,61 @@ mod tests { fn end_to_end_with_recoding() { let bytes = bytes(); - let ks = [3, 5]; - let n = 5; - - #[rustfmt::skip] - let scenarii = [ - // ```mermaid - // graph TD; - // a[n+1]; b[n+2]; c[n+3]; - // - // 1; - // 3-->a; 5-->a; - // 2-->b; 4-->b; - // a-->c; b-->c; - // ``` - ( - "simple", - vec![ - vec![2, 4], // = n - vec![1, 3], // = (n + 1) - vec![n, (n + 1)], // = (n + 2) = ((2, 4), (1, 3)) - ], - vec![ - vec![2, 4, n], - - vec![1, 3, (n + 1)], - - vec![n, (n + 1), (n + 2)], - vec![1, 3, n, (n + 2)], - vec![2, 4, (n + 1), (n + 2)], - vec![1, 2, 3, 4, (n + 2)], - ], - ), - // ```mermaid - // graph TD; - // a[n+1]; b[n+2]; - // - // 1-->a; a-->b; - // 2; 3; 4; 5; - // ``` - ( - "chain", - vec![ - vec![0], // = (n) = (0) - vec![(n)], // = (n + 1) = (0) - ], - vec![vec![0, (n)], vec![0, (n + 1)], vec![(n), (n + 1)]], - ), - ]; + fn get_scenarii(n: usize) -> Vec<(String, Vec<Vec<usize>>, Vec<Vec<usize>>)> { + vec![ + // ```mermaid + // graph TD; + // a[n+1]; b[n+2]; c[n+3]; + // + // 1; + // 3-->a; 5-->a; + // 2-->b; 4-->b; + // a-->c; b-->c; + // ``` + ( + "simple".into(), + vec![ + vec![2, 4], // = n + vec![1, 3], // = (n + 1) + vec![n, (n + 1)], // = (n + 2) = ((2, 4), (1, 3)) + ], + vec![ + vec![2, 4, n], + // + vec![1, 3, (n + 1)], + vec![n, (n + 1), (n + 2)], + vec![1, 3, n, (n + 2)], + vec![2, 4, (n + 1), (n + 2)], + vec![1, 2, 3, 4, (n + 2)], + ], + ), + // ```mermaid + // graph TD; + // a[n+1]; b[n+2]; + // + // 1-->a; a-->b; + // 2; 3; 4; 5; + // ``` + ( + "chain".into(), + vec![ + vec![0], // = (n) = (0) + vec![(n)], // = (n + 1) = (0) + ], + vec![vec![0, (n)], vec![0, (n + 1)], vec![(n), (n + 1)]], + ), + ] + } - for k in ks { - for (name, steps, should_not_decode) in scenarii.clone() { + for (k, n) in [(3, 5), (5, 5)] { + for (name, steps, should_not_decode) in get_scenarii(n) { end_to_end_with_recoding_template::<Fr>( &bytes, k, n, steps, should_not_decode, - name, + &name, ); } } -- GitLab From 456aa11c36104fe7ac75fdbf54dd97325a272765 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 7 Jun 2024 11:14:23 +0200 Subject: [PATCH 11/13] refactor types --- src/fec.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/fec.rs b/src/fec.rs index a7789c82..b575f673 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -209,6 +209,9 @@ mod tests { use super::recode_with_coeffs; + type LC = Vec<usize>; + type LCExclusion = Vec<usize>; + fn bytes() -> Vec<u8> { include_bytes!("../tests/dragoon_32x32.png").to_vec() } @@ -250,7 +253,7 @@ mod tests { n: usize, test_case: &str, limit: Option<usize>, - should_not_be_decodable: Vec<Vec<usize>>, + should_not_be_decodable: Vec<LCExclusion>, ) { let there_are_recoded_shards = shards.len() > n; @@ -324,8 +327,8 @@ mod tests { data: &[u8], k: usize, n: usize, - recoding_steps: Vec<Vec<usize>>, - should_not_be_decodable: Vec<Vec<usize>>, + recoding_steps: Vec<LC>, + should_not_be_decodable: Vec<LCExclusion>, name: &str, ) { let mut rng = ark_std::test_rng(); @@ -377,7 +380,7 @@ mod tests { fn end_to_end_with_recoding() { let bytes = bytes(); - fn get_scenarii(n: usize) -> Vec<(String, Vec<Vec<usize>>, Vec<Vec<usize>>)> { + fn get_scenarii(n: usize) -> Vec<(String, Vec<LC>, Vec<LCExclusion>)> { vec![ // ```mermaid // graph TD; -- GitLab From 74f4092007b9f3f7cb339c0ee3bfc4151ae160c9 Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 7 Jun 2024 11:15:25 +0200 Subject: [PATCH 12/13] test recoding with $(k, n) = (8, 10)$ --- src/fec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fec.rs b/src/fec.rs index b575f673..ded71a1f 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -426,7 +426,7 @@ mod tests { ] } - for (k, n) in [(3, 5), (5, 5)] { + for (k, n) in [(3, 5), (5, 5), (8, 10)] { for (name, steps, should_not_decode) in get_scenarii(n) { end_to_end_with_recoding_template::<Fr>( &bytes, -- GitLab From c18d6bc669de6e254593e3c66ec58d70328e9fbd Mon Sep 17 00:00:00 2001 From: "a.stevan" <antoine.stevan@isae-supaero.fr> Date: Fri, 7 Jun 2024 11:24:41 +0200 Subject: [PATCH 13/13] make Clippy happy --- src/fec.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fec.rs b/src/fec.rs index ded71a1f..a1fd2da6 100644 --- a/src/fec.rs +++ b/src/fec.rs @@ -266,7 +266,7 @@ mod tests { { let is: Vec<usize> = c.iter().map(|(i, _)| *i).collect(); if there_are_recoded_shards { - let contains_recoded_shards = *is.iter().max().unwrap() <= n - 1; + let contains_recoded_shards = *is.iter().max().unwrap() < n; if contains_recoded_shards { continue; } @@ -275,6 +275,7 @@ mod tests { let pretty_is = is .iter() .map(|&i| { + #[allow(clippy::comparison_chain)] if i == n { "(n)".into() } else if i > n { -- GitLab