From 11f136f98b34071bb7d880f878f3f1801b36a4b5 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 11:53:21 +0200 Subject: [PATCH 01/22] Add code coverage --- .github/workflows/coverage.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000000..6d682e6f0b --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,22 @@ +name: coverage + +on: [push] +jobs: + test: + name: coverage + runs-on: ubuntu-latest + container: + image: xd009642/tarpaulin:develop-nightly + options: --security-opt seccomp=unconfined + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Generate code coverage + run: | + cargo +nightly tarpaulin --verbose --all-features --workspace --timeout 120 --out xml + + - name: Upload to codecov.io + uses: codecov/codecov-action@v2 + with: + fail_ci_if_error: true From 649a95759facd830db39c4f0c809b5194b6eb79d Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 12:04:16 +0200 Subject: [PATCH 02/22] fixed tarpaulin --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6d682e6f0b..50a786567d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -6,7 +6,7 @@ jobs: name: coverage runs-on: ubuntu-latest container: - image: xd009642/tarpaulin:develop-nightly + image: xd009642/tarpaulin:0.30.0 options: --security-opt seccomp=unconfined steps: - name: Checkout repository From a5cc671b04fbdc1caffedcfa0926e9aeb532e3e7 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 12:05:31 +0200 Subject: [PATCH 03/22] non-nightly --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 50a786567d..e12b6fbbe4 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,7 +14,7 @@ jobs: - name: Generate code coverage run: | - cargo +nightly tarpaulin --verbose --all-features --workspace --timeout 120 --out xml + cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml - name: Upload to codecov.io uses: codecov/codecov-action@v2 From aa8bd468dc6d5ee4892559ba2af8ffa4b968d6c0 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 12:25:25 +0200 Subject: [PATCH 04/22] Disable dhat when tarpaulin --- halo2_proofs/tests/frontend_backend_split.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/halo2_proofs/tests/frontend_backend_split.rs b/halo2_proofs/tests/frontend_backend_split.rs index 0c58069340..c1a620593f 100644 --- a/halo2_proofs/tests/frontend_backend_split.rs +++ b/halo2_proofs/tests/frontend_backend_split.rs @@ -505,7 +505,7 @@ const WIDTH_FACTOR: usize = 1; #[test] fn test_mycircuit_full_legacy() { - #[cfg(feature = "heap-profiling")] + #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] let _profiler = dhat::Profiler::new_heap(); use halo2_proofs::plonk::{ @@ -566,7 +566,7 @@ fn test_mycircuit_full_legacy() { fn test_mycircuit_full_split() { use halo2_middleware::zal::impls::{H2cEngine, PlonkEngineConfig}; - #[cfg(feature = "heap-profiling")] + #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] let _profiler = dhat::Profiler::new_heap(); let engine = PlonkEngineConfig::new() From f693e9923375e4db3d95b5100f0dfa3ff1ae6b15 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 15:47:00 +0200 Subject: [PATCH 05/22] Add codecov token --- .github/workflows/coverage.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e12b6fbbe4..e15d30bdd1 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -17,6 +17,7 @@ jobs: cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml - name: Upload to codecov.io - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v4.0.1 with: + token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true From c560fd592d206e5e38374b1f6d3961bbb299ace7 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 16:21:54 +0200 Subject: [PATCH 06/22] Add codecov workaround --- .github/workflows/coverage.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e15d30bdd1..58080c5b8f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -15,9 +15,14 @@ jobs: - name: Generate code coverage run: | cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml - + + - name: Workaround for codecov/feedback#263 + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Upload to codecov.io uses: codecov/codecov-action@v4.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true + \ No newline at end of file From c9c620aa34395482d64028f06180c2cc2a489c86 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 16:35:07 +0200 Subject: [PATCH 07/22] Update badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db13170372..b516829d31 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# halo2 [![Crates.io](https://img.shields.io/crates/v/halo2.svg)](https://crates.io/crates/halo2) # +# halo2 [![Crates.io](https://img.shields.io/crates/v/halo2.svg)](https://crates.io/crates/halo2) [![codecov](https://codecov.io/github/privacy-scaling-explorations/halo2/graph/badge.svg?token=6WX7KBHFIP)](https://codecov.io/github/privacy-scaling-explorations/halo2) ## [Documentation](https://privacy-scaling-explorations.github.io/halo2/halo2_proofs) From 04dbd3812103a59393f02b11eb3fae1b412c0cb0 Mon Sep 17 00:00:00 2001 From: adria0 Date: Thu, 16 May 2024 17:21:13 +0200 Subject: [PATCH 08/22] Add examples to coverage --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 58080c5b8f..2d24b246ce 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,7 +14,7 @@ jobs: - name: Generate code coverage run: | - cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml + cargo tarpaulin --tests --examples --verbose --all-features --workspace --timeout 120 --out xml - name: Workaround for codecov/feedback#263 run: | From 80731d70dbb1d876453a4194e822130f163d5260 Mon Sep 17 00:00:00 2001 From: adria0 Date: Fri, 17 May 2024 10:54:32 +0200 Subject: [PATCH 09/22] wip --- halo2_frontend/src/circuit/value.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/halo2_frontend/src/circuit/value.rs b/halo2_frontend/src/circuit/value.rs index e0426f6bfa..7fa2cb0469 100644 --- a/halo2_frontend/src/circuit/value.rs +++ b/halo2_frontend/src/circuit/value.rs @@ -697,3 +697,18 @@ impl Value> { } } } + +#[cfg(test)] +mod test { + use super::*; + type V = Value; + fn assert_eq(a: V, b: V) { + assert_eq!(a.inner, b.inner); + } + + #[test] + fn test_check_inits() { + assert_eq!(V::unknown().inner, None); + assert_eq(V::default(),V::unknown()); + } +} From 312e446ced4446b72c607ade0999ed17979aa77c Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 20 May 2024 11:36:52 +0200 Subject: [PATCH 10/22] value coverage --- halo2_frontend/src/circuit/value.rs | 220 +++++++++++++++++++++++++++- 1 file changed, 213 insertions(+), 7 deletions(-) diff --git a/halo2_frontend/src/circuit/value.rs b/halo2_frontend/src/circuit/value.rs index 7fa2cb0469..26d7acc66b 100644 --- a/halo2_frontend/src/circuit/value.rs +++ b/halo2_frontend/src/circuit/value.rs @@ -25,6 +25,7 @@ impl Default for Value { impl Value { /// Constructs an unwitnessed value. + #[must_use] pub const fn unknown() -> Self { Self { inner: None } } @@ -38,6 +39,7 @@ impl Value { /// /// let v = Value::known(37); /// ``` + #[must_use] pub const fn known(value: V) -> Self { Self { inner: Some(value) } } @@ -45,11 +47,13 @@ impl Value { /// Obtains the inner value for assigning into the circuit. /// /// Returns `Error::Synthesis` if this is [`Value::unknown()`]. + #[must_use] pub fn assign(self) -> Result { self.inner.ok_or(Error::Synthesis) } /// Converts from `&Value` to `Value<&V>`. + #[must_use] pub fn as_ref(&self) -> Value<&V> { Value { inner: self.inner.as_ref(), @@ -57,6 +61,7 @@ impl Value { } /// Converts from `&mut Value` to `Value<&mut V>`. + #[must_use] pub fn as_mut(&mut self) -> Value<&mut V> { Value { inner: self.inner.as_mut(), @@ -71,6 +76,7 @@ impl Value { /// # Panics /// /// Panics if `f` returns `false`. + #[must_use] pub fn assert_if_known bool>(&self, f: F) { if let Some(value) = self.inner.as_ref() { assert!(f(value)); @@ -81,6 +87,7 @@ impl Value { /// /// The error check is ignored if `self` is [`Value::unknown()`]. Do not try to /// enforce circuit constraints with this method! + #[must_use] pub fn error_if_known_and bool>(&self, f: F) -> Result<(), Error> { match self.inner.as_ref() { Some(value) if f(value) => Err(Error::Synthesis), @@ -89,6 +96,7 @@ impl Value { } /// Maps a `Value` to `Value` by applying a function to the contained value. + #[must_use] pub fn map W>(self, f: F) -> Value { Value { inner: self.inner.map(f), @@ -97,6 +105,7 @@ impl Value { /// Returns [`Value::unknown()`] if the value is [`Value::unknown()`], otherwise calls /// `f` with the wrapped value and returns the result. + #[must_use] pub fn and_then Value>(self, f: F) -> Value { match self.inner { Some(v) => f(v), @@ -108,6 +117,7 @@ impl Value { /// /// If `self` is `Value::known(s)` and `other` is `Value::known(o)`, this method /// returns `Value::known((s, o))`. Otherwise, [`Value::unknown()`] is returned. + #[must_use] pub fn zip(self, other: Value) -> Value<(V, W)> { Value { inner: self.inner.zip(other.inner), @@ -121,6 +131,7 @@ impl Value<(V, W)> { /// If `self` is `Value::known((a, b)), this method returns /// `(Value::known(a), Value::known(b))`. Otherwise, /// `(Value::unknown(), Value::unknown())` is returned. + #[must_use] pub fn unzip(self) -> (Value, Value) { match self.inner { Some((a, b)) => (Value::known(a), Value::known(b)), @@ -181,6 +192,7 @@ impl Value<[V; LEN]> { /// Transposes a `Value<[V; LEN]>` into a `[Value; LEN]`. /// /// [`Value::unknown()`] will be mapped to `[Value::unknown(); LEN]`. + #[must_use] pub fn transpose_array(self) -> [Value; LEN] { let mut ret = [Value::unknown(); LEN]; if let Some(arr) = self.inner { @@ -204,6 +216,7 @@ where /// # Panics /// /// Panics if `self` is `Value::known(values)` and `values.len() != length`. + #[must_use] pub fn transpose_vec(self, length: usize) -> Vec> { match self.inner { Some(values) => { @@ -225,6 +238,7 @@ impl> FromIterator> for Value { /// elements are taken, and the [`Value::unknown()`] is returned. Should no /// [`Value::unknown()`] occur, a container of type `V` containing the values of each /// [`Value`] is returned. + #[must_use] fn from_iter>>(iter: I) -> Self { Self { inner: iter.into_iter().map(|v| v.inner).collect(), @@ -239,6 +253,7 @@ impl> FromIterator> for Value { impl Neg for Value { type Output = Value; + #[must_use] fn neg(self) -> Self::Output { Value { inner: self.inner.map(|v| -v), @@ -256,6 +271,7 @@ where { type Output = Value; + #[must_use] fn add(self, rhs: Self) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b), @@ -269,6 +285,7 @@ where { type Output = Value; + #[must_use] fn add(self, rhs: Self) -> Self::Output { Value { inner: self @@ -286,6 +303,7 @@ where { type Output = Value; + #[must_use] fn add(self, rhs: Value<&V>) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b), @@ -299,6 +317,7 @@ where { type Output = Value; + #[must_use] fn add(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b), @@ -312,6 +331,7 @@ where { type Output = Value; + #[must_use] fn add(self, rhs: &Self) -> Self::Output { self + rhs.as_ref() } @@ -323,6 +343,7 @@ where { type Output = Value; + #[must_use] fn add(self, rhs: Value) -> Self::Output { self.as_ref() + rhs } @@ -338,6 +359,7 @@ where { type Output = Value; + #[must_use] fn sub(self, rhs: Self) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b), @@ -351,6 +373,7 @@ where { type Output = Value; + #[must_use] fn sub(self, rhs: Self) -> Self::Output { Value { inner: self @@ -368,6 +391,7 @@ where { type Output = Value; + #[must_use] fn sub(self, rhs: Value<&V>) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b), @@ -381,6 +405,7 @@ where { type Output = Value; + #[must_use] fn sub(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b), @@ -394,6 +419,7 @@ where { type Output = Value; + #[must_use] fn sub(self, rhs: &Self) -> Self::Output { self - rhs.as_ref() } @@ -405,6 +431,7 @@ where { type Output = Value; + #[must_use] fn sub(self, rhs: Value) -> Self::Output { self.as_ref() - rhs } @@ -420,6 +447,7 @@ where { type Output = Value; + #[must_use] fn mul(self, rhs: Self) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b), @@ -433,6 +461,7 @@ where { type Output = Value; + #[must_use] fn mul(self, rhs: Self) -> Self::Output { Value { inner: self @@ -450,6 +479,7 @@ where { type Output = Value; + #[must_use] fn mul(self, rhs: Value<&V>) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b), @@ -463,6 +493,7 @@ where { type Output = Value; + #[must_use] fn mul(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b), @@ -476,6 +507,7 @@ where { type Output = Value; + #[must_use] fn mul(self, rhs: &Self) -> Self::Output { self * rhs.as_ref() } @@ -487,6 +519,7 @@ where { type Output = Value; + #[must_use] fn mul(self, rhs: Value) -> Self::Output { self.as_ref() * rhs } @@ -497,6 +530,7 @@ where // impl From> for Value> { + #[must_use] fn from(value: Value) -> Self { Self { inner: value.inner.map(Assigned::from), @@ -507,6 +541,7 @@ impl From> for Value> { impl Add> for Value> { type Output = Value>; + #[must_use] fn add(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b), @@ -517,6 +552,7 @@ impl Add> for Value> { impl Add for Value> { type Output = Value>; + #[must_use] fn add(self, rhs: F) -> Self::Output { self + Value::known(rhs) } @@ -525,6 +561,7 @@ impl Add for Value> { impl Add> for Value<&Assigned> { type Output = Value>; + #[must_use] fn add(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b), @@ -535,6 +572,7 @@ impl Add> for Value<&Assigned> { impl Add for Value<&Assigned> { type Output = Value>; + #[must_use] fn add(self, rhs: F) -> Self::Output { self + Value::known(rhs) } @@ -543,6 +581,7 @@ impl Add for Value<&Assigned> { impl Sub> for Value> { type Output = Value>; + #[must_use] fn sub(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b), @@ -553,6 +592,7 @@ impl Sub> for Value> { impl Sub for Value> { type Output = Value>; + #[must_use] fn sub(self, rhs: F) -> Self::Output { self - Value::known(rhs) } @@ -561,6 +601,7 @@ impl Sub for Value> { impl Sub> for Value<&Assigned> { type Output = Value>; + #[must_use] fn sub(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b), @@ -571,6 +612,7 @@ impl Sub> for Value<&Assigned> { impl Sub for Value<&Assigned> { type Output = Value>; + #[must_use] fn sub(self, rhs: F) -> Self::Output { self - Value::known(rhs) } @@ -579,6 +621,7 @@ impl Sub for Value<&Assigned> { impl Mul> for Value> { type Output = Value>; + #[must_use] fn mul(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b), @@ -589,6 +632,7 @@ impl Mul> for Value> { impl Mul for Value> { type Output = Value>; + #[must_use] fn mul(self, rhs: F) -> Self::Output { self * Value::known(rhs) } @@ -597,6 +641,7 @@ impl Mul for Value> { impl Mul> for Value<&Assigned> { type Output = Value>; + #[must_use] fn mul(self, rhs: Value) -> Self::Output { Value { inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b), @@ -607,6 +652,7 @@ impl Mul> for Value<&Assigned> { impl Mul for Value<&Assigned> { type Output = Value>; + #[must_use] fn mul(self, rhs: F) -> Self::Output { self * Value::known(rhs) } @@ -614,6 +660,7 @@ impl Mul for Value<&Assigned> { impl Value { /// Returns the field element corresponding to this value. + #[must_use] pub fn to_field(&self) -> Value> where for<'v> Assigned: From<&'v V>, @@ -624,6 +671,7 @@ impl Value { } /// Returns the field element corresponding to this value. + #[must_use] pub fn into_field(self) -> Value> where V: Into>, @@ -645,8 +693,9 @@ impl Value { /// /// let v = Value::known(F::from(2)); /// let v: Value> = v.into(); - /// v.double(); + /// let _ = v.double(); /// ``` + #[must_use] pub fn double(&self) -> Value> where V: Borrow>, @@ -657,6 +706,7 @@ impl Value { } /// Squares this field element. + #[must_use] pub fn square(&self) -> Value> where V: Borrow>, @@ -667,6 +717,7 @@ impl Value { } /// Cubes this field element. + #[must_use] pub fn cube(&self) -> Value> where V: Borrow>, @@ -677,6 +728,7 @@ impl Value { } /// Inverts this assigned value (taking the inverse of zero to be zero). + #[must_use] pub fn invert(&self) -> Value> where V: Borrow>, @@ -691,6 +743,7 @@ impl Value> { /// Evaluates this value directly, performing an unbatched inversion if necessary. /// /// If the denominator is zero, the returned value is zero. + #[must_use] pub fn evaluate(self) -> Value { Value { inner: self.inner.map(|v| v.evaluate()), @@ -701,14 +754,167 @@ impl Value> { #[cfg(test)] mod test { use super::*; - type V = Value; - fn assert_eq(a: V, b: V) { - assert_eq!(a.inner, b.inner); + use halo2curves::bn256::Fr; + + type V = Value; + + impl PartialEq for V { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } + } + impl PartialEq for Value> { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } + } + + + #[test] + fn test_value_as_mut() { + let mut v_some = V::known(1); + let mut v_none = V::default(); + v_some.as_mut().map(|v| *v=3); + v_none.as_mut().map(|v| *v=3); + assert_eq!(v_some, V::known(3)); + assert_eq!(v_none, V::unknown()); + } + + #[test] + fn test_value_assert_if_known_ok() { + V::known(1).assert_if_known(|v| *v == 1); + V::unknown().assert_if_known(|v| *v == 1); + } + + #[test] + #[should_panic] + fn test_value_assert_if_known_ko() { + V::known(1).assert_if_known(|v| *v == 2); + } + + #[test] + fn test_value_error_if_known() { + assert!(V::known(1).error_if_known_and(|v| *v == 1).is_err()); + assert!(V::known(1).error_if_known_and(|v| *v == 2).is_ok()); + assert!(V::unknown().error_if_known_and(|_| true).is_ok()); + } + + #[test] + fn test_map() { + assert_eq!(V::known(1).map(|v| v+1), V::known(2)); + assert_eq!(V::unknown().map(|v| v+1), V::unknown()); + } + + #[test] + fn test_value_and_then() { + let v = V::known(1); + assert_eq!(v.and_then(|v| V::known(v + 1)), V::known(2)); + assert_eq!(v.and_then(|_| V::unknown()), V::unknown()); + assert_eq!(V::unknown().and_then(|v| V::known(v + 1)), V::unknown()); + } + + #[test] + fn test_value_zip() { + assert_eq!(V::known(1).zip(V::known(2)).unzip(), (V::known(1), V::known(2))); + assert_eq!(V::known(1).zip(V::unknown()).unzip(), (V::unknown(), V::unknown())); + assert_eq!(V::unknown().zip(V::known(2)).unzip(), (Value::unknown(), V::unknown())); + assert_eq!(V::unknown().zip(V::unknown()).unzip(), (Value::unknown(), V::unknown())); + } + + #[test] + fn test_value_copies() { + let copy = Value::<&mut i64>::known(&mut 1).copied(); + let clon = Value::<&mut i64>::known(&mut 1).cloned(); + assert_eq!(copy, clon); + assert_eq!(copy, Value::known(1)); + } + + #[test] + fn test_value_transpose_array() { + assert_eq!(Value::<[_; 2]>::known([1, 2]).transpose_array(), [V::known(1), V::known(2)]); + } + + #[test] + fn test_value_transpose_vec_ok() { + assert_eq!(Value::<[_; 2]>::known([1, 2]).transpose_vec(2), vec![V::known(1), V::known(2)]); + } + + #[test] + #[should_panic] + fn test_value_transpose_vec_ko_1() { + assert_eq!(Value::<[_; 2]>::known([1, 2]).transpose_vec(1), vec![V::known(1), V::known(2)]); + } + + #[test] + #[should_panic] + fn test_value_transpose_vec_ko_2() { + assert_eq!(Value::<[_; 2]>::known([1, 2]).transpose_vec(3), vec![V::known(1), V::known(2)]); } #[test] - fn test_check_inits() { - assert_eq!(V::unknown().inner, None); - assert_eq(V::default(),V::unknown()); + fn test_value_from_iter() { + assert_eq!(Value::>::from_iter([V::known(1), V::known(2)]).inner, Some(vec![1, 2])); + assert_eq!(Value::>::from_iter([V::known(1), V::unknown()]).inner, None); } + + #[test] + fn test_value_ops() { + assert_eq!(-V::known(5), Value::known(-5)); + + assert_eq!(V::known(5) + V::known(2), V::known(7)); + assert_eq!(&V::known(5) + V::known(2), V::known(7)); + assert_eq!(V::known(5) + &V::known(2), V::known(7)); + assert_eq!(&V::known(5) + &V::known(2), V::known(7)); + + assert_eq!(V::known(5) - V::known(2), V::known(3)); + assert_eq!(&V::known(5) - V::known(2), V::known(3)); + assert_eq!(V::known(5) - &V::known(2), V::known(3)); + assert_eq!(&V::known(5) - &V::known(2), V::known(3)); + + assert_eq!(V::known(5) * V::known(2), V::known(10)); + assert_eq!(&V::known(5) * V::known(2), V::known(10)); + assert_eq!(V::known(5) * &V::known(2), V::known(10)); + assert_eq!(&V::known(5) * &V::known(2), V::known(10)); + } + + #[test] + fn test_value_assigned() { + + let fr_two = || Fr::from(2); + let fr_three = || Fr::from(3); + + let one = Value::known(Assigned::Trivial(Fr::one())); + let two = Value::known(Assigned::Trivial(Fr::from(2))); + let six = Value::known(Assigned::Trivial(Fr::from(6))); + + let v : Value> = Value::known(Fr::one()).into(); + assert_eq!(v, Value::known(Assigned::Trivial(Fr::one()))); + + assert_eq!(one + Fr::one(), two); + assert_eq!(one + Value::known(Fr::one()), two); + assert_eq!(Value::known(&Assigned::Trivial(Fr::one())) + Value::known(Fr::one()), two); + assert_eq!(Value::known(&Assigned::Trivial(Fr::one())) + Fr::one(), two); + + assert_eq!(two - Value::known(Fr::one()), one); + assert_eq!(two - Fr::one(), one); + assert_eq!(Value::known(&Assigned::Trivial(fr_two())) - Value::known(Fr::one()), one); + assert_eq!(Value::known(&Assigned::Trivial(fr_two())) - Fr::one(), one); + + assert_eq!(two * Value::known(fr_three()), six); + assert_eq!(two * fr_three(), six); + assert_eq!(Value::known(&Assigned::Trivial(fr_two())) * Value::known(fr_three()), six); + assert_eq!(Value::known(&Assigned::Trivial(fr_two())) * fr_three(), six); + } + + #[test] + fn test_value_impl() { + assert_eq!(Value::known(Fr::one()).to_field(), Value::known(Assigned::Trivial(Fr::one()))); + assert_eq!(Value::known(Fr::one()).into_field(), Value::known(Assigned::Trivial(Fr::one()))); + + assert_eq!(Value::known(Assigned::Trivial(Fr::from(3))).double(), Value::known(Assigned::Trivial(Fr::from(6)))); + assert_eq!(Value::known(Assigned::Trivial(Fr::from(3))).square(), Value::known(Assigned::Trivial(Fr::from(9)))); + assert_eq!(Value::known(Assigned::Trivial(Fr::from(3))).cube(), Value::known(Assigned::Trivial(Fr::from(27)))); + assert_eq!(Value::known(Assigned::Trivial(Fr::from(3))).invert().invert(), Value::known(Assigned::Trivial(Fr::from(3)))); + } + } From 68c97b79fa3a770898e80d80dfe71f54d6174d20 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 20 May 2024 11:52:26 +0200 Subject: [PATCH 11/22] minor fixes --- halo2_frontend/src/circuit/value.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/halo2_frontend/src/circuit/value.rs b/halo2_frontend/src/circuit/value.rs index 33aa7e4494..df2210cd15 100644 --- a/halo2_frontend/src/circuit/value.rs +++ b/halo2_frontend/src/circuit/value.rs @@ -47,13 +47,11 @@ impl Value { /// Obtains the inner value for assigning into the circuit. /// /// Returns `Error::Synthesis` if this is [`Value::unknown()`]. - #[must_use] pub fn assign(self) -> Result { self.inner.ok_or(Error::Synthesis) } /// Converts from `&Value` to `Value<&V>`. - #[must_use] pub fn as_ref(&self) -> Value<&V> { Value { inner: self.inner.as_ref(), @@ -61,7 +59,6 @@ impl Value { } /// Converts from `&mut Value` to `Value<&mut V>`. - #[must_use] pub fn as_mut(&mut self) -> Value<&mut V> { Value { inner: self.inner.as_mut(), @@ -76,7 +73,6 @@ impl Value { /// # Panics /// /// Panics if `f` returns `false`. - #[must_use] pub fn assert_if_known bool>(&self, f: F) { if let Some(value) = self.inner.as_ref() { assert!(f(value)); @@ -87,7 +83,6 @@ impl Value { /// /// The error check is ignored if `self` is [`Value::unknown()`]. Do not try to /// enforce circuit constraints with this method! - #[must_use] pub fn error_if_known_and bool>(&self, f: F) -> Result<(), Error> { match self.inner.as_ref() { Some(value) if f(value) => Err(Error::Synthesis), @@ -96,7 +91,6 @@ impl Value { } /// Maps a `Value` to `Value` by applying a function to the contained value. - #[must_use] pub fn map W>(self, f: F) -> Value { Value { inner: self.inner.map(f), @@ -836,8 +830,8 @@ mod test { fn test_value_copies() { let copy = Value::<&mut i64>::known(&mut 1).copied(); let clon = Value::<&mut i64>::known(&mut 1).cloned(); - assert_eq!(copy, clon); assert_eq!(copy, Value::known(1)); + assert_eq!(clon, Value::known(1)); } #[test] @@ -854,6 +848,16 @@ mod test { Value::<[_; 2]>::known([1, 2]).transpose_vec(2), vec![V::known(1), V::known(2)] ); + assert_eq!( + Value::<[_; 2]>::unknown().transpose_vec(2), + vec![V::unknown(), V::unknown()] + ); + + // TODO: check if should be this allowed or not + assert_eq!( + Value::<[_; 6]>::unknown().transpose_vec(2), + vec![V::unknown(), V::unknown()] + ); } #[test] From dc0760141bdcddd515ec26954b0b8789af7af22d Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 20 May 2024 15:40:29 +0200 Subject: [PATCH 12/22] example2test --- halo2_proofs/{examples => tests}/serialization.rs | 3 ++- halo2_proofs/{examples => tests}/shuffle.rs | 3 ++- halo2_proofs/{examples => tests}/shuffle_api.rs | 3 ++- halo2_proofs/{examples => tests}/vector-ops-unblinded.rs | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) rename halo2_proofs/{examples => tests}/serialization.rs (99%) rename halo2_proofs/{examples => tests}/shuffle.rs (99%) rename halo2_proofs/{examples => tests}/shuffle_api.rs (99%) rename halo2_proofs/{examples => tests}/vector-ops-unblinded.rs (99%) diff --git a/halo2_proofs/examples/serialization.rs b/halo2_proofs/tests/serialization.rs similarity index 99% rename from halo2_proofs/examples/serialization.rs rename to halo2_proofs/tests/serialization.rs index 824ddc2a7b..929c61db39 100644 --- a/halo2_proofs/examples/serialization.rs +++ b/halo2_proofs/tests/serialization.rs @@ -128,7 +128,8 @@ impl Circuit for StandardPlonk { } } -fn main() { +#[test] +fn test_serialization() { let k = 4; let circuit = StandardPlonk(Fr::random(OsRng)); let params = ParamsKZG::::setup(k, OsRng); diff --git a/halo2_proofs/examples/shuffle.rs b/halo2_proofs/tests/shuffle.rs similarity index 99% rename from halo2_proofs/examples/shuffle.rs rename to halo2_proofs/tests/shuffle.rs index f61d17fd09..7ecfb49edc 100644 --- a/halo2_proofs/examples/shuffle.rs +++ b/halo2_proofs/tests/shuffle.rs @@ -314,7 +314,8 @@ fn test_prover( assert_eq!(accepted, expected); } -fn main() { +#[test] +fn test_shuffle() { const W: usize = 4; const H: usize = 32; const K: u32 = 8; diff --git a/halo2_proofs/examples/shuffle_api.rs b/halo2_proofs/tests/shuffle_api.rs similarity index 99% rename from halo2_proofs/examples/shuffle_api.rs rename to halo2_proofs/tests/shuffle_api.rs index f3080cd393..e7034e6f36 100644 --- a/halo2_proofs/examples/shuffle_api.rs +++ b/halo2_proofs/tests/shuffle_api.rs @@ -190,7 +190,8 @@ where assert_eq!(accepted, expected); } -fn main() { +#[test] +fn test_shuffle_api() { use halo2_proofs::dev::MockProver; use halo2curves::pasta::Fp; const K: u32 = 4; diff --git a/halo2_proofs/examples/vector-ops-unblinded.rs b/halo2_proofs/tests/vector-ops-unblinded.rs similarity index 99% rename from halo2_proofs/examples/vector-ops-unblinded.rs rename to halo2_proofs/tests/vector-ops-unblinded.rs index 386d6b34a3..01c24fef4d 100644 --- a/halo2_proofs/examples/vector-ops-unblinded.rs +++ b/halo2_proofs/tests/vector-ops-unblinded.rs @@ -515,7 +515,8 @@ where proof } -fn main() { +#[test] +fn test_vector_ops_unbinded() { use halo2curves::pasta::Fp; const N: usize = 10; From c57017db9cae8e1df9b17fa4bdff6106ca26b2e9 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 20 May 2024 15:55:55 +0200 Subject: [PATCH 13/22] tune workflow --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2d24b246ce..58080c5b8f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,7 +14,7 @@ jobs: - name: Generate code coverage run: | - cargo tarpaulin --tests --examples --verbose --all-features --workspace --timeout 120 --out xml + cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml - name: Workaround for codecov/feedback#263 run: | From 94fca8de3efab4783738e3021ada647022c4881c Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 20 May 2024 16:12:19 +0200 Subject: [PATCH 14/22] codecov ignore --- codecov.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..ef12584327 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,3 @@ +ignore: + - halo2_proofs/benches + - halo2_proofs/examples \ No newline at end of file From fea3545cf7841cd4b81c7aeb8371d0a8b93a4497 Mon Sep 17 00:00:00 2001 From: adria0 Date: Mon, 20 May 2024 16:22:07 +0200 Subject: [PATCH 15/22] do not cover tests --- codecov.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index ef12584327..200ef90d74 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,4 @@ ignore: - halo2_proofs/benches - - halo2_proofs/examples \ No newline at end of file + - halo2_proofs/examples + - halo2_proofs/tests \ No newline at end of file From d842426aa6e9f7805ec3ec72c9dc82b416d7a421 Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 09:36:48 +0200 Subject: [PATCH 16/22] active --line --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 58080c5b8f..39517725c9 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,7 +14,7 @@ jobs: - name: Generate code coverage run: | - cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml + cargo tarpaulin --line --verbose --all-features --workspace --timeout 120 --out xml - name: Workaround for codecov/feedback#263 run: | From 98ada274b3e600f04f3e7778b969c534761e5495 Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 09:49:09 +0200 Subject: [PATCH 17/22] test llvm-cov --- .github/workflows/coverage.yml | 37 +++++++++++++++------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 39517725c9..21896f49de 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,28 +1,23 @@ name: coverage -on: [push] +on: [pull_request, push] + jobs: - test: - name: coverage + coverage: runs-on: ubuntu-latest - container: - image: xd009642/tarpaulin:0.30.0 - options: --security-opt seccomp=unconfined + env: + CARGO_TERM_COLOR: always steps: - - name: Checkout repository - uses: actions/checkout@v2 - + - uses: actions/checkout@v4 + - name: Install Rust + run: rustup update stable + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov - name: Generate code coverage - run: | - cargo tarpaulin --line --verbose --all-features --workspace --timeout 120 --out xml - - - name: Workaround for codecov/feedback#263 - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - - - name: Upload to codecov.io - uses: codecov/codecov-action@v4.0.1 + run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: true - \ No newline at end of file + token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos + files: lcov.info + fail_ci_if_error: true \ No newline at end of file From 89d0f11f6b6c4a4481df7eca4f8cbe03b3448c6b Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 09:56:50 +0200 Subject: [PATCH 18/22] disable dhat --- halo2_proofs/tests/frontend_backend_split.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/halo2_proofs/tests/frontend_backend_split.rs b/halo2_proofs/tests/frontend_backend_split.rs index c1a620593f..e55d372945 100644 --- a/halo2_proofs/tests/frontend_backend_split.rs +++ b/halo2_proofs/tests/frontend_backend_split.rs @@ -505,8 +505,8 @@ const WIDTH_FACTOR: usize = 1; #[test] fn test_mycircuit_full_legacy() { - #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] - let _profiler = dhat::Profiler::new_heap(); +// #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] +// let _profiler = dhat::Profiler::new_heap(); use halo2_proofs::plonk::{ create_proof, keygen_pk as keygen_pk_legacy, keygen_vk as keygen_vk_legacy, @@ -566,8 +566,8 @@ fn test_mycircuit_full_legacy() { fn test_mycircuit_full_split() { use halo2_middleware::zal::impls::{H2cEngine, PlonkEngineConfig}; - #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] - let _profiler = dhat::Profiler::new_heap(); + // #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] + // let _profiler = dhat::Profiler::new_heap(); let engine = PlonkEngineConfig::new() .set_curve::() From 541520b8832392f8d001fd92cbc07465fb6c8d21 Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 10:46:40 +0200 Subject: [PATCH 19/22] cfg(coverage) in dhat --- halo2_proofs/tests/frontend_backend_split.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/halo2_proofs/tests/frontend_backend_split.rs b/halo2_proofs/tests/frontend_backend_split.rs index e55d372945..721c763459 100644 --- a/halo2_proofs/tests/frontend_backend_split.rs +++ b/halo2_proofs/tests/frontend_backend_split.rs @@ -505,8 +505,8 @@ const WIDTH_FACTOR: usize = 1; #[test] fn test_mycircuit_full_legacy() { -// #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] -// let _profiler = dhat::Profiler::new_heap(); + #[cfg(all(feature = "heap-profiling", coverage))] + let _profiler = dhat::Profiler::new_heap(); use halo2_proofs::plonk::{ create_proof, keygen_pk as keygen_pk_legacy, keygen_vk as keygen_vk_legacy, @@ -566,8 +566,8 @@ fn test_mycircuit_full_legacy() { fn test_mycircuit_full_split() { use halo2_middleware::zal::impls::{H2cEngine, PlonkEngineConfig}; - // #[cfg(all(feature = "heap-profiling", not(tarpaulin)))] - // let _profiler = dhat::Profiler::new_heap(); + #[cfg(all(feature = "heap-profiling", coverage))] + let _profiler = dhat::Profiler::new_heap(); let engine = PlonkEngineConfig::new() .set_curve::() From e9e0117981b78a3d3c0fcef8e0c4de61cfb270ba Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 10:56:29 +0200 Subject: [PATCH 20/22] filter coverage, fix cfg(coverage) --- codecov.yml | 6 +++++- halo2_proofs/tests/frontend_backend_split.rs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/codecov.yml b/codecov.yml index 200ef90d74..e94688662e 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,4 +1,8 @@ ignore: - halo2_proofs/benches - halo2_proofs/examples - - halo2_proofs/tests \ No newline at end of file + - halo2_proofs/tests + - halo2_frontend/graph + - halo2_frontend/graph.rs + - halo2_frontend/costs.rs + - halo2_frontend/cost_model.rs \ No newline at end of file diff --git a/halo2_proofs/tests/frontend_backend_split.rs b/halo2_proofs/tests/frontend_backend_split.rs index 721c763459..5ba0fcd3e5 100644 --- a/halo2_proofs/tests/frontend_backend_split.rs +++ b/halo2_proofs/tests/frontend_backend_split.rs @@ -505,7 +505,7 @@ const WIDTH_FACTOR: usize = 1; #[test] fn test_mycircuit_full_legacy() { - #[cfg(all(feature = "heap-profiling", coverage))] + #[cfg(all(feature = "heap-profiling", not(coverage)))] let _profiler = dhat::Profiler::new_heap(); use halo2_proofs::plonk::{ @@ -566,7 +566,7 @@ fn test_mycircuit_full_legacy() { fn test_mycircuit_full_split() { use halo2_middleware::zal::impls::{H2cEngine, PlonkEngineConfig}; - #[cfg(all(feature = "heap-profiling", coverage))] + #[cfg(all(feature = "heap-profiling", not(coverage)))] let _profiler = dhat::Profiler::new_heap(); let engine = PlonkEngineConfig::new() From c26b8e89ca257b1d98653bd1a402e932487965cf Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 11:05:12 +0200 Subject: [PATCH 21/22] fix codecov.yml --- codecov.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/codecov.yml b/codecov.yml index e94688662e..ec65ebc105 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,7 +2,7 @@ ignore: - halo2_proofs/benches - halo2_proofs/examples - halo2_proofs/tests - - halo2_frontend/graph - - halo2_frontend/graph.rs - - halo2_frontend/costs.rs - - halo2_frontend/cost_model.rs \ No newline at end of file + - halo2_frontend/src/dev/graph + - halo2_frontend/src/dev/graph.rs + - halo2_frontend/src/dev/costs.rs + - halo2_frontend/src/dev/cost_model.rs \ No newline at end of file From 411064b622c54f34814aa351ac65efe1c448deac Mon Sep 17 00:00:00 2001 From: adria0 Date: Tue, 21 May 2024 11:24:15 +0200 Subject: [PATCH 22/22] make clippy happy --- halo2_frontend/src/circuit/value.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/halo2_frontend/src/circuit/value.rs b/halo2_frontend/src/circuit/value.rs index df2210cd15..a169d60e41 100644 --- a/halo2_frontend/src/circuit/value.rs +++ b/halo2_frontend/src/circuit/value.rs @@ -747,6 +747,8 @@ impl Value> { #[cfg(test)] mod test { + #![allow(clippy::op_ref)] + use super::*; use halo2curves::bn256::Fr;