From baa6cffcc3107f77e16a9e0c79200d826d2498a9 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 21 Oct 2024 13:39:48 +0000 Subject: [PATCH 1/4] feat: Constrain VK hashing --- .../parity-lib/src/root/root_parity_input.nr | 1 + .../parity-lib/src/root/root_parity_inputs.nr | 15 +- .../src/root/root_rollup_parity_input.nr | 1 + .../src/abis/previous_rollup_block_data.nr | 2 + .../src/abis/previous_rollup_data.nr | 2 + .../block_merge/block_merge_rollup_inputs.nr | 20 ++- .../src/merge/merge_rollup_inputs.nr | 20 ++- .../rollup-lib/src/tests/l1_to_l2_roots.nr | 8 +- .../src/tests/previous_rollup_block_data.nr | 10 +- .../src/tests/previous_rollup_data.nr | 10 +- .../crates/types/src/abis/kernel_data.nr | 2 + .../types/src/abis/private_kernel_data.nr | 2 + .../types/src/abis/public_kernel_data.nr | 2 + .../crates/types/src/constants.nr | 38 ++--- .../crates/types/src/hash.nr | 4 + .../crates/types/src/lib.nr | 6 +- .../crates/types/src/merkle_tree/mod.nr | 2 +- .../types/src/recursion/verification_key.nr | 8 +- .../crates/types/src/tests/fixture_builder.nr | 22 ++- .../crates/types/src/tests/fixtures.nr | 2 +- .../types/src/tests/fixtures/vk_tree.nr | 60 ++++--- .../crates/types/src/tests/mod.nr | 2 +- noir/noir-repo/noir_stdlib/src/hash/sha256.nr | 151 +++++++++--------- 23 files changed, 233 insertions(+), 157 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr index c84e6436f19..66b9884a315 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr @@ -37,6 +37,7 @@ impl Verifiable for RootParityInput { impl RootParityInput { fn validate_in_vk_tree(self) { + self.verification_key.check_hash(); assert_check_membership( self.verification_key.hash, BASE_PARITY_INDEX as Field, diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr index 9f7a818df05..07cda571aa2 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr @@ -59,6 +59,8 @@ mod tests { use dep::types::constants::BASE_PARITY_INDEX; use super::NUM_BASE_PARITY_PER_ROOT_PARITY; + use types::hash::verification_key_hash; + use types::tests::fixtures::vk_tree::generate_fake_honk_vk_for_index; fn test_setup() -> [RootParityInput; NUM_BASE_PARITY_PER_ROOT_PARITY] { // 31 byte test SHA roots @@ -71,12 +73,10 @@ mod tests { let vk_tree = fixtures::vk_tree::get_vk_merkle_tree(); - let vk_hash = vk_tree.leaves[BASE_PARITY_INDEX]; let vk_path = vk_tree.get_sibling_path(BASE_PARITY_INDEX); let vk_tree_root = vk_tree.get_root(); - let mut vk1 = VerificationKey::empty(); - vk1.hash = vk_hash; + let vk1 = generate_fake_honk_vk_for_index(BASE_PARITY_INDEX); let children = [ RootParityInput { @@ -123,7 +123,8 @@ mod tests { #[test(should_fail_with = "Inconsistent vk hashes across base parity circuits")] fn test_asserts_incorrect_vk_hash_1() { let mut vk2 = VerificationKey::empty(); - vk2.hash = 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904a; + vk2.key[0] = 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904a; + vk2.hash = verification_key_hash(vk2.key); let mut children = test_setup(); children[1].verification_key = vk2; let root_parity_inputs = RootParityInputs { children }; @@ -139,7 +140,8 @@ mod tests { #[test(should_fail_with = "Inconsistent vk hashes across base parity circuits")] fn test_asserts_incorrect_vk_hash_2() { let mut vk2 = VerificationKey::empty(); - vk2.hash = 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904a; + vk2.key[0] = 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904a; + vk2.hash = verification_key_hash(vk2.key); let mut children = test_setup(); children[2].verification_key = vk2; let root_parity_inputs = RootParityInputs { children }; @@ -155,7 +157,8 @@ mod tests { #[test(should_fail_with = "Inconsistent vk hashes across base parity circuits")] fn test_asserts_incorrect_vk_hash_3() { let mut vk2 = VerificationKey::empty(); - vk2.hash = 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904a; + vk2.key[0] = 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904a; + vk2.hash = verification_key_hash(vk2.key); let mut children = test_setup(); children[3].verification_key = vk2; let root_parity_inputs = RootParityInputs { children }; diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr index 3fb976cbc13..018541f82a2 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr @@ -40,6 +40,7 @@ impl Verifiable for RootRollupParityInput { impl RootRollupParityInput { fn validate_in_vk_tree(self) { + self.verification_key.check_hash(); assert_check_membership( self.verification_key.hash, ROOT_PARITY_INDEX as Field, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr index a11a39605c5..94f4ef54add 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr @@ -36,6 +36,8 @@ impl Empty for PreviousRollupBlockData { impl PreviousRollupBlockData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { + self.vk.check_hash(); + let leaf_index = self.vk_witness.leaf_index as u32; let index_hint = unsafe { find_index_hint(allowed_indices, |index: u32| index == leaf_index) diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr index 13e4599fdb0..9682bbe1824 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr @@ -36,6 +36,8 @@ impl Empty for PreviousRollupData { impl PreviousRollupData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { + self.vk.check_hash(); + let leaf_index = self.vk_witness.leaf_index as u32; let index_hint = unsafe { find_index_hint(allowed_indices, |index: u32| index == leaf_index) diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr index 0fda86c3e3c..5ed1dd7c633 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr @@ -69,6 +69,8 @@ mod tests { use crate::{tests::block_merge_rollup_inputs::default_block_merge_rollup_inputs}; use dep::types::{hash::accumulate_sha256}; use dep::types::constants::{BLOCK_ROOT_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX, ROOT_PARITY_INDEX}; + use types::merkle_tree::merkle_tree::MerkleTree; + use dep::types::tests::fixtures; #[test(should_fail_with = "input blocks have different chain id")] fn constants_different_chain_id_fails() { @@ -145,8 +147,10 @@ mod tests { #[test] fn valid_previous_circuit_block_root() { let mut inputs = default_block_merge_rollup_inputs(); - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[BLOCK_ROOT_ROLLUP_INDEX]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; + inputs.previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = BLOCK_ROOT_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(BLOCK_ROOT_ROLLUP_INDEX); let _outputs = inputs.block_merge_rollup_circuit(); @@ -155,8 +159,10 @@ mod tests { #[test] fn valid_previous_circuit_block_merge() { let mut inputs = default_block_merge_rollup_inputs(); - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[BLOCK_MERGE_ROLLUP_INDEX]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; + inputs.previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(BLOCK_MERGE_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = BLOCK_MERGE_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(BLOCK_MERGE_ROLLUP_INDEX); let _outputs = inputs.block_merge_rollup_circuit(); @@ -165,8 +171,10 @@ mod tests { #[test(should_fail_with = "Invalid vk index")] fn invalid_previous_circuit() { let mut inputs = default_block_merge_rollup_inputs(); - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[ROOT_PARITY_INDEX]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; + inputs.previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); let _outputs = inputs.block_merge_rollup_circuit(); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index b9a284353a7..e6e9c7f0755 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -65,6 +65,8 @@ mod tests { use crate::{tests::merge_rollup_inputs::default_merge_rollup_inputs}; use dep::types::hash::accumulate_sha256; use dep::types::constants::{MERGE_ROLLUP_INDEX, BASE_ROLLUP_INDEX, ROOT_PARITY_INDEX}; + use types::merkle_tree::merkle_tree::MerkleTree; + use types::tests::fixtures; #[test(should_fail_with = "The rollup should be filled greedily from L to R, but received a L base and R merge")] fn different_rollup_type_fails() { @@ -178,9 +180,11 @@ mod tests { fn valid_previous_circuit_base() { let mut inputs = default_merge_rollup_inputs(); - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[BASE_ROLLUP_INDEX]; + inputs.previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(BASE_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = BASE_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(BASE_ROLLUP_INDEX); @@ -191,9 +195,11 @@ mod tests { fn valid_previous_circuit_merge() { let mut inputs = default_merge_rollup_inputs(); - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[MERGE_ROLLUP_INDEX]; + inputs.previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(MERGE_ROLLUP_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = MERGE_ROLLUP_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(MERGE_ROLLUP_INDEX); @@ -203,8 +209,10 @@ mod tests { #[test(should_fail_with = "Invalid vk index")] fn invalid_previous_circuit() { let mut inputs = default_merge_rollup_inputs(); - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[ROOT_PARITY_INDEX]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; + inputs.previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX); inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); let _outputs = inputs.merge_rollup_circuit(); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr index 34b7cf47b72..22392e83b4e 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr @@ -1,17 +1,19 @@ use dep::types::constants::ROOT_PARITY_INDEX; use dep::types::tests::fixtures; use dep::parity_lib::{root::root_rollup_parity_input::RootRollupParityInput}; +use types::merkle_tree::merkle_tree::MerkleTree; pub fn default_root_rollup_parity_input() -> RootRollupParityInput { let mut input = RootRollupParityInput::empty(); let vk_index = ROOT_PARITY_INDEX; - let vk_tree = fixtures::vk_tree::get_vk_merkle_tree(); - let vk_hash = vk_tree.leaves[vk_index]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; let vk_path = vk_tree.get_sibling_path(vk_index); let vk_tree_root = vk_tree.get_root(); - input.verification_key.hash = vk_hash; + input.verification_key = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); input.vk_path = vk_path; input.public_inputs.vk_tree_root = vk_tree_root; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr index 14d655f2835..ac0cfefee62 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr @@ -3,21 +3,23 @@ use dep::types::constants::BLOCK_ROOT_ROLLUP_INDEX; use dep::types::tests::fixtures; use dep::types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot; use dep::types::merkle_tree::MembershipWitness; +use types::merkle_tree::merkle_tree::MerkleTree; pub fn default_previous_rollup_block_data() -> [PreviousRollupBlockData; 2] { let mut previous_rollup_data = [PreviousRollupBlockData::empty(); 2]; let vk_index = BLOCK_ROOT_ROLLUP_INDEX; - let vk_tree = fixtures::vk_tree::get_vk_merkle_tree(); - let vk_hash = vk_tree.leaves[vk_index]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; let vk_path = vk_tree.get_sibling_path(vk_index); let vk_tree_root = vk_tree.get_root(); previous_rollup_data[0].block_root_or_block_merge_public_inputs.vk_tree_root = vk_tree_root; previous_rollup_data[1].block_root_or_block_merge_public_inputs.vk_tree_root = vk_tree_root; - previous_rollup_data[0].vk.hash = vk_hash; - previous_rollup_data[1].vk.hash = vk_hash; + previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); + previous_rollup_data[1].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); previous_rollup_data[0].vk_witness = MembershipWitness { leaf_index: vk_index as Field, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr index f41b33dca84..cfcb107eaf6 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr @@ -4,21 +4,23 @@ use dep::types::constants::BASE_ROLLUP_INDEX; use dep::types::tests::fixtures; use dep::types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot; use dep::types::merkle_tree::MembershipWitness; +use types::merkle_tree::merkle_tree::MerkleTree; pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] { let mut previous_rollup_data = [PreviousRollupData::empty(); 2]; let vk_index = BASE_ROLLUP_INDEX; - let vk_tree = fixtures::vk_tree::get_vk_merkle_tree(); - let vk_hash = vk_tree.leaves[vk_index]; + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; let vk_path = vk_tree.get_sibling_path(vk_index); let vk_tree_root = vk_tree.get_root(); previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.vk_tree_root = vk_tree_root; previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.vk_tree_root = vk_tree_root; - previous_rollup_data[0].vk.hash = vk_hash; - previous_rollup_data[1].vk.hash = vk_hash; + previous_rollup_data[0].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); + previous_rollup_data[1].vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index); previous_rollup_data[0].vk_witness = MembershipWitness { leaf_index: vk_index as Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr index cf3149dbf3b..e4fd5d86ce2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr @@ -22,6 +22,8 @@ impl Verifiable for KernelData { impl KernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { + self.vk.check_hash(); + let index_hint = unsafe { find_index_hint(allowed_indices, |index: u32| index == self.vk_index) }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index ee1b86c7b5e..150f33fdcf2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -14,6 +14,8 @@ pub struct PrivateKernelData { impl PrivateKernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { + self.vk.check_hash(); + let index_in_allowed_list = if self.vk_index >= PRIVATE_KERNEL_RESET_INDEX { // Kernel circuits only need to include PRIVATE_KERNEL_RESET_INDEX in the list to allow all private kernel reset variants. PRIVATE_KERNEL_RESET_INDEX diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr index 46f9a826293..3277655de97 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr @@ -22,6 +22,8 @@ impl Verifiable for PublicKernelData { impl PublicKernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { + self.vk.check_hash(); + let index_hint = unsafe { find_index_hint(allowed_indices, |index: u32| index == self.vk_index) }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 4a5e317ecbf..673e442514f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -98,25 +98,25 @@ global MAX_PUBLIC_DATA_HINTS: u32 = 128; global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: u32 = 16; // VK TREE CONSTANTS -global EMPTY_NESTED_INDEX: u32 = 0; -global PRIVATE_KERNEL_EMPTY_INDEX: u32 = 1; -global PRIVATE_KERNEL_INIT_INDEX: u32 = 2; -global PRIVATE_KERNEL_INNER_INDEX: u32 = 3; -global PRIVATE_KERNEL_TAIL_INDEX: u32 = 4; -global PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX: u32 = 5; -global PUBLIC_KERNEL_MERGE_INDEX: u32 = 6; -global PUBLIC_KERNEL_TAIL_INDEX: u32 = 7; -global PUBLIC_KERNEL_INNER_INDEX: u32 = 8; // TODO(#7124): To be deprecated. -global BASE_PARITY_INDEX: u32 = 10; -global ROOT_PARITY_INDEX: u32 = 11; -global BASE_ROLLUP_INDEX: u32 = 12; -global MERGE_ROLLUP_INDEX: u32 = 13; -global BLOCK_ROOT_ROLLUP_INDEX: u32 = 14; -global BLOCK_MERGE_ROLLUP_INDEX: u32 = 15; -global ROOT_ROLLUP_INDEX: u32 = 16; -global BLOCK_ROOT_ROLLUP_EMPTY_INDEX: u32 = 17; -global TUBE_INDEX: u32 = 18; -global PRIVATE_KERNEL_RESET_INDEX: u32 = 20; +comptime global EMPTY_NESTED_INDEX: u32 = 0; +comptime global PRIVATE_KERNEL_EMPTY_INDEX: u32 = 1; +comptime global PRIVATE_KERNEL_INIT_INDEX: u32 = 2; +comptime global PRIVATE_KERNEL_INNER_INDEX: u32 = 3; +comptime global PRIVATE_KERNEL_TAIL_INDEX: u32 = 4; +comptime global PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX: u32 = 5; +comptime global PUBLIC_KERNEL_MERGE_INDEX: u32 = 6; +comptime global PUBLIC_KERNEL_TAIL_INDEX: u32 = 7; +comptime global PUBLIC_KERNEL_INNER_INDEX: u32 = 8; // TODO(#7124): To be deprecated. +comptime global BASE_PARITY_INDEX: u32 = 10; +comptime global ROOT_PARITY_INDEX: u32 = 11; +comptime global BASE_ROLLUP_INDEX: u32 = 12; +comptime global MERGE_ROLLUP_INDEX: u32 = 13; +comptime global BLOCK_ROOT_ROLLUP_INDEX: u32 = 14; +comptime global BLOCK_MERGE_ROLLUP_INDEX: u32 = 15; +comptime global ROOT_ROLLUP_INDEX: u32 = 16; +comptime global BLOCK_ROOT_ROLLUP_EMPTY_INDEX: u32 = 17; +comptime global TUBE_INDEX: u32 = 18; +comptime global PRIVATE_KERNEL_RESET_INDEX: u32 = 20; // Important: Do not define indexes after the PRIVATE_KERNEL_RESET_INDEX. They are allocated for the variants of private kernel reset. // MISC CONSTANTS diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index f42d28afe0b..a9530bd304b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -252,6 +252,10 @@ pub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX] hash } +pub fn verification_key_hash(key: [Field; N]) -> Field { + crate::hash::poseidon2_hash(key) +} + #[inline_always] pub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field { std::hash::pedersen_hash_with_separator(inputs, hash_index) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr index 28c7b7b94e6..348b531c597 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr @@ -8,14 +8,14 @@ mod scalar; mod contrakt; mod transaction; mod abis; -mod constants; +pub mod constants; mod contract_class_id; mod merkle_tree; mod contract_instance; mod messaging; -mod hash; -mod traits; +pub mod hash; +pub mod traits; mod type_serialization; mod content_commitment; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr index 47f3007f449..a88c4b01e9a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr @@ -2,7 +2,7 @@ mod append_only_tree; mod indexed_tree; mod leaf_preimage; mod membership; -mod merkle_tree; +pub mod merkle_tree; mod root; mod variable_merkle_tree; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr index f4f5b9762c9..fc5c1651864 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr @@ -1,6 +1,6 @@ use crate::{ traits::{Serialize, Deserialize, Empty}, - constants::{HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS} + constants::{HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS}, }; pub struct VerificationKey { @@ -8,6 +8,12 @@ pub struct VerificationKey { hash: Field, } +impl VerificationKey { + pub fn check_hash(self) { + assert_eq(self.hash, crate::hash::verification_key_hash(self.key), "Invalid VK hash"); + } +} + impl Serialize for VerificationKey { fn serialize(self) -> [Field; N + 1] { let mut fields = [0; N + 1]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index e5df48c4108..108502b93c7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -47,10 +47,19 @@ use crate::{ compute_l2_to_l1_hash, compute_tx_logs_hash, compute_siloed_nullifier, silo_note_hash, silo_unencrypted_log_hash, mask_encrypted_log_hash }, - header::Header, merkle_tree::membership::MembershipWitness, + header::Header, merkle_tree::{membership::MembershipWitness, MerkleTree}, messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, partial_state_reference::PartialStateReference, - tests::{fixtures, fixtures::{contracts::ContractData, contract_functions::ContractFunction}}, + tests::{ + fixtures, + fixtures::{ + contracts::ContractData, contract_functions::ContractFunction, + vk_tree::{ + generate_fake_honk_vk_for_index, generate_fake_client_ivc_vk_for_index, get_vk_merkle_tree, + VK_TREE_WIDTH +} +} +}, transaction::{tx_context::TxContext, tx_request::TxRequest}, traits::Empty, recursion::{ verification_key::{HonkVerificationKey, ClientIVCVerificationKey, VerificationKey}, @@ -201,11 +210,12 @@ impl FixtureBuilder { pub fn in_vk_tree(&mut self, vk_index: u32) -> Self { self.vk_index = vk_index; - let vk_tree = fixtures::vk_tree::get_vk_merkle_tree(); + let vk_tree: MerkleTree = comptime { + fixtures::vk_tree::get_vk_merkle_tree() + }; - let vk_hash = vk_tree.leaves[vk_index]; - self.honk_vk.hash = vk_hash; - self.client_ivc_vk.hash = vk_hash; + self.honk_vk = fixtures::vk_tree::generate_fake_honk_vk_for_index(vk_index) ; + self.client_ivc_vk = fixtures::vk_tree::generate_fake_client_ivc_vk_for_index(vk_index); self.vk_path = vk_tree.get_sibling_path(vk_index); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr index aaee83d9f05..6e361b74752 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr @@ -1,7 +1,7 @@ mod contract_functions; mod contracts; mod protocol_contract_tree; -mod vk_tree; +pub mod vk_tree; use crate::{address::AztecAddress, point::Point}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr index 472dd5ae5ff..83de6523bd8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr @@ -4,34 +4,54 @@ use crate::constants::{ PRIVATE_KERNEL_EMPTY_INDEX, PUBLIC_KERNEL_INNER_INDEX, PUBLIC_KERNEL_MERGE_INDEX, PUBLIC_KERNEL_TAIL_INDEX, BASE_PARITY_INDEX, ROOT_PARITY_INDEX, BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX, ROOT_ROLLUP_INDEX, - BLOCK_ROOT_ROLLUP_EMPTY_INDEX + BLOCK_ROOT_ROLLUP_EMPTY_INDEX, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, + CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS }; use crate::merkle_tree::merkle_tree::MerkleTree; +use crate::recursion::verification_key::VerificationKey; +use crate::hash::verification_key_hash; -global VK_TREE_WIDTH: u32 = (1 as u8 << VK_TREE_HEIGHT as u8) as u32; +pub global VK_TREE_WIDTH: u32 = (1 as u8 << VK_TREE_HEIGHT as u8) as u32; + +fn generate_fake_vk_for_index(index: u32) -> [Field; N] { + let mut vk = [0; N]; + vk[0] = index as Field; + vk +} + +pub fn generate_fake_honk_vk_for_index(index: u32) -> VerificationKey { + let key = generate_fake_vk_for_index(index); + VerificationKey { key, hash: verification_key_hash(key) } +} + +pub fn generate_fake_client_ivc_vk_for_index(index: u32) -> VerificationKey { + let key = generate_fake_vk_for_index(index); + VerificationKey { key, hash: verification_key_hash(key) } +} pub fn get_vk_merkle_tree() -> MerkleTree { let mut leaves = [0; VK_TREE_WIDTH]; // Fake VK hashes for testing purposes - leaves[PRIVATE_KERNEL_INIT_INDEX] = 0; - leaves[PRIVATE_KERNEL_INNER_INDEX] = 1; - leaves[PRIVATE_KERNEL_TAIL_INDEX] = 10; - leaves[PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX] = 11; - leaves[EMPTY_NESTED_INDEX] = 12; - leaves[PRIVATE_KERNEL_EMPTY_INDEX] = 13; - leaves[PUBLIC_KERNEL_INNER_INDEX] = 15; - leaves[PUBLIC_KERNEL_MERGE_INDEX] = 16; - leaves[PUBLIC_KERNEL_TAIL_INDEX] = 17; - leaves[BASE_PARITY_INDEX] = 18; - leaves[ROOT_PARITY_INDEX] = 19; - leaves[BASE_ROLLUP_INDEX] = 20; - leaves[MERGE_ROLLUP_INDEX] = 21; - leaves[BLOCK_ROOT_ROLLUP_INDEX] = 22; - leaves[BLOCK_MERGE_ROLLUP_INDEX] = 23; - leaves[ROOT_ROLLUP_INDEX] = 24; - leaves[BLOCK_ROOT_ROLLUP_EMPTY_INDEX] = 25; - leaves[PRIVATE_KERNEL_RESET_INDEX] = 26; + leaves[PRIVATE_KERNEL_INIT_INDEX] = generate_fake_client_ivc_vk_for_index(PRIVATE_KERNEL_INIT_INDEX).hash; + leaves[PRIVATE_KERNEL_INNER_INDEX] = generate_fake_client_ivc_vk_for_index(PRIVATE_KERNEL_INNER_INDEX).hash; + leaves[PRIVATE_KERNEL_TAIL_INDEX] = generate_fake_client_ivc_vk_for_index(PRIVATE_KERNEL_TAIL_INDEX).hash; + leaves[PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX] = generate_fake_client_ivc_vk_for_index(PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX).hash; + leaves[PRIVATE_KERNEL_RESET_INDEX] = generate_fake_client_ivc_vk_for_index(PRIVATE_KERNEL_RESET_INDEX).hash; + + leaves[EMPTY_NESTED_INDEX] = generate_fake_honk_vk_for_index(EMPTY_NESTED_INDEX).hash; + leaves[PRIVATE_KERNEL_EMPTY_INDEX] = generate_fake_honk_vk_for_index(PRIVATE_KERNEL_EMPTY_INDEX).hash; + leaves[PUBLIC_KERNEL_INNER_INDEX] = generate_fake_honk_vk_for_index(PUBLIC_KERNEL_INNER_INDEX).hash; + leaves[PUBLIC_KERNEL_MERGE_INDEX] = generate_fake_honk_vk_for_index(PUBLIC_KERNEL_MERGE_INDEX).hash; + leaves[PUBLIC_KERNEL_TAIL_INDEX] = generate_fake_honk_vk_for_index(PUBLIC_KERNEL_TAIL_INDEX).hash; + leaves[BASE_PARITY_INDEX] = generate_fake_honk_vk_for_index(BASE_PARITY_INDEX).hash; + leaves[ROOT_PARITY_INDEX] = generate_fake_honk_vk_for_index(ROOT_PARITY_INDEX).hash; + leaves[BASE_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(BASE_ROLLUP_INDEX).hash; + leaves[MERGE_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(MERGE_ROLLUP_INDEX).hash; + leaves[BLOCK_ROOT_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_INDEX).hash; + leaves[BLOCK_MERGE_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(BLOCK_MERGE_ROLLUP_INDEX).hash; + leaves[ROOT_ROLLUP_INDEX] = generate_fake_honk_vk_for_index(ROOT_ROLLUP_INDEX).hash; + leaves[BLOCK_ROOT_ROLLUP_EMPTY_INDEX] = generate_fake_honk_vk_for_index(BLOCK_ROOT_ROLLUP_EMPTY_INDEX).hash; MerkleTree::new(leaves) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr index 129deea3194..29d53f6506e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr @@ -1,5 +1,5 @@ mod fixture_builder; -mod fixtures; +pub mod fixtures; mod merkle_tree_utils; mod types; mod utils; diff --git a/noir/noir-repo/noir_stdlib/src/hash/sha256.nr b/noir/noir-repo/noir_stdlib/src/hash/sha256.nr index 6c56a722fa7..c2cf65e5ec8 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/sha256.nr @@ -82,86 +82,87 @@ global BLOCK_SIZE = 64; // Variable size SHA-256 hash pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { - let message_size = message_size as u32; - let num_blocks = N / BLOCK_SIZE; - let mut msg_block: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE]; - let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value - let mut msg_byte_ptr = 0; // Pointer into msg_block - - for i in 0..num_blocks { - let msg_start = BLOCK_SIZE * i; - let (new_msg_block, new_msg_byte_ptr) = unsafe { - build_msg_block_iter(msg, message_size, msg_start) - }; - if msg_start < message_size { - msg_block = new_msg_block; - } - - if !is_unconstrained() { - // Verify the block we are compressing was appropriately constructed - let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if is_unconstrained() { + sha256_var_unconstrained(msg, message_size) + } else { + let message_size = message_size as u32; + let num_blocks = N / BLOCK_SIZE; + let mut msg_block: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE]; + let mut h: [u32; 8] = [ + 1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225 + ]; // Intermediate hash, starting with the canonical initial value + let mut msg_byte_ptr = 0; // Pointer into msg_block + + for i in 0..num_blocks { + let msg_start = BLOCK_SIZE * i; + let (new_msg_block, new_msg_byte_ptr) = unsafe { + build_msg_block_iter(msg, message_size, msg_start) + }; if msg_start < message_size { + msg_block = new_msg_block; + } + + if !is_unconstrained() { + // Verify the block we are compressing was appropriately constructed + let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + } + } else if msg_start < message_size { msg_byte_ptr = new_msg_byte_ptr; } - } else if msg_start < message_size { - msg_byte_ptr = new_msg_byte_ptr; - } - // If the block is filled, compress it. - // An un-filled block is handled after this loop. - if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) { - h = sha256_compression(msg_u8_to_u32(msg_block), h); + // If the block is filled, compress it. + // An un-filled block is handled after this loop. + if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) { + h = sha256_compression(msg_u8_to_u32(msg_block), h); + } } - } - let modulo = N % BLOCK_SIZE; - // Handle setup of the final msg block. - // This case is only hit if the msg is less than the block size, - // or our message cannot be evenly split into blocks. - if modulo != 0 { - let msg_start = BLOCK_SIZE * num_blocks; - let (new_msg_block, new_msg_byte_ptr) = unsafe { - build_msg_block_iter(msg, message_size, msg_start) - }; + let modulo = N % BLOCK_SIZE; + // Handle setup of the final msg block. + // This case is only hit if the msg is less than the block size, + // or our message cannot be evenly split into blocks. + if modulo != 0 { + let msg_start = BLOCK_SIZE * num_blocks; + let (new_msg_block, new_msg_byte_ptr) = unsafe { + build_msg_block_iter(msg, message_size, msg_start) + }; - if msg_start < message_size { - msg_block = new_msg_block; - } - - if !is_unconstrained() { - let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); if msg_start < message_size { + msg_block = new_msg_block; + } + + if !is_unconstrained() { + let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + } + } else if msg_start < message_size { msg_byte_ptr = new_msg_byte_ptr; } - } else if msg_start < message_size { - msg_byte_ptr = new_msg_byte_ptr; } - } - if msg_byte_ptr == BLOCK_SIZE { - msg_byte_ptr = 0; - } + if msg_byte_ptr == BLOCK_SIZE { + msg_byte_ptr = 0; + } + + // This variable is used to get around the compiler under-constrained check giving a warning. + // We want to check against a constant zero, but if it does not come from the circuit inputs + // or return values the compiler check will issue a warning. + let zero = msg_block[0] - msg_block[0]; - // This variable is used to get around the compiler under-constrained check giving a warning. - // We want to check against a constant zero, but if it does not come from the circuit inputs - // or return values the compiler check will issue a warning. - let zero = msg_block[0] - msg_block[0]; - - // Pad the rest such that we have a [u32; 2] block at the end representing the length - // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). - msg_block[msg_byte_ptr] = 1 << 7; - let last_block = msg_block; - msg_byte_ptr = msg_byte_ptr + 1; - - unsafe { - let (new_msg_block, new_msg_byte_ptr) = pad_msg_block(msg_block, msg_byte_ptr); - msg_block = new_msg_block; - if crate::runtime::is_unconstrained() { - msg_byte_ptr = new_msg_byte_ptr; + // Pad the rest such that we have a [u32; 2] block at the end representing the length + // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). + msg_block[msg_byte_ptr] = 1 << 7; + let last_block = msg_block; + msg_byte_ptr = msg_byte_ptr + 1; + + unsafe { + let (new_msg_block, new_msg_byte_ptr) = pad_msg_block(msg_block, msg_byte_ptr); + msg_block = new_msg_block; } - } - if !crate::runtime::is_unconstrained() { for i in 0..BLOCK_SIZE { assert_eq(msg_block[i], last_block[i]); } @@ -175,19 +176,17 @@ pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { msg_byte_ptr += 1; } } - } - if msg_byte_ptr >= 57 { - h = sha256_compression(msg_u8_to_u32(msg_block), h); + if msg_byte_ptr >= 57 { + h = sha256_compression(msg_u8_to_u32(msg_block), h); - msg_byte_ptr = 0; - } + msg_byte_ptr = 0; + } - msg_block = unsafe { - attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) - }; + msg_block = unsafe { + attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) + }; - if !crate::runtime::is_unconstrained() { for i in 0..56 { let predicate = (i < msg_byte_ptr) as u8; let expected_byte = predicate * last_block[i]; @@ -201,9 +200,9 @@ pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { reconstructed_len = 256 * reconstructed_len + msg_block[i] as Field; } assert_eq(reconstructed_len, len as Field); - } - hash_final_block(msg_block, h) + hash_final_block(msg_block, h) + } } unconstrained fn pad_msg_block( From c77f2f8bdbf2790a0d58c143bc7157c7de5cc1f2 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 21 Oct 2024 14:29:06 +0000 Subject: [PATCH 2/4] revert extraneous changes --- noir/noir-repo/noir_stdlib/src/hash/sha256.nr | 151 +++++++++--------- 1 file changed, 76 insertions(+), 75 deletions(-) diff --git a/noir/noir-repo/noir_stdlib/src/hash/sha256.nr b/noir/noir-repo/noir_stdlib/src/hash/sha256.nr index c2cf65e5ec8..6c56a722fa7 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/sha256.nr @@ -82,87 +82,86 @@ global BLOCK_SIZE = 64; // Variable size SHA-256 hash pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { - if is_unconstrained() { - sha256_var_unconstrained(msg, message_size) - } else { - let message_size = message_size as u32; - let num_blocks = N / BLOCK_SIZE; - let mut msg_block: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE]; - let mut h: [u32; 8] = [ - 1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225 - ]; // Intermediate hash, starting with the canonical initial value - let mut msg_byte_ptr = 0; // Pointer into msg_block - - for i in 0..num_blocks { - let msg_start = BLOCK_SIZE * i; - let (new_msg_block, new_msg_byte_ptr) = unsafe { - build_msg_block_iter(msg, message_size, msg_start) - }; - if msg_start < message_size { - msg_block = new_msg_block; - } + let message_size = message_size as u32; + let num_blocks = N / BLOCK_SIZE; + let mut msg_block: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE]; + let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value + let mut msg_byte_ptr = 0; // Pointer into msg_block - if !is_unconstrained() { - // Verify the block we are compressing was appropriately constructed - let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); - if msg_start < message_size { - msg_byte_ptr = new_msg_byte_ptr; - } - } else if msg_start < message_size { + for i in 0..num_blocks { + let msg_start = BLOCK_SIZE * i; + let (new_msg_block, new_msg_byte_ptr) = unsafe { + build_msg_block_iter(msg, message_size, msg_start) + }; + if msg_start < message_size { + msg_block = new_msg_block; + } + + if !is_unconstrained() { + // Verify the block we are compressing was appropriately constructed + let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if msg_start < message_size { msg_byte_ptr = new_msg_byte_ptr; } + } else if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + } - // If the block is filled, compress it. - // An un-filled block is handled after this loop. - if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) { - h = sha256_compression(msg_u8_to_u32(msg_block), h); - } + // If the block is filled, compress it. + // An un-filled block is handled after this loop. + if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) { + h = sha256_compression(msg_u8_to_u32(msg_block), h); } + } - let modulo = N % BLOCK_SIZE; - // Handle setup of the final msg block. - // This case is only hit if the msg is less than the block size, - // or our message cannot be evenly split into blocks. - if modulo != 0 { - let msg_start = BLOCK_SIZE * num_blocks; - let (new_msg_block, new_msg_byte_ptr) = unsafe { - build_msg_block_iter(msg, message_size, msg_start) - }; + let modulo = N % BLOCK_SIZE; + // Handle setup of the final msg block. + // This case is only hit if the msg is less than the block size, + // or our message cannot be evenly split into blocks. + if modulo != 0 { + let msg_start = BLOCK_SIZE * num_blocks; + let (new_msg_block, new_msg_byte_ptr) = unsafe { + build_msg_block_iter(msg, message_size, msg_start) + }; - if msg_start < message_size { - msg_block = new_msg_block; - } + if msg_start < message_size { + msg_block = new_msg_block; + } - if !is_unconstrained() { - let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); - if msg_start < message_size { - msg_byte_ptr = new_msg_byte_ptr; - } - } else if msg_start < message_size { + if !is_unconstrained() { + let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if msg_start < message_size { msg_byte_ptr = new_msg_byte_ptr; } + } else if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; } + } - if msg_byte_ptr == BLOCK_SIZE { - msg_byte_ptr = 0; - } - - // This variable is used to get around the compiler under-constrained check giving a warning. - // We want to check against a constant zero, but if it does not come from the circuit inputs - // or return values the compiler check will issue a warning. - let zero = msg_block[0] - msg_block[0]; - - // Pad the rest such that we have a [u32; 2] block at the end representing the length - // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). - msg_block[msg_byte_ptr] = 1 << 7; - let last_block = msg_block; - msg_byte_ptr = msg_byte_ptr + 1; + if msg_byte_ptr == BLOCK_SIZE { + msg_byte_ptr = 0; + } - unsafe { - let (new_msg_block, new_msg_byte_ptr) = pad_msg_block(msg_block, msg_byte_ptr); - msg_block = new_msg_block; + // This variable is used to get around the compiler under-constrained check giving a warning. + // We want to check against a constant zero, but if it does not come from the circuit inputs + // or return values the compiler check will issue a warning. + let zero = msg_block[0] - msg_block[0]; + + // Pad the rest such that we have a [u32; 2] block at the end representing the length + // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). + msg_block[msg_byte_ptr] = 1 << 7; + let last_block = msg_block; + msg_byte_ptr = msg_byte_ptr + 1; + + unsafe { + let (new_msg_block, new_msg_byte_ptr) = pad_msg_block(msg_block, msg_byte_ptr); + msg_block = new_msg_block; + if crate::runtime::is_unconstrained() { + msg_byte_ptr = new_msg_byte_ptr; } + } + if !crate::runtime::is_unconstrained() { for i in 0..BLOCK_SIZE { assert_eq(msg_block[i], last_block[i]); } @@ -176,17 +175,19 @@ pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { msg_byte_ptr += 1; } } + } - if msg_byte_ptr >= 57 { - h = sha256_compression(msg_u8_to_u32(msg_block), h); + if msg_byte_ptr >= 57 { + h = sha256_compression(msg_u8_to_u32(msg_block), h); - msg_byte_ptr = 0; - } + msg_byte_ptr = 0; + } - msg_block = unsafe { - attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) - }; + msg_block = unsafe { + attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) + }; + if !crate::runtime::is_unconstrained() { for i in 0..56 { let predicate = (i < msg_byte_ptr) as u8; let expected_byte = predicate * last_block[i]; @@ -200,9 +201,9 @@ pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { reconstructed_len = 256 * reconstructed_len + msg_block[i] as Field; } assert_eq(reconstructed_len, len as Field); - - hash_final_block(msg_block, h) } + + hash_final_block(msg_block, h) } unconstrained fn pad_msg_block( From 54cbedc917e620f15ab62bd09a4a79507a70f503 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 21 Oct 2024 15:02:05 +0000 Subject: [PATCH 3/4] fmt --- .../crates/types/src/recursion/verification_key.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr index fc5c1651864..165b576a6a1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/recursion/verification_key.nr @@ -1,6 +1,6 @@ use crate::{ traits::{Serialize, Deserialize, Empty}, - constants::{HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS}, + constants::{HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS} }; pub struct VerificationKey { From 840cbbedacdbe5b8a514042f5550507c55414fb2 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 21 Oct 2024 15:05:31 +0000 Subject: [PATCH 4/4] remove comment --- .../crates/parity-lib/src/root/root_parity_inputs.nr | 2 -- 1 file changed, 2 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr index 07cda571aa2..e765f5e3137 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr @@ -41,8 +41,6 @@ impl RootParityInputs { assert( self.children[i].vk_path == self.children[0].vk_path, "Inconsistent vk paths across base parity circuits" ); - //TODO: Do we need to validate this following hash - //assert(hash(self.children[i].verification_key) == self.children[i].verification_key.hash); self.children[i].verify(); self.children[i].validate_in_vk_tree(); }