From 095ef5618e7b6329fb152779457df7dc02886bcc Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Thu, 25 Jul 2024 15:54:56 -0400 Subject: [PATCH 1/2] move tests from stdlib to test_programs, add github action to test-rust-workspace to ensure zero stdlib tests --- .github/workflows/test-rust-workspace.yml | 16 ++ noir_stdlib/src/cmp.nr | 20 -- noir_stdlib/src/collections/bounded_vec.nr | 159 ------------- noir_stdlib/src/collections/vec.nr | 33 --- noir_stdlib/src/field/bn254.nr | 99 -------- noir_stdlib/src/hash/keccak.nr | 35 --- noir_stdlib/src/hash/mod.nr | 109 --------- noir_stdlib/src/hash/poseidon/mod.nr | 25 -- noir_stdlib/src/uint128.nr | 218 ------------------ .../noir_test_success/bn254/Nargo.toml | 7 + .../noir_test_success/bn254/src/main.nr | 98 ++++++++ .../noir_test_success/bounded_vec/src/main.nr | 164 ++++++++++++- .../noir_test_success/cmp/Nargo.toml | 7 + .../noir_test_success/cmp/src/main.nr | 19 ++ .../noir_test_success/keccak/Nargo.toml | 7 + .../noir_test_success/keccak/src/main.nr | 33 +++ .../noir_test_success/pedersen/Nargo.toml | 7 + .../noir_test_success/pedersen/src/main.nr | 111 +++++++++ .../noir_test_success/poseidon/Nargo.toml | 7 + .../noir_test_success/poseidon/src/main.nr | 24 ++ .../noir_test_success/uint128/Nargo.toml | 7 + .../noir_test_success/uint128/src/main.nr | 217 +++++++++++++++++ .../noir_test_success/vec/Nargo.toml | 7 + .../noir_test_success/vec/src/main.nr | 32 +++ 24 files changed, 760 insertions(+), 701 deletions(-) create mode 100644 test_programs/noir_test_success/bn254/Nargo.toml create mode 100644 test_programs/noir_test_success/bn254/src/main.nr create mode 100644 test_programs/noir_test_success/cmp/Nargo.toml create mode 100644 test_programs/noir_test_success/cmp/src/main.nr create mode 100644 test_programs/noir_test_success/keccak/Nargo.toml create mode 100644 test_programs/noir_test_success/keccak/src/main.nr create mode 100644 test_programs/noir_test_success/pedersen/Nargo.toml create mode 100644 test_programs/noir_test_success/pedersen/src/main.nr create mode 100644 test_programs/noir_test_success/poseidon/Nargo.toml create mode 100644 test_programs/noir_test_success/poseidon/src/main.nr create mode 100644 test_programs/noir_test_success/uint128/Nargo.toml create mode 100644 test_programs/noir_test_success/uint128/src/main.nr create mode 100644 test_programs/noir_test_success/vec/Nargo.toml create mode 100644 test_programs/noir_test_success/vec/src/main.nr diff --git a/.github/workflows/test-rust-workspace.yml b/.github/workflows/test-rust-workspace.yml index 1f3ee5e2268..36cdd3b1ebe 100644 --- a/.github/workflows/test-rust-workspace.yml +++ b/.github/workflows/test-rust-workspace.yml @@ -13,6 +13,22 @@ concurrency: cancel-in-progress: true jobs: + ban-noir-stdlib-tests: + name: Ensure zero tests in noir_stdlib + runs-on: ubuntu-latest + # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. + if: ${{ always() }} + + steps: + - name: Report overall success + run: | + && echo 'failure: tests in the stdlib' || echo 'success: no tests in the stdlib' + if grep -r "\s*#\[test]" noir_stdlib; then + exit 1 # test found in noir_stdlib, fail + else + exit 0 + fi + build-test-artifacts: name: Build test artifacts runs-on: ubuntu-latest diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr index bdd5e2bc5ec..ec988725c47 100644 --- a/noir_stdlib/src/cmp.nr +++ b/noir_stdlib/src/cmp.nr @@ -346,23 +346,3 @@ pub fn max(v1: T, v2: T) -> T where T: Ord { pub fn min(v1: T, v2: T) -> T where T: Ord { if v1 > v2 { v2 } else { v1 } } - -mod cmp_tests { - use crate::cmp::{min, max}; - - #[test] - fn sanity_check_min() { - assert_eq(min(0 as u64, 1 as u64), 0); - assert_eq(min(0 as u64, 0 as u64), 0); - assert_eq(min(1 as u64, 1 as u64), 1); - assert_eq(min(255 as u8, 0 as u8), 0); - } - - #[test] - fn sanity_check_max() { - assert_eq(max(0 as u64, 1 as u64), 1); - assert_eq(max(0 as u64, 0 as u64), 0); - assert_eq(max(1 as u64, 1 as u64), 1); - assert_eq(max(255 as u8, 0 as u8), 255); - } -} diff --git a/noir_stdlib/src/collections/bounded_vec.nr b/noir_stdlib/src/collections/bounded_vec.nr index a56d6f60390..1ecde75b26f 100644 --- a/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir_stdlib/src/collections/bounded_vec.nr @@ -150,162 +150,3 @@ impl From<[T; Len]> for BoundedVec BoundedVec::from_array(array) } } - -mod bounded_vec_tests { - - mod get { - use crate::collections::bounded_vec::BoundedVec; - - #[test(should_fail_with = "Attempted to read past end of BoundedVec")] - fn panics_when_reading_elements_past_end_of_vec() { - let vec: BoundedVec = BoundedVec::new(); - - crate::println(vec.get(0)); - } - } - - mod set { - use crate::collections::bounded_vec::BoundedVec; - - #[test] - fn set_updates_values_properly() { - let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]); - - vec.set(0, 42); - assert_eq(vec.storage, [42, 0, 0, 0, 0]); - - vec.set(1, 43); - assert_eq(vec.storage, [42, 43, 0, 0, 0]); - - vec.set(2, 44); - assert_eq(vec.storage, [42, 43, 44, 0, 0]); - - vec.set(1, 10); - assert_eq(vec.storage, [42, 10, 44, 0, 0]); - - vec.set(0, 0); - assert_eq(vec.storage, [0, 10, 44, 0, 0]); - } - - #[test(should_fail_with = "Attempted to write past end of BoundedVec")] - fn panics_when_writing_elements_past_end_of_vec() { - let mut vec: BoundedVec = BoundedVec::new(); - vec.set(0, 42); - - // Need to use println to avoid DIE removing the write operation. - crate::println(vec.get(0)); - } - } - - mod map { - use crate::collections::bounded_vec::BoundedVec; - - #[test] - fn applies_function_correctly() { - // docs:start:bounded-vec-map-example - let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); - let result = vec.map(|value| value * 2); - // docs:end:bounded-vec-map-example - let expected = BoundedVec::from_array([2, 4, 6, 8]); - - assert_eq(result, expected); - } - - #[test] - fn applies_function_that_changes_return_type() { - let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); - let result = vec.map(|value| (value * 2) as Field); - let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]); - - assert_eq(result, expected); - } - - #[test] - fn does_not_apply_function_past_len() { - let vec: BoundedVec = BoundedVec::from_array([0, 1]); - let result = vec.map(|value| if value == 0 { 5 } else { value }); - let expected = BoundedVec::from_array([5, 1]); - - assert_eq(result, expected); - assert_eq(result.storage()[2], 0); - } - } - - mod from_array { - use crate::collections::bounded_vec::BoundedVec; - - #[test] - fn empty() { - let empty_array: [Field; 0] = []; - let bounded_vec = BoundedVec::from_array([]); - - assert_eq(bounded_vec.max_len(), 0); - assert_eq(bounded_vec.len(), 0); - assert_eq(bounded_vec.storage(), empty_array); - } - - #[test] - fn equal_len() { - let array = [1, 2, 3]; - let bounded_vec = BoundedVec::from_array(array); - - assert_eq(bounded_vec.max_len(), 3); - assert_eq(bounded_vec.len(), 3); - assert_eq(bounded_vec.storage(), array); - } - - #[test] - fn max_len_greater_then_array_len() { - let array = [1, 2, 3]; - let bounded_vec: BoundedVec = BoundedVec::from_array(array); - - assert_eq(bounded_vec.max_len(), 10); - assert_eq(bounded_vec.len(), 3); - assert_eq(bounded_vec.storage()[0], 1); - assert_eq(bounded_vec.storage()[1], 2); - assert_eq(bounded_vec.storage()[2], 3); - } - - #[test(should_fail_with="from array out of bounds")] - fn max_len_lower_then_array_len() { - let _: BoundedVec = BoundedVec::from_array([0; 3]); - } - } - - mod trait_from { - use crate::collections::bounded_vec::BoundedVec; - - #[test] - fn simple() { - let array = [1, 2]; - let bounded_vec: BoundedVec = BoundedVec::from(array); - - assert_eq(bounded_vec.max_len(), 10); - assert_eq(bounded_vec.len(), 2); - assert_eq(bounded_vec.storage()[0], 1); - assert_eq(bounded_vec.storage()[1], 2); - } - } - - mod trait_eq { - use crate::collections::bounded_vec::BoundedVec; - - #[test] - fn empty_equality() { - let mut bounded_vec1: BoundedVec = BoundedVec::new(); - let mut bounded_vec2: BoundedVec = BoundedVec::new(); - - assert_eq(bounded_vec1, bounded_vec2); - } - - #[test] - fn inequality() { - let mut bounded_vec1: BoundedVec = BoundedVec::new(); - let mut bounded_vec2: BoundedVec = BoundedVec::new(); - bounded_vec1.push(1); - bounded_vec2.push(2); - - assert(bounded_vec1 != bounded_vec2); - } - } -} diff --git a/noir_stdlib/src/collections/vec.nr b/noir_stdlib/src/collections/vec.nr index cedae7f5ce1..59cd095482d 100644 --- a/noir_stdlib/src/collections/vec.nr +++ b/noir_stdlib/src/collections/vec.nr @@ -63,36 +63,3 @@ impl Vec { self.slice.len() } } - -mod tests { - use crate::collections::vec::Vec; - - #[test] - fn set_updates_values_properly() { - let mut vec = Vec { slice: &[0, 0, 0, 0, 0] }; - - vec.set(0, 42); - assert_eq(vec.slice, &[42, 0, 0, 0, 0]); - - vec.set(1, 43); - assert_eq(vec.slice, &[42, 43, 0, 0, 0]); - - vec.set(2, 44); - assert_eq(vec.slice, &[42, 43, 44, 0, 0]); - - vec.set(1, 10); - assert_eq(vec.slice, &[42, 10, 44, 0, 0]); - - vec.set(0, 0); - assert_eq(vec.slice, &[0, 10, 44, 0, 0]); - } - - #[test(should_fail)] - fn panics_when_writing_elements_past_end_of_vec() { - let mut vec = Vec::new(); - vec.set(0, 42); - - // Need to use println to avoid DIE removing the write operation. - crate::println(vec.get(0)); - } -} diff --git a/noir_stdlib/src/field/bn254.nr b/noir_stdlib/src/field/bn254.nr index e8db0a30c38..a0f10831101 100644 --- a/noir_stdlib/src/field/bn254.nr +++ b/noir_stdlib/src/field/bn254.nr @@ -133,102 +133,3 @@ pub fn gt(a: Field, b: Field) -> bool { pub fn lt(a: Field, b: Field) -> bool { gt(b, a) } - -mod tests { - // TODO: Allow imports from "super" - use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI}; - - #[test] - fn check_decompose() { - assert_eq(decompose(TWO_POW_128), (0, 1)); - assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); - assert_eq(decompose(0x1234567890), (0x1234567890, 0)); - } - - #[test] - unconstrained fn check_decompose_unconstrained() { - assert_eq(decompose(TWO_POW_128), (0, 1)); - assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); - assert_eq(decompose(0x1234567890), (0x1234567890, 0)); - } - - #[test] - fn check_compute_lt() { - assert(compute_lt(0, 1, 16)); - assert(compute_lt(0, 0x100, 16)); - assert(compute_lt(0x100, TWO_POW_128 - 1, 16)); - assert(!compute_lt(0, TWO_POW_128, 16)); - } - - #[test] - fn check_compute_lte() { - assert(compute_lte(0, 1, 16)); - assert(compute_lte(0, 0x100, 16)); - assert(compute_lte(0x100, TWO_POW_128 - 1, 16)); - assert(!compute_lte(0, TWO_POW_128, 16)); - - assert(compute_lte(0, 0, 16)); - assert(compute_lte(0x100, 0x100, 16)); - assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16)); - assert(compute_lte(TWO_POW_128, TWO_POW_128, 16)); - } - - #[test] - fn check_assert_gt() { - assert_gt(1, 0); - assert_gt(0x100, 0); - assert_gt((0 - 1), (0 - 2)); - assert_gt(TWO_POW_128, 0); - assert_gt(0 - 1, 0); - } - - #[test] - unconstrained fn check_assert_gt_unconstrained() { - assert_gt(1, 0); - assert_gt(0x100, 0); - assert_gt((0 - 1), (0 - 2)); - assert_gt(TWO_POW_128, 0); - assert_gt(0 - 1, 0); - } - - #[test] - fn check_gt() { - assert(gt(1, 0)); - assert(gt(0x100, 0)); - assert(gt((0 - 1), (0 - 2))); - assert(gt(TWO_POW_128, 0)); - assert(!gt(0, 0)); - assert(!gt(0, 0x100)); - assert(gt(0 - 1, 0 - 2)); - assert(!gt(0 - 2, 0 - 1)); - } - - #[test] - unconstrained fn check_gt_unconstrained() { - assert(gt(1, 0)); - assert(gt(0x100, 0)); - assert(gt((0 - 1), (0 - 2))); - assert(gt(TWO_POW_128, 0)); - assert(!gt(0, 0)); - assert(!gt(0, 0x100)); - assert(gt(0 - 1, 0 - 2)); - assert(!gt(0 - 2, 0 - 1)); - } - - #[test] - fn check_plo_phi() { - assert_eq(PLO + PHI * TWO_POW_128, 0); - let p_bytes = crate::field::modulus_le_bytes(); - let mut p_low: Field = 0; - let mut p_high: Field = 0; - - let mut offset = 1; - for i in 0..16 { - p_low += (p_bytes[i] as Field) * offset; - p_high += (p_bytes[i + 16] as Field) * offset; - offset *= 256; - } - assert_eq(p_low, PLO); - assert_eq(p_high, PHI); - } -} diff --git a/noir_stdlib/src/hash/keccak.nr b/noir_stdlib/src/hash/keccak.nr index a747676731a..313b7a6dbdb 100644 --- a/noir_stdlib/src/hash/keccak.nr +++ b/noir_stdlib/src/hash/keccak.nr @@ -104,38 +104,3 @@ pub(crate) fn keccak256(mut input: [u8; N], message_size: u32) -> [u } result } - -mod tests { - use crate::hash::keccak::keccak256; - - #[test] - fn smoke_test() { - let input = [0xbd]; - let result = [ - 0x5a, 0x50, 0x2f, 0x9f, 0xca, 0x46, 0x7b, 0x26, 0x6d, 0x5b, 0x78, 0x33, 0x65, 0x19, 0x37, 0xe8, 0x05, 0x27, 0x0c, 0xa3, 0xf3, 0xaf, 0x1c, 0x0d, 0xd2, 0x46, 0x2d, 0xca, 0x4b, 0x3b, 0x1a, 0xbf - ]; - assert_eq(keccak256(input, input.len()), result); - } - - #[test] - fn hash_hello_world() { - // "hello world" - let input = [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]; - let result = [ - 0xec, 0xd0, 0xe1, 0x8, 0xa9, 0x8e, 0x19, 0x2a, 0xf1, 0xd2, 0xc2, 0x50, 0x55, 0xf4, 0xe3, 0xbe, 0xd7, 0x84, 0xb5, 0xc8, 0x77, 0x20, 0x4e, 0x73, 0x21, 0x9a, 0x52, 0x3, 0x25, 0x1f, 0xea, 0xab - ]; - assert_eq(keccak256(input, input.len()), result); - } - - #[test] - fn var_size_hash() { - let input = [ - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223 - ]; - let result = [ - 226, 37, 115, 94, 94, 196, 72, 116, 194, 105, 79, 233, 65, 12, 30, 94, 181, 131, 170, 219, 171, 166, 236, 88, 143, 67, 255, 160, 248, 214, 39, 129 - ]; - assert_eq(keccak256(input, 13), result); - } -} - diff --git a/noir_stdlib/src/hash/mod.nr b/noir_stdlib/src/hash/mod.nr index 40d50abc9e5..b07a788d903 100644 --- a/noir_stdlib/src/hash/mod.nr +++ b/noir_stdlib/src/hash/mod.nr @@ -264,112 +264,3 @@ impl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: self.4.hash(state); } } - -// Some test vectors for Pedersen hash and Pedersen Commitment. -// They have been generated using the same functions so the tests are for now useless -// but they will be useful when we switch to Noir implementation. -#[test] -fn assert_pedersen() { - assert_eq( - pedersen_hash_with_separator([1], 1), 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f - ); - assert_eq( - pedersen_commitment_with_separator([1], 1), EmbeddedCurvePoint { - x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402, - y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126, - is_infinite: false - } - ); - - assert_eq( - pedersen_hash_with_separator([1, 2], 2), 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2], 2), EmbeddedCurvePoint { - x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753, - y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3], 3), 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3], 3), EmbeddedCurvePoint { - x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85, - y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4], 4), 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4], 4), EmbeddedCurvePoint { - x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9, - y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4, 5], 5), 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5), EmbeddedCurvePoint { - x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29, - y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6), 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6), EmbeddedCurvePoint { - x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697, - y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7), 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7), EmbeddedCurvePoint { - x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939, - y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8), 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8), EmbeddedCurvePoint { - x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443, - y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9), 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9), EmbeddedCurvePoint { - x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d, - y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2, - is_infinite: false - } - ); - assert_eq( - pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10), 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94 - ); - assert_eq( - pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10), EmbeddedCurvePoint { - x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c, - y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245, - is_infinite: false - } - ); -} - diff --git a/noir_stdlib/src/hash/poseidon/mod.nr b/noir_stdlib/src/hash/poseidon/mod.nr index 963808f6053..0abbdfb1bd4 100644 --- a/noir_stdlib/src/hash/poseidon/mod.nr +++ b/noir_stdlib/src/hash/poseidon/mod.nr @@ -244,28 +244,3 @@ impl Default for PoseidonHasher{ } } } - -mod poseidon_tests { - use crate::hash::poseidon; - - #[test] - fn reference_impl_test_vectors() { - // hardcoded test vectors from https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/test_vectors.txt - { - let mut state = [0, 1, 2]; - let mut expected = [ - 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a, 0x0fca49b798923ab0239de1c9e7a4a9a2210312b6a2f616d18b5a87f9b628ae29, 0x0e7ae82e40091e63cbd4f16a6d16310b3729d4b6e138fcf54110e2867045a30c - ]; - assert_eq(expected, poseidon::bn254::perm::x5_3(state), "Failed to reproduce output for [0, 1, 2]"); - } - { - let mut state = [0, 1, 2, 3, 4]; - let mut expected = [ - 0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465, 0x1148aaef609aa338b27dafd89bb98862d8bb2b429aceac47d86206154ffe053d, 0x24febb87fed7462e23f6665ff9a0111f4044c38ee1672c1ac6b0637d34f24907, 0x0eb08f6d809668a981c186beaf6110060707059576406b248e5d9cf6e78b3d3e, 0x07748bc6877c9b82c8b98666ee9d0626ec7f5be4205f79ee8528ef1c4a376fc7 - ]; - assert_eq( - expected, poseidon::bn254::perm::x5_5(state), "Failed to reproduce output for [0, 1, 2, 3, 4]" - ); - } - } -} diff --git a/noir_stdlib/src/uint128.nr b/noir_stdlib/src/uint128.nr index e99818bafa0..063ad94c5a9 100644 --- a/noir_stdlib/src/uint128.nr +++ b/noir_stdlib/src/uint128.nr @@ -314,221 +314,3 @@ impl Shr for U128 { self / U128::from_integer(y) } } - -mod tests { - use crate::uint128::{U128, pow64, pow63}; - - #[test] - fn test_not(lo: u64, hi: u64) { - let num = U128::from_u64s_le(lo, hi); - let not_num = num.not(); - - assert_eq(not_num.hi, (hi.not() as Field)); - assert_eq(not_num.lo, (lo.not() as Field)); - - let not_not_num = not_num.not(); - assert_eq(num, not_not_num); - } - #[test] - fn test_construction() { - // Check little-endian u64 is inversed with big-endian u64 construction - let a = U128::from_u64s_le(2, 1); - let b = U128::from_u64s_be(1, 2); - assert_eq(a, b); - // Check byte construction is equivalent - let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908); - assert_eq(c, d); - } - #[test] - fn test_byte_decomposition() { - let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908); - // Get big-endian and little-endian byte decompostions - let le_bytes_a= a.to_le_bytes(); - let be_bytes_a= a.to_be_bytes(); - - // Check equivalence - for i in 0..16 { - assert_eq(le_bytes_a[i], be_bytes_a[15 - i]); - } - // Reconstruct U128 from byte decomposition - let b= U128::from_le_bytes(le_bytes_a); - // Check that it's the same element - assert_eq(a, b); - } - #[test] - fn test_hex_constuction() { - let a = U128::from_u64s_le(0x1, 0x2); - let b = U128::from_hex("0x20000000000000001"); - assert_eq(a, b); - - let c= U128::from_hex("0xffffffffffffffffffffffffffffffff"); - let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff); - assert_eq(c, d); - - let e= U128::from_hex("0x00000000000000000000000000000000"); - let f= U128::from_u64s_le(0, 0); - assert_eq(e, f); - } - - // Ascii decode tests - - #[test] - fn test_ascii_decode_correct_range() { - // '0'..'9' range - for i in 0..10 { - let decoded= U128::decode_ascii(48 + i); - assert_eq(decoded, i as Field); - } - // 'A'..'F' range - for i in 0..6 { - let decoded = U128::decode_ascii(65 + i); - assert_eq(decoded, (i + 10) as Field); - } - // 'a'..'f' range - for i in 0..6 { - let decoded = U128::decode_ascii(97 + i); - assert_eq(decoded, (i + 10) as Field); - } - } - - #[test(should_fail)] - fn test_ascii_decode_range_less_than_48_fails_0() { - crate::println(U128::decode_ascii(0)); - } - #[test(should_fail)] - fn test_ascii_decode_range_less_than_48_fails_1() { - crate::println(U128::decode_ascii(47)); - } - - #[test(should_fail)] - fn test_ascii_decode_range_58_64_fails_0() { - let _ = U128::decode_ascii(58); - } - #[test(should_fail)] - fn test_ascii_decode_range_58_64_fails_1() { - let _ = U128::decode_ascii(64); - } - #[test(should_fail)] - fn test_ascii_decode_range_71_96_fails_0() { - let _ = U128::decode_ascii(71); - } - #[test(should_fail)] - fn test_ascii_decode_range_71_96_fails_1() { - let _ = U128::decode_ascii(96); - } - #[test(should_fail)] - fn test_ascii_decode_range_greater_than_102_fails() { - let _ = U128::decode_ascii(103); - } - - #[test(should_fail)] - fn test_ascii_decode_regression() { - // This code will actually fail because of ascii_decode, - // but in the past it was possible to create a value > (1<<128) - let a = U128::from_hex("0x~fffffffffffffffffffffffffffffff"); - let b:Field= a.to_integer(); - let c= b.to_le_bytes(17); - assert(c[16] != 0); - } - - #[test] - fn test_unconstrained_div() { - // Test the potential overflow case - let a= U128::from_u64s_le(0x0, 0xffffffffffffffff); - let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe); - let c= U128::one(); - let d= U128::from_u64s_le(0x0, 0x1); - let (q,r) = a.unconstrained_div(b); - assert_eq(q, c); - assert_eq(r, d); - - let a = U128::from_u64s_le(2, 0); - let b = U128::one(); - // Check the case where a is a multiple of b - let (c,d ) = a.unconstrained_div(b); - assert_eq((c, d), (a, U128::zero())); - - // Check where b is a multiple of a - let (c,d) = b.unconstrained_div(a); - assert_eq((c, d), (U128::zero(), b)); - - // Dividing by zero returns 0,0 - let a = U128::from_u64s_le(0x1, 0x0); - let b = U128::zero(); - let (c,d)= a.unconstrained_div(b); - assert_eq((c, d), (U128::zero(), U128::zero())); - - // Dividing 1<<127 by 1<<127 (special case) - let a = U128::from_u64s_le(0x0, pow63 as u64); - let b = U128::from_u64s_le(0x0, pow63 as u64); - let (c,d )= a.unconstrained_div(b); - assert_eq((c, d), (U128::one(), U128::zero())); - } - - #[test] - fn integer_conversions() { - // Maximum - let start:Field = 0xffffffffffffffffffffffffffffffff; - let a = U128::from_integer(start); - let end = a.to_integer(); - assert_eq(start, end); - - // Minimum - let start:Field = 0x0; - let a = U128::from_integer(start); - let end = a.to_integer(); - assert_eq(start, end); - - // Low limb - let start:Field = 0xffffffffffffffff; - let a = U128::from_integer(start); - let end = a.to_integer(); - assert_eq(start, end); - - // High limb - let start:Field = 0xffffffffffffffff0000000000000000; - let a = U128::from_integer(start); - let end = a.to_integer(); - assert_eq(start, end); - } - - #[test] - fn integer_conversions_fuzz(lo: u64, hi: u64) { - let start: Field = (lo as Field) + pow64 * (hi as Field); - let a = U128::from_integer(start); - let end = a.to_integer(); - assert_eq(start, end); - } - - #[test] - fn test_wrapping_mul() { - // 1*0==0 - assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one())); - - // 0*1==0 - assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero())); - - // 1*1==1 - assert_eq(U128::one(), U128::one().wrapping_mul(U128::one())); - - // 0 * ( 1 << 64 ) == 0 - assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1))); - - // ( 1 << 64 ) * 0 == 0 - assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero())); - - // 1 * ( 1 << 64 ) == 1 << 64 - assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one())); - - // ( 1 << 64 ) * 1 == 1 << 64 - assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1))); - - // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64 - assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1))); - // -1 * -1 == 1 - assert_eq( - U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff)) - ); - } -} diff --git a/test_programs/noir_test_success/bn254/Nargo.toml b/test_programs/noir_test_success/bn254/Nargo.toml new file mode 100644 index 00000000000..b435096b1de --- /dev/null +++ b/test_programs/noir_test_success/bn254/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bn254" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/bn254/src/main.nr b/test_programs/noir_test_success/bn254/src/main.nr new file mode 100644 index 00000000000..5c86fba5b68 --- /dev/null +++ b/test_programs/noir_test_success/bn254/src/main.nr @@ -0,0 +1,98 @@ +// TODO: Allow imports from "super" +use std::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI}; + +fn main() { } + +#[test] +fn check_decompose() { + assert_eq(decompose(TWO_POW_128), (0, 1)); + assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); + assert_eq(decompose(0x1234567890), (0x1234567890, 0)); +} + +#[test] +unconstrained fn check_decompose_unconstrained() { + assert_eq(decompose(TWO_POW_128), (0, 1)); + assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); + assert_eq(decompose(0x1234567890), (0x1234567890, 0)); +} + +#[test] +fn check_compute_lt() { + assert(compute_lt(0, 1, 16)); + assert(compute_lt(0, 0x100, 16)); + assert(compute_lt(0x100, TWO_POW_128 - 1, 16)); + assert(!compute_lt(0, TWO_POW_128, 16)); +} + +#[test] +fn check_compute_lte() { + assert(compute_lte(0, 1, 16)); + assert(compute_lte(0, 0x100, 16)); + assert(compute_lte(0x100, TWO_POW_128 - 1, 16)); + assert(!compute_lte(0, TWO_POW_128, 16)); + + assert(compute_lte(0, 0, 16)); + assert(compute_lte(0x100, 0x100, 16)); + assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16)); + assert(compute_lte(TWO_POW_128, TWO_POW_128, 16)); +} + +#[test] +fn check_assert_gt() { + assert_gt(1, 0); + assert_gt(0x100, 0); + assert_gt((0 - 1), (0 - 2)); + assert_gt(TWO_POW_128, 0); + assert_gt(0 - 1, 0); +} + +#[test] +unconstrained fn check_assert_gt_unconstrained() { + assert_gt(1, 0); + assert_gt(0x100, 0); + assert_gt((0 - 1), (0 - 2)); + assert_gt(TWO_POW_128, 0); + assert_gt(0 - 1, 0); +} + +#[test] +fn check_gt() { + assert(gt(1, 0)); + assert(gt(0x100, 0)); + assert(gt((0 - 1), (0 - 2))); + assert(gt(TWO_POW_128, 0)); + assert(!gt(0, 0)); + assert(!gt(0, 0x100)); + assert(gt(0 - 1, 0 - 2)); + assert(!gt(0 - 2, 0 - 1)); +} + +#[test] +unconstrained fn check_gt_unconstrained() { + assert(gt(1, 0)); + assert(gt(0x100, 0)); + assert(gt((0 - 1), (0 - 2))); + assert(gt(TWO_POW_128, 0)); + assert(!gt(0, 0)); + assert(!gt(0, 0x100)); + assert(gt(0 - 1, 0 - 2)); + assert(!gt(0 - 2, 0 - 1)); +} + +#[test] +fn check_plo_phi() { + assert_eq(PLO + PHI * TWO_POW_128, 0); + let p_bytes = std::field::modulus_le_bytes(); + let mut p_low: Field = 0; + let mut p_high: Field = 0; + + let mut offset = 1; + for i in 0..16 { + p_low += (p_bytes[i] as Field) * offset; + p_high += (p_bytes[i + 16] as Field) * offset; + offset *= 256; + } + assert_eq(p_low, PLO); + assert_eq(p_high, PHI); +} diff --git a/test_programs/noir_test_success/bounded_vec/src/main.nr b/test_programs/noir_test_success/bounded_vec/src/main.nr index e5aa5f88a94..cb806e812be 100644 --- a/test_programs/noir_test_success/bounded_vec/src/main.nr +++ b/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -1,6 +1,6 @@ #[test] fn test_vec_new_foo() { - foo(); + let _ = foo(); } #[test(should_fail)] @@ -11,7 +11,7 @@ fn test_vec_new_bad() { // docs:start:new_example fn foo() -> BoundedVec { // Ok! MaxLen is specified with a type annotation - let v1: BoundedVec = BoundedVec::new(); + let _v1: BoundedVec = BoundedVec::new(); let v2 = BoundedVec::new(); // Ok! MaxLen is known from the type of foo's return value @@ -52,7 +52,7 @@ fn test_vec_get_unchecked() { } // docs:start:get_unchecked_example -fn sum_of_first_three(v: BoundedVec) -> u32 { +fn sum_of_first_three(v: BoundedVec) -> u32 { // Always ensure the length is larger than the largest // index passed to get_unchecked assert(v.len() > 2); @@ -270,3 +270,161 @@ fn test_vec_any_not_default() { assert(!vec.any(|v| v == default_value)); } +mod bounded_vec_tests { + + mod get { + use std::collections::bounded_vec::BoundedVec; + + #[test(should_fail_with = "Attempted to read past end of BoundedVec")] + fn panics_when_reading_elements_past_end_of_vec() { + let vec: BoundedVec = BoundedVec::new(); + + std::println(vec.get(0)); + } + } + + mod set { + use std::collections::bounded_vec::BoundedVec; + + #[test] + fn set_updates_values_properly() { + let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]); + + vec.set(0, 42); + assert_eq(vec.storage, [42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.storage, [42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.storage, [42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.storage, [42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.storage, [0, 10, 44, 0, 0]); + } + + #[test(should_fail_with = "Attempted to write past end of BoundedVec")] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + std::println(vec.get(0)); + } + } + + mod map { + use std::collections::bounded_vec::BoundedVec; + + #[test] + fn applies_function_correctly() { + // docs:start:bounded-vec-map-example + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); + // docs:end:bounded-vec-map-example + let expected = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn applies_function_that_changes_return_type() { + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| (value * 2) as Field); + let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn does_not_apply_function_past_len() { + let vec: BoundedVec = BoundedVec::from_array([0, 1]); + let result = vec.map(|value| if value == 0 { 5 } else { value }); + let expected = BoundedVec::from_array([5, 1]); + + assert_eq(result, expected); + assert_eq(result.storage()[2], 0); + } + } + + mod from_array { + use std::collections::bounded_vec::BoundedVec; + + #[test] + fn empty() { + let empty_array: [Field; 0] = []; + let bounded_vec = BoundedVec::from_array([]); + + assert_eq(bounded_vec.max_len(), 0); + assert_eq(bounded_vec.len(), 0); + assert_eq(bounded_vec.storage(), empty_array); + } + + #[test] + fn equal_len() { + let array = [1, 2, 3]; + let bounded_vec = BoundedVec::from_array(array); + + assert_eq(bounded_vec.max_len(), 3); + assert_eq(bounded_vec.len(), 3); + assert_eq(bounded_vec.storage(), array); + } + + #[test] + fn max_len_greater_then_array_len() { + let array = [1, 2, 3]; + let bounded_vec: BoundedVec = BoundedVec::from_array(array); + + assert_eq(bounded_vec.max_len(), 10); + assert_eq(bounded_vec.len(), 3); + assert_eq(bounded_vec.storage()[0], 1); + assert_eq(bounded_vec.storage()[1], 2); + assert_eq(bounded_vec.storage()[2], 3); + } + + #[test(should_fail_with="from array out of bounds")] + fn max_len_lower_then_array_len() { + let _: BoundedVec = BoundedVec::from_array([0; 3]); + } + } + + mod trait_from { + use std::collections::bounded_vec::BoundedVec; + + #[test] + fn simple() { + let array = [1, 2]; + let bounded_vec: BoundedVec = BoundedVec::from(array); + + assert_eq(bounded_vec.max_len(), 10); + assert_eq(bounded_vec.len(), 2); + assert_eq(bounded_vec.storage()[0], 1); + assert_eq(bounded_vec.storage()[1], 2); + } + } + + mod trait_eq { + use std::collections::bounded_vec::BoundedVec; + + #[test] + fn empty_equality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + + assert_eq(bounded_vec1, bounded_vec2); + } + + #[test] + fn inequality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + bounded_vec1.push(1); + bounded_vec2.push(2); + + assert(bounded_vec1 != bounded_vec2); + } + } +} diff --git a/test_programs/noir_test_success/cmp/Nargo.toml b/test_programs/noir_test_success/cmp/Nargo.toml new file mode 100644 index 00000000000..b921dc0aaec --- /dev/null +++ b/test_programs/noir_test_success/cmp/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cmp" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/cmp/src/main.nr b/test_programs/noir_test_success/cmp/src/main.nr new file mode 100644 index 00000000000..dce0074ad53 --- /dev/null +++ b/test_programs/noir_test_success/cmp/src/main.nr @@ -0,0 +1,19 @@ +use std::cmp::{min, max}; + +fn main() { } + +#[test] +fn sanity_check_min() { + assert_eq(min(0 as u64, 1 as u64), 0); + assert_eq(min(0 as u64, 0 as u64), 0); + assert_eq(min(1 as u64, 1 as u64), 1); + assert_eq(min(255 as u8, 0 as u8), 0); +} + +#[test] +fn sanity_check_max() { + assert_eq(max(0 as u64, 1 as u64), 1); + assert_eq(max(0 as u64, 0 as u64), 0); + assert_eq(max(1 as u64, 1 as u64), 1); + assert_eq(max(255 as u8, 0 as u8), 255); +} diff --git a/test_programs/noir_test_success/keccak/Nargo.toml b/test_programs/noir_test_success/keccak/Nargo.toml new file mode 100644 index 00000000000..a5048493d4b --- /dev/null +++ b/test_programs/noir_test_success/keccak/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "keccak" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/keccak/src/main.nr b/test_programs/noir_test_success/keccak/src/main.nr new file mode 100644 index 00000000000..f0d109a66af --- /dev/null +++ b/test_programs/noir_test_success/keccak/src/main.nr @@ -0,0 +1,33 @@ +use std::hash::keccak::keccak256; + +fn main() { } + +#[test] +fn smoke_test() { + let input = [0xbd]; + let result = [ + 0x5a, 0x50, 0x2f, 0x9f, 0xca, 0x46, 0x7b, 0x26, 0x6d, 0x5b, 0x78, 0x33, 0x65, 0x19, 0x37, 0xe8, 0x05, 0x27, 0x0c, 0xa3, 0xf3, 0xaf, 0x1c, 0x0d, 0xd2, 0x46, 0x2d, 0xca, 0x4b, 0x3b, 0x1a, 0xbf + ]; + assert_eq(keccak256(input, input.len()), result); +} + +#[test] +fn hash_hello_world() { + // "hello world" + let input = [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]; + let result = [ + 0xec, 0xd0, 0xe1, 0x8, 0xa9, 0x8e, 0x19, 0x2a, 0xf1, 0xd2, 0xc2, 0x50, 0x55, 0xf4, 0xe3, 0xbe, 0xd7, 0x84, 0xb5, 0xc8, 0x77, 0x20, 0x4e, 0x73, 0x21, 0x9a, 0x52, 0x3, 0x25, 0x1f, 0xea, 0xab + ]; + assert_eq(keccak256(input, input.len()), result); +} + +#[test] +fn var_size_hash() { + let input = [ + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223 + ]; + let result = [ + 226, 37, 115, 94, 94, 196, 72, 116, 194, 105, 79, 233, 65, 12, 30, 94, 181, 131, 170, 219, 171, 166, 236, 88, 143, 67, 255, 160, 248, 214, 39, 129 + ]; + assert_eq(keccak256(input, 13), result); +} diff --git a/test_programs/noir_test_success/pedersen/Nargo.toml b/test_programs/noir_test_success/pedersen/Nargo.toml new file mode 100644 index 00000000000..91c6ac5835a --- /dev/null +++ b/test_programs/noir_test_success/pedersen/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pedersen" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/pedersen/src/main.nr b/test_programs/noir_test_success/pedersen/src/main.nr new file mode 100644 index 00000000000..00715d64969 --- /dev/null +++ b/test_programs/noir_test_success/pedersen/src/main.nr @@ -0,0 +1,111 @@ +use std::embedded_curve_ops::EmbeddedCurvePoint; +use std::hash::{pedersen_hash_with_separator, pedersen_commitment_with_separator}; + +// Some test vectors for Pedersen hash and Pedersen Commitment. +// They have been generated using the same functions so the tests are for now useless +// but they will be useful when we switch to Noir implementation. +#[test] +fn assert_pedersen() { + assert_eq( + pedersen_hash_with_separator([1], 1), 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f + ); + assert_eq( + pedersen_commitment_with_separator([1], 1), EmbeddedCurvePoint { + x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402, + y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126, + is_infinite: false + } + ); + + assert_eq( + pedersen_hash_with_separator([1, 2], 2), 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2], 2), EmbeddedCurvePoint { + x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753, + y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3], 3), 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3], 3), EmbeddedCurvePoint { + x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85, + y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4], 4), 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4], 4), EmbeddedCurvePoint { + x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9, + y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5], 5), 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5), EmbeddedCurvePoint { + x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29, + y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6), 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6), EmbeddedCurvePoint { + x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697, + y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7), 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7), EmbeddedCurvePoint { + x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939, + y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8), 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8), EmbeddedCurvePoint { + x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443, + y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9), 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9), EmbeddedCurvePoint { + x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d, + y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2, + is_infinite: false + } + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10), 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94 + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10), EmbeddedCurvePoint { + x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c, + y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245, + is_infinite: false + } + ); +} + diff --git a/test_programs/noir_test_success/poseidon/Nargo.toml b/test_programs/noir_test_success/poseidon/Nargo.toml new file mode 100644 index 00000000000..739ccfc1f82 --- /dev/null +++ b/test_programs/noir_test_success/poseidon/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "poseidon" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/poseidon/src/main.nr b/test_programs/noir_test_success/poseidon/src/main.nr new file mode 100644 index 00000000000..d0c11a03453 --- /dev/null +++ b/test_programs/noir_test_success/poseidon/src/main.nr @@ -0,0 +1,24 @@ +use std::hash::poseidon; + +fn main() { } + +#[test] +fn reference_impl_test_vectors() { + // hardcoded test vectors from https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/test_vectors.txt + { + let mut state = [0, 1, 2]; + let mut expected = [ + 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a, 0x0fca49b798923ab0239de1c9e7a4a9a2210312b6a2f616d18b5a87f9b628ae29, 0x0e7ae82e40091e63cbd4f16a6d16310b3729d4b6e138fcf54110e2867045a30c + ]; + assert_eq(expected, poseidon::bn254::perm::x5_3(state), "Failed to reproduce output for [0, 1, 2]"); + } + { + let mut state = [0, 1, 2, 3, 4]; + let mut expected = [ + 0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465, 0x1148aaef609aa338b27dafd89bb98862d8bb2b429aceac47d86206154ffe053d, 0x24febb87fed7462e23f6665ff9a0111f4044c38ee1672c1ac6b0637d34f24907, 0x0eb08f6d809668a981c186beaf6110060707059576406b248e5d9cf6e78b3d3e, 0x07748bc6877c9b82c8b98666ee9d0626ec7f5be4205f79ee8528ef1c4a376fc7 + ]; + assert_eq( + expected, poseidon::bn254::perm::x5_5(state), "Failed to reproduce output for [0, 1, 2, 3, 4]" + ); + } +} diff --git a/test_programs/noir_test_success/uint128/Nargo.toml b/test_programs/noir_test_success/uint128/Nargo.toml new file mode 100644 index 00000000000..645ba4ece2b --- /dev/null +++ b/test_programs/noir_test_success/uint128/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "uint128" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/uint128/src/main.nr b/test_programs/noir_test_success/uint128/src/main.nr new file mode 100644 index 00000000000..ed391c0343f --- /dev/null +++ b/test_programs/noir_test_success/uint128/src/main.nr @@ -0,0 +1,217 @@ +use std::uint128::{U128, pow64, pow63}; + +fn main() { } + +#[test] +fn test_not(lo: u64, hi: u64) { + let num = U128::from_u64s_le(lo, hi); + let not_num = num.not(); + + assert_eq(not_num.hi, (hi.not() as Field)); + assert_eq(not_num.lo, (lo.not() as Field)); + + let not_not_num = not_num.not(); + assert_eq(num, not_not_num); +} +#[test] +fn test_construction() { + // Check little-endian u64 is inversed with big-endian u64 construction + let a = U128::from_u64s_le(2, 1); + let b = U128::from_u64s_be(1, 2); + assert_eq(a, b); + // Check byte construction is equivalent + let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908); + assert_eq(c, d); +} +#[test] +fn test_byte_decomposition() { + let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908); + // Get big-endian and little-endian byte decompostions + let le_bytes_a= a.to_le_bytes(); + let be_bytes_a= a.to_be_bytes(); + + // Check equivalence + for i in 0..16 { + assert_eq(le_bytes_a[i], be_bytes_a[15 - i]); + } + // Reconstruct U128 from byte decomposition + let b= U128::from_le_bytes(le_bytes_a); + // Check that it's the same element + assert_eq(a, b); +} +#[test] +fn test_hex_constuction() { + let a = U128::from_u64s_le(0x1, 0x2); + let b = U128::from_hex("0x20000000000000001"); + assert_eq(a, b); + + let c= U128::from_hex("0xffffffffffffffffffffffffffffffff"); + let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff); + assert_eq(c, d); + + let e= U128::from_hex("0x00000000000000000000000000000000"); + let f= U128::from_u64s_le(0, 0); + assert_eq(e, f); +} + +// Ascii decode tests + +#[test] +fn test_ascii_decode_correct_range() { + // '0'..'9' range + for i in 0..10 { + let decoded= U128::decode_ascii(48 + i); + assert_eq(decoded, i as Field); + } + // 'A'..'F' range + for i in 0..6 { + let decoded = U128::decode_ascii(65 + i); + assert_eq(decoded, (i + 10) as Field); + } + // 'a'..'f' range + for i in 0..6 { + let decoded = U128::decode_ascii(97 + i); + assert_eq(decoded, (i + 10) as Field); + } +} + +#[test(should_fail)] +fn test_ascii_decode_range_less_than_48_fails_0() { + crate::println(U128::decode_ascii(0)); +} +#[test(should_fail)] +fn test_ascii_decode_range_less_than_48_fails_1() { + crate::println(U128::decode_ascii(47)); +} + +#[test(should_fail)] +fn test_ascii_decode_range_58_64_fails_0() { + let _ = U128::decode_ascii(58); +} +#[test(should_fail)] +fn test_ascii_decode_range_58_64_fails_1() { + let _ = U128::decode_ascii(64); +} +#[test(should_fail)] +fn test_ascii_decode_range_71_96_fails_0() { + let _ = U128::decode_ascii(71); +} +#[test(should_fail)] +fn test_ascii_decode_range_71_96_fails_1() { + let _ = U128::decode_ascii(96); +} +#[test(should_fail)] +fn test_ascii_decode_range_greater_than_102_fails() { + let _ = U128::decode_ascii(103); +} + +#[test(should_fail)] +fn test_ascii_decode_regression() { + // This code will actually fail because of ascii_decode, + // but in the past it was possible to create a value > (1<<128) + let a = U128::from_hex("0x~fffffffffffffffffffffffffffffff"); + let b:Field= a.to_integer(); + let c= b.to_le_bytes(17); + assert(c[16] != 0); +} + +#[test] +fn test_unconstrained_div() { + // Test the potential overflow case + let a= U128::from_u64s_le(0x0, 0xffffffffffffffff); + let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe); + let c= U128::one(); + let d= U128::from_u64s_le(0x0, 0x1); + let (q,r) = a.unconstrained_div(b); + assert_eq(q, c); + assert_eq(r, d); + + let a = U128::from_u64s_le(2, 0); + let b = U128::one(); + // Check the case where a is a multiple of b + let (c,d ) = a.unconstrained_div(b); + assert_eq((c, d), (a, U128::zero())); + + // Check where b is a multiple of a + let (c,d) = b.unconstrained_div(a); + assert_eq((c, d), (U128::zero(), b)); + + // Dividing by zero returns 0,0 + let a = U128::from_u64s_le(0x1, 0x0); + let b = U128::zero(); + let (c,d)= a.unconstrained_div(b); + assert_eq((c, d), (U128::zero(), U128::zero())); + + // Dividing 1<<127 by 1<<127 (special case) + let a = U128::from_u64s_le(0x0, pow63 as u64); + let b = U128::from_u64s_le(0x0, pow63 as u64); + let (c,d )= a.unconstrained_div(b); + assert_eq((c, d), (U128::one(), U128::zero())); +} + +#[test] +fn integer_conversions() { + // Maximum + let start:Field = 0xffffffffffffffffffffffffffffffff; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + + // Minimum + let start:Field = 0x0; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + + // Low limb + let start:Field = 0xffffffffffffffff; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + + // High limb + let start:Field = 0xffffffffffffffff0000000000000000; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); +} + +#[test] +fn integer_conversions_fuzz(lo: u64, hi: u64) { + let start: Field = (lo as Field) + pow64 * (hi as Field); + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); +} + +#[test] +fn test_wrapping_mul() { + // 1*0==0 + assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one())); + + // 0*1==0 + assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero())); + + // 1*1==1 + assert_eq(U128::one(), U128::one().wrapping_mul(U128::one())); + + // 0 * ( 1 << 64 ) == 0 + assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1))); + + // ( 1 << 64 ) * 0 == 0 + assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero())); + + // 1 * ( 1 << 64 ) == 1 << 64 + assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one())); + + // ( 1 << 64 ) * 1 == 1 << 64 + assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1))); + + // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64 + assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1))); + // -1 * -1 == 1 + assert_eq( + U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff)) + ); +} diff --git a/test_programs/noir_test_success/vec/Nargo.toml b/test_programs/noir_test_success/vec/Nargo.toml new file mode 100644 index 00000000000..527360ee0f9 --- /dev/null +++ b/test_programs/noir_test_success/vec/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "vec" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/vec/src/main.nr b/test_programs/noir_test_success/vec/src/main.nr new file mode 100644 index 00000000000..8547db72830 --- /dev/null +++ b/test_programs/noir_test_success/vec/src/main.nr @@ -0,0 +1,32 @@ +use std::collections::vec::Vec; + +fn main() { } + +#[test] +fn set_updates_values_properly() { + let mut vec = Vec { slice: &[0, 0, 0, 0, 0] }; + + vec.set(0, 42); + assert_eq(vec.slice, &[42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.slice, &[42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.slice, &[42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.slice, &[42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.slice, &[0, 10, 44, 0, 0]); +} + +#[test(should_fail)] +fn panics_when_writing_elements_past_end_of_vec() { + let mut vec = Vec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); +} From 58e4ec9512816dd01a450d4debb447bbe2dfd0b7 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Thu, 25 Jul 2024 16:14:38 -0400 Subject: [PATCH 2/2] fix docs link to vec map example --- docs/docs/noir/standard_library/containers/boundedvec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/noir/standard_library/containers/boundedvec.md b/docs/docs/noir/standard_library/containers/boundedvec.md index 98b7d584033..c5765197480 100644 --- a/docs/docs/noir/standard_library/containers/boundedvec.md +++ b/docs/docs/noir/standard_library/containers/boundedvec.md @@ -256,7 +256,7 @@ Creates a new vector of equal size by calling a closure on each element in this Example: -#include_code bounded-vec-map-example noir_stdlib/src/collections/bounded_vec.nr rust +#include_code bounded-vec-map-example test_programs/noir_test_success/bounded_vec/src/main.nr rust ### any