diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index 7c5623cfd327..8beff1afb1d1 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -1,15 +1,53 @@ use dep::protocol_types::{ - address::AztecAddress, - constants::GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, - hash::{pedersen_hash, silo_nullifier}}; + address::{AztecAddress, EthAddress}, + constants::{GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, GENERATOR_INDEX__NULLIFIER}, + hash::{pedersen_hash, silo_nullifier} +}; -use dep::protocol_types::hash::{hash_args, hash_args_array}; +use dep::protocol_types::hash::{hash_args, hash_args_array, sha256_to_field}; pub fn compute_secret_hash(secret: Field) -> Field { // TODO(#1205) This is probably not the right index to use pedersen_hash([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET) } +pub fn compute_message_hash( + sender: EthAddress, + chain_id: Field, + recipient: AztecAddress, + version: Field, + content: Field, + secret_hash: Field +) -> Field { + let mut hash_bytes = [0 as u8; 192]; + let sender_bytes = sender.to_field().to_be_bytes(32); + let chain_id_bytes = chain_id.to_be_bytes(32); + let recipient_bytes = recipient.to_field().to_be_bytes(32); + let version_bytes = version.to_be_bytes(32); + let content_bytes = content.to_be_bytes(32); + let secret_hash_bytes = secret_hash.to_be_bytes(32); + + for i in 0..32 { + hash_bytes[i] = sender_bytes[i]; + hash_bytes[i + 32] = chain_id_bytes[i]; + hash_bytes[i + 64] = recipient_bytes[i]; + hash_bytes[i + 96] = version_bytes[i]; + hash_bytes[i + 128] = content_bytes[i]; + hash_bytes[i + 160] = secret_hash_bytes[i]; + } + + sha256_to_field(hash_bytes) +} + +// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash +// in the L1 to L2 message tree +pub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field { + pedersen_hash( + [message_hash, secret, leaf_index], + GENERATOR_INDEX__NULLIFIER + ) +} + pub fn compute_siloed_nullifier(address: AztecAddress, nullifier: Field) -> Field { silo_nullifier(address, nullifier) -} \ No newline at end of file +} diff --git a/noir-projects/aztec-nr/aztec/src/messaging.nr b/noir-projects/aztec-nr/aztec/src/messaging.nr index 6e3943677096..3f649e9e4bf7 100644 --- a/noir-projects/aztec-nr/aztec/src/messaging.nr +++ b/noir-projects/aztec-nr/aztec/src/messaging.nr @@ -1,9 +1,9 @@ -mod l1_to_l2_message; - -use crate::oracle::get_l1_to_l2_membership_witness::get_l1_to_l2_membership_witness; +use crate::{ + hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier}, + oracle::get_l1_to_l2_membership_witness::get_l1_to_l2_membership_witness +}; use dep::std::merkle::compute_merkle_root; -use crate::messaging::l1_to_l2_message::L1ToL2Message; use dep::protocol_types::{constants::L1_TO_L2_MSG_TREE_HEIGHT, address::{AztecAddress, EthAddress}, utils::arr_copy_slice}; pub fn process_l1_to_l2_message( @@ -15,15 +15,8 @@ pub fn process_l1_to_l2_message( content: Field, secret: Field ) -> Field { - let mut msg = L1ToL2Message::new( - portal_contract_address, - chain_id, - storage_contract_address, - version, - content, - secret - ); - let message_hash = msg.hash(); + let secret_hash = compute_secret_hash(secret); + let message_hash = compute_message_hash(portal_contract_address, chain_id, storage_contract_address, version, content, secret_hash); let returned_message = get_l1_to_l2_membership_witness(storage_contract_address, message_hash, secret); let leaf_index = returned_message[0]; @@ -34,12 +27,5 @@ pub fn process_l1_to_l2_message( let root = compute_merkle_root(message_hash, leaf_index, sibling_path); assert(root == l1_to_l2_root, "Message not in state"); - // Note: Had to add this line to make it work (wasted an hour debugging this). L1ToL2Message noir struct is - // an abomination and it would not have ever got to that state if people followed the logical rule of - // "deserialize(serialize(object)) == object" always being true (there are a few params which are not - // serialzied). Will refactor that in a separate PR. - // TODO(#5420) - msg.tree_index = leaf_index; - - msg.compute_nullifier() + compute_message_nullifier(message_hash, secret, leaf_index) } diff --git a/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr b/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr deleted file mode 100644 index 6fd9a65e60c5..000000000000 --- a/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr +++ /dev/null @@ -1,89 +0,0 @@ -use dep::protocol_types::{ - address::{AztecAddress, EthAddress}, - constants::{L1_TO_L2_MESSAGE_LENGTH, GENERATOR_INDEX__NULLIFIER, GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET}, - hash::{pedersen_hash, sha256_to_field} -}; - -struct L1ToL2Message { - sender: EthAddress, - chain_id: Field, - recipient: AztecAddress, - version: Field, - content: Field, - secret: Field, - secret_hash: Field, - tree_index: Field -} - -impl L1ToL2Message { - pub fn new( - sender: EthAddress, - chain_id: Field, - recipient: AztecAddress, - version: Field, - content: Field, - secret: Field - ) -> L1ToL2Message { - let secret_hash = pedersen_hash([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET); - Self { - sender, - chain_id, - recipient, - version, - content, - secret, - secret_hash, - tree_index: 0 - } - } - - pub fn deserialize( - fields: [Field; L1_TO_L2_MESSAGE_LENGTH], - secret: Field, // TODO(#5420): refactor this so that this param does not have to be passed separately - tree_index: Field // TODO(#5420): refactor this so that this param does not have to be passed separately - ) -> L1ToL2Message { - L1ToL2Message { - sender: EthAddress::from_field(fields[0]), - chain_id: fields[1], - recipient: AztecAddress::from_field(fields[2]), - version: fields[3], - content: fields[4], - secret, - secret_hash: fields[5], - tree_index - } - } - - fn hash(self: Self) -> Field { - let mut hash_bytes = [0 as u8; 192]; - let sender_bytes = self.sender.to_field().to_be_bytes(32); - let chain_id_bytes = self.chain_id.to_be_bytes(32); - let recipient_bytes = self.recipient.to_field().to_be_bytes(32); - let version_bytes = self.version.to_be_bytes(32); - let content_bytes = self.content.to_be_bytes(32); - let secret_hash_bytes = self.secret_hash.to_be_bytes(32); - - for i in 0..32 { - hash_bytes[i] = sender_bytes[i]; - hash_bytes[i + 32] = chain_id_bytes[i]; - hash_bytes[i + 64] = recipient_bytes[i]; - hash_bytes[i + 96] = version_bytes[i]; - hash_bytes[i + 128] = content_bytes[i]; - hash_bytes[i + 160] = secret_hash_bytes[i]; - } - - let message_hash = sha256_to_field(hash_bytes); - message_hash - } - - // The nullifier of a l1 to l2 message is the hash of the message salted with the secret and tree index - // docs:start:l1_to_l2_message_compute_nullifier - pub fn compute_nullifier(self: Self) -> Field { - let message_hash = self.hash(); - pedersen_hash( - [message_hash, self.secret, self.tree_index], - GENERATOR_INDEX__NULLIFIER - ) - } - // docs:end:l1_to_l2_message_compute_nullifier -}