diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index a6fb98c7c8c..5fb9064db73 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -182,15 +182,15 @@ library Constants { uint256 internal constant PUBLIC_DATA_READ_LENGTH = 2; uint256 internal constant VALIDATION_REQUESTS_LENGTH = 1090; uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; - uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 333; + uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 364; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 41; uint256 internal constant PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 15; uint256 internal constant CALL_REQUEST_LENGTH = 7; uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1160; uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2300; - uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 983; - uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3323; - uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 384; + uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 991; + uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3339; + uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 415; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 11; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 28; uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 9; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr index b89b318dc73..faafffcdf70 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr @@ -10,10 +10,7 @@ use dep::types::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL }, - hash::{ - silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, - silo_unencrypted_log_hash -}, + hash::{silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier}, traits::is_empty, transaction::tx_request::TxRequest, utils::arrays::{array_length, array_to_bounded_vec, sort_by_counters_asc, sort_by_counters_desc} }; @@ -293,7 +290,6 @@ impl PrivateKernelCircuitPublicInputsComposer { self.silo_nullifiers(); self.silo_l2_to_l1_messages(); self.silo_encrypted_logs(); - self.silo_unencrypted_logs(); } fn silo_note_hashes(&mut self) { @@ -333,11 +329,4 @@ impl PrivateKernelCircuitPublicInputsComposer { self.public_inputs.end.encrypted_logs_hashes.storage[i].log_hash.value = silo_encrypted_log_hash(logs[i]); } } - - fn silo_unencrypted_logs(&mut self) { - let logs = self.public_inputs.end.unencrypted_logs_hashes.storage; - for i in 0..logs.len() { - self.public_inputs.end.unencrypted_logs_hashes.storage[i].log_hash.value = silo_unencrypted_log_hash(logs[i]); - } - } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr index f20103b878a..50de33ebc3c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr @@ -41,7 +41,7 @@ impl TailOutputComposer { data.l2_to_l1_msgs = source.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content); data.note_encrypted_logs_hash = compute_tx_note_logs_hash(source.note_encrypted_logs_hashes.storage.map(|l: NoteLogHash| l.expose_to_public())); data.encrypted_logs_hash = compute_tx_logs_hash(source.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.expose_to_public())); - data.unencrypted_logs_hash = compute_tx_logs_hash(source.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.expose_to_public())); + data.unencrypted_logs_hashes = source.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.expose_to_public()); data.note_encrypted_log_preimages_length = source.note_encrypted_logs_hashes.storage.fold(0, |len, l: NoteLogHash| len + l.length); data.encrypted_log_preimages_length = source.encrypted_logs_hashes.storage.fold(0, |len, l: ScopedEncryptedLogHash| len + l.log_hash.length); data.unencrypted_log_preimages_length = source.unencrypted_logs_hashes.storage.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr index 81f3d225a47..135c7312a72 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr @@ -12,9 +12,10 @@ use dep::types::{ }, hash::{ compute_tx_logs_hash, compute_tx_note_logs_hash, silo_encrypted_log_hash, silo_l2_to_l1_message, - silo_note_hash, silo_nullifier, silo_unencrypted_log_hash + silo_note_hash, silo_nullifier }, - traits::is_empty, utils::arrays::assert_sorted_transformed_value_array + traits::is_empty, + utils::arrays::{assert_sorted_transformed_value_array, assert_sorted_array_with_order_hints} }; struct TailOutputValidator { @@ -136,21 +137,16 @@ impl TailOutputValidator { assert_eq(hash, self.output.end.encrypted_logs_hash, "mismatch encrypted_logs_hash"); // unencrypted_log_hashes - validate_value_transformation( - self.previous_kernel.end.unencrypted_logs_hashes, - hints.siloed_unencrypted_log_hashes, - |slh: ScopedLogHash, lh: LogHash| (lh.value == silo_unencrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) - ); - assert_sorted_transformed_value_array( + assert_sorted_array_with_order_hints( self.previous_kernel.end.unencrypted_logs_hashes, - hints.siloed_unencrypted_log_hashes, - hints.sorted_siloed_unencrypted_log_hashes, + hints.sorted_unencrypted_log_hashes, hints.sorted_unencrypted_log_hash_hints ); - let hash = compute_tx_logs_hash(hints.sorted_siloed_unencrypted_log_hashes); - assert_eq(hash, self.output.end.unencrypted_logs_hash, "mismatch unencrypted_logs_hash"); + assert_eq( + hints.sorted_unencrypted_log_hashes.map(|log: ScopedLogHash| log.expose_to_public()), self.output.end.unencrypted_logs_hashes, "mismatch unencrypted_logs_hashes" + ); } fn validate_gas_limits(self) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr index 8309ae39aa1..7dd95e99431 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr @@ -7,10 +7,7 @@ use dep::types::{ MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - hash::{ - silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, - silo_unencrypted_log_hash -}, + hash::{silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier}, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Empty, is_empty}, utils::arrays::{OrderHint, sort_by_counters_asc, sort_get_order_hints_asc} }; @@ -34,8 +31,7 @@ struct Hints { sorted_siloed_encrypted_log_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hash_hints: [OrderHint; MAX_ENCRYPTED_LOGS_PER_TX], // Unencrypted log hashes. - siloed_unencrypted_log_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_siloed_unencrypted_log_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_log_hash_hints: [OrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], } @@ -83,12 +79,7 @@ unconstrained pub fn generate_kernel_circuit_output_hints(previous_kernel: Priva let sorted_encrypted_log_hash_hints = sort_get_order_hints_asc(previous_kernel.end.encrypted_logs_hashes); // unencrypted_logs - let mut siloed_log_hashes = previous_kernel.end.unencrypted_logs_hashes; - for i in 0..siloed_log_hashes.len() { - siloed_log_hashes[i].log_hash.value = silo_unencrypted_log_hash(previous_kernel.end.unencrypted_logs_hashes[i]); - } - let sorted_siloed_unencrypted_log_hashes = sort_by_counters_asc(siloed_log_hashes).map(|h: ScopedLogHash| h.inner()); - let siloed_unencrypted_log_hashes = siloed_log_hashes.map(|h: ScopedLogHash| h.inner()); + let sorted_unencrypted_log_hashes = sort_by_counters_asc(previous_kernel.end.unencrypted_logs_hashes); let sorted_unencrypted_log_hash_hints = sort_get_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes); Hints { @@ -104,8 +95,7 @@ unconstrained pub fn generate_kernel_circuit_output_hints(previous_kernel: Priva sorted_note_encrypted_log_hash_hints, siloed_encrypted_log_hashes, sorted_encrypted_log_hash_hints, - siloed_unencrypted_log_hashes, - sorted_siloed_unencrypted_log_hashes, + sorted_unencrypted_log_hashes, sorted_unencrypted_log_hash_hints } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr index eb3a21da7ec..6c85ef2e5c9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr @@ -1,7 +1,7 @@ use dep::types::{ abis::{ accumulated_data::{public_accumulated_data_builder::PublicAccumulatedDataBuilder}, gas::Gas, - log_hash::LogHash + log_hash::{LogHash, ScopedLogHash} }, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, L2_GAS_PER_NOTE_HASH, @@ -29,7 +29,7 @@ fn meter_gas_used(data: PublicAccumulatedDataBuilder) -> Gas { metered_da_bytes += encrypted_log_preimages_length as u32; metered_l2_gas += encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - let unencrypted_log_preimages_length = data.unencrypted_logs_hashes.storage.fold(0, |len, l: LogHash| len + l.length); + let unencrypted_log_preimages_length = data.unencrypted_logs_hashes.storage.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); metered_da_bytes += unencrypted_log_preimages_length as u32; metered_l2_gas += unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr index 5566b3af809..dcbf1722b4f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr @@ -10,10 +10,7 @@ use dep::types::{ kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, nullifier::Nullifier }, - hash::{ - silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, - silo_unencrypted_log_hash -}, + hash::{silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier}, traits::{Empty, is_empty_array}, utils::arrays::{assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc} }; @@ -151,15 +148,10 @@ impl TailToPublicOutputValidator { ); // unencrypted_logs_hashes - validate_value_transformation( - prev_data.unencrypted_logs_hashes, - hints.siloed_unencrypted_logs_hashes, - |slh: ScopedLogHash, lh: LogHash| (lh.value == silo_unencrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) & (lh.counter == 0) - ); assert_split_sorted_transformed_value_arrays_asc( prev_data.unencrypted_logs_hashes, - hints.siloed_unencrypted_logs_hashes, + prev_data.unencrypted_logs_hashes, split_counter, output_non_revertible.unencrypted_logs_hashes, output_revertible.unencrypted_logs_hashes, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr index 12643aa6b50..1602dc9f43e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr @@ -8,10 +8,7 @@ use dep::types::{ MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - hash::{ - silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, - silo_unencrypted_log_hash -}, + hash::{silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier}, messaging::l2_to_l1_message::ScopedL2ToL1Message, utils::arrays::{sort_get_split_order_hints_asc, sort_get_split_order_hints_desc, SplitOrderHints} }; @@ -33,7 +30,6 @@ struct TailToPublicOutputHints { siloed_encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hash_hints: SplitOrderHints, // Unencrypted log hashes. - siloed_unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_log_hash_hints: SplitOrderHints, // Public call requests. public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], @@ -91,11 +87,6 @@ unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: Priva let sorted_encrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.encrypted_logs_hashes, split_counter); // unencrypted_logs - let mut siloed_log_hashes = previous_kernel.end.unencrypted_logs_hashes; - for i in 0..siloed_log_hashes.len() { - siloed_log_hashes[i].log_hash.value = silo_unencrypted_log_hash(previous_kernel.end.unencrypted_logs_hashes[i]); - } - let siloed_unencrypted_logs_hashes = siloed_log_hashes.map(|h: ScopedLogHash| h.inner()); let sorted_unencrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes, split_counter); // public_call_requests @@ -115,7 +106,6 @@ unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: Priva sorted_note_encrypted_log_hash_hints, siloed_encrypted_logs_hashes, sorted_encrypted_log_hash_hints, - siloed_unencrypted_logs_hashes, sorted_unencrypted_log_hash_hints, public_call_requests, sorted_public_call_request_hints diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 20433ada5cf..f455f500d56 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -60,13 +60,11 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, max_block_number::MaxBlockNumber, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, gas::Gas + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, gas::Gas, + log_hash::ScopedLogHash }, address::{AztecAddress, EthAddress}, scalar::Scalar, - hash::{ - sha256_to_field, silo_note_hash, silo_nullifier, compute_siloed_encrypted_log_hash, - compute_siloed_unencrypted_log_hash - }, + hash::{sha256_to_field, silo_note_hash, silo_nullifier, compute_siloed_encrypted_log_hash}, tests::fixture_builder::FixtureBuilder, utils::{arrays::array_length}, traits::{Empty, is_empty}, point::Point }; @@ -176,23 +174,9 @@ mod tests { let expected_encrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - let siloed_unencrypted_logs_hashes = [ - compute_siloed_unencrypted_log_hash( - builder.previous_kernel.storage_contract_address, - prev_unencrypted_logs_hash - ), compute_siloed_unencrypted_log_hash( - builder.previous_kernel.storage_contract_address, - unencrypted_logs_hash - ) - ]; - // noir-fmt:ignore - let hash_bytes: [u8; MAX_UNENCRYPTED_LOGS_PER_TX * 32] = siloed_unencrypted_logs_hashes[0] - .to_be_bytes(32) - .append(siloed_unencrypted_logs_hashes[1].to_be_bytes(32)) - .append(&[0; MAX_UNENCRYPTED_LOGS_PER_TX * 32 - 64]) - .as_array(); - let expected_unencrypted_logs_hash = sha256_to_field(hash_bytes); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq( + public_inputs.end.unencrypted_logs_hashes, builder.previous_kernel.unencrypted_logs_hashes.storage.map(|log: ScopedLogHash| log.expose_to_public()) + ); } unconstrained fn compute_hash_bytes( diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr index cb2dedc44ab..46109355c55 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr @@ -113,15 +113,14 @@ fn validate_accumulated_values_unencrypted_log_hashes_unordered_succeeds() { builder.validate(); } -#[test(should_fail_with="mismatch unencrypted_logs_hash")] -fn validate_accumulated_values_unencrypted_log_hashes_wrong_hash_fails() { +#[test(should_fail_with="mismatch unencrypted_logs_hashes")] +fn validate_accumulated_values_unencrypted_log_hashes_wrong_order_fails() { let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_unencrypted_log_hashes(3); builder.output.append_unencrypted_log_hashes(3); - // Swap the items in the output, making them out of order, and then hash. + // Swap the items in the output, making them out of order swap_items(&mut builder.output.unencrypted_logs_hashes, 0, 2); - builder.output.hash_unencrypted_log_hashes(); builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr index ddbc2e36998..7aff5323355 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr @@ -32,7 +32,6 @@ fn tail_to_public_output_composer_succeeds() { siloed_data_builder.add_siloed_encrypted_log_hash(2001, 2); builder.previous_kernel.add_unencrypted_log_hash(3001, 51); - siloed_data_builder.add_siloed_unencrypted_log_hash(3001, 51); builder.previous_kernel.append_public_call_requests(2); @@ -56,7 +55,6 @@ fn tail_to_public_output_composer_succeeds() { siloed_data_builder.add_siloed_encrypted_log_hash(2003, 24); builder.previous_kernel.add_unencrypted_log_hash(3002, 4); - siloed_data_builder.add_siloed_unencrypted_log_hash(3002, 4); builder.previous_kernel.append_public_call_requests(3); @@ -112,12 +110,12 @@ fn tail_to_public_output_composer_succeeds() { assert_array_eq(output.end.encrypted_logs_hashes, [siloed[1], siloed[2]]); // unencrypted_logs_hashes - let siloed = siloed_data.unencrypted_logs_hashes; + let unsiloed = unsiloed_data.unencrypted_logs_hashes; assert_array_eq( output.end_non_revertible.unencrypted_logs_hashes, - [siloed[0]] + [unsiloed[0]] ); - assert_array_eq(output.end.unencrypted_logs_hashes, [siloed[1]]); + assert_array_eq(output.end.unencrypted_logs_hashes, [unsiloed[1]]); // public_call_stack let unsiloed = unsiloed_data.public_call_stack; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index a5fe9348609..a485380deb3 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -4,7 +4,7 @@ use dep::types::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputsBuilder, public_kernel_data::PublicKernelData, note_hash::NoteHash, nullifier::Nullifier, public_call_data::PublicCallData, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, log_hash::LogHash, + public_data_update_request::PublicDataUpdateRequest, log_hash::{ScopedLogHash, LogHash}, global_variables::GlobalVariables, combined_constant_data::CombinedConstantData }, address::AztecAddress, @@ -15,10 +15,7 @@ use dep::types::{ MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, - hash::{ - compute_siloed_note_hash, compute_siloed_nullifier, compute_l2_to_l1_hash, - compute_siloed_unencrypted_log_hash -}, + hash::{compute_siloed_note_hash, compute_siloed_nullifier, compute_l2_to_l1_hash}, utils::{arrays::{array_length, array_to_bounded_vec}}, traits::{is_empty, is_empty_array} }; @@ -514,12 +511,11 @@ pub fn propagate_new_unencrypted_logs(public_call: PublicCallData, public_inputs // new unencrypted logs let new_logs = public_call.call_stack_item.public_inputs.unencrypted_logs_hashes; let storage_contract_address = public_call.call_stack_item.public_inputs.call_context.storage_contract_address; - let mut new_logs_to_insert : BoundedVec = BoundedVec::new(); + let mut new_logs_to_insert : BoundedVec = BoundedVec::new(); for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL { let new_log = new_logs[i]; if new_log.value != 0 { - let siloed_new_log = compute_siloed_unencrypted_log_hash(storage_contract_address, new_log.value); - new_logs_to_insert.push(LogHash { value: siloed_new_log, counter: new_log.counter, length: new_log.length }); + new_logs_to_insert.push(ScopedLogHash { log_hash: new_log, contract_address: storage_contract_address }); } } public_inputs.end.unencrypted_logs_hashes.extend_from_bounded_vec(new_logs_to_insert); @@ -532,12 +528,11 @@ pub fn propagate_new_unencrypted_logs_non_revertible( // new unencrypted logs let new_logs = public_call.call_stack_item.public_inputs.unencrypted_logs_hashes; let storage_contract_address = public_call.call_stack_item.public_inputs.call_context.storage_contract_address; - let mut new_logs_to_insert : BoundedVec = BoundedVec::new(); + let mut new_logs_to_insert : BoundedVec = BoundedVec::new(); for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL { let new_log = new_logs[i]; if new_log.value != 0 { - let siloed_new_log = compute_siloed_unencrypted_log_hash(storage_contract_address, new_log.value); - new_logs_to_insert.push(LogHash { value: siloed_new_log, counter: new_log.counter, length: new_log.length }); + new_logs_to_insert.push(ScopedLogHash { log_hash: new_log, contract_address: storage_contract_address }); } } public_inputs.end_non_revertible.unencrypted_logs_hashes.extend_from_bounded_vec(new_logs_to_insert); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index 160e7c8e706..7c046d0cc15 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -110,15 +110,12 @@ mod tests { use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, - public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - read_request::ReadRequest + note_hash::{NoteHash, ScopedNoteHash}, log_hash::ScopedLogHash, + nullifier::{Nullifier, ScopedNullifier}, public_data_read::PublicDataRead, + public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - hash::{ - compute_l2_to_l1_hash, compute_siloed_note_hash, compute_siloed_nullifier, - compute_siloed_unencrypted_log_hash - }, + hash::{compute_l2_to_l1_hash, compute_siloed_note_hash, compute_siloed_nullifier}, messaging::l2_to_l1_message::L2ToL1Message, tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, utils::arrays::{array_eq, array_length}, traits::is_empty @@ -361,11 +358,12 @@ mod tests { ); let prev_data = builder.previous_kernel.to_public_accumulated_data(); - let mut expected_unencrypted_logs = [ - prev_data.unencrypted_logs_hashes[0], builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] + let expected_unencrypted_logs = [ + prev_data.unencrypted_logs_hashes[0], ScopedLogHash { + log_hash: builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0], + contract_address: builder.public_call.contract_address + } ]; - // silo the new log hash - expected_unencrypted_logs[1].value = compute_siloed_unencrypted_log_hash(builder.public_call.contract_address, expected_unencrypted_logs[1].value); // we assume the encrypted log is already siloed from private kernels let expected_encrypted_logs = [prev_data.encrypted_logs_hashes[0]]; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index bb7f785607e..ea8542f56e3 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -96,10 +96,10 @@ mod tests { call_request::CallRequest, function_selector::FunctionSelector, gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - public_call_data::PublicCallData, read_request::ReadRequest + public_call_data::PublicCallData, read_request::ReadRequest, log_hash::ScopedLogHash }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - contrakt::storage_read::StorageRead, hash::compute_siloed_unencrypted_log_hash, + contrakt::storage_read::StorageRead, tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, utils::{arrays::{array_eq, array_length}}, traits::is_empty }; @@ -460,11 +460,12 @@ mod tests { ); let prev_data = builder.previous_kernel.to_public_accumulated_data(); - let mut expected_unencrypted_logs = [ - prev_data.unencrypted_logs_hashes[0], builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] + let expected_unencrypted_logs = [ + prev_data.unencrypted_logs_hashes[0], ScopedLogHash { + log_hash: builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0], + contract_address: builder.public_call.contract_address + } ]; - // silo the new log hash - expected_unencrypted_logs[1].value = compute_siloed_unencrypted_log_hash(builder.public_call.contract_address, expected_unencrypted_logs[1].value); // we assume the encrypted log is already siloed from private kernels let expected_encrypted_logs = [prev_data.encrypted_logs_hashes[0]]; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 30e065b3041..82bb1f68e23 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -115,7 +115,8 @@ mod tests { kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage, accumulated_data::{CombinedAccumulatedData, CombineHints}, - public_data_update_request::PublicDataUpdateRequest, note_hash::NoteHash, log_hash::LogHash + public_data_update_request::PublicDataUpdateRequest, note_hash::NoteHash, + log_hash::{ScopedLogHash, LogHash} }, address::AztecAddress, constants::{ @@ -326,7 +327,10 @@ mod tests { previous_kernel.public_inputs.end_non_revertible.unencrypted_logs_hashes, previous_kernel.public_inputs.end.unencrypted_logs_hashes ); - let sorted = sort_get_sorted_hints(merged, |a: LogHash, b: LogHash| a.counter() < b.counter()); + let sorted = sort_get_sorted_hints( + merged, + |a: ScopedLogHash, b: ScopedLogHash| a.counter() < b.counter() + ); let sorted_unencrypted_logs_hashes = sorted.sorted_array; let sorted_unencrypted_logs_hashes_indexes = sorted.sorted_index_hints; @@ -414,9 +418,9 @@ mod tests { let expected_encrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - let hash_bytes: [u8; MAX_UNENCRYPTED_LOGS_PER_TX * 32] = prev_unencrypted_logs_hash.to_be_bytes(32).append(unencrypted_logs_hash.to_be_bytes(32)).append(&[0; MAX_UNENCRYPTED_LOGS_PER_TX * 32 - 64]).as_array(); - let expected_unencrypted_logs_hash = sha256_to_field(hash_bytes); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq( + public_inputs.end.unencrypted_logs_hashes, builder.previous_revertible.unencrypted_logs_hashes.storage + ); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index b92619c190d..ac095b4b3cb 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -166,10 +166,10 @@ mod tests { abis::{ call_request::CallRequest, function_selector::FunctionSelector, gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest + public_data_update_request::PublicDataUpdateRequest, log_hash::ScopedLogHash }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - contrakt::storage_read::StorageRead, hash::compute_siloed_unencrypted_log_hash, + contrakt::storage_read::StorageRead, tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, utils::{arrays::{array_eq, array_length}}, traits::is_empty }; @@ -449,11 +449,12 @@ mod tests { ); let prev_data = builder.previous_kernel.to_public_accumulated_data(); - let mut expected_unencrypted_logs = [ - prev_data.unencrypted_logs_hashes[0], builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] + let expected_unencrypted_logs = [ + prev_data.unencrypted_logs_hashes[0], ScopedLogHash { + log_hash: builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0], + contract_address: builder.public_call.contract_address + } ]; - // silo the new log hash - expected_unencrypted_logs[1].value = compute_siloed_unencrypted_log_hash(builder.public_call.contract_address, expected_unencrypted_logs[1].value); // we assume the encrypted log is already siloed from private kernels let expected_encrypted_logs = [prev_data.encrypted_logs_hashes[0]]; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index 2d817320c42..c6a2aa17d49 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -1,16 +1,17 @@ use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; use crate::abis::previous_rollup_data::PreviousRollupData; use dep::types::{ - hash::accumulate_sha256, merkle_tree::VariableMerkleTree, + hash::{accumulate_sha256, silo_unencrypted_log_hash, compute_tx_logs_hash}, + merkle_tree::VariableMerkleTree, constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, utils::{uint256::U256, arrays::array_length}, abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, accumulated_data::CombinedAccumulatedData, - public_data_update_request::PublicDataUpdateRequest + public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, ScopedLogHash} } }; @@ -111,6 +112,19 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) - ) } +fn scope_and_hash_unencrypted_logs(unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX]) -> Field { + let scoped_logs = unencrypted_logs_hashes.map( + |log: ScopedLogHash| { + LogHash { + value: silo_unencrypted_log_hash(log), + counter: log.log_hash.counter, + length: log.log_hash.length + } + } + ); + compute_tx_logs_hash(scoped_logs) +} + // Tx effects hash consists of // 1 field for revert code // 1 field for transaction fee @@ -149,7 +163,7 @@ pub fn compute_tx_effects_hash( let unencrypted_logs_length = combined.unencrypted_log_preimages_length; let note_encrypted_logs_hash = combined.note_encrypted_logs_hash; let encrypted_logs_hash = combined.encrypted_logs_hash; - let unencrypted_logs_hash = combined.unencrypted_logs_hash; + let unencrypted_logs_hash = scope_and_hash_unencrypted_logs(combined.unencrypted_logs_hashes); let mut offset = 0; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr index 9f0cbf36b2d..155b42f0360 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr @@ -3,7 +3,7 @@ use crate::{ abis::{ accumulated_data::public_accumulated_data::PublicAccumulatedData, note_hash::NoteHash, nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, - log_hash::{LogHash, NoteLogHash}, gas::Gas, side_effect::{Ordered, Positioned} + log_hash::{LogHash, NoteLogHash, ScopedLogHash}, gas::Gas, side_effect::{Ordered, Positioned} }, constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, @@ -17,7 +17,7 @@ use crate::{ struct CombineHints { sorted_note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u32; MAX_NOTE_HASHES_PER_TX], - sorted_unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_logs_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX], // the public data update requests are sorted by their leaf index AND counter sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], @@ -34,7 +34,7 @@ struct CombinedAccumulatedData { note_encrypted_logs_hash: Field, encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -107,21 +107,20 @@ impl CombinedAccumulatedData { combine_hints.sorted_unencrypted_logs_hashes_indexes, asc_sort_by_counters ); - let unencrypted_logs_hash = compute_tx_logs_hash(combine_hints.sorted_unencrypted_logs_hashes); let note_encrypted_log_preimages_length = non_revertible.note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) + revertible.note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length); let encrypted_log_preimages_length = non_revertible.encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) + revertible.encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length); - let unencrypted_log_preimages_length = non_revertible.unencrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) - + revertible.unencrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length); + let unencrypted_log_preimages_length = non_revertible.unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length) + + revertible.unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length); CombinedAccumulatedData { note_hashes: combine_hints.sorted_note_hashes.map(|n: NoteHash| n.value), nullifiers: array_merge(non_revertible.nullifiers, revertible.nullifiers).map(|n: Nullifier| n.value), l2_to_l1_msgs: array_merge(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs), note_encrypted_logs_hash, encrypted_logs_hash, - unencrypted_logs_hash, + unencrypted_logs_hashes: combine_hints.sorted_unencrypted_logs_hashes, note_encrypted_log_preimages_length, encrypted_log_preimages_length, unencrypted_log_preimages_length, @@ -139,7 +138,7 @@ impl Empty for CombinedAccumulatedData { l2_to_l1_msgs: [0; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hash: 0, encrypted_logs_hash: 0, - unencrypted_logs_hash: 0, + unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], note_encrypted_log_preimages_length: 0, encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, @@ -158,7 +157,9 @@ impl Serialize for CombinedAccumulatedData { fields.extend_from_array(self.l2_to_l1_msgs); fields.push(self.note_encrypted_logs_hash); fields.push(self.encrypted_logs_hash); - fields.push(self.unencrypted_logs_hash); + for i in 0..self.unencrypted_logs_hashes.len() { + fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + } fields.push(self.note_encrypted_log_preimages_length); fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); @@ -185,7 +186,7 @@ impl Deserialize for CombinedAccumulatedData { l2_to_l1_msgs: reader.read_array([0; MAX_L2_TO_L1_MSGS_PER_TX]), note_encrypted_logs_hash: reader.read(), encrypted_logs_hash: reader.read(), - unencrypted_logs_hash: reader.read(), + unencrypted_logs_hashes: reader.read_struct_array(ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), note_encrypted_log_preimages_length: reader.read(), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), @@ -204,7 +205,7 @@ impl Eq for CombinedAccumulatedData { (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hash == other.note_encrypted_logs_hash) & (self.encrypted_logs_hash == other.encrypted_logs_hash) & - (self.unencrypted_logs_hash == other.unencrypted_logs_hash) & + (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & (self.note_encrypted_log_preimages_length == other.note_encrypted_log_preimages_length) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & (self.unencrypted_log_preimages_length == other.unencrypted_log_preimages_length) & diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr index ae6392b2386..63c0217705e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ call_request::CallRequest, public_data_update_request::PublicDataUpdateRequest, gas::Gas, - note_hash::NoteHash, nullifier::Nullifier, log_hash::{LogHash, NoteLogHash} + note_hash::NoteHash, nullifier::Nullifier, log_hash::{LogHash, ScopedLogHash, NoteLogHash} }, constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -18,7 +18,7 @@ struct PublicAccumulatedData { note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], @@ -35,7 +35,7 @@ impl Empty for PublicAccumulatedData { l2_to_l1_msgs: [0; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], public_call_stack: [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], gas_used: Gas::empty(), @@ -95,7 +95,7 @@ impl Deserialize for PublicAccumulatedData { l2_to_l1_msgs: reader.read_array([0; MAX_L2_TO_L1_MSGS_PER_TX]), note_encrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX]), encrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), - unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), + unencrypted_logs_hashes: reader.read_struct_array(ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), public_data_update_requests: reader.read_struct_array(PublicDataUpdateRequest::deserialize, [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]), public_call_stack: reader.read_struct_array(CallRequest::deserialize, [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), gas_used: reader.read_struct(Gas::deserialize), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr index 7d8237922d4..d7864bd945d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ gas::Gas, accumulated_data::public_accumulated_data::PublicAccumulatedData, call_request::CallRequest, note_hash::NoteHash, nullifier::Nullifier, - public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash} + public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash, ScopedLogHash} }, constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -19,7 +19,7 @@ struct PublicAccumulatedDataBuilder { note_encrypted_logs_hashes: BoundedVec, encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, public_data_update_requests: BoundedVec, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr index 6d5ad39702f..f5983f4dbde 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr @@ -132,10 +132,12 @@ impl Deserialize for ScopedLogHash { } impl ScopedLogHash { - pub fn expose_to_public(self) -> LogHash { + pub fn expose_to_public(self) -> Self { // Hide the counter when exposing to public. - // The log hash must already be siloed when we call this. - LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length } + Self { + log_hash: LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }, + contract_address: self.contract_address + } } } 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 e63fc49bd8f..73f7dc39ae9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -238,7 +238,7 @@ global PUBLIC_DATA_READ_LENGTH = 2; global VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; -global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + 6 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; +global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + 5 + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; global COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH + 1; global PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH + 3 + 2 * GAS_LENGTH; @@ -246,7 +246,7 @@ global CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + (SCOPED_PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; -global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + GAS_LENGTH; +global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + GAS_LENGTH; global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + 1 + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + AZTEC_ADDRESS_LENGTH; global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + COMBINED_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 1 + AZTEC_ADDRESS_LENGTH; 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 de1d41b7fd1..947d5e03ce4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -113,7 +113,7 @@ pub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field { } } -pub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field { +fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field { accumulate_sha256([address.to_field(), log_hash]) } 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 13f3a1850f9..880977717c5 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 @@ -336,10 +336,6 @@ impl FixtureBuilder { storage: self.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.log_hash).map(|l: EncryptedLogHash| LogHash { value: l.value, counter: l.counter, length: l.length }), len: self.encrypted_logs_hashes.len() }; - let unencrypted_logs_hashes = BoundedVec { - storage: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.log_hash), - len: self.unencrypted_logs_hashes.len() - }; PublicAccumulatedDataBuilder { note_hashes, @@ -347,7 +343,7 @@ impl FixtureBuilder { l2_to_l1_msgs, note_encrypted_logs_hashes, encrypted_logs_hashes, - unencrypted_logs_hashes, + unencrypted_logs_hashes: self.unencrypted_logs_hashes, public_data_update_requests: self.public_data_update_requests, public_call_stack: self.public_call_requests, gas_used: self.gas_used @@ -381,7 +377,7 @@ impl FixtureBuilder { l2_to_l1_msgs: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), note_encrypted_logs_hash: self.note_encrypted_logs_hash, encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.expose_to_public()), note_encrypted_log_preimages_length: self.note_encrypted_log_preimages_length, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, @@ -758,13 +754,6 @@ impl FixtureBuilder { self.unencrypted_log_preimages_length += length; } - pub fn add_siloed_unencrypted_log_hash(&mut self, hash: Field, length: Field) { - let mut log_hash = LogHash { value: hash, counter: self.next_counter(), length }.scope(self.storage_contract_address); - log_hash.log_hash.value = silo_unencrypted_log_hash(log_hash); - self.unencrypted_logs_hashes.push(log_hash); - self.unencrypted_log_preimages_length += length; - } - pub fn append_unencrypted_log_hashes(&mut self, num: u32) { let index_offset = self.unencrypted_logs_hashes.len(); for i in 0..self.unencrypted_logs_hashes.max_len() { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index e3f5439b22c..d306726a26f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -8,7 +8,7 @@ mod sort_get_sorted_tuple; mod sort_get_split_order_hints; // Re-exports. -use assert_sorted_array::assert_sorted_array; +use assert_sorted_array::{assert_sorted_array_with_order_hints, assert_sorted_array}; use assert_split_sorted_transformed_value_arrays::{assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc}; use assert_sorted_transformed_value_array::assert_sorted_transformed_value_array; use sort_by_counters::{sort_by_counters_asc, sort_by_counters_desc}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_array.nr index 99852a832cb..4a1edc2598a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_array.nr @@ -1,4 +1,4 @@ -use crate::{abis::side_effect::Ordered, traits::{Empty, is_empty}}; +use crate::{abis::side_effect::Ordered, traits::{Empty, is_empty}, utils::arrays::sort_get_order_hints::OrderHint}; pub fn assert_sorted_array( original_array: [T; N], @@ -24,66 +24,238 @@ pub fn assert_sorted_array( } } -#[test] -fn assert_sorted_array_custom_asc_success() { - let original = [30, 20, 90, 50, 0, 0]; - let sorted = [20, 30, 50, 90, 0, 0]; - let indexes = [1, 0, 3, 2, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +// original_array must be valid, i.e. validate_array(original_array) == true +pub fn assert_sorted_array_with_order_hints( + original_array: [T; N], + sorted_array: [T; N], + hints: [OrderHint; N] +) where T: Ordered + Empty + Eq { + for i in 0..N { + let original_value = original_array[i]; + if is_empty(original_value) { + assert(is_empty(sorted_array[i]), "Empty values must not be mixed with sorted values"); + } else { + let hint = hints[i]; + assert_eq(sorted_array[hint.sorted_index], original_value, "Mismatch sorted values"); + if i != 0 { + assert( + sorted_array[i].counter() > sorted_array[i - 1].counter(), "Array must be sorted by counter in ascending order" + ); + } + } + } } -#[test] -fn assert_sorted_array_custom_desc_success() { - let original = [30, 20, 90, 50, 0, 0]; - let sorted = [90, 50, 30, 20, 0, 0]; - let indexes = [2, 3, 0, 1, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| b.lt(a)); -} +mod tests { + use crate::{ + abis::side_effect::Ordered, traits::Empty, + utils::arrays::{ + assert_sorted_array::{assert_sorted_array, assert_sorted_array_with_order_hints}, + sort_get_order_hints::OrderHint + } + }; -#[test] -fn assert_sorted_array_custom_all_empty_success() { - let original = [0, 0, 0, 0, 0, 0]; - let sorted = [0, 0, 0, 0, 0, 0]; - let indexes = [0, 0, 0, 0, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); -} + #[test] + fn assert_sorted_array_custom_asc_success() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 50, 90, 0, 0]; + let indexes = [1, 0, 3, 2, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } -#[test(should_fail_with="Values not sorted")] -fn assert_sorted_array_custom_wrong_ordering_fails() { - let original = [30, 20, 90, 50, 0, 0]; - let sorted = [20, 30, 90, 50, 0, 0]; - let indexes = [1, 0, 2, 3, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); -} + #[test] + fn assert_sorted_array_custom_desc_success() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [90, 50, 30, 20, 0, 0]; + let indexes = [2, 3, 0, 1, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| b.lt(a)); + } -#[test(should_fail_with="Values not sorted")] -fn assert_sorted_array_custom_misplaced_sorted_fails() { - let original = [30, 20, 90, 50, 0, 0]; - let sorted = [20, 30, 50, 0, 0, 90]; - let indexes = [1, 0, 5, 2, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); -} + #[test] + fn assert_sorted_array_custom_all_empty_success() { + let original = [0, 0, 0, 0, 0, 0]; + let sorted = [0, 0, 0, 0, 0, 0]; + let indexes = [0, 0, 0, 0, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } -#[test(should_fail_with="Invalid index")] -fn assert_sorted_array_custom_wrong_index_fails() { - let original = [30, 20, 90, 50, 0, 0]; - let sorted = [20, 30, 50, 90, 0, 0]; - let indexes = [1, 1, 2, 3, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); -} + #[test(should_fail_with="Values not sorted")] + fn assert_sorted_array_custom_wrong_ordering_fails() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 90, 50, 0, 0]; + let indexes = [1, 0, 2, 3, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } -#[test(should_fail_with="Empty values must be padded to the right")] -fn assert_sorted_array_custom_not_padded_fails() { - let original = [30, 20, 90, 0, 50, 0]; - let sorted = [20, 30, 90, 0, 0, 0]; - let indexes = [1, 0, 2, 0, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); -} + #[test(should_fail_with="Values not sorted")] + fn assert_sorted_array_custom_misplaced_sorted_fails() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 50, 0, 0, 90]; + let indexes = [1, 0, 5, 2, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } + + #[test(should_fail_with="Invalid index")] + fn assert_sorted_array_custom_wrong_index_fails() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 50, 90, 0, 0]; + let indexes = [1, 1, 2, 3, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } + + #[test(should_fail_with="Empty values must be padded to the right")] + fn assert_sorted_array_custom_not_padded_fails() { + let original = [30, 20, 90, 0, 50, 0]; + let sorted = [20, 30, 90, 0, 0, 0]; + let indexes = [1, 0, 2, 0, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } + + #[test(should_fail_with="Empty values must not be mixed with sorted values")] + fn assert_sorted_array_custom_mixed_empty_fails() { + let original = [30, 20, 90, 0, 0, 0]; + let sorted = [20, 30, 90, 0, 0, 10]; + let indexes = [1, 0, 2, 0, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + } + + struct TestItem { + name: Field, + price: Field, + tax: Field, + counter: u32, + } + + impl Ordered for TestItem { + fn counter(self) -> u32 { + self.counter + } + } + + impl Empty for TestItem { + fn empty() -> Self { + TestItem { name: 0, price: 0, tax: 0, counter: 0 } + } + } -#[test(should_fail_with="Empty values must not be mixed with sorted values")] -fn assert_sorted_array_custom_mixed_empty_fails() { - let original = [30, 20, 90, 0, 0, 0]; - let sorted = [20, 30, 90, 0, 0, 10]; - let indexes = [1, 0, 2, 0, 0, 0]; - assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); + impl Eq for TestItem { + fn eq(self, other: Self) -> bool { + (self.name == other.name) & (self.price == other.price) & (self.tax == other.tax) & (self.counter == other.counter) + } + } + + struct TestDataBuilder { + original_array: [T; N], + sorted_array: [T; N], + hints: [OrderHint; N], + } + + impl TestDataBuilder { + pub fn new() -> Self { + let original_array = [ + TestItem { name: 100, price: 10, tax: 5, counter: 44 }, + TestItem { name: 200, price: 20, tax: 6, counter: 22 }, + TestItem { name: 300, price: 30, tax: 7, counter: 11 }, + TestItem { name: 400, price: 40, tax: 8, counter: 33 }, + TestItem::empty(), + TestItem::empty() + ]; + + let sorted_array = [ + TestItem { name: 300, price: 30, tax: 7, counter: 11 }, + TestItem { name: 200, price: 20, tax: 6, counter: 22 }, + TestItem { name: 400, price: 40, tax: 8, counter: 33 }, + TestItem { name: 100, price: 10, tax: 5, counter: 44 }, + TestItem::empty(), + TestItem::empty() + ]; + + let hints = [ + OrderHint { counter: 11, sorted_index: 3 }, + OrderHint { counter: 22, sorted_index: 1 }, + OrderHint { counter: 33, sorted_index: 0 }, + OrderHint { counter: 44, sorted_index: 2 }, + OrderHint { counter: 0, sorted_index: 0 }, + OrderHint { counter: 0, sorted_index: 0 } + ]; + + TestDataBuilder { original_array, sorted_array, hints } + } + + pub fn execute(self) { + assert_sorted_array_with_order_hints(self.original_array, self.sorted_array, self.hints); + } + } + + #[test] + fn assert_sorted_array_with_order_hints_succeeds() { + let builder = TestDataBuilder::new(); + builder.execute(); + } + + #[test(should_fail_with="Mismatch sorted values")] + fn assert_sorted_array_with_order_hints_mismatch_value_fails() { + let mut builder = TestDataBuilder::new(); + + // Tweak the value at index 1. + builder.sorted_array[1].price += 1; + + builder.execute(); + } + + #[test(should_fail_with="Mismatch sorted values")] + fn assert_sorted_array_with_order_hints_mismatch_counter_fails() { + let mut builder = TestDataBuilder::new(); + + // Tweak the counter at index 1. + builder.sorted_array[1].counter += 1; + + builder.execute(); + } + + #[test(should_fail_with="Array must be sorted by counter in ascending order")] + fn assert_sorted_array_with_order_hints_unordered_fails() { + let mut builder = TestDataBuilder::new(); + + // Swap the values at index 1 and 2. + let tmp = builder.sorted_array[1]; + builder.sorted_array[1] = builder.sorted_array[2]; + builder.sorted_array[2] = tmp; + + // Update counters in hints. + let tmp = builder.hints[1].counter; + builder.hints[1].counter = builder.hints[2].counter; + builder.hints[2].counter = tmp; + + // Update sorted indexes. + // Original: 44, 22, 11, 33 + // New: 11, 33, 22, 44 + builder.hints[0].sorted_index = 3; + builder.hints[1].sorted_index = 2; + builder.hints[2].sorted_index = 0; + builder.hints[3].sorted_index = 1; + + builder.execute(); + } + + #[test(should_fail_with="Empty values must not be mixed with sorted values")] + fn assert_sorted_array_with_order_hints_extra_non_empty_fails() { + let mut builder = TestDataBuilder::new(); + + // Add a random item. + builder.sorted_array[4] = TestItem { name: 500, price: 10, tax: 5, counter: 55 }; + + builder.execute(); + } + + #[test(should_fail_with="Mismatch sorted values")] + fn assert_sorted_array_with_order_hints_missing_item_fails() { + let mut builder = TestDataBuilder::new(); + + // Remove an item. + builder.sorted_array[3] = TestItem::empty(); + + builder.execute(); + } } + diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts index 90610fa5331..37687e45016 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -4,6 +4,7 @@ import { MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + type ScopedLogHash, } from '@aztec/circuits.js'; import { sha256Trunc } from '@aztec/foundation/crypto'; import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; @@ -120,6 +121,35 @@ export abstract class TxL2Logs): TxL2Logs { + for (const fnLogs of this.functionLogs) { + let include = false; + for (const log of fnLogs.logs) { + if ('contractAddress' in log === false) { + throw new Error("Can't run filterScoped in logs without contractAddress"); + } + if ( + scopedLogHashes.findIndex( + slh => slh.contractAddress.equals(log.contractAddress) && slh.value.equals(Fr.fromBuffer(log.hash())), + ) != -1 + ) { + include = true; + } + } + if (include) { + output.addFunctionLogs([fnLogs]); + } + } + return output; + } } export class UnencryptedTxL2Logs extends TxL2Logs { @@ -184,20 +214,29 @@ export class UnencryptedTxL2Logs extends TxL2Logs { */ public override hash(): Buffer { const unrolledLogs = this.unrollLogs(); - if (unrolledLogs.length == 0) { + return UnencryptedTxL2Logs.hashSiloedLogs(unrolledLogs.map(log => log.getSiloedHash())); + } + + /** + * Hashes siloed unencrypted logs as in the same way as the base rollup would. + * @param siloedLogHashes - The siloed log hashes + * @returns The hash of the logs. + */ + public static hashSiloedLogs(siloedLogHashes: Buffer[]): Buffer { + if (siloedLogHashes.length == 0) { return Buffer.alloc(32); } - let flattenedLogs = Buffer.alloc(0); - for (const logsFromSingleFunctionCall of unrolledLogs) { - flattenedLogs = Buffer.concat([flattenedLogs, logsFromSingleFunctionCall.getSiloedHash()]); + let allSiloedLogHashes = Buffer.alloc(0); + for (const siloedLogHash of siloedLogHashes) { + allSiloedLogHashes = Buffer.concat([allSiloedLogHashes, siloedLogHash]); } // pad the end of logs with 0s - for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX - unrolledLogs.length; i++) { - flattenedLogs = Buffer.concat([flattenedLogs, Buffer.alloc(32)]); + for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX - siloedLogHashes.length; i++) { + allSiloedLogHashes = Buffer.concat([allSiloedLogHashes, Buffer.alloc(32)]); } - return sha256Trunc(flattenedLogs); + return sha256Trunc(allSiloedLogHashes); } } diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 5059012ffb5..f14f28d93b4 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -6,11 +6,13 @@ import { LogHash, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, Nullifier, PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PublicAccumulatedDataBuilder, PublicCallRequest, + ScopedLogHash, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js'; @@ -136,11 +138,14 @@ export const mockTx = ( unencryptedLogs.functionLogs.forEach(functionLog => { functionLog.logs.forEach(log => { if (data.forPublic) { - const hash = new LogHash( - Fr.fromBuffer(log.getSiloedHash()), - i++, - // +4 for encoding the length of the buffer - new Fr(log.length + 4), + const hash = new ScopedLogHash( + new LogHash( + Fr.fromBuffer(log.hash()), + i++, + // +4 for encoding the length of the buffer + new Fr(log.length + 4), + ), + log.contractAddress, ); // make the first log non-revertible if (functionCount === 0) { @@ -157,7 +162,13 @@ export const mockTx = ( data.forRollup!.end.nullifiers[0] = firstNullifier.value; data.forRollup!.end.noteEncryptedLogsHash = Fr.fromBuffer(noteEncryptedLogs.hash()); data.forRollup!.end.encryptedLogsHash = Fr.fromBuffer(encryptedLogs.hash()); - data.forRollup!.end.unencryptedLogsHash = Fr.fromBuffer(unencryptedLogs.hash()); + data.forRollup!.end.unencryptedLogsHashes = makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty); + unencryptedLogs.unrollLogs().forEach((log, i) => { + data.forRollup!.end.unencryptedLogsHashes[i] = new ScopedLogHash( + new LogHash(Fr.fromBuffer(log.hash()), 0, new Fr(log.length)), + log.contractAddress, + ); + }); } const tx = new Tx( diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index 2f89ec1434b..97b2d6ee9cf 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -297,7 +297,11 @@ function validateProcessedTxLogs(tx: ProcessedTx): void { ); } const unencryptedLogs = tx.unencryptedLogs || UnencryptedTxL2Logs.empty(); - kernelHash = tx.data.end.unencryptedLogsHash; + kernelHash = Fr.fromBuffer( + UnencryptedTxL2Logs.hashSiloedLogs( + tx.data.end.unencryptedLogsHashes.filter(hash => !hash.isEmpty()).map(h => h.getSiloedHash()), + ), + ); referenceHash = Fr.fromBuffer(unencryptedLogs.hash()); if (!referenceHash.equals(kernelHash)) { throw new Error( diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 39e0184f659..2a27b793832 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -274,7 +274,7 @@ export class Tx { EncryptedTxL2Logs.empty(), ); - this.unencryptedLogs = this.unencryptedLogs.filter( + this.unencryptedLogs = this.unencryptedLogs.filterScoped( kernelOutput.endNonRevertibleData.unencryptedLogsHashes, UnencryptedTxL2Logs.empty(), ); diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index f3331eef127..de5d97ce61a 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -166,15 +166,15 @@ export const SCOPED_READ_REQUEST_LEN = 3; export const PUBLIC_DATA_READ_LENGTH = 2; export const VALIDATION_REQUESTS_LENGTH = 1090; export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; -export const COMBINED_ACCUMULATED_DATA_LENGTH = 333; +export const COMBINED_ACCUMULATED_DATA_LENGTH = 364; export const COMBINED_CONSTANT_DATA_LENGTH = 41; export const PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 15; export const CALL_REQUEST_LENGTH = 7; export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1160; export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2300; -export const PUBLIC_ACCUMULATED_DATA_LENGTH = 983; -export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3323; -export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 384; +export const PUBLIC_ACCUMULATED_DATA_LENGTH = 991; +export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3339; +export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 415; export const CONSTANT_ROLLUP_DATA_LENGTH = 11; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 28; export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 9; diff --git a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts index b999251e551..99ed439287a 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts @@ -17,7 +17,7 @@ import { sortByCounterGetSortedHints, sortByPositionThenCounterGetSortedHints, } from '../../utils/index.js'; -import { LogHash } from '../log_hash.js'; +import { ScopedLogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; import { type PublicAccumulatedData } from './public_accumulated_data.js'; @@ -26,7 +26,7 @@ export class CombineHints { constructor( public readonly sortedNoteHashes: Tuple, public readonly sortedNoteHashesIndexes: Tuple, - public readonly sortedUnencryptedLogsHashes: Tuple, + public readonly sortedUnencryptedLogsHashes: Tuple, public readonly sortedUnencryptedLogsHashesIndexes: Tuple, public readonly sortedPublicDataUpdateRequests: Tuple< PublicDataUpdateRequest, @@ -66,7 +66,7 @@ export class CombineHints { return new CombineHints( reader.readArray(MAX_NOTE_HASHES_PER_TX, NoteHash), reader.readNumbers(MAX_NOTE_HASHES_PER_TX), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readNumbers(MAX_UNENCRYPTED_LOGS_PER_TX), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts index 1adc6ae26c9..b079b815f05 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -10,8 +10,10 @@ import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { Gas } from '../gas.js'; +import { ScopedLogHash } from '../log_hash.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; /** @@ -45,7 +47,7 @@ export class CombinedAccumulatedData { * Accumulated unencrypted logs hash from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHash: Fr, + public unencryptedLogsHashes: Tuple, /** * Total accumulated length of the encrypted note log preimages emitted in all the previous kernel iterations */ @@ -74,7 +76,7 @@ export class CombinedAccumulatedData { arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + this.noteEncryptedLogsHash.size + this.encryptedLogsHash.size + - this.unencryptedLogsHash.size + + arraySerializedSizeOfNonEmpty(this.unencryptedLogsHashes) + this.noteEncryptedLogPreimagesLength.size + this.encryptedLogPreimagesLength.size + this.unencryptedLogPreimagesLength.size + @@ -90,7 +92,7 @@ export class CombinedAccumulatedData { fields.l2ToL1Msgs, fields.noteEncryptedLogsHash, fields.encryptedLogsHash, - fields.unencryptedLogsHash, + fields.unencryptedLogsHashes, fields.noteEncryptedLogPreimagesLength, fields.encryptedLogPreimagesLength, fields.unencryptedLogPreimagesLength, @@ -124,7 +126,7 @@ export class CombinedAccumulatedData { reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, Fr), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - Fr.fromBuffer(reader), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), @@ -149,7 +151,7 @@ export class CombinedAccumulatedData { makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.zero), Fr.zero(), Fr.zero(), - Fr.zero(), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), Fr.zero(), Fr.zero(), Fr.zero(), @@ -174,7 +176,10 @@ export class CombinedAccumulatedData { .join(', ')}], noteEncryptedLogsHash: ${this.noteEncryptedLogsHash.toString()}, encryptedLogsHash: ${this.encryptedLogsHash.toString()}, - unencryptedLogsHash: ${this.unencryptedLogsHash.toString()}, + unencryptedLogsHashes: : [${this.unencryptedLogsHashes + .filter(x => !x.isEmpty()) + .map(x => inspect(x)) + .join(', ')}], noteEncryptedLogPreimagesLength: ${this.noteEncryptedLogPreimagesLength.toString()}, encryptedLogPreimagesLength: ${this.encryptedLogPreimagesLength.toString()}, unencryptedLogPreimagesLength: ${this.unencryptedLogPreimagesLength.toString()}, diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts index 2ca2bb57322..1d18673b79f 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts @@ -17,7 +17,7 @@ import { } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; -import { LogHash } from '../log_hash.js'; +import { LogHash, ScopedLogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { Nullifier } from '../nullifier.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; @@ -50,7 +50,7 @@ export class PublicAccumulatedData { * Accumulated unencrypted logs hashes from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. */ - public readonly unencryptedLogsHashes: Tuple, + public readonly unencryptedLogsHashes: Tuple, /** * All the public data update requests made in this transaction. */ @@ -165,7 +165,7 @@ export class PublicAccumulatedData { reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, Fr), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), reader.readObject(Gas), @@ -180,7 +180,7 @@ export class PublicAccumulatedData { reader.readFieldArray(MAX_L2_TO_L1_MSGS_PER_TX), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), reader.readObject(Gas), @@ -203,7 +203,7 @@ export class PublicAccumulatedData { makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.zero), makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, LogHash.empty), - makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), Gas.empty(), diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts index 52505461fef..c01d01eb8c5 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts @@ -13,7 +13,7 @@ import { } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; -import { LogHash } from '../log_hash.js'; +import { LogHash, ScopedLogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { Nullifier } from '../nullifier.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; @@ -31,7 +31,7 @@ export class PublicAccumulatedDataBuilder { private l2ToL1Msgs: Fr[] = []; private noteEncryptedLogsHashes: LogHash[] = []; private encryptedLogsHashes: LogHash[] = []; - private unencryptedLogsHashes: LogHash[] = []; + private unencryptedLogsHashes: ScopedLogHash[] = []; private publicDataUpdateRequests: PublicDataUpdateRequest[] = []; private publicCallStack: CallRequest[] = []; private gasUsed: Gas = Gas.empty(); @@ -86,12 +86,12 @@ export class PublicAccumulatedDataBuilder { return this; } - pushUnencryptedLogsHash(unencryptedLogsHash: LogHash) { + pushUnencryptedLogsHash(unencryptedLogsHash: ScopedLogHash) { this.unencryptedLogsHashes.push(unencryptedLogsHash); return this; } - withUnencryptedLogsHashes(unencryptedLogsHashes: LogHash[]) { + withUnencryptedLogsHashes(unencryptedLogsHashes: ScopedLogHash[]) { this.unencryptedLogsHashes = unencryptedLogsHashes; return this; } @@ -128,7 +128,7 @@ export class PublicAccumulatedDataBuilder { padArrayEnd(this.l2ToL1Msgs, Fr.ZERO, MAX_L2_TO_L1_MSGS_PER_TX), padArrayEnd(this.noteEncryptedLogsHashes, LogHash.empty(), MAX_NOTE_ENCRYPTED_LOGS_PER_TX), padArrayEnd(this.encryptedLogsHashes, LogHash.empty(), MAX_ENCRYPTED_LOGS_PER_TX), - padArrayEnd(this.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX), + padArrayEnd(this.unencryptedLogsHashes, ScopedLogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX), padArrayEnd( this.publicDataUpdateRequests, PublicDataUpdateRequest.empty(), diff --git a/yarn-project/circuits.js/src/structs/log_hash.ts b/yarn-project/circuits.js/src/structs/log_hash.ts index 86105784e5c..a51086e5d11 100644 --- a/yarn-project/circuits.js/src/structs/log_hash.ts +++ b/yarn-project/circuits.js/src/structs/log_hash.ts @@ -1,4 +1,5 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { sha256Trunc } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -84,6 +85,10 @@ export class ScopedLogHash implements Ordered { toString(): string { return `logHash=${this.logHash} contractAddress=${this.contractAddress}`; } + + getSiloedHash(): Buffer { + return sha256Trunc(Buffer.concat([this.contractAddress.toBuffer(), this.value.toBuffer()])); + } } export class NoteLogHash implements Ordered { diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 9df75d8d6ad..414032008c8 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -127,6 +127,7 @@ import { RootRollupInputs, RootRollupPublicInputs, ScopedKeyValidationRequestAndGenerator, + ScopedLogHash, ScopedReadRequest, StateDiffHints, StateReference, @@ -171,6 +172,10 @@ function makeNoteLogHash(seed: number) { return new NoteLogHash(fr(seed + 3), seed + 1, fr(seed + 2), seed); } +function makeScopedLogHash(seed: number) { + return new ScopedLogHash(makeLogHash(seed), makeAztecAddress(seed + 3)); +} + function makeNoteHash(seed: number) { return new NoteHash(fr(seed), seed + 1); } @@ -347,7 +352,7 @@ export function makeCombinedAccumulatedData(seed = 1, full = false): CombinedAcc tupleGenerator(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), fr(seed + 0x700), // note encrypted logs hash fr(seed + 0x800), // encrypted logs hash - fr(seed + 0x900), // unencrypted logs hash + tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x900, ScopedLogHash.empty), // unencrypted logs fr(seed + 0xa00), // note_encrypted_log_preimages_length fr(seed + 0xb00), // encrypted_log_preimages_length fr(seed + 0xc00), // unencrypted_log_preimages_length @@ -379,7 +384,7 @@ export function makePublicAccumulatedData(seed = 1, full = false): PublicAccumul tupleGenerator(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), tupleGenerator(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x700, LogHash.empty), // note encrypted logs hashes tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x800, LogHash.empty), // encrypted logs hashes - tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x900, LogHash.empty), // unencrypted logs hashes + tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x900, ScopedLogHash.empty), // unencrypted logs hashes tupleGenerator( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, @@ -707,7 +712,7 @@ export function makeCombineHints(seed = 1): CombineHints { return CombineHints.from({ sortedNoteHashes: makeTuple(MAX_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x100), sortedNoteHashesIndexes: makeTuple(MAX_NOTE_HASHES_PER_TX, i => i, seed + 0x200), - sortedUnencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x300), + sortedUnencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x300), sortedUnencryptedLogsHashesIndexes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, i => i, seed + 0x400), sortedPublicDataUpdateRequests: makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 3443492eb40..49d1d01888a 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -191,7 +191,6 @@ describe('L1Publisher integration', () => { processedTx.data.end.nullifiers[processedTx.data.end.nullifiers.length - 1] = Fr.ZERO; processedTx.data.end.l2ToL1Msgs = makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); processedTx.data.end.encryptedLogsHash = Fr.fromBuffer(processedTx.encryptedLogs.hash()); - processedTx.data.end.unencryptedLogsHash = Fr.fromBuffer(processedTx.unencryptedLogs.hash()); return processedTx; }; diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 45ad64d3e7a..7bc509a2562 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1298,7 +1298,11 @@ export function mapPublicAccumulatedDataFromNoir( mapLogHashFromNoir, ), mapTupleFromNoir(publicAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), - mapTupleFromNoir(publicAccumulatedData.unencrypted_logs_hashes, MAX_UNENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), + mapTupleFromNoir( + publicAccumulatedData.unencrypted_logs_hashes, + MAX_UNENCRYPTED_LOGS_PER_TX, + mapScopedLogHashFromNoir, + ), mapTupleFromNoir( publicAccumulatedData.public_data_update_requests, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -1322,7 +1326,7 @@ export function mapPublicAccumulatedDataToNoir( l2_to_l1_msgs: mapTuple(publicAccumulatedData.l2ToL1Msgs, mapFieldToNoir), note_encrypted_logs_hashes: mapTuple(publicAccumulatedData.noteEncryptedLogsHashes, mapLogHashToNoir), encrypted_logs_hashes: mapTuple(publicAccumulatedData.encryptedLogsHashes, mapLogHashToNoir), - unencrypted_logs_hashes: mapTuple(publicAccumulatedData.unencryptedLogsHashes, mapLogHashToNoir), + unencrypted_logs_hashes: mapTuple(publicAccumulatedData.unencryptedLogsHashes, mapScopedLogHashToNoir), public_data_update_requests: mapTuple( publicAccumulatedData.publicDataUpdateRequests, mapPublicDataUpdateRequestToNoir, @@ -1387,7 +1391,11 @@ export function mapCombinedAccumulatedDataFromNoir( mapTupleFromNoir(combinedAccumulatedData.l2_to_l1_msgs, MAX_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), mapFieldFromNoir(combinedAccumulatedData.note_encrypted_logs_hash), mapFieldFromNoir(combinedAccumulatedData.encrypted_logs_hash), - mapFieldFromNoir(combinedAccumulatedData.unencrypted_logs_hash), + mapTupleFromNoir( + combinedAccumulatedData.unencrypted_logs_hashes, + MAX_UNENCRYPTED_LOGS_PER_TX, + mapScopedLogHashFromNoir, + ), mapFieldFromNoir(combinedAccumulatedData.note_encrypted_log_preimages_length), mapFieldFromNoir(combinedAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(combinedAccumulatedData.unencrypted_log_preimages_length), @@ -1409,7 +1417,7 @@ export function mapCombinedAccumulatedDataToNoir( l2_to_l1_msgs: mapTuple(combinedAccumulatedData.l2ToL1Msgs, mapFieldToNoir), note_encrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.noteEncryptedLogsHash), encrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.encryptedLogsHash), - unencrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.unencryptedLogsHash), + unencrypted_logs_hashes: mapTuple(combinedAccumulatedData.unencryptedLogsHashes, mapScopedLogHashToNoir), note_encrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.noteEncryptedLogPreimagesLength), encrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.unencryptedLogPreimagesLength), @@ -1697,7 +1705,7 @@ export function mapCombineHintsToNoir(combineHints: CombineHints): CombineHintsN return { sorted_note_hashes: mapTuple(combineHints.sortedNoteHashes, mapNoteHashToNoir), sorted_note_hashes_indexes: mapTuple(combineHints.sortedNoteHashesIndexes, mapNumberToNoir), - sorted_unencrypted_logs_hashes: mapTuple(combineHints.sortedUnencryptedLogsHashes, mapLogHashToNoir), + sorted_unencrypted_logs_hashes: mapTuple(combineHints.sortedUnencryptedLogsHashes, mapScopedLogHashToNoir), sorted_unencrypted_logs_hashes_indexes: mapTuple(combineHints.sortedUnencryptedLogsHashesIndexes, mapNumberToNoir), sorted_public_data_update_requests: mapTuple( combineHints.sortedPublicDataUpdateRequests, diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index e960506c43f..16a99350135 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -123,7 +123,6 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se processedTx.data.end.l2ToL1Msgs = makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); processedTx.data.end.noteEncryptedLogsHash = Fr.fromBuffer(processedTx.noteEncryptedLogs.hash()); processedTx.data.end.encryptedLogsHash = Fr.fromBuffer(processedTx.encryptedLogs.hash()); - processedTx.data.end.unencryptedLogsHash = Fr.fromBuffer(processedTx.unencryptedLogs.hash()); return processedTx; }; diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index d8ffb6655eb..385f50e629e 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -7,6 +7,7 @@ import { PublicKernelType, Tx, type TxEffect, + UnencryptedTxL2Logs, makeEmptyProcessedTx, makePaddingProcessedTx, mapPublicKernelToCircuitName, @@ -648,15 +649,17 @@ export class ProvingOrchestrator { ); return; } - if ( - !tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash - .toBuffer() - .equals(tx.processedTx.unencryptedLogs.hash()) - ) { + + const txUnencryptedLogs = UnencryptedTxL2Logs.hashSiloedLogs( + tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHashes + .filter(log => !log.isEmpty()) + .map(log => log.getSiloedHash()), + ); + if (!txUnencryptedLogs.equals(tx.processedTx.unencryptedLogs.hash())) { provingState.reject( - `Unencrypted logs hash mismatch: ${ - tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash - } === ${Fr.fromBuffer(tx.processedTx.unencryptedLogs.hash())}`, + `Unencrypted logs hash mismatch: ${Fr.fromBuffer(txUnencryptedLogs)} === ${Fr.fromBuffer( + tx.processedTx.unencryptedLogs.hash(), + )}`, ); return; }