From 1896b7458385eaa63fd4e48ac06f62b210f15dc0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 8 Mar 2024 15:29:05 +0000 Subject: [PATCH] finished parity circuits --- .../parity-lib/src/base/base_parity_inputs.nr | 26 +++++++--- .../crates/parity-lib/src/lib.nr | 5 +- .../parity-lib/src/root/root_parity_inputs.nr | 36 ++++++++----- .../crates/parity-lib/src/utils.nr | 1 + .../src/utils/sha256_merkle_tree.nr | 51 +++++++++++++++++++ 5 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr index 3a9bb5411a75..07c748762c16 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr @@ -1,10 +1,14 @@ -use crate::parity_public_inputs::ParityPublicInputs; +use crate::{ + parity_public_inputs::ParityPublicInputs, + utils::sha256_merkle_tree::Sha256MerkleTree, +}; use dep::types::{ constants::NUM_FIELDS_PER_SHA256, + merkle_tree::MerkleTree, mocked::AggregationObject, }; -global NUM_MSGS_PER_BASE_PARITY: Field = 4; +global NUM_MSGS_PER_BASE_PARITY: u64 = 4; struct BaseParityInputs { msgs: [[Field; NUM_FIELDS_PER_SHA256]; NUM_MSGS_PER_BASE_PARITY], @@ -12,13 +16,21 @@ struct BaseParityInputs { impl BaseParityInputs { pub fn base_parity_circuit(self) -> ParityPublicInputs { - // sha_root = MERKLE_TREE(inputs.msgs, SHA256); - // converted_root = MERKLE_TREE(inputs.msgs, SNARK_FRIENDLY_HASH_FUNCTION); - // return ParityPublicInputs(sha_root, converted_root) + let sha_tree = Sha256MerkleTree::new(self.msgs); + + // TODO: nuke this flattening once we truncate sha256 to 1 field + let mut flat_msgs = [0; NUM_FIELDS_PER_SHA256 * NUM_MSGS_PER_BASE_PARITY]; + for i in 0..NUM_MSGS_PER_BASE_PARITY { + for j in 0..NUM_FIELDS_PER_SHA256 { + flat_msgs[i * NUM_FIELDS_PER_SHA256 + j] = self.msgs[i][j]; + } + } + let pedersen_tree = MerkleTree::new(flat_msgs); + ParityPublicInputs { aggregation_object: AggregationObject {}, - sha_root: [0, 0], - converted_root: 0, + sha_root: sha_tree.get_root(), + converted_root: pedersen_tree.get_root(), } } } \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr index 613b78fe3653..c4cdf2ff697e 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr @@ -1,10 +1,7 @@ -// Base parity mod base; - -// Root parity mod root; - mod parity_public_inputs; +mod utils; use crate::base::base_parity_inputs::BaseParityInputs; use crate::root::root_parity_input::RootParityInput; 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 99b2dead6efc..4cb979748e34 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 @@ -1,30 +1,38 @@ -use dep::types::mocked::AggregationObject; +use dep::types::{ + constants::NUM_FIELDS_PER_SHA256, + merkle_tree::MerkleTree, + mocked::AggregationObject, +}; use crate::{ parity_public_inputs::ParityPublicInputs, root::root_parity_input::RootParityInput, + utils::sha256_merkle_tree::Sha256MerkleTree, }; +global NUM_BASE_PARITY_PER_ROOT_PARITY: u64 = 4; + struct RootParityInputs { - children: [RootParityInput; 2], + children: [RootParityInput; NUM_BASE_PARITY_PER_ROOT_PARITY], } impl RootParityInputs { pub fn root_parity_circuit(self) -> ParityPublicInputs { - // for msg in inputs.children: - // assert msg.proof.verify(msg.public_inputs); + // TODO: verify proofs of inputs.children + + let mut sha_roots = [[0; NUM_FIELDS_PER_SHA256]; NUM_BASE_PARITY_PER_ROOT_PARITY]; + let mut converted_roots = [0; NUM_BASE_PARITY_PER_ROOT_PARITY]; + for i in 0..NUM_BASE_PARITY_PER_ROOT_PARITY { + sha_roots[i] = self.children[i].public_inputs.sha_root; + converted_roots[i] = self.children[i].public_inputs.converted_root; + } + + let sha_tree = Sha256MerkleTree::new(sha_roots); + let pedersen_tree = MerkleTree::new(converted_roots); - // sha_root = MERKLE_TREE( - // [msg.public_inputs.sha_root for msg in inputs.children], - // SHA256 - // ); - // converted_root = MERKLE_TREE( - // [msg.public_inputs.converted_root for msg in inputs.children], - // SNARK_FRIENDLY_HASH_FUNCTION - // ); ParityPublicInputs { aggregation_object: AggregationObject {}, - sha_root: [0, 0], - converted_root: 0, + sha_root: sha_tree.get_root(), + converted_root: pedersen_tree.get_root(), } } } \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr new file mode 100644 index 000000000000..2d74cfe73d55 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr @@ -0,0 +1 @@ +mod sha256_merkle_tree; \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr new file mode 100644 index 000000000000..12f5e85e448d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr @@ -0,0 +1,51 @@ +use dep::types::{ + constants::NUM_FIELDS_PER_SHA256, + hash::accumulate_sha256, +}; + +// Note: Once we'll truncate sha256 to 1 Field we can nuke this and generalize the standard MerkleTree over different +// hash functions. +struct Sha256MerkleTree { + leaves: [[Field; NUM_FIELDS_PER_SHA256]; N], + nodes: [[Field; NUM_FIELDS_PER_SHA256]; N], +} + +impl Sha256MerkleTree { + pub fn new(leaves: [[Field; NUM_FIELDS_PER_SHA256]; N]) -> Self { + let mut nodes = [[0; NUM_FIELDS_PER_SHA256]; N]; + + // We need one less node than leaves, but we cannot have computed array lengths + let total_nodes = N - 1; + let half_size = N / 2; + + // hash base layer + for i in 0..half_size { + nodes[i] = accumulate_sha256( + [ + U128::from_integer(leaves[2*i][0]), + U128::from_integer(leaves[2*i][1]), + U128::from_integer(leaves[2*i+1][0]), + U128::from_integer(leaves[2*i+1][1]) + ] + ); + } + + // hash the other layers + for i in 0..(total_nodes - half_size) { + nodes[half_size+i] = accumulate_sha256( + [ + U128::from_integer(nodes[2*i][0]), + U128::from_integer(nodes[2*i][1]), + U128::from_integer(nodes[2*i+1][0]), + U128::from_integer(nodes[2*i+1][1]) + ] + ); + } + + Sha256MerkleTree { leaves, nodes } + } + + fn get_root(self) -> [Field; NUM_FIELDS_PER_SHA256] { + self.nodes[N - 2] + } +} \ No newline at end of file