From 457487795c6bce1db336b2ba80060ad016dd1265 Mon Sep 17 00:00:00 2001 From: Miranda Wood Date: Thu, 16 May 2024 12:10:07 +0100 Subject: [PATCH] feat: squash transient note logs (#6268) Closes #1641 ## This PR: ### Logs as `SideEffect`s -> `LogHash` or `NoteLogHash` Adds new structs to track logs in the kernel circuits, so we can track individual log lengths (and assign gas accordingly) and separate logs linked to notes from generic logs. The length changes contribute to #4712 but this PR does not close it - we need some more work in ts to ensure logs from the non-revertible side actually persist to the tx. ### Adds `note_encrypted_logs` To aid the kernels/pxe/note dbs in managing note encrypted logs, most of the changed files are adding a new array of note logs to anything already containing `.encrypted_logs_`. Since all our current contracts/tests only emit encrypted logs for notes, the values expected in `.encrypted_logs` have basically moved over to `.note_encrypted_logs`. A later PR will add code for generic encrypted logs (see below). Includes adding logs to the note cache in `client_execution_context` and removing `LogsCache`, as the note cache handles note specific logs. ### Squashes transient note logs Removes any logs linked to note hashes nullified in the same tx. This involves adding note logs to transient hints for the private kernel tail and chopping them inside the circuit. ### TODOs/Notes - This PR ended up pretty large, so while we can silo log hashes now, it would be cleaner to do in a follow up PR. - There are some small changes to public/AVM contexts which are mostly to replace `SideEffect` with `LogHash` and a couple of things addressed in comments below. - Currently, the only encrypted logs that are emitted are linked to notes. To allow for generic values emitted as encrypted logs, I'll need to add a new oracle call and methods, which makes sense to do once we encrypt inside the circuit (#1139). - Total logs length (e.g. `encrypted_log_preimages_length` is no longer required now we track indvidual lengths (it's also not trusted since it comes from contexts), so it can be removed from the kernels. - We originally tried to track log lengths the same way as `ts`, which adds 4 bytes to each nested 'group' of logs: `L2BlockL2Logs.txLogs = TxL2Logs -> .functionLogs = FunctionL2Logs -> .logs = EncryptedL2Log[]` but this never actually matched up because we accumulate and sort logs regardless of what call they came from. E.g. 3 groups of `FunctionL2Logs` would each have +4 length when added to a tx, but we take the contents, sort them, then add to a single `FunctionL2Logs.logs` array before assigning to a tx, so end up with a single +4 length. This length value is only used on L1 to destructure the blob of bytes representing logs. Any incorrect lengths would lead to a logs hash mismatch, so we don't need to match them in the circuit anyway. For this reason, I've removed a few unnecessary +4s from the circuits. --- .../vm/avm_trace/aztec_constants.hpp | 26 +-- .../src/core/libraries/ConstantsGen.sol | 28 +-- .../core/libraries/decoders/TxsDecoder.sol | 79 ++++---- .../decoders/helpers/TxsDecoderHelper.sol | 2 +- l1-contracts/test/fixtures/empty_block_0.json | 14 +- l1-contracts/test/fixtures/empty_block_1.json | 18 +- l1-contracts/test/fixtures/mixed_block_0.json | 16 +- l1-contracts/test/fixtures/mixed_block_1.json | 20 +- .../aztec-nr/address-note/src/address_note.nr | 4 +- .../aztec/src/context/private_context.nr | 83 ++++++-- .../aztec/src/context/public_context.nr | 23 +-- .../oracle/enqueue_public_function_call.nr | 4 +- .../aztec-nr/value-note/src/value_note.nr | 4 +- .../src/subscription_note.nr | 4 +- .../src/types/card_note.nr | 4 +- .../src/ecdsa_public_key_note.nr | 4 +- .../src/public_key_note.nr | 4 +- .../src/types/token_note.nr | 4 +- .../token_contract/src/types/token_note.nr | 4 +- .../kernel_circuit_public_inputs_composer.nr | 28 ++- .../src/private_call_data_validator.nr | 2 + ...e_kernel_circuit_public_inputs_composer.nr | 31 ++- .../src/private_kernel_init.nr | 11 +- .../src/private_kernel_inner.nr | 12 +- .../src/private_kernel_reset.nr | 73 +++++-- .../src/private_kernel_tail.nr | 47 +++-- .../src/private_kernel_tail_to_public.nr | 96 +++++++-- .../src/tests/validate_arrays.nr | 24 ++- .../src/tests/validate_call.nr | 6 +- .../src/tests/validate_call_requests.nr | 16 +- .../crates/public-kernel-lib/src/common.nr | 12 +- .../src/public_kernel_app_logic.nr | 17 +- .../src/reset/transient_data.nr | 185 ++++++++++++++++-- .../src/tests/squash_transient_data.nr | 21 +- .../crates/rollup-lib/src/components.nr | 9 +- .../crates/types/src/abis.nr | 1 + .../combined_accumulated_data.nr | 14 +- .../private_accumulated_data.nr | 24 ++- .../private_accumulated_data_builder.nr | 172 +++++++++++++--- .../public_accumulated_data.nr | 24 ++- .../public_accumulated_data_builder.nr | 11 +- .../crates/types/src/abis/log_hash.nr | 126 ++++++++++++ .../types/src/abis/private_call_stack_item.nr | 2 +- .../src/abis/private_circuit_public_inputs.nr | 25 ++- .../types/src/abis/public_call_stack_item.nr | 4 +- .../src/abis/public_circuit_public_inputs.nr | 10 +- .../crates/types/src/constants.nr | 18 +- .../crates/types/src/hash.nr | 27 ++- .../crates/types/src/tests/fixture_builder.nr | 38 +++- .../src/tests/private_call_data_builder.nr | 4 +- .../private_circuit_public_inputs_builder.nr | 15 +- .../src/tests/public_call_data_builder.nr | 4 +- .../public_circuit_public_inputs_builder.nr | 4 +- .../archiver/src/archiver/archiver.test.ts | 9 + .../archiver/src/archiver/archiver.ts | 4 +- .../archiver/src/archiver/archiver_store.ts | 2 + .../src/archiver/archiver_store_test_suite.ts | 39 +++- .../kv_archiver_store/kv_archiver_store.ts | 3 +- .../archiver/kv_archiver_store/log_store.ts | 21 +- .../memory_archiver_store.test.ts | 7 +- .../memory_archiver_store.ts | 26 ++- yarn-project/circuit-types/src/body.ts | 6 + yarn-project/circuit-types/src/l2_block.ts | 12 +- .../circuit-types/src/logs/log_type.ts | 7 +- .../circuit-types/src/logs/tx_l2_logs.ts | 12 +- yarn-project/circuit-types/src/mocks.ts | 17 +- yarn-project/circuit-types/src/stats/stats.ts | 4 + .../circuit-types/src/tx/processed_tx.ts | 6 +- yarn-project/circuit-types/src/tx/tx.ts | 13 ++ .../circuit-types/src/tx_effect.test.ts | 2 +- yarn-project/circuit-types/src/tx_effect.ts | 19 +- yarn-project/circuits.js/src/constants.gen.ts | 23 ++- .../contract_address.test.ts.snap | 2 - .../src/contract/contract_address.test.ts | 15 +- .../hints/build_transient_data_hints.test.ts | 32 ++- .../src/hints/build_transient_data_hints.ts | 28 ++- .../circuits.js/src/keys/index.test.ts | 2 +- .../private_call_stack_item.test.ts.snap | 4 +- ...private_circuit_public_inputs.test.ts.snap | 4 +- .../public_call_stack_item.test.ts.snap | 8 +- .../public_circuit_public_inputs.test.ts.snap | 4 +- yarn-project/circuits.js/src/structs/index.ts | 1 + .../kernel/combined_accumulated_data.ts | 9 + .../kernel/private_accumulated_data.ts | 34 ++-- ...ate_kernel_reset_circuit_private_inputs.ts | 12 +- ...vate_kernel_tail_circuit_private_inputs.ts | 23 ++- .../structs/kernel/public_accumulated_data.ts | 36 ++-- .../circuits.js/src/structs/log_hash.ts | 72 +++++++ .../structs/private_circuit_public_inputs.ts | 29 ++- .../structs/public_circuit_public_inputs.ts | 10 +- .../circuits.js/src/tests/factories.ts | 38 ++-- .../src/benchmarks/bench_proving.test.ts | 2 +- .../src/benchmarks/bench_tx_size_fees.test.ts | 12 +- .../end-to-end/src/e2e_2_pxes.test.ts | 10 +- .../end-to-end/src/e2e_block_building.test.ts | 2 +- .../end-to-end/src/e2e_key_rotation.test.ts | 4 +- .../e2e_multiple_accounts_1_enc_key.test.ts | 4 +- .../e2e_pending_note_hashes_contract.test.ts | 21 ++ yarn-project/end-to-end/src/fixtures/utils.ts | 4 +- .../src/type_conversion.ts | 103 +++++++--- yarn-project/p2p/src/service/tx_messages.ts | 8 +- .../prover-client/src/mocks/fixtures.ts | 1 + .../src/orchestrator/orchestrator.ts | 12 ++ .../src/kernel_prover/kernel_prover.test.ts | 1 + .../pxe/src/kernel_prover/kernel_prover.ts | 1 + .../build_private_kernel_reset_hints.ts | 10 +- .../build_private_kernel_reset_outputs.ts | 13 +- .../build_private_kernel_tail_hints.ts | 53 ++--- .../src/note_processor/produce_note_dao.ts | 22 +-- .../pxe/src/pxe_service/pxe_service.ts | 3 + .../pxe/src/synchronizer/synchronizer.ts | 12 +- .../simulator/src/avm/journal/journal.ts | 15 +- .../src/client/client_execution_context.ts | 95 ++++++--- .../src/client/execution_note_cache.ts | 30 ++- .../src/client/execution_result.test.ts | 1 + .../simulator/src/client/execution_result.ts | 28 ++- .../simulator/src/client/logs_cache.ts | 65 ------ .../src/client/private_execution.test.ts | 75 +++---- .../simulator/src/client/private_execution.ts | 3 + .../simulator/src/client/simulator.ts | 2 - .../src/public/abstract_phase_manager.ts | 8 +- .../simulator/src/public/execution.ts | 4 +- yarn-project/simulator/src/public/executor.ts | 2 +- .../simulator/src/public/index.test.ts | 3 +- .../src/public/public_processor.test.ts | 1 + .../src/public/tail_phase_manager.ts | 10 +- yarn-project/simulator/src/public/utils.ts | 4 +- 127 files changed, 1952 insertions(+), 745 deletions(-) create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr create mode 100644 yarn-project/circuits.js/src/structs/log_hash.ts delete mode 100644 yarn-project/simulator/src/client/logs_cache.ts diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp index 62246d48614..c56cc0dfc54 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp @@ -14,6 +14,7 @@ const size_t MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; const size_t MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; const size_t MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; const size_t MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; +const size_t MAX_NOTE_ENCRYPTED_LOGS_PER_CALL = 16; const size_t MAX_ENCRYPTED_LOGS_PER_CALL = 4; const size_t MAX_UNENCRYPTED_LOGS_PER_CALL = 4; const size_t MAX_NEW_NOTE_HASHES_PER_TX = 64; @@ -27,6 +28,7 @@ const size_t MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; const size_t MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; const size_t MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; const size_t MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; +const size_t MAX_NOTE_ENCRYPTED_LOGS_PER_TX = 64; const size_t MAX_ENCRYPTED_LOGS_PER_TX = 8; const size_t MAX_UNENCRYPTED_LOGS_PER_TX = 8; const size_t NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; @@ -94,6 +96,8 @@ const size_t NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; const size_t SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; const size_t PARTIAL_STATE_REFERENCE_LENGTH = 6; const size_t READ_REQUEST_LENGTH = 2; +const size_t LOG_HASH_LENGTH = 3; +const size_t NOTE_LOG_HASH_LENGTH = 4; const size_t NOTE_HASH_LENGTH = 2; const size_t SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; const size_t NULLIFIER_LENGTH = 3; @@ -112,17 +116,17 @@ const size_t PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + - (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + - HEADER_LENGTH + TX_CONTEXT_LENGTH; + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; const size_t PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + - (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + - (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + - AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + + /* transaction_fee */ 1; const size_t PRIVATE_CALL_STACK_ITEM_LENGTH = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; const size_t PUBLIC_CONTEXT_INPUTS_LENGTH = @@ -137,24 +141,24 @@ const size_t VALIDATION_REQUESTS_LENGTH = (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); const size_t PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; const size_t COMBINED_ACCUMULATED_DATA_LENGTH = - MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 + + MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 5 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; const size_t COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; const size_t CALLER_CONTEXT_LENGTH = 2 * AZTEC_ADDRESS_LENGTH; const size_t CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; const size_t PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + - (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + - (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + - (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); const size_t PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; const size_t PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NEW_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NEW_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + - (MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_ENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH) + - (MAX_UNENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH) + 2 + + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + 2 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + GAS_LENGTH; const size_t PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 3f5440263ac..4aeefe97ccc 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -26,6 +26,7 @@ library Constants { uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 16; + uint256 internal constant MAX_NOTE_ENCRYPTED_LOGS_PER_CALL = 16; uint256 internal constant MAX_ENCRYPTED_LOGS_PER_CALL = 4; uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_CALL = 4; uint256 internal constant MAX_NEW_NOTE_HASHES_PER_TX = 64; @@ -39,6 +40,7 @@ library Constants { uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 64; + uint256 internal constant MAX_NOTE_ENCRYPTED_LOGS_PER_TX = 64; uint256 internal constant MAX_ENCRYPTED_LOGS_PER_TX = 8; uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_TX = 8; uint256 internal constant NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; @@ -123,6 +125,8 @@ library Constants { NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; + uint256 internal constant LOG_HASH_LENGTH = 3; + uint256 internal constant NOTE_LOG_HASH_LENGTH = 4; uint256 internal constant NOTE_HASH_LENGTH = 2; uint256 internal constant SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; uint256 internal constant NULLIFIER_LENGTH = 3; @@ -143,8 +147,9 @@ library Constants { + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 - + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; + + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + + (LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) @@ -153,9 +158,8 @@ library Constants { + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH - + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH /* revert_code */ + 1 + 2 * GAS_LENGTH /* transaction_fee */ - + 1; + + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + + AZTEC_ADDRESS_LENGTH /* revert_code */ + 1 + 2 * GAS_LENGTH /* transaction_fee */ + 1; uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; uint256 internal constant PUBLIC_CONTEXT_INPUTS_LENGTH = @@ -170,7 +174,7 @@ library Constants { + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX - + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 + + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 5 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; @@ -181,9 +185,9 @@ library Constants { SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX ) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) - + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 - + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + + (LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + + 2 + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH @@ -191,9 +195,9 @@ library Constants { uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = ( MAX_NEW_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH ) + (MAX_NEW_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1) - + (MAX_ENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH) - + (MAX_UNENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH) + 2 - + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + + 2 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + GAS_LENGTH; uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH diff --git a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol index 71cc0c19113..9f3a29bc495 100644 --- a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol +++ b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol @@ -16,32 +16,34 @@ import {Hash} from "../Hash.sol"; * ------------------- * L2 Body Data Specification * ------------------- - * | byte start | num bytes | name - * | --- | --- | --- - * | 0x0 | 0x4 | len(numTxs) (denoted t) - * | | | TxEffect 0 { - * | 0x4 | 0x1 | revertCode - * | 0x5 | 0x20 | transactionFee - * | 0x25 | 0x1 | len(newNoteHashes) (denoted b) - * | 0x25 + 0x1 | b * 0x20 | newNoteHashes - * | 0x25 + 0x1 + b * 0x20 | 0x1 | len(newNullifiers) (denoted c) - * | 0x25 + 0x1 + b * 0x20 + 0x1 | c * 0x20 | newNullifiers - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d) - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f) - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g) - * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs - * | | | }, - * | | | TxEffect 1 { - * | | | ... - * | | | }, - * | | | ... - * | | | TxEffect (t - 1) { - * | | | ... - * | | | }, + * | byte start | num bytes | name + * | --- | --- | --- + * | 0x0 | 0x4 | len(numTxs) (denoted t) + * | | | TxEffect 0 { + * | 0x4 | 0x1 | revertCode + * | 0x5 | 0x20 | transactionFee + * | 0x25 | 0x1 | len(newNoteHashes) (denoted b) + * | 0x25 + 0x1 | b * 0x20 | newNoteHashes + * | 0x25 + 0x1 + b * 0x20 | 0x1 | len(newNullifiers) (denoted c) + * | 0x25 + 0x1 + b * 0x20 + 0x1 | c * 0x20 | newNullifiers + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d) + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newNoteEncryptedLogs) (denoted f) + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newNoteEncryptedLogs + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newEncryptedLogs) (denoted g) + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newEncryptedLogs + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 + g | 0x04 | byteLen(newUnencryptedLogs) (denoted h) + * | 0x25 + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 + g + 0x04| h | newUnencryptedLogs + * | | | }, + * | | | TxEffect 1 { + * | | | ... + * | | | }, + * | | | ... + * | | | TxEffect (t - 1) { + * | | | ... + * | | | }, */ library TxsDecoder { struct ArrayOffsets { @@ -64,6 +66,7 @@ library TxsDecoder { struct ConsumablesVars { bytes32[] baseLeaves; bytes baseLeaf; + bytes32 noteEncryptedLogsHash; bytes32 encryptedLogsHash; bytes32 unencryptedLogsHash; } @@ -97,6 +100,7 @@ library TxsDecoder { * newNullifiersKernel, * newL2ToL1MsgsKernel, * newPublicDataWritesKernel, + * noteEncryptedLogsHash | * encryptedLogsHash, | * unencryptedLogsHash, ____|=> Computed below from logs' preimages. * ); @@ -144,8 +148,9 @@ library TxsDecoder { * Compute encrypted and unencrypted logs hashes corresponding to the current leaf. * Note: will advance offsets by the number of bytes processed. */ - (vars.encryptedLogsHash, offset) = computeKernelLogsHash(offset, _body); - (vars.unencryptedLogsHash, offset) = computeKernelLogsHash(offset, _body); + (vars.noteEncryptedLogsHash, offset) = computeKernelLogsHash(offset, _body, true); + (vars.encryptedLogsHash, offset) = computeKernelLogsHash(offset, _body, false); + (vars.unencryptedLogsHash, offset) = computeKernelLogsHash(offset, _body, false); // Insertions are split into multiple `bytes.concat` to work around stack too deep. vars.baseLeaf = bytes.concat( @@ -180,7 +185,7 @@ library TxsDecoder { Constants.PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP ) ), - bytes.concat(vars.encryptedLogsHash, vars.unencryptedLogsHash) + bytes.concat(vars.noteEncryptedLogsHash, vars.encryptedLogsHash, vars.unencryptedLogsHash) ); vars.baseLeaves[i] = Hash.sha256ToField(vars.baseLeaf); @@ -189,7 +194,7 @@ library TxsDecoder { // We pad base leaves with hashes of empty tx effect. for (uint256 i = numTxEffects; i < vars.baseLeaves.length; i++) { // Value taken from tx_effect.test.ts "hash of empty tx effect matches snapshot" test case - vars.baseLeaves[i] = hex"00822c2cdfbc7a6e5f4dd355251f4dfc9af1b1a64152464b9b83c5007eeed0f3"; + vars.baseLeaves[i] = hex"00543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7"; } } @@ -228,7 +233,7 @@ library TxsDecoder { * @dev Link to a relevant discussion: * https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426/9 */ - function computeKernelLogsHash(uint256 _offsetInBlock, bytes calldata _body) + function computeKernelLogsHash(uint256 _offsetInBlock, bytes calldata _body, bool noteLogs) internal pure returns (bytes32, uint256) @@ -268,10 +273,14 @@ library TxsDecoder { // padded to MAX_LOGS * 32 bytes // NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX - flattenedLogHashes = bytes.concat( - flattenedLogHashes, - new bytes(Constants.MAX_ENCRYPTED_LOGS_PER_TX * 32 - flattenedLogHashes.length) - ); + uint256 len; + if (noteLogs) { + len = Constants.MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32; + } else { + len = Constants.MAX_ENCRYPTED_LOGS_PER_TX * 32; + } + flattenedLogHashes = + bytes.concat(flattenedLogHashes, new bytes(len - flattenedLogHashes.length)); bytes32 kernelPublicInputsLogsHash = Hash.sha256ToField(flattenedLogHashes); diff --git a/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol b/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol index 5b5b0da696a..e4c7a6a1a96 100644 --- a/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol +++ b/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol @@ -15,7 +15,7 @@ contract TxsDecoderHelper { pure returns (bytes32, uint256) { - return TxsDecoder.computeKernelLogsHash(0, _kernelLogs); + return TxsDecoder.computeKernelLogsHash(0, _kernelLogs, false); } function computeNumTxEffectsToPad(uint32 _numTxEffects) external pure returns (uint32) { diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index 9ee905086d5..e7e90d6eb2a 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -8,23 +8,23 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x092e7b5812f430a11de252abb67ba28c237b78aa717cf67a0a7d13ac229cb476", + "archive": "0x28db6a7d7f6d68e8eae12643769246709897c59c72fc94b5b6ce00655b245e42", "body": "0x00000000", - "txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c", + "txsEffectsHash": "0x00f6922770c8d944eb7b03abaad695fa06ad1c395d3fbe216dfb508691d16a2f", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3", "txTreeHeight": 1, - "txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c" + "txsEffectsHash": "0x00f6922770c8d944eb7b03abaad695fa06ad1c395d3fbe216dfb508691d16a2f" }, "globalVariables": { "blockNumber": 1, "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xb35cee29ec094ab8b8be05b158e0bf50d2432952", - "feeRecipient": "0x2e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b02", + "coinbase": "0x4fdc8e41d48477a1e7f9b7a5de5dc36546fdd89e", + "feeRecipient": "0x2aa0b5a2607f90e00553c29ce8bf75a8a453bc167be277fdcbe7c0ff284852fd", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -55,8 +55,8 @@ } } }, - "header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf0000000100000000000000000000000000000000000000000000000000000000000000010041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000b35cee29ec094ab8b8be05b158e0bf50d24329522e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00ae98c27e880d898c1dd0cdb9b2da88de6719f7b3bf0707a4f13381ac22dce8", + "header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf00000001000000000000000000000000000000000000000000000000000000000000000100f6922770c8d944eb7b03abaad695fa06ad1c395d3fbe216dfb508691d16a2f00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000004fdc8e41d48477a1e7f9b7a5de5dc36546fdd89e2aa0b5a2607f90e00553c29ce8bf75a8a453bc167be277fdcbe7c0ff284852fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00f30a1da4a60be604e620ab3c0e4f960d0d47b647cde7c460e64a6c7e667e33", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index c3943f409b8..ddaeffe7c95 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,23 +8,23 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x0a195ab304da7c6cf916ff7a40cb570f728481aac14b2d5df776c5306d0671f5", + "archive": "0x133f7fd0f4773b3d206b02f672a0fdd1e1a1ea9e562063c758ce4ddf6d92d079", "body": "0x00000000", - "txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c", + "txsEffectsHash": "0x00f6922770c8d944eb7b03abaad695fa06ad1c395d3fbe216dfb508691d16a2f", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3", "txTreeHeight": 1, - "txsEffectsHash": "0x0041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c" + "txsEffectsHash": "0x00f6922770c8d944eb7b03abaad695fa06ad1c395d3fbe216dfb508691d16a2f" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1714575319, + "timestamp": 1715590033, "version": 1, - "coinbase": "0xb35cee29ec094ab8b8be05b158e0bf50d2432952", - "feeRecipient": "0x2e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b02", + "coinbase": "0x4fdc8e41d48477a1e7f9b7a5de5dc36546fdd89e", + "feeRecipient": "0x2aa0b5a2607f90e00553c29ce8bf75a8a453bc167be277fdcbe7c0ff284852fd", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -32,7 +32,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x092e7b5812f430a11de252abb67ba28c237b78aa717cf67a0a7d13ac229cb476" + "root": "0x28db6a7d7f6d68e8eae12643769246709897c59c72fc94b5b6ce00655b245e42" }, "stateReference": { "l1ToL2MessageTree": { @@ -55,8 +55,8 @@ } } }, - "header": "0x092e7b5812f430a11de252abb67ba28c237b78aa717cf67a0a7d13ac229cb4760000000200000000000000000000000000000000000000000000000000000000000000010041e05321b3603fcde9458e9c664d50a08187c7fdeeb6a1cf39932849df577c00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000663257d7b35cee29ec094ab8b8be05b158e0bf50d24329522e318034e3a2c52d895e8af8e14f8b95c5e49c461d12b4657ab8c85539013b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00dde76c303e0e4d99151f2178e0b6cca10687f5a956084cae2fe6d320e3b9ec", + "header": "0x28db6a7d7f6d68e8eae12643769246709897c59c72fc94b5b6ce00655b245e4200000002000000000000000000000000000000000000000000000000000000000000000100f6922770c8d944eb7b03abaad695fa06ad1c395d3fbe216dfb508691d16a2f00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006641d3914fdc8e41d48477a1e7f9b7a5de5dc36546fdd89e2aa0b5a2607f90e00553c29ce8bf75a8a453bc167be277fdcbe7c0ff284852fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00dacc45bae55cf4217a7a66cd1ff9c2fb65726a10c8d4835a8a7c7a9ac0f18c", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json index 0b530058c85..a45b53a9218 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -34,23 +34,23 @@ ] }, "block": { - "archive": "0x2b150d57be5d2e2388f713c07c5d0c7027e9ad445bfcf69b40df5248265dd8e4", - "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341200000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381200000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c12000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e90000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000", - "txsEffectsHash": "0x00477d4a1d0644228f0e879d652f50db59171b3a2f6ff05e165dd123f96c7c5c", + "archive": "0x14db96bbda96c21937acb03438fd47f6b4e3dcc43e3bae7eb42a510b2ff79336", + "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341200000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f0000000000000000000000000000000000000000000000000000000000000569000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381200000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c12000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f0000000000000000000000000000000000000000000000000000000000000629000000000000000000000000", + "txsEffectsHash": "0x002ee1d8e2394274380df0be51690be06b2b63ef311e78b40b1265c0f99a9d30", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb6", "txTreeHeight": 2, - "txsEffectsHash": "0x00477d4a1d0644228f0e879d652f50db59171b3a2f6ff05e165dd123f96c7c5c" + "txsEffectsHash": "0x002ee1d8e2394274380df0be51690be06b2b63ef311e78b40b1265c0f99a9d30" }, "globalVariables": { "blockNumber": 1, "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0x5a0f751996207a761dbff6a27555efd60e4e417a", - "feeRecipient": "0x12db2f677917ea79157a28311ed18fbb877d6f219eb0dd0bd293865a73b9974f", + "coinbase": "0x070d0edcf7534bcdc79c52d27ac37b054cdd4ead", + "feeRecipient": "0x1d71544bd0344426b834affcd4f0ee7b9a91de7f7338543704d18dada2f22cda", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -81,8 +81,8 @@ } } }, - "header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf00000001000000000000000000000000000000000000000000000000000000000000000200477d4a1d0644228f0e879d652f50db59171b3a2f6ff05e165dd123f96c7c5c00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb61864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a20000018028d06967b6a4a1cc3c799fb6f008b63a2ffecd5034b81aa10792a6659f8aca22000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000005a0f751996207a761dbff6a27555efd60e4e417a12db2f677917ea79157a28311ed18fbb877d6f219eb0dd0bd293865a73b9974f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x0083dd303f00ea4f6607f63f4a74fb82b0ed3405db6a65077d2ceba0525b97c1", + "header": "0x067a48e3140b6f15d71751ededfa0cccde3d436bb71aa7fec226b0bfe51dc5cf000000010000000000000000000000000000000000000000000000000000000000000002002ee1d8e2394274380df0be51690be06b2b63ef311e78b40b1265c0f99a9d3000089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb61864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a20000018028d06967b6a4a1cc3c799fb6f008b63a2ffecd5034b81aa10792a6659f8aca22000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000070d0edcf7534bcdc79c52d27ac37b054cdd4ead1d71544bd0344426b834affcd4f0ee7b9a91de7f7338543704d18dada2f22cda00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00e929996ec411efaf772fb5f834a8c1cdd7acff15860838d97d4a307233f3e9", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index cc4ff9315eb..bb57755621f 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -34,23 +34,23 @@ ] }, "block": { - "archive": "0x1a3e82de10d8ab2eb7739d364a80269f7939936e8390cea095731327b8c00fb9", - "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e0200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be0200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481200000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c12000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e90000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501200000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000", - "txsEffectsHash": "0x00902f9012ecfc339e956228b63b1945db02ffe1bc9001c1d7e8b99831543656", + "archive": "0x04188e450ea5264545b2711cbe727a9fdc10eaff88627c4a5d609e31f444c799", + "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e0200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f0000000000000000000000000000000000000000000000000000000000000669000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be0200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481200000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c12000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501200000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f0000000000000000000000000000000000000000000000000000000000000729000000000000000000000000", + "txsEffectsHash": "0x001b663907c766f24a512f0fa2ec4603eb4fc404fc4e0d384697ef3b64214a25", "decodedHeader": { "contentCommitment": { "inHash": "0x00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937", "outHash": "0x00a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd", "txTreeHeight": 2, - "txsEffectsHash": "0x00902f9012ecfc339e956228b63b1945db02ffe1bc9001c1d7e8b99831543656" + "txsEffectsHash": "0x001b663907c766f24a512f0fa2ec4603eb4fc404fc4e0d384697ef3b64214a25" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1714575277, + "timestamp": 1715589990, "version": 1, - "coinbase": "0x5a0f751996207a761dbff6a27555efd60e4e417a", - "feeRecipient": "0x12db2f677917ea79157a28311ed18fbb877d6f219eb0dd0bd293865a73b9974f", + "coinbase": "0x070d0edcf7534bcdc79c52d27ac37b054cdd4ead", + "feeRecipient": "0x1d71544bd0344426b834affcd4f0ee7b9a91de7f7338543704d18dada2f22cda", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -58,7 +58,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x2b150d57be5d2e2388f713c07c5d0c7027e9ad445bfcf69b40df5248265dd8e4" + "root": "0x14db96bbda96c21937acb03438fd47f6b4e3dcc43e3bae7eb42a510b2ff79336" }, "stateReference": { "l1ToL2MessageTree": { @@ -81,8 +81,8 @@ } } }, - "header": "0x2b150d57be5d2e2388f713c07c5d0c7027e9ad445bfcf69b40df5248265dd8e400000002000000000000000000000000000000000000000000000000000000000000000200902f9012ecfc339e956228b63b1945db02ffe1bc9001c1d7e8b9983154365600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802ecba8caa69552bb0d9bdf0d13eb328aeb6f166a1509678d9bfa9970971d69ab000001400000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000663257ad5a0f751996207a761dbff6a27555efd60e4e417a12db2f677917ea79157a28311ed18fbb877d6f219eb0dd0bd293865a73b9974f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00580cc4e46735b4d1e6803f5bef9ff32097b698b1257deca089162f73200afc", + "header": "0x14db96bbda96c21937acb03438fd47f6b4e3dcc43e3bae7eb42a510b2ff79336000000020000000000000000000000000000000000000000000000000000000000000002001b663907c766f24a512f0fa2ec4603eb4fc404fc4e0d384697ef3b64214a2500212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802ecba8caa69552bb0d9bdf0d13eb328aeb6f166a1509678d9bfa9970971d69ab000001400000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006641d366070d0edcf7534bcdc79c52d27ac37b054cdd4ead1d71544bd0344426b834affcd4f0ee7b9a91de7f7338543704d18dada2f22cda00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00c8e7dc62f509a09c1d4c39def1725ac8fd4303197c7bd591951270b2a0df3b", "numTxs": 4 } } \ No newline at end of file diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 8480c0cce7a..8ee0ecce031 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -44,12 +44,12 @@ impl NoteInterface for AddressNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { // docs:start:encrypted - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); // docs:end:encrypted } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index ce7987cf015..43dd101a97c 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -2,6 +2,7 @@ use crate::{ context::{inputs::PrivateContextInputs, interface::ContextInterface}, keys::getters::get_nullifier_keys, messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash}, + note::{note_interface::NoteInterface, utils::compute_note_hash_for_insertion}, oracle::{ nullifier_keys::NullifierKeys, arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, @@ -18,7 +19,7 @@ use dep::protocol_types::{ nullifier_key_validation_request::NullifierKeyValidationRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs, public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash, - nullifier::Nullifier, side_effect::SideEffect + nullifier::Nullifier, log_hash::{LogHash, NoteLogHash} }, address::{AztecAddress, EthAddress}, constants::{ @@ -26,12 +27,12 @@ use dep::protocol_types::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, - traits::{is_empty, Deserialize, Empty} + traits::{is_empty, Deserialize, Empty}, utils::arrays::find_index }; // When finished, one can call .finish() to convert back to the abi @@ -64,8 +65,9 @@ struct PrivateContext { // Header of a block whose state is used during private execution (not the block the transaction is included in). historical_header: Header, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + note_encrypted_logs_hashes: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, @@ -126,6 +128,7 @@ impl PrivateContext { public_call_stack_hashes: BoundedVec::new(), public_teardown_function_hash: 0, new_l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, @@ -170,10 +173,11 @@ impl PrivateContext { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, - encrypted_log_preimages_length: self.encrypted_log_preimages_length + 4, - unencrypted_log_preimages_length: self.unencrypted_log_preimages_length + 4, + encrypted_log_preimages_length: self.encrypted_log_preimages_length, + unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, historical_header: self.historical_header, tx_context: self.inputs.tx_context } @@ -257,14 +261,16 @@ impl PrivateContext { pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog { let event_selector = 5; // TODO: compute actual event selector. let contract_address = self.this_address(); + let counter = self.next_counter(); let log_slice = log.to_be_bytes_arr(); let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log); - let side_effect = SideEffect { value: log_hash, counter: self.next_counter() }; - self.unencrypted_logs_hashes.push(side_effect); // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - self.unencrypted_log_preimages_length += 44 + log_slice.len().to_field(); + let len = 44 + log_slice.len().to_field(); + let side_effect = LogHash { value: log_hash, counter, length: len }; + self.unencrypted_logs_hashes.push(side_effect); + self.unencrypted_log_preimages_length += len; // call oracle - let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, side_effect.counter); + let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter); } // This fn exists separately from emit_unencrypted_log because sha hashing the preimage @@ -279,12 +285,13 @@ impl PrivateContext { let contract_address = self.this_address(); let counter = self.next_counter(); let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter); - let side_effect = SideEffect { value: log_hash, counter }; - self.unencrypted_logs_hashes.push(side_effect); // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - self.unencrypted_log_preimages_length += 44 + N*32; + let len = 44 + N * 32; + let side_effect = LogHash { value: log_hash, counter, length: len }; + self.unencrypted_logs_hashes.push(side_effect); + self.unencrypted_log_preimages_length += len; } - + // TODO(1139): Convert to generic input once we encrypt inside the circuit pub fn emit_encrypted_log( &mut self, contract_address: AztecAddress, @@ -304,12 +311,49 @@ impl PrivateContext { preimage, counter ); + // = 32*all fields + bytes for encryption (112) + processed log len (4) + let len = 112 + 32 * (N + 3) + 4; let log_hash = compute_encrypted_log_hash(encrypted_log); - let side_effect = SideEffect { value: log_hash, counter }; + let side_effect = LogHash { value: log_hash, counter, length: len }; self.encrypted_logs_hashes.push(side_effect); - let encrypted_log_byte_len = 112 + 32 * (N + 3); - // + processed log len (4) - self.encrypted_log_preimages_length += encrypted_log_byte_len + 4; + self.encrypted_log_preimages_length += len; + } + + pub fn emit_note_encrypted_log( + &mut self, + contract_address: AztecAddress, + storage_slot: Field, + note_type_id: Field, + encryption_pub_key: GrumpkinPoint, + note: Note + ) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + let note_hash = compute_note_hash_for_insertion(note); + let note_exists_index = find_index( + self.new_note_hashes.storage, + |n: NoteHash| n.value == note_hash + ); + assert( + note_exists_index != MAX_NEW_NOTE_HASHES_PER_CALL, "Can only emit a note log for an existing note." + ); + let note_hash_counter = self.new_note_hashes.storage[note_exists_index].counter; + let preimage = note.serialize_content(); + let counter = self.next_counter(); + // TODO(1139): perform encryption in the circuit + // The oracle call should come last, but we require the encrypted value for now + let encrypted_log: [Field; M] = emit_encrypted_log( + contract_address, + storage_slot, + note_type_id, + encryption_pub_key, + preimage, + counter + ); + // = 32*all fields + bytes for encryption (112) + processed log len (4) + let len = 112 + 32 * (preimage.len() as Field + 3) + 4; + let log_hash = compute_encrypted_log_hash(encrypted_log); + let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter }; + self.note_encrypted_logs_hashes.push(side_effect); + self.encrypted_log_preimages_length += len; } pub fn call_private_function( @@ -626,6 +670,7 @@ impl Empty for PrivateContext { public_teardown_function_hash: 0, new_l2_to_l1_msgs : BoundedVec::new(), historical_header: Header::empty(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 569d8716206..1df47065f4a 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -9,19 +9,15 @@ use crate::{ }; use dep::protocol_types::{ abis::{ - global_variables::GlobalVariables, function_selector::FunctionSelector, - private_circuit_public_inputs::PrivateCircuitPublicInputs, - public_call_stack_item::PublicCallStackItem, - public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest, - note_hash::NoteHash, nullifier::Nullifier, side_effect::SideEffect + function_selector::FunctionSelector, public_circuit_public_inputs::PublicCircuitPublicInputs, + read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier, log_hash::LogHash }, hash::silo_nullifier, address::{AztecAddress, EthAddress}, constants::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{Deserialize, Empty} @@ -45,7 +41,7 @@ struct PublicContext { new_l2_to_l1_msgs: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, unencrypted_log_preimages_length: Field, // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block @@ -158,7 +154,7 @@ impl PublicContext { start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, - unencrypted_log_preimages_length: self.unencrypted_log_preimages_length + 4, + unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, historical_header: self.inputs.historical_header, global_variables: self.inputs.public_global_variables, prover_address: self.prover_address, @@ -285,10 +281,11 @@ impl PublicContextInterface for PublicContext { event_selector, log ); - let side_effect = SideEffect { value: log_hash, counter: self.next_counter() }; - self.unencrypted_logs_hashes.push(side_effect); // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - self.unencrypted_log_preimages_length = self.unencrypted_log_preimages_length + 44 + log_slice.len().to_field(); + let len = 44 + log_slice.len().to_field(); + let side_effect = LogHash { value: log_hash, counter: self.next_counter(), length: len }; + self.unencrypted_logs_hashes.push(side_effect); + self.unencrypted_log_preimages_length += len; // Call oracle to broadcast log let _void = emit_unencrypted_log_oracle(contract_address, event_selector, log, side_effect.counter); } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index 65341ba396a..39b5a52e859 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -3,7 +3,7 @@ use dep::protocol_types::{ function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem, function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs, call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier, - side_effect::SideEffect, global_variables::GlobalVariables, gas::Gas + log_hash::LogHash, global_variables::GlobalVariables, gas::Gas }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress, @@ -95,7 +95,7 @@ pub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_F new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0, end_side_effect_counter: 0, - unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], unencrypted_log_preimages_length: 0, historical_header: Header::empty(), global_variables: GlobalVariables::empty(), diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 0d98dec28a7..13d9943efd3 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -47,12 +47,12 @@ impl NoteInterface for ValueNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 49e8bc43652..f0029823418 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -40,12 +40,12 @@ impl NoteInterface for SubscriptionNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 5f57d70fa5a..9767ed03b92 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -51,12 +51,12 @@ impl NoteInterface for CardNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index 0a9d4aa2497..359c6fceae1 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -86,12 +86,12 @@ impl NoteInterface for EcdsaPublicKeyNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 71601730d87..aa79ae7755c 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -39,12 +39,12 @@ impl NoteInterface for PublicKeyNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index b5df8c9ba14..17a75d2a4e1 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -51,12 +51,12 @@ impl NoteInterface for TokenNote { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index b5df8c9ba14..17a75d2a4e1 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -51,12 +51,12 @@ impl NoteInterface for TokenNote { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - context.emit_encrypted_log( + context.emit_note_encrypted_log( (*context).this_address(), slot, Self::get_note_type_id(), ivpk_m, - self.serialize_content(), + self, ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index 770cf2d7101..c5f8835c4bc 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -2,11 +2,12 @@ use dep::types::{ abis::{ private_kernel_data::PrivateKernelData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder, PublicKernelCircuitPublicInputs}, - note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::{SideEffect, Ordered}, gas::Gas + note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::Ordered, + log_hash::{LogHash, NoteLogHash}, gas::Gas }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, hash::{compute_l2_to_l1_hash, compute_note_hash_nonce, compute_unique_note_hash, silo_note_hash, silo_nullifier}, utils::arrays::{array_length, array_to_bounded_vec, assert_sorted_array} @@ -27,9 +28,11 @@ struct KernelCircuitPublicInputsComposer { sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes_indexes: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], } @@ -40,9 +43,11 @@ impl KernelCircuitPublicInputsComposer { sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes_indexes: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX] ) -> Self { let public_inputs = PrivateKernelCircuitPublicInputsBuilder::empty(); @@ -54,6 +59,8 @@ impl KernelCircuitPublicInputsComposer { sorted_note_hashes_indexes, sorted_nullifiers, sorted_nullifiers_indexes, + sorted_note_encrypted_log_hashes, + sorted_note_encrypted_log_hashes_indexes, sorted_encrypted_log_hashes, sorted_encrypted_log_hashes_indexes, sorted_unencrypted_log_hashes, @@ -113,6 +120,7 @@ impl KernelCircuitPublicInputsComposer { self.silo_note_hashes(); self.silo_nullifiers(); self.silo_l2_to_l1_messages(); + // TODO(Miranda): Silo logs here } fn silo_note_hashes(&mut self) { @@ -188,6 +196,14 @@ impl KernelCircuitPublicInputsComposer { ); self.public_inputs.end.new_nullifiers = array_to_bounded_vec(self.sorted_nullifiers); + assert_sorted_array( + accumulated_data.note_encrypted_logs_hashes, + self.sorted_note_encrypted_log_hashes, + self.sorted_note_encrypted_log_hashes_indexes, + asc_sort_by_counters + ); + self.public_inputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(self.sorted_note_encrypted_log_hashes); + assert_sorted_array( accumulated_data.encrypted_logs_hashes, self.sorted_encrypted_log_hashes, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_call_data_validator.nr index 0a43701e29a..98dcf2727f8 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_call_data_validator.nr @@ -22,6 +22,7 @@ fn validate_arrays(data: PrivateCallData) -> ArrayLengths { new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs), private_call_stack_hashes: validate_array(public_inputs.private_call_stack_hashes), public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes), + note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes), encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes), unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes) } @@ -148,6 +149,7 @@ struct ArrayLengths { new_l2_to_l1_msgs: u64, private_call_stack_hashes: u64, public_call_stack_hashes: u64, + note_encrypted_logs_hashes: u64, encrypted_logs_hashes: u64, unencrypted_logs_hashes: u64, } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr index 7073fad466d..32e9219529e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_circuit_public_inputs_composer.nr @@ -2,15 +2,16 @@ use dep::types::{ abis::{ call_request::CallRequest, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder}, - max_block_number::MaxBlockNumber, nullifier::Nullifier, - private_circuit_public_inputs::PrivateCircuitPublicInputs + max_block_number::MaxBlockNumber, nullifier::Nullifier, note_hash::ScopedNoteHash, + log_hash::NoteLogHash, private_circuit_public_inputs::PrivateCircuitPublicInputs }, address::AztecAddress, constants::{ - MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL }, - traits::is_empty, transaction::tx_request::TxRequest, utils::arrays::array_to_bounded_vec + traits::is_empty, transaction::tx_request::TxRequest, + utils::arrays::{array_to_bounded_vec, find_index} }; struct DataSource { @@ -65,6 +66,7 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.end.new_note_hashes = array_to_bounded_vec(start.new_note_hashes); public_inputs.end.new_nullifiers = array_to_bounded_vec(start.new_nullifiers); public_inputs.end.new_l2_to_l1_msgs = array_to_bounded_vec(start.new_l2_to_l1_msgs); + public_inputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(start.note_encrypted_logs_hashes); public_inputs.end.encrypted_logs_hashes = array_to_bounded_vec(start.encrypted_logs_hashes); public_inputs.end.unencrypted_logs_hashes = array_to_bounded_vec(start.unencrypted_logs_hashes); public_inputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; @@ -186,12 +188,33 @@ impl PrivateKernelCircuitPublicInputsComposer { fn propagate_logs(&mut self, source: DataSource) { self.public_inputs.end.encrypted_logs_hashes.extend_from_bounded_vec(array_to_bounded_vec(source.private_call_public_inputs.encrypted_logs_hashes)); self.public_inputs.end.unencrypted_logs_hashes.extend_from_bounded_vec(array_to_bounded_vec(source.private_call_public_inputs.unencrypted_logs_hashes)); + let note_logs = source.private_call_public_inputs.note_encrypted_logs_hashes; + for i in 0..note_logs.len() { + if !is_empty(note_logs[i]) { + let note_index = self.match_log_to_note(note_logs[i]); + assert( + note_index < MAX_NEW_NOTE_HASHES_PER_TX, "Could not find note hash linked to note log." + ); + assert( + note_logs[i].note_hash_counter + == self.public_inputs.end.new_note_hashes.get_unchecked(note_index).counter(), "Could not find note hash linked to note log." + ); + self.public_inputs.end.note_encrypted_logs_hashes.push(note_logs[i]); + } + } // Add log preimages lengths from current iteration to accumulated lengths. self.public_inputs.end.encrypted_log_preimages_length += source.private_call_public_inputs.encrypted_log_preimages_length; self.public_inputs.end.unencrypted_log_preimages_length += source.private_call_public_inputs.unencrypted_log_preimages_length; } + unconstrained fn match_log_to_note(self, note_log: NoteLogHash) -> u64 { + find_index( + self.public_inputs.end.new_note_hashes.storage, + |n: ScopedNoteHash| n.counter() == note_log.note_hash_counter + ) + } + fn propagate_private_call_requests(&mut self, source: DataSource) { let call_requests = source.private_call_requests; for i in 0..call_requests.len() { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index 51e163f494e..c6ae0c8d193 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -55,7 +55,7 @@ mod tests { kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, note_hash::NoteHash, nullifier_key_validation_request::NullifierKeyValidationRequest, private_kernel::private_call_data::PrivateCallData, read_request::ReadRequest, - nullifier::Nullifier, side_effect::SideEffect + nullifier::Nullifier, log_hash::{LogHash, NoteLogHash} }, address::{AztecAddress, EthAddress}, constants::MAX_NEW_NOTE_HASHES_PER_CALL, grumpkin_point::GrumpkinPoint, messaging::l2_to_l1_message::L2ToL1Message, @@ -211,6 +211,15 @@ mod tests { ); } + #[test(should_fail_with = "Could not find note hash linked to note log.")] + fn input_validation_note_log_not_linked() { + let mut builder = PrivateKernelInitInputsBuilder::new(); + + builder.private_call.public_inputs.note_encrypted_logs_hashes.extend_from_array([NoteLogHash { value: 9123, counter: 2, length: 2, note_hash_counter: 1 }]); + + builder.failed(); + } + #[test] unconstrained fn propagate_fee_payer() { let mut builder = PrivateKernelInitInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index b4d4090f5b5..26018af0064 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -55,7 +55,7 @@ mod tests { abis::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, note_hash::NoteHash, nullifier::Nullifier, - read_request::ReadRequest, side_effect::SideEffect + read_request::ReadRequest, log_hash::{LogHash, NoteLogHash} }, address::{AztecAddress, EthAddress}, constants::MAX_NEW_NOTE_HASHES_PER_CALL, messaging::l2_to_l1_message::L2ToL1Message, utils::{arrays::array_length}, @@ -120,7 +120,7 @@ mod tests { builder.private_call.public_inputs.append_new_note_hashes(1); // Mock the previous new note hashes to be full, therefore no more note_hashes can be added. - builder.previous_kernel.append_new_note_hashes(MAX_NEW_NOTE_HASHES_PER_TX); + builder.previous_kernel.append_new_note_hashes(MAX_NEW_NOTE_HASHES_PER_TX, false); builder.failed(); } @@ -245,6 +245,14 @@ mod tests { assert_eq(public_inputs.end.unencrypted_logs_hashes[1].value, unencrypted_logs_hash); } + #[test(should_fail_with = "Could not find note hash linked to note log.")] + unconstrained fn input_validation_note_log_not_linked() { + let mut builder = PrivateKernelInnerInputsBuilder::new(); + + builder.private_call.public_inputs.note_encrypted_logs_hashes.push(NoteLogHash { value: 9123, counter: 2, length: 2, note_hash_counter: 1 }); + builder.failed(); + } + #[test] unconstrained fn propagate_fee_payer_init_succeeds() { let mut builder = PrivateKernelInnerInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index 69110229d27..99b827e9be9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -7,11 +7,12 @@ use dep::types::{ abis::{ private_kernel_data::{PrivateKernelData, verify_previous_kernel_proof}, kernel_circuit_public_inputs::KernelCircuitPublicInputs, note_hash::ScopedNoteHash, - nullifier::ScopedNullifier, side_effect::SideEffect + nullifier::ScopedNullifier, log_hash::NoteLogHash }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, utils::arrays::array_length, traits::is_empty, PrivateKernelCircuitPublicInputs @@ -21,11 +22,13 @@ use dep::types::{ struct PrivateKernelResetOutputs { note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], + note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], } struct PrivateKernelResetHints { transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints: NoteHashReadRequestHints, nullifier_read_request_hints: NullifierReadRequestHints, master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], @@ -55,17 +58,22 @@ impl PrivateKernelResetCircuitPrivateInputs { master_nullifier_secret_keys: self.hints.master_nullifier_secret_keys }.validate(); - verify_squashed_transient_note_hashes_and_nullifiers( + let removed_logs_len = verify_squashed_transient_note_hashes_and_nullifiers( previous_public_inputs.end.new_note_hashes, previous_public_inputs.end.new_nullifiers, + previous_public_inputs.end.note_encrypted_logs_hashes, self.outputs.note_hashes, self.outputs.nullifiers, + self.outputs.note_encrypted_log_hashes, self.hints.transient_nullifier_indexes_for_note_hashes, - self.hints.transient_note_hash_indexes_for_nullifiers + self.hints.transient_note_hash_indexes_for_nullifiers, + self.hints.transient_note_hash_indexes_for_logs ); previous_public_inputs.end.new_note_hashes = self.outputs.note_hashes; previous_public_inputs.end.new_nullifiers = self.outputs.nullifiers; + previous_public_inputs.end.note_encrypted_logs_hashes = self.outputs.note_encrypted_log_hashes; + previous_public_inputs.end.encrypted_log_preimages_length -= removed_logs_len; previous_public_inputs } @@ -77,21 +85,21 @@ mod tests { tests::{ note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder, nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers} + squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers, squash_transient_logs} }, reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, DA_BYTES_PER_FIELD + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + DA_BYTES_PER_FIELD }; use dep::types::{ abis::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, note_hash::{NoteHash, ScopedNoteHash}, - nullifier::{Nullifier, ScopedNullifier}, side_effect::SideEffect, - read_request::ScopedReadRequest + nullifier::{Nullifier, ScopedNullifier}, log_hash::NoteLogHash, read_request::ScopedReadRequest }, address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, hash::{compute_note_hash_nonce, compute_unique_note_hash, sha256_to_field, silo_note_hash, silo_nullifier}, @@ -103,6 +111,7 @@ mod tests { previous_kernel: FixtureBuilder, transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder, nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, } @@ -116,6 +125,7 @@ mod tests { previous_kernel, transient_nullifier_indexes_for_note_hashes: [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(MAX_NOTE_HASH_READ_REQUESTS_PER_TX), nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) } @@ -139,21 +149,34 @@ mod tests { } pub fn nullify_pending_note_hash(&mut self, nullifier_index: u64, note_hash_index: u64) { + let note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).note_hash; self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter(); - self.previous_kernel.new_nullifiers.storage[nullifier_index].nullifier.note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).note_hash.value; + self.previous_kernel.new_nullifiers.storage[nullifier_index].nullifier.note_hash = note_hash.value; self.transient_nullifier_indexes_for_note_hashes[note_hash_index] = nullifier_index; self.transient_note_hash_indexes_for_nullifiers[nullifier_index] = note_hash_index; + for i in 0..self.previous_kernel.note_encrypted_logs_hashes.len() { + // we may have many, or no, logs per note hash, so we cycle rather than .find + if self.previous_kernel.note_encrypted_logs_hashes.storage[i].note_hash_counter + == note_hash.counter { + self.transient_note_hash_indexes_for_logs[i] = note_hash_index; + } + } } pub fn execute(&mut self) -> PrivateKernelCircuitPublicInputs { let outputs = PrivateKernelResetOutputs { note_hashes: squash_transient_note_hashes(self.previous_kernel.new_note_hashes.storage), - nullifiers: squash_transient_nullifiers(self.previous_kernel.new_nullifiers.storage) + nullifiers: squash_transient_nullifiers(self.previous_kernel.new_nullifiers.storage), + note_encrypted_log_hashes: squash_transient_logs( + self.previous_kernel.note_encrypted_logs_hashes.storage, + self.previous_kernel.new_note_hashes.storage + ) }; let hints = PrivateKernelResetHints { transient_nullifier_indexes_for_note_hashes: self.transient_nullifier_indexes_for_note_hashes, transient_note_hash_indexes_for_nullifiers: self.transient_note_hash_indexes_for_nullifiers, + transient_note_hash_indexes_for_logs: self.transient_note_hash_indexes_for_logs, note_hash_read_request_hints: self.note_hash_read_request_hints_builder.to_hints(), nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), master_nullifier_secret_keys: [GrumpkinPrivateKey::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX] @@ -191,7 +214,7 @@ mod tests { unconstrained fn two_pending_note_hash_read_request() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_new_note_hashes(3, false); builder.add_pending_note_hash_read_request(1); builder.add_pending_note_hash_read_request(0); @@ -202,7 +225,7 @@ mod tests { unconstrained fn pending_note_hash_read_request_wrong_hint_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_new_note_hashes(3, false); builder.add_pending_note_hash_read_request(1); let mut hint = builder.note_hash_read_request_hints_builder.pending_read_hints.pop(); hint.pending_value_index = 2; @@ -264,7 +287,7 @@ mod tests { unconstrained fn propagates_unverified_requests() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_new_note_hashes(3, false); builder.previous_kernel.append_new_nullifiers(3); builder.add_pending_note_hash_read_request(0); @@ -291,7 +314,7 @@ mod tests { #[test] unconstrained fn native_squash_one_of_one_transient_matches_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(1); + builder.previous_kernel.append_new_note_hashes(1, true); builder.previous_kernel.append_new_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); @@ -307,17 +330,19 @@ mod tests { [new_nullifiers[0], new_nullifiers[2]] ) ); + assert(is_empty_array(public_inputs.end.note_encrypted_logs_hashes)); } #[test] unconstrained fn native_squash_one_of_two_transient_matches_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_new_note_hashes(2, true); builder.previous_kernel.append_new_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let new_note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; let public_inputs = builder.execute(); // The 0th hash is chopped. @@ -330,12 +355,20 @@ mod tests { [new_nullifiers[0], new_nullifiers[2]] ) ); + + // The 0th note log is chopped. + assert( + array_eq( + public_inputs.end.note_encrypted_logs_hashes, + [new_note_logs[1]] + ) + ); } #[test] unconstrained fn native_squash_two_of_two_transient_matches_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_new_note_hashes(2, true); builder.previous_kernel.append_new_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 1; builder.nullify_pending_note_hash(1, 1); @@ -348,13 +381,14 @@ mod tests { // Only the first nullifier is left after squashing. assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0]])); + assert(is_empty_array(public_inputs.end.note_encrypted_logs_hashes)); } #[test] unconstrained fn squash_unordered_transient_notes_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_new_note_hashes(3, true); // Shuffle the note hashes so they will have to be re-ordered. let tmp = builder.previous_kernel.new_note_hashes.storage[0]; builder.previous_kernel.new_note_hashes.storage[0] = builder.previous_kernel.new_note_hashes.storage[1]; @@ -382,12 +416,13 @@ mod tests { // Only the first nullifier is left after squashing. assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0]])); + assert(is_empty_array(public_inputs.end.note_encrypted_logs_hashes)); } #[test(should_fail_with="Value of the hinted transient note hash does not match")] unconstrained fn wrong_transient_nullifier_index_for_note_hash_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(1); + builder.previous_kernel.append_new_note_hashes(1, false); builder.previous_kernel.append_new_nullifiers(1); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); @@ -399,7 +434,7 @@ mod tests { #[test(should_fail_with="Invalid transient nullifier index hint")] unconstrained fn wrong_transient_nullifier_index_hint_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_new_note_hashes(2, false); builder.previous_kernel.append_new_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 1; builder.nullify_pending_note_hash(1, 1); 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 f8470fa2433..3c887b05361 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 @@ -3,11 +3,12 @@ use dep::types::{ abis::{ private_kernel_data::{PrivateKernelData, verify_previous_kernel_proof}, kernel_circuit_public_inputs::KernelCircuitPublicInputs, note_hash::ScopedNoteHash, - nullifier::ScopedNullifier, side_effect::SideEffect + nullifier::ScopedNullifier, log_hash::{LogHash, NoteLogHash} }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, utils::arrays::array_length, traits::is_empty }; @@ -17,9 +18,11 @@ struct PrivateKernelTailHints { sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes_indexes: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], } @@ -47,6 +50,8 @@ impl PrivateKernelTailCircuitPrivateInputs { self.hints.sorted_new_note_hashes_indexes, self.hints.sorted_new_nullifiers, self.hints.sorted_new_nullifiers_indexes, + self.hints.sorted_note_encrypted_log_hashes, + self.hints.sorted_note_encrypted_log_hashes_indexes, self.hints.sorted_encrypted_log_hashes, self.hints.sorted_encrypted_log_hashes_indexes, self.hints.sorted_unencrypted_log_hashes, @@ -61,20 +66,21 @@ mod tests { tests::{ note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder, nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers} + squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers, squash_transient_logs} }, reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE }; use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, max_block_number::MaxBlockNumber, note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, - side_effect::SideEffect, gas::Gas + log_hash::{LogHash, NoteLogHash}, gas::Gas }, address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, hash::{compute_note_hash_nonce, compute_unique_note_hash, sha256_to_field, silo_note_hash, silo_nullifier}, @@ -88,6 +94,7 @@ mod tests { previous_kernel: FixtureBuilder, transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder, nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, } @@ -103,6 +110,7 @@ mod tests { previous_kernel, transient_nullifier_indexes_for_note_hashes: [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(MAX_NOTE_HASH_READ_REQUESTS_PER_TX), nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) } @@ -148,16 +156,23 @@ mod tests { let sorted_new_nullifiers = sorted.sorted_array; let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; + let sorted = sort_get_sorted_hints( + self.previous_kernel.note_encrypted_logs_hashes.storage, + |a: NoteLogHash, b: NoteLogHash| a.counter < b.counter + ); + let sorted_note_encrypted_log_hashes = sorted.sorted_array; + let sorted_note_encrypted_log_hashes_indexes = sorted.sorted_index_hints; + let sorted = sort_get_sorted_hints( self.previous_kernel.encrypted_logs_hashes.storage, - |a: SideEffect, b: SideEffect| a.counter < b.counter + |a: LogHash, b: LogHash| a.counter < b.counter ); let sorted_encrypted_log_hashes = sorted.sorted_array; let sorted_encrypted_log_hashes_indexes = sorted.sorted_index_hints; let sorted = sort_get_sorted_hints( self.previous_kernel.unencrypted_logs_hashes.storage, - |a: SideEffect, b: SideEffect| a.counter < b.counter + |a: LogHash, b: LogHash| a.counter < b.counter ); let sorted_unencrypted_log_hashes = sorted.sorted_array; let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; @@ -185,6 +200,8 @@ mod tests { sorted_new_note_hashes_indexes, sorted_new_nullifiers, sorted_new_nullifiers_indexes, + sorted_note_encrypted_log_hashes, + sorted_note_encrypted_log_hashes_indexes, sorted_encrypted_log_hashes, sorted_encrypted_log_hashes_indexes, sorted_unencrypted_log_hashes, @@ -268,7 +285,7 @@ mod tests { unconstrained fn ordering_of_note_hashes_and_nullifiers() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(10); + builder.previous_kernel.append_new_note_hashes(10, false); builder.previous_kernel.append_new_nullifiers(10); let sorted_note_hashes = builder.previous_kernel.new_note_hashes.storage; @@ -298,7 +315,7 @@ mod tests { #[test] unconstrained fn native_empty_nullified_note_hash_means_persistent_nullifier_0() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_new_note_hashes(2, false); builder.previous_kernel.append_new_nullifiers(2); let public_inputs = builder.execute(); assert_eq(array_length(public_inputs.end.new_note_hashes), 2); @@ -331,8 +348,8 @@ mod tests { #[test(should_fail_with="Non empty note hash read requests")] unconstrained fn non_empty_note_hash_read_requests() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); - builder.previous_kernel.add_read_request_for_pending_note_hash(1); + builder.previous_kernel.append_new_note_hashes(3, false); + let _void = builder.previous_kernel.add_read_request_for_pending_note_hash(1); builder.failed(); } @@ -340,14 +357,14 @@ mod tests { unconstrained fn non_empty_nullifier_read_requests() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.append_new_nullifiers(3); - builder.previous_kernel.add_read_request_for_pending_nullifier(1); + let _void = builder.previous_kernel.add_read_request_for_pending_nullifier(1); builder.failed(); } #[test(should_fail_with="Non empty nullifier key validation requests")] unconstrained fn non_empty_nullifier_key_validations() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.add_request_for_nullifier_key_validation(GrumpkinPoint::new(1, 2), 27); + let _void = builder.previous_kernel.add_request_for_nullifier_key_validation(GrumpkinPoint::new(1, 2), 27); builder.failed(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 9809e1d2fff..3fd1370fcf1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -3,11 +3,12 @@ use dep::types::{ abis::{ private_kernel_data::{PrivateKernelData, verify_previous_kernel_proof}, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, note_hash::ScopedNoteHash, - nullifier::ScopedNullifier, side_effect::SideEffect + nullifier::ScopedNullifier, log_hash::{LogHash, NoteLogHash} }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, utils::arrays::array_length, traits::is_empty }; @@ -17,9 +18,11 @@ struct PrivateKernelTailToPublicHints { sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hashes_indexes: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], } @@ -46,6 +49,8 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { self.hints.sorted_new_note_hashes_indexes, self.hints.sorted_new_nullifiers, self.hints.sorted_new_nullifiers_indexes, + self.hints.sorted_note_encrypted_log_hashes, + self.hints.sorted_note_encrypted_log_hashes_indexes, self.hints.sorted_encrypted_log_hashes, self.hints.sorted_encrypted_log_hashes_indexes, self.hints.sorted_unencrypted_log_hashes, @@ -60,20 +65,20 @@ mod tests { tests::{ note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder, nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers} + squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers, squash_transient_logs} }, reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE + DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }; use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, gas::Gas, note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, - side_effect::SideEffect + log_hash::{LogHash, NoteLogHash} }, address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, hash::{compute_note_hash_nonce, compute_unique_note_hash, silo_note_hash, silo_nullifier}, @@ -86,6 +91,7 @@ mod tests { previous_kernel: FixtureBuilder, transient_nullifier_indexes_for_note_hashes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [u64; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [u64; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder, nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, } @@ -101,6 +107,7 @@ mod tests { previous_kernel, transient_nullifier_indexes_for_note_hashes: [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX], transient_note_hash_indexes_for_nullifiers: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(MAX_NOTE_HASH_READ_REQUESTS_PER_TX), nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) } @@ -137,6 +144,17 @@ mod tests { output } + pub fn compute_output_note_logs(_self: Self, logs: [NoteLogHash; N]) -> [NoteLogHash; N] { + let mut output = [NoteLogHash::empty(); N]; + for i in 0..N { + if logs[i].value != 0 { + // TODO(Miranda): silo logs + output[i] = logs[i].expose_to_public(); // Counter is cleared so it's not exposed to the public. + } + } + output + } + pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { let sorted = sort_get_sorted_hints( self.previous_kernel.new_note_hashes.storage, @@ -152,16 +170,23 @@ mod tests { let sorted_new_nullifiers = sorted.sorted_array; let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; + let sorted = sort_get_sorted_hints( + self.previous_kernel.note_encrypted_logs_hashes.storage, + |a: NoteLogHash, b: NoteLogHash| a.counter < b.counter + ); + let sorted_note_encrypted_log_hashes = sorted.sorted_array; + let sorted_note_encrypted_log_hashes_indexes = sorted.sorted_index_hints; + let sorted = sort_get_sorted_hints( self.previous_kernel.encrypted_logs_hashes.storage, - |a: SideEffect, b: SideEffect| a.counter < b.counter + |a: LogHash, b: LogHash| a.counter < b.counter ); let sorted_encrypted_log_hashes = sorted.sorted_array; let sorted_encrypted_log_hashes_indexes = sorted.sorted_index_hints; let sorted = sort_get_sorted_hints( self.previous_kernel.unencrypted_logs_hashes.storage, - |a: SideEffect, b: SideEffect| a.counter < b.counter + |a: LogHash, b: LogHash| a.counter < b.counter ); let sorted_unencrypted_log_hashes = sorted.sorted_array; let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; @@ -171,6 +196,8 @@ mod tests { sorted_new_note_hashes_indexes, sorted_new_nullifiers, sorted_new_nullifiers_indexes, + sorted_note_encrypted_log_hashes, + sorted_note_encrypted_log_hashes_indexes, sorted_encrypted_log_hashes, sorted_encrypted_log_hashes_indexes, sorted_unencrypted_log_hashes, @@ -194,7 +221,7 @@ mod tests { unconstrained fn ordering_of_note_hashes_and_nullifiers() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(10); + builder.previous_kernel.append_new_note_hashes(10, false); builder.previous_kernel.append_new_nullifiers(10); let sorted_note_hashes = builder.previous_kernel.new_note_hashes.storage; @@ -284,16 +311,18 @@ mod tests { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); // expect 2 non-revertible note hashes - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_new_note_hashes(2, true); builder.previous_kernel.end_setup(); // expect 2 revertible note hashes - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_new_note_hashes(2, true); let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; + let new_note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; let public_inputs = builder.execute(); let siloed_note_hashes = builder.compute_output_note_hashes(new_note_hashes); + let public_note_logs = builder.compute_output_note_logs(new_note_logs); assert( array_eq( @@ -302,19 +331,54 @@ mod tests { ) ); + assert( + array_eq( + public_inputs.end_non_revertible.note_encrypted_logs_hashes, + [public_note_logs[0], public_note_logs[1]] + ) + ); + assert( array_eq( public_inputs.end.new_note_hashes, [siloed_note_hashes[2], siloed_note_hashes[3]] ) ); + + assert( + array_eq( + public_inputs.end.note_encrypted_logs_hashes, + [public_note_logs[2], public_note_logs[3]] + ) + ); + + let revertible_logs_len = (new_note_logs[2].length + new_note_logs[3].length) as u32; + let non_revertible_logs_len = (new_note_logs[0].length + new_note_logs[1].length) as u32; + + assert_eq( + public_inputs.end.gas_used, Gas::new( + (2 * DA_BYTES_PER_FIELD + revertible_logs_len) * DA_GAS_PER_BYTE, + 0 + ) + ); + assert_eq(public_inputs.end.encrypted_log_preimages_length as u32, revertible_logs_len); + assert_eq( + public_inputs.end_non_revertible.gas_used, Gas::new( + (3 * DA_BYTES_PER_FIELD + non_revertible_logs_len) * DA_GAS_PER_BYTE, + 0 + ) + + Gas::tx_overhead() + ); + assert_eq( + public_inputs.end_non_revertible.encrypted_log_preimages_length as u32, non_revertible_logs_len + ); } #[test(should_fail_with="Non empty note hash read requests")] unconstrained fn non_empty_note_hash_read_requests() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); - builder.previous_kernel.add_read_request_for_pending_note_hash(1); + builder.previous_kernel.append_new_note_hashes(3, false); + let _void = builder.previous_kernel.add_read_request_for_pending_note_hash(1); builder.failed(); } @@ -322,14 +386,14 @@ mod tests { unconstrained fn non_empty_nullifier_read_requests() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.append_new_nullifiers(3); - builder.previous_kernel.add_read_request_for_pending_nullifier(1); + let _void = builder.previous_kernel.add_read_request_for_pending_nullifier(1); builder.failed(); } #[test(should_fail_with="Non empty nullifier key validation requests")] unconstrained fn non_empty_nullifier_key_validations() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.add_request_for_nullifier_key_validation(GrumpkinPoint::new(1, 2), 27); + let _void = builder.previous_kernel.add_request_for_nullifier_key_validation(GrumpkinPoint::new(1, 2), 27); builder.failed(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_arrays.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_arrays.nr index 048511b151c..a8c1b2f6efd 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_arrays.nr @@ -1,6 +1,6 @@ use crate::tests::private_call_data_validator_builder::PrivateCallDataValidatorBuilder; use dep::types::{ - abis::{note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest, side_effect::SideEffect}, + abis::{note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest, log_hash::{LogHash, NoteLogHash}}, address::EthAddress, grumpkin_point::GrumpkinPoint, messaging::l2_to_l1_message::L2ToL1Message }; @@ -113,8 +113,8 @@ fn validate_arrays_malformed_encrypted_logs_hashes_fails() { builder.private_call.public_inputs.encrypted_logs_hashes.extend_from_array( [ - SideEffect { value: 0, counter: 0 }, - SideEffect { value: 9123, counter: 1 } + LogHash { value: 0, counter: 0, length: 0 }, + LogHash { value: 9123, counter: 1, length: 2 } ] ); @@ -127,8 +127,22 @@ fn validate_arrays_malformed_unencrypted_logs_hashes_fails() { builder.private_call.public_inputs.unencrypted_logs_hashes.extend_from_array( [ - SideEffect { value: 0, counter: 0 }, - SideEffect { value: 9123, counter: 1 } + LogHash { value: 0, counter: 0, length: 0 }, + LogHash { value: 9123, counter: 1, length: 2 } + ] + ); + + builder.validate(); +} + +#[test(should_fail_with="invalid array")] +fn input_validation_malformed_arrays_note_logs() { + let mut builder = PrivateCallDataValidatorBuilder::new(); + + builder.private_call.public_inputs.note_encrypted_logs_hashes.extend_from_array( + [ + NoteLogHash { value: 0, counter: 0, length: 0, note_hash_counter: 0 }, + NoteLogHash { value: 9123, counter: 2, length: 2, note_hash_counter: 1 } ] ); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call.nr index 947e7895c6d..2852f3048da 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call.nr @@ -1,6 +1,6 @@ use crate::tests::private_call_data_validator_builder::PrivateCallDataValidatorBuilder; use dep::types::{ - abis::{note_hash::NoteHash, nullifier::Nullifier, side_effect::SideEffect}, address::EthAddress, + abis::{note_hash::NoteHash, nullifier::Nullifier, log_hash::LogHash}, address::EthAddress, messaging::l2_to_l1_message::L2ToL1Message }; @@ -83,7 +83,7 @@ fn validate_call_is_static_creating_l2_to_l1_msgs_fails() { fn validate_call_is_static_creating_encrypted_logs_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.public_inputs.encrypted_logs_hashes.push(SideEffect { value: 9123, counter: 1 }); + builder.private_call.public_inputs.encrypted_logs_hashes.push(LogHash { value: 9123, counter: 1, length: 2 }); builder.validate(); } @@ -92,7 +92,7 @@ fn validate_call_is_static_creating_encrypted_logs_hashes_fails() { fn validate_call_is_static_creating_unencrypted_logs_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.public_inputs.unencrypted_logs_hashes.push(SideEffect { value: 9123, counter: 1 }); + builder.private_call.public_inputs.unencrypted_logs_hashes.push(LogHash { value: 9123, counter: 1, length: 2 }); builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call_requests.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call_requests.nr index 8747c02df9d..58fede8fb72 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/validate_call_requests.nr @@ -201,7 +201,7 @@ fn validate_public_call_requests_more_hashes_fails() { fn validate_teardown_call_request_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(false); + builder.private_call.add_teardown_call_request(false); builder.validate(); } @@ -210,7 +210,7 @@ fn validate_teardown_call_request_succeeds() { fn validate_teardown_call_request_delegate_calls_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); builder.validate(); } @@ -219,7 +219,7 @@ fn validate_teardown_call_request_delegate_calls_succeeds() { fn validate_teardown_call_request_incorrect_hash_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); // Change the hash to be a different value. builder.private_call.public_teardown_call_request.hash += 1; @@ -230,7 +230,7 @@ fn validate_teardown_call_request_incorrect_hash_fails() { fn validate_teardown_call_request_incorrect_caller_address_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); // Change the caller contract address to be a different value. builder.private_call.public_teardown_call_request.caller_contract_address.inner += 1; @@ -241,7 +241,7 @@ fn validate_teardown_call_request_incorrect_caller_address_fails() { fn validate_teardown_call_request_incorrect_caller_storage_contract_address_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); // Change the storage contract to be a different value. builder.private_call.public_teardown_call_request.caller_context.storage_contract_address.inner += 1; @@ -252,7 +252,7 @@ fn validate_teardown_call_request_incorrect_caller_storage_contract_address_fail fn validate_teardown_call_request_incorrect_caller_msg_sender_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); // Change the msg_sender to be a different value. builder.private_call.public_teardown_call_request.caller_context.msg_sender.inner += 1; @@ -263,7 +263,7 @@ fn validate_teardown_call_request_incorrect_caller_msg_sender_fails() { fn validate_teardown_call_request_fewer_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); // Remove the call stack item hash. builder.private_call.public_inputs.public_teardown_function_hash = 0; @@ -274,7 +274,7 @@ fn validate_teardown_call_request_fewer_hashes_fails() { fn validate_teardown_call_request_more_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.add_teaddown_call_request(true); + builder.private_call.add_teardown_call_request(true); // Remove the call request. builder.private_call.public_teardown_call_request = CallRequest::empty(); 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 3c0e9b0fbe1..f3d0717b994 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, side_effect::SideEffect, + public_data_update_request::PublicDataUpdateRequest, log_hash::LogHash, global_variables::GlobalVariables, combined_constant_data::CombinedConstantData }, address::AztecAddress, @@ -95,6 +95,7 @@ pub fn initialize_emitted_end_values( circuit_outputs.end.public_data_update_requests = array_to_bounded_vec(start.public_data_update_requests); circuit_outputs.end.unencrypted_logs_hashes = array_to_bounded_vec(start.unencrypted_logs_hashes); circuit_outputs.end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length; + circuit_outputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(start.note_encrypted_logs_hashes); circuit_outputs.end.encrypted_logs_hashes = array_to_bounded_vec(start.encrypted_logs_hashes); circuit_outputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; } @@ -106,6 +107,7 @@ pub fn initialize_emitted_end_values( circuit_outputs.end_non_revertible.public_data_update_requests = array_to_bounded_vec(start_non_revertible.public_data_update_requests); circuit_outputs.end_non_revertible.unencrypted_logs_hashes = array_to_bounded_vec(start_non_revertible.unencrypted_logs_hashes); circuit_outputs.end_non_revertible.unencrypted_log_preimages_length = start_non_revertible.unencrypted_log_preimages_length; + circuit_outputs.end_non_revertible.note_encrypted_logs_hashes = array_to_bounded_vec(start_non_revertible.note_encrypted_logs_hashes); circuit_outputs.end_non_revertible.encrypted_logs_hashes = array_to_bounded_vec(start_non_revertible.encrypted_logs_hashes); circuit_outputs.end_non_revertible.encrypted_log_preimages_length = start_non_revertible.encrypted_log_preimages_length; @@ -160,10 +162,8 @@ fn perform_static_call_checks(public_call: PublicCallData) { let new_l2_to_l1_msgs_length = array_length(public_inputs.new_l2_to_l1_msgs); assert(new_l2_to_l1_msgs_length == 0, "new_l2_to_l1_msgs must be empty for static calls"); - // TODO: reevaluate when implementing https://github.com/AztecProtocol/aztec-packages/issues/1165 - // This 4 magical number is the minimum size of the buffer, since it has to store the total length of all the serialized logs. assert( - public_inputs.unencrypted_log_preimages_length == 4, "No unencrypted logs are allowed for static calls" + public_inputs.unencrypted_log_preimages_length == 0, "No unencrypted logs are allowed for static calls" ); } } @@ -571,7 +571,7 @@ 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; // TODO(Miranda): silo logs here once we have finalised struct - 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 { @@ -590,7 +590,7 @@ pub fn propagate_new_unencrypted_logs_non_revertible( // new unencrypted logs let new_logs = public_call.call_stack_item.public_inputs.unencrypted_logs_hashes; // TODO(Miranda): silo logs here once we have finalised struct - 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 { 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 206b8de6ffa..1e85632b895 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 @@ -186,23 +186,30 @@ mod tests { fn circuit_outputs_should_be_correctly_populated_with_previous_commitments() { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); let contract_address = builder.public_call.contract_address; - // Setup 2 new note hashes on the previous kernel. - builder.previous_kernel.append_new_note_hashes(2); + // Setup 2 new note hashes and logs on the previous kernel. + builder.previous_kernel.append_new_note_hashes(2, true); let previous = builder.previous_kernel.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash); // Setup 2 new note hashes on the current public inputs. let current = [ - NoteHash { value: previous[1].value + 1, counter: 3 }, - NoteHash { value: previous[1].value + 2, counter: 4 } + NoteHash { value: previous[1].value + 1, counter: 5 }, + NoteHash { value: previous[1].value + 2, counter: 6 } ]; + let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; builder.public_call.public_inputs.new_note_hashes.extend_from_array(current); let siloed = current.map(|c: NoteHash| silo_note_hash(contract_address, c.value)); let new_note_hashes = [ - previous[0], previous[1], NoteHash { value: siloed[0], counter: 3 }, NoteHash { value: siloed[1], counter: 4 } + previous[0], previous[1], NoteHash { value: siloed[0], counter: 5 }, NoteHash { value: siloed[1], counter: 6 } ]; let public_inputs = builder.execute(); assert(array_eq(public_inputs.end.new_note_hashes, new_note_hashes)); + assert( + array_eq( + public_inputs.end.note_encrypted_logs_hashes, + [note_logs[0], note_logs[1]] + ) + ); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index a109bdbeb78..31ae3dcf3e0 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -1,13 +1,19 @@ -use dep::types::{abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier}, traits::is_empty}; +use dep::types::{ + abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier, log_hash::NoteLogHash}, + traits::is_empty +}; -pub fn verify_squashed_transient_note_hashes_and_nullifiers( +pub fn verify_squashed_transient_note_hashes_and_nullifiers( note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], nullifiers: [ScopedNullifier; NUM_NULLIFIERS], + note_logs: [NoteLogHash; NUM_LOGS], expected_note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], expected_nullifiers: [ScopedNullifier; NUM_NULLIFIERS], + expected_note_logs: [NoteLogHash; NUM_LOGS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], - transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS] -) { + transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS], + transient_note_hash_indexes_for_logs: [u64; NUM_LOGS] +) -> Field { let mut note_hashes_kept = 0; let mut note_hashes_removed = 0; for i in 0..NUM_NOTE_HASHES { @@ -54,37 +60,76 @@ pub fn verify_squashed_transient_note_hashes_and_nullifiers { + struct TestDataBuilder { num_note_hashes: u64, num_nullifiers: u64, note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], nullifiers: [ScopedNullifier; NUM_NULLIFIERS], + note_logs: [NoteLogHash; NUM_LOGS], expected_note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], expected_nullifiers: [ScopedNullifier; NUM_NULLIFIERS], + expected_note_logs: [NoteLogHash; NUM_LOGS], transient_nullifier_indexes_for_note_hashes: [u64; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u64; NUM_NULLIFIERS], + transient_note_hash_indexes_for_logs: [u64; NUM_LOGS] } - impl TestDataBuilder { - pub fn default() -> TestDataBuilder<3, 3> { + impl TestDataBuilder { + pub fn default() -> TestDataBuilder<3, 3, 2> { let contract_address = AztecAddress::from_field(987654); let note_hashes = [ @@ -99,25 +144,35 @@ mod tests { Nullifier { value: 66, counter: 600, note_hash: 0 }.scope(contract_address) ]; + let note_logs = [ + NoteLogHash { value: 77, counter: 700, length: 70, note_hash_counter: 100 }, + NoteLogHash { value: 88, counter: 800, length: 80, note_hash_counter: 200 } + ]; + let expected_note_hashes = [note_hashes[1], ScopedNoteHash::empty(), ScopedNoteHash::empty()]; let expected_nullifiers = [nullifiers[2], ScopedNullifier::empty(), ScopedNullifier::empty()]; + let expected_note_logs = [note_logs[1], NoteLogHash::empty()]; let transient_nullifier_indexes_for_note_hashes = [1, 3, 0]; let transient_note_hash_indexes_for_nullifiers = [2, 0, 3]; + let transient_note_hash_indexes_for_logs = [0, 3]; TestDataBuilder { num_note_hashes: 3, num_nullifiers: 3, note_hashes, nullifiers, + note_logs, expected_note_hashes, expected_nullifiers, + expected_note_logs, transient_nullifier_indexes_for_note_hashes, - transient_note_hash_indexes_for_nullifiers + transient_note_hash_indexes_for_nullifiers, + transient_note_hash_indexes_for_logs } } - pub fn default_all_clear() -> TestDataBuilder<3, 3> { + pub fn default_all_clear() -> TestDataBuilder<3, 3, 4> { let contract_address = AztecAddress::from_field(987654); let note_hashes = [ @@ -132,38 +187,68 @@ mod tests { Nullifier { value: 66, counter: 600, note_hash: 22 }.scope(contract_address) ]; + // tests removing two logs for one note hash + let note_logs = [ + NoteLogHash { value: 77, counter: 700, length: 70, note_hash_counter: 100 }, + NoteLogHash { value: 88, counter: 800, length: 80, note_hash_counter: 300 }, + NoteLogHash { value: 99, counter: 900, length: 90, note_hash_counter: 200 }, + NoteLogHash { value: 111, counter: 1000, length: 100, note_hash_counter: 300 } + ]; + let expected_note_hashes = [ScopedNoteHash::empty(); 3]; let expected_nullifiers = [ScopedNullifier::empty(); 3]; + let expected_note_logs = [NoteLogHash::empty(); 4]; let transient_nullifier_indexes_for_note_hashes = [1, 2, 0]; let transient_note_hash_indexes_for_nullifiers = [2, 0, 1]; + let transient_note_hash_indexes_for_logs = [0, 2, 1, 2]; TestDataBuilder { num_note_hashes: 3, num_nullifiers: 3, note_hashes, nullifiers, + note_logs, expected_note_hashes, expected_nullifiers, + expected_note_logs, transient_nullifier_indexes_for_note_hashes, - transient_note_hash_indexes_for_nullifiers + transient_note_hash_indexes_for_nullifiers, + transient_note_hash_indexes_for_logs } } pub fn verify(self) { - verify_squashed_transient_note_hashes_and_nullifiers( + let _void = verify_squashed_transient_note_hashes_and_nullifiers( self.note_hashes, self.nullifiers, + self.note_logs, self.expected_note_hashes, self.expected_nullifiers, + self.expected_note_logs, self.transient_nullifier_indexes_for_note_hashes, - self.transient_note_hash_indexes_for_nullifiers + self.transient_note_hash_indexes_for_nullifiers, + self.transient_note_hash_indexes_for_logs ); } + + pub fn verify_length(self) -> Field { + verify_squashed_transient_note_hashes_and_nullifiers( + self.note_hashes, + self.nullifiers, + self.note_logs, + self.expected_note_hashes, + self.expected_nullifiers, + self.expected_note_logs, + self.transient_nullifier_indexes_for_note_hashes, + self.transient_note_hash_indexes_for_nullifiers, + self.transient_note_hash_indexes_for_logs + ) + } } #[test] - fn verify_squahed_transient_note_hashes_and_nullifiers_with_propagated_values() { + fn verify_squashed_transient_note_hashes_and_nullifiers_with_propagated_values() { TestDataBuilder::default().verify(); } @@ -184,6 +269,10 @@ mod tests { builder.transient_note_hash_indexes_for_nullifiers[2] = builder.num_note_hashes; builder.expected_nullifiers[0] = builder.nullifiers[2]; + // Keep the log at index 2. + builder.transient_note_hash_indexes_for_logs[2] = builder.num_note_hashes; + builder.expected_note_logs[0] = builder.note_logs[2]; + builder.verify(); } @@ -277,6 +366,51 @@ mod tests { builder.verify(); } + #[test(should_fail_with="Empty log must be padded to the right")] + fn unexpected_log_value() { + let mut builder = TestDataBuilder::default_all_clear(); + + builder.expected_note_logs[2].value = 1; + + builder.verify(); + } + + #[test(should_fail_with="Propagated note log does not match")] + fn wrong_expected_log_value() { + let mut builder = TestDataBuilder::default(); + + builder.expected_note_logs[0].value += 1; + + builder.verify(); + } + + #[test(should_fail_with="Propagated note log does not match")] + fn wrong_expected_log_counter() { + let mut builder = TestDataBuilder::default(); + + builder.expected_note_logs[0].counter += 1; + + builder.verify(); + } + + #[test(should_fail_with="Hinted transient note log not nullified")] + fn log_not_nullified() { + let mut builder = TestDataBuilder::default(); + + builder.transient_note_hash_indexes_for_logs[1] = 1; + + builder.verify(); + } + + #[test(should_fail_with="Value of the hinted transient note hash does not match log")] + fn wrong_log_note_hash() { + let mut builder = TestDataBuilder::default(); + + builder.note_logs[0].note_hash_counter += 1; + + builder.verify(); + } + #[test(should_fail_with="Invalid transient nullifier index hint")] fn propagate_more_note_hashes_than_nullifiers() { let mut builder = TestDataBuilder::default_all_clear(); @@ -298,4 +432,25 @@ mod tests { builder.verify(); } + + #[test(should_fail_with="Empty log must be padded to the right")] + fn remove_too_many_logs() { + let mut builder = TestDataBuilder::default(); + // Remove the log at index 1, but don't remove from expected_logs + builder.note_logs[1].note_hash_counter = 300; + builder.transient_note_hash_indexes_for_logs[1] = 2; + + builder.verify(); + } + + #[test] + fn remove_correct_logs_len() { + let mut builder = TestDataBuilder::default(); + let expected_len_removed = builder.note_logs[0].length; + assert_eq(builder.verify_length(), expected_len_removed); + + let mut builder = TestDataBuilder::default_all_clear(); + let expected_len_removed = builder.note_logs.fold(0, |a, b: NoteLogHash| a + b.length); + assert_eq(builder.verify_length(), expected_len_removed); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr index 264ff0af167..faf9bb69102 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/squash_transient_data.nr @@ -1,4 +1,4 @@ -use dep::types::abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier}; +use dep::types::abis::{note_hash::ScopedNoteHash, nullifier::ScopedNullifier, log_hash::NoteLogHash}; pub fn squash_transient_note_hashes(note_hashes: [ScopedNoteHash; N]) -> [ScopedNoteHash; N] { let mut final_note_hashes = [ScopedNoteHash::empty(); N]; @@ -29,3 +29,22 @@ pub fn squash_transient_nullifiers(nullifiers: [ScopedNullifier; N]) -> [Scop final_nullifiers } + +pub fn squash_transient_logs( + logs: [NoteLogHash; N], + note_hashes: [ScopedNoteHash; M] +) -> [NoteLogHash; N] { + let mut final_logs = [NoteLogHash::empty(); N]; + + let mut num_logs = 0; + for i in 0..N { + let mut log = logs[i]; + let is_nullified = note_hashes.any(|n: ScopedNoteHash| (n.counter() == log.note_hash_counter) & (n.nullifier_counter != 0)); + if !is_nullified { + final_logs[num_logs] = log; + num_logs += 1; + } + } + + final_logs +} 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 b918335e232..17a45be11c3 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 @@ -124,7 +124,7 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) - ) } -global TX_EFFECTS_HASH_INPUT_FIELDS = 198; +global TX_EFFECTS_HASH_INPUT_FIELDS = 199; // Computes the tx effects hash for a base rollup (a single transaction) // TODO(Alvaro): This is too slow for brillig without the array optimization @@ -142,6 +142,7 @@ pub fn compute_tx_effects_hash( // 2 l2 -> l1 messages -> 2 fields // 32 public data update requests -> 64 fields // 1 contract deployments -> 3 fields + // 1 note encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! // 1 encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! // 1 unencrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! let mut txs_effects_hash_input = [0; TX_EFFECTS_HASH_INPUT_FIELDS]; @@ -150,6 +151,7 @@ pub fn compute_tx_effects_hash( let new_nullifiers = combined.new_nullifiers; let new_l2_to_l1_msgs = combined.new_l2_to_l1_msgs; let public_data_update_requests = combined.public_data_update_requests; + 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; @@ -185,6 +187,10 @@ pub fn compute_tx_effects_hash( } offset += MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2; + txs_effects_hash_input[offset] = note_encrypted_logs_hash; + + offset += NUM_ENCRYPTED_LOGS_HASHES_PER_TX; + txs_effects_hash_input[offset] = encrypted_logs_hash; offset += NUM_ENCRYPTED_LOGS_HASHES_PER_TX; @@ -217,6 +223,7 @@ fn consistent_TX_EFFECTS_HASH_INPUT_FIELDS() { + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + MAX_NEW_L2_TO_L1_MSGS_PER_TX + NUM_ENCRYPTED_LOGS_HASHES_PER_TX + + NUM_ENCRYPTED_LOGS_HASHES_PER_TX + NUM_UNENCRYPTED_LOGS_HASHES_PER_TX; assert(TX_EFFECTS_HASH_INPUT_FIELDS == expected_size, "tx effects hash input size is incorrect"); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr index 878bb933b1f..8c12f9caeb1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr @@ -13,6 +13,7 @@ mod combined_constant_data; mod side_effect; mod read_request; +mod log_hash; mod note_hash; mod nullifier; mod nullifier_key_validation_request; 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 452cac06dc0..1c224a9d35f 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 @@ -1,5 +1,5 @@ use crate::{ - hash::compute_tx_logs_hash, + hash::{compute_tx_logs_hash, compute_tx_note_logs_hash}, abis::{ accumulated_data::public_accumulated_data::PublicAccumulatedData, note_hash::NoteHash, nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect, @@ -17,6 +17,7 @@ struct CombinedAccumulatedData { new_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_encrypted_logs_hash: Field, encrypted_logs_hash: Field, unencrypted_logs_hash: Field, @@ -33,6 +34,12 @@ struct CombinedAccumulatedData { impl CombinedAccumulatedData { pub fn combine(non_revertible: PublicAccumulatedData, revertible: PublicAccumulatedData) -> Self { // TODO(Miranda): Hash here or elsewhere? + let note_encrypted_logs_hash = compute_tx_note_logs_hash( + array_merge( + non_revertible.note_encrypted_logs_hashes, + revertible.note_encrypted_logs_hashes + ) + ); let encrypted_logs_hash = compute_tx_logs_hash( array_merge( non_revertible.encrypted_logs_hashes, @@ -52,6 +59,7 @@ impl CombinedAccumulatedData { non_revertible.new_l2_to_l1_msgs, revertible.new_l2_to_l1_msgs ), + note_encrypted_logs_hash, encrypted_logs_hash, unencrypted_logs_hash, encrypted_log_preimages_length: non_revertible.encrypted_log_preimages_length @@ -73,6 +81,7 @@ impl Empty for CombinedAccumulatedData { new_note_hashes: [0; MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [0; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [0; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_encrypted_logs_hash: 0, encrypted_logs_hash: 0, unencrypted_logs_hash: 0, encrypted_log_preimages_length: 0, @@ -90,6 +99,7 @@ impl Serialize for CombinedAccumulatedData { fields.extend_from_array(self.new_note_hashes); fields.extend_from_array(self.new_nullifiers); fields.extend_from_array(self.new_l2_to_l1_msgs); + fields.push(self.note_encrypted_logs_hash); fields.push(self.encrypted_logs_hash); fields.push(self.unencrypted_logs_hash); fields.push(self.encrypted_log_preimages_length); @@ -115,6 +125,7 @@ impl Deserialize for CombinedAccumulatedData { new_note_hashes: reader.read_array([0; MAX_NEW_NOTE_HASHES_PER_TX]), new_nullifiers: reader.read_array([0; MAX_NEW_NULLIFIERS_PER_TX]), new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_TX]), + note_encrypted_logs_hash: reader.read(), encrypted_logs_hash: reader.read(), unencrypted_logs_hash: reader.read(), encrypted_log_preimages_length: reader.read(), @@ -132,6 +143,7 @@ impl Eq for CombinedAccumulatedData { (self.new_note_hashes == other.new_note_hashes) & (self.new_nullifiers == other.new_nullifiers) & (self.new_l2_to_l1_msgs == other.new_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.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 4984175614c..8d225670ec8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ call_request::CallRequest, gas::Gas, note_hash::ScopedNoteHash, nullifier::ScopedNullifier, - side_effect::SideEffect + log_hash::{LogHash, NoteLogHash} }, traits::{Serialize, Deserialize, Eq, Empty}, messaging::l2_to_l1_message::ScopedL2ToL1Message, utils::reader::Reader @@ -9,7 +9,7 @@ use crate::{ use crate::constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, PRIVATE_ACCUMULATED_DATA_LENGTH + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, PRIVATE_ACCUMULATED_DATA_LENGTH }; struct PrivateAccumulatedData { @@ -17,8 +17,9 @@ struct PrivateAccumulatedData { new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [LogHash; 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. @@ -45,6 +46,10 @@ impl Serialize for PrivateAccumulatedData { fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize()); } + for i in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { + fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize()); + } + for i in 0..MAX_ENCRYPTED_LOGS_PER_TX { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } @@ -78,8 +83,9 @@ impl Deserialize for PrivateAccumulatedData { new_note_hashes: reader.read_struct_array(ScopedNoteHash::deserialize, [ScopedNoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX]), new_nullifiers: reader.read_struct_array(ScopedNullifier::deserialize, [ScopedNullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX]), new_l2_to_l1_msgs: reader.read_struct_array(ScopedL2ToL1Message::deserialize, [ScopedL2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_TX]), - encrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), - unencrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), + note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::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]), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), private_call_stack: reader.read_struct_array(CallRequest::deserialize, [CallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX]), @@ -95,6 +101,7 @@ impl Eq for PrivateAccumulatedData { (self.new_note_hashes == other.new_note_hashes) & (self.new_nullifiers == other.new_nullifiers) & (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & @@ -110,8 +117,9 @@ impl Empty for PrivateAccumulatedData { new_note_hashes: [ScopedNoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [ScopedNullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hashes: [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + note_encrypted_logs_hashes: [NoteLogHash::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], encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, private_call_stack: [CallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 08597103279..ecf583f00e9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -1,5 +1,5 @@ use crate::{ - hash::compute_tx_logs_hash, + hash::{compute_tx_logs_hash, compute_tx_note_logs_hash}, abis::{ gas::Gas, accumulated_data::{ @@ -8,13 +8,13 @@ use crate::{ public_accumulated_data_builder::PublicAccumulatedDataBuilder }, call_request::CallRequest, note_hash::{NoteHash, ScopedNoteHash}, nullifier::ScopedNullifier, - public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect + public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash} }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Empty, is_empty} }; @@ -28,8 +28,9 @@ struct PrivateAccumulatedDataBuilder { new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + note_encrypted_logs_hashes: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -47,6 +48,7 @@ impl PrivateAccumulatedDataBuilder { new_note_hashes: self.new_note_hashes.storage, new_nullifiers: self.new_nullifiers.storage, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -58,6 +60,7 @@ impl PrivateAccumulatedDataBuilder { pub fn to_combined(self, teardown_gas: Gas) -> CombinedAccumulatedData { // TODO(Miranda): Hash here or elsewhere? + let note_encrypted_logs_hash = compute_tx_note_logs_hash(self.note_encrypted_logs_hashes.storage); let encrypted_logs_hash = compute_tx_logs_hash(self.encrypted_logs_hashes.storage); let unencrypted_logs_hash = compute_tx_logs_hash(self.unencrypted_logs_hashes.storage); let gas_used = self.to_metered_gas_used() + Gas::tx_overhead() + teardown_gas; @@ -66,6 +69,7 @@ impl PrivateAccumulatedDataBuilder { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), + note_encrypted_logs_hash, encrypted_logs_hash, unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -172,12 +176,30 @@ impl PrivateAccumulatedDataBuilder { } } + for i in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { + let note_encrypted_logs_hash_private = self.note_encrypted_logs_hashes.storage[i]; + let note_encrypted_logs_hash = note_encrypted_logs_hash_private.expose_to_public(); + if note_encrypted_logs_hash_private.counter < min_revertible_side_effect_counter { + non_revertible_builder.note_encrypted_logs_hashes.push(note_encrypted_logs_hash); + non_revertible_builder.encrypted_log_preimages_length += note_encrypted_logs_hash.length; + non_revertible_da_gas_used += note_encrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; + } else { + revertible_builder.note_encrypted_logs_hashes.push(note_encrypted_logs_hash); + revertible_builder.encrypted_log_preimages_length += note_encrypted_logs_hash.length; + revertible_da_gas_used += note_encrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; + } + } + for i in 0..MAX_ENCRYPTED_LOGS_PER_TX { let encrypted_logs_hash = self.encrypted_logs_hashes.storage[i]; if encrypted_logs_hash.counter < min_revertible_side_effect_counter { non_revertible_builder.encrypted_logs_hashes.push(encrypted_logs_hash); + non_revertible_builder.encrypted_log_preimages_length += encrypted_logs_hash.length; + non_revertible_da_gas_used += encrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; } else { revertible_builder.encrypted_logs_hashes.push(encrypted_logs_hash); + revertible_builder.encrypted_log_preimages_length += encrypted_logs_hash.length; + revertible_da_gas_used += encrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; } } @@ -185,16 +207,25 @@ impl PrivateAccumulatedDataBuilder { let unencrypted_logs_hash = self.unencrypted_logs_hashes.storage[i]; if unencrypted_logs_hash.counter < min_revertible_side_effect_counter { non_revertible_builder.unencrypted_logs_hashes.push(unencrypted_logs_hash); + non_revertible_builder.unencrypted_log_preimages_length += unencrypted_logs_hash.length; + non_revertible_da_gas_used += unencrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; } else { revertible_builder.unencrypted_logs_hashes.push(unencrypted_logs_hash); + revertible_builder.unencrypted_log_preimages_length += unencrypted_logs_hash.length; + revertible_da_gas_used += unencrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; } } - // TODO(1641) & TODO(4712): Once we track logs with more info, including individual lens, split here - revertible_builder.encrypted_log_preimages_length = self.encrypted_log_preimages_length; - revertible_builder.unencrypted_log_preimages_length = self.unencrypted_log_preimages_length; - - revertible_da_gas_used += DA_GAS_PER_BYTE * (self.encrypted_log_preimages_length as u32 + self.unencrypted_log_preimages_length as u32); + assert( + revertible_builder.encrypted_log_preimages_length + + non_revertible_builder.encrypted_log_preimages_length + == self.encrypted_log_preimages_length, "encrypted logs length mismatch" + ); + assert( + revertible_builder.unencrypted_log_preimages_length + + non_revertible_builder.unencrypted_log_preimages_length + == self.unencrypted_log_preimages_length, "unencrypted logs length mismatch" + ); revertible_builder.gas_used = Gas::new(revertible_da_gas_used, revertible_l2_gas_used); non_revertible_builder.gas_used = Gas::tx_overhead() + Gas::new(non_revertible_da_gas_used, non_revertible_l2_gas_used); @@ -208,7 +239,7 @@ mod tests { accumulated_data::private_accumulated_data_builder::PrivateAccumulatedDataBuilder, gas::Gas, call_request::CallRequest, caller_context::CallerContext, note_hash::NoteHash, nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, - side_effect::SideEffect + log_hash::{LogHash, NoteLogHash} }, address::{AztecAddress, EthAddress}, messaging::l2_to_l1_message::L2ToL1Message, utils::arrays::array_eq, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} @@ -219,22 +250,24 @@ mod tests { let mut builder = PrivateAccumulatedDataBuilder::empty(); let contract_address = AztecAddress::from_field(8989); - let min_revertible_side_effect_counter = 7; + let min_revertible_side_effect_counter = 13; - // Non revertible: counter < 7 + // Non revertible: counter < 13 let non_revertible_note_hashes = [ NoteHash { value: 1, counter: 1 }.scope(20, contract_address), - NoteHash { value: 2, counter: 3 }.scope(5, contract_address) + NoteHash { value: 2, counter: 4 }.scope(5, contract_address) ]; + let non_revertible_note_logs = [NoteLogHash { value: 11, counter: 2, length: 2, note_hash_counter: 1 }]; + let non_revertible_nullifiers = [ - Nullifier { value: 10, note_hash: 1, counter: 2 }.scope(contract_address), - Nullifier { value: 20, note_hash: 2, counter: 4 }.scope(contract_address) + Nullifier { value: 10, note_hash: 1, counter: 3 }.scope(contract_address), + Nullifier { value: 20, note_hash: 2, counter: 5 }.scope(contract_address) ]; let non_revertible_l2_to_l1_messages = [ - L2ToL1Message { recipient: EthAddress::from_field(3030), content: 333333, counter: 5 }.scope(AztecAddress::from_field(9900)) + L2ToL1Message { recipient: EthAddress::from_field(3030), content: 333333, counter: 6 }.scope(AztecAddress::from_field(9900)) ]; let non_revertible_public_stack = [ @@ -242,32 +275,44 @@ mod tests { hash: 1, caller_contract_address: AztecAddress::from_field(1), caller_context: CallerContext::empty(), - start_side_effect_counter: 5, + start_side_effect_counter: 6, end_side_effect_counter: 0 }, CallRequest { hash: 2, caller_contract_address: AztecAddress::from_field(1), caller_context: CallerContext::empty(), - start_side_effect_counter: 6, + start_side_effect_counter: 7, end_side_effect_counter: 0 } ]; - // Revertible: counter >= 7 + let non_revertible_enc_log_hashes = [ + LogHash { value: 11, counter: 9, length: 2 }, + LogHash { value: 22, counter: 10, length: 2 } + ]; + + let non_revertible_unenc_log_hashes = [ + LogHash { value: 33, counter: 11, length: 5 }, + LogHash { value: 44, counter: 12, length: 5 } + ]; + + // Revertible: counter >= 13 let revertible_note_hashes = [ - NoteHash { value: 3, counter: 7 }.scope(15, contract_address), - NoteHash { value: 4, counter: 10 }.scope(0, contract_address) + NoteHash { value: 3, counter: 13 }.scope(15, contract_address), + NoteHash { value: 4, counter: 16 }.scope(0, contract_address) ]; + let revertible_note_logs = [NoteLogHash { value: 33, counter: 14, length: 2, note_hash_counter: 13 }]; + let revertible_nullifiers = [ - Nullifier { value: 30, note_hash: 3, counter: 8 }.scope(contract_address), - Nullifier { value: 40, note_hash: 4, counter: 11 }.scope(contract_address) + Nullifier { value: 30, note_hash: 3, counter: 15 }.scope(contract_address), + Nullifier { value: 40, note_hash: 4, counter: 18 }.scope(contract_address) ]; let revertible_l2_to_l1_messages = [ - L2ToL1Message { recipient: EthAddress::from_field(3030), content: 444444, counter: 13 }.scope(AztecAddress::from_field(7788)) + L2ToL1Message { recipient: EthAddress::from_field(3030), content: 444444, counter: 19 }.scope(AztecAddress::from_field(7788)) ]; let revertible_public_call_stack = [ @@ -275,11 +320,21 @@ mod tests { hash: 3, caller_contract_address: AztecAddress::from_field(3), caller_context: CallerContext::empty(), - start_side_effect_counter: 9, + start_side_effect_counter: 17, end_side_effect_counter: 0 } ]; + let revertible_enc_log_hashes = [ + LogHash { value: 55, counter: 20, length: 2 }, + LogHash { value: 66, counter: 21, length: 2 } + ]; + + let revertible_unenc_log_hashes = [ + LogHash { value: 77, counter: 22, length: 5 }, + LogHash { value: 88, counter: 23, length: 5 } + ]; + builder.new_note_hashes.extend_from_array(non_revertible_note_hashes); builder.new_note_hashes.extend_from_array(revertible_note_hashes); @@ -292,6 +347,20 @@ mod tests { builder.public_call_stack.extend_from_array(non_revertible_public_stack); builder.public_call_stack.extend_from_array(revertible_public_call_stack); + builder.note_encrypted_logs_hashes.extend_from_array(non_revertible_note_logs); + builder.note_encrypted_logs_hashes.extend_from_array(revertible_note_logs); + + builder.encrypted_logs_hashes.extend_from_array(non_revertible_enc_log_hashes); + builder.encrypted_logs_hashes.extend_from_array(revertible_enc_log_hashes); + builder.encrypted_log_preimages_length = 12; + + builder.unencrypted_logs_hashes.extend_from_array(non_revertible_unenc_log_hashes); + builder.unencrypted_logs_hashes.extend_from_array(revertible_unenc_log_hashes); + builder.unencrypted_log_preimages_length = 20; + + let public_non_revertible_note_logs = non_revertible_note_logs.map(|n: NoteLogHash| n.expose_to_public()); + let public_revertible_note_logs = revertible_note_logs.map(|n: NoteLogHash| n.expose_to_public()); + let (non_revertible, revertible) = builder.split_to_public(min_revertible_side_effect_counter, Gas::new(42, 17)); assert( @@ -314,6 +383,24 @@ mod tests { ); assert(array_eq(non_revertible.new_l2_to_l1_msgs, [333333])); assert(array_eq(non_revertible.public_call_stack, non_revertible_public_stack)); + assert( + array_eq( + non_revertible.note_encrypted_logs_hashes, + public_non_revertible_note_logs + ) + ); + assert( + array_eq( + non_revertible.encrypted_logs_hashes, + non_revertible_enc_log_hashes + ) + ); + assert( + array_eq( + non_revertible.unencrypted_logs_hashes, + non_revertible_unenc_log_hashes + ) + ); assert( array_eq( @@ -335,14 +422,40 @@ mod tests { ); assert(array_eq(revertible.new_l2_to_l1_msgs, [444444])); assert(array_eq(revertible.public_call_stack, revertible_public_call_stack)); + assert( + array_eq( + revertible.note_encrypted_logs_hashes, + public_revertible_note_logs + ) + ); + assert(array_eq(revertible.encrypted_logs_hashes, revertible_enc_log_hashes)); + assert( + array_eq( + revertible.unencrypted_logs_hashes, + revertible_unenc_log_hashes + ) + ); assert_eq( - revertible.gas_used, Gas::new(4 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 0) + Gas::new(42, 17) + revertible.gas_used, Gas::new( + (4 * DA_BYTES_PER_FIELD + + revertible.encrypted_log_preimages_length as u32 + + revertible.unencrypted_log_preimages_length as u32) + * DA_GAS_PER_BYTE, + 0 + ) + + Gas::new(42, 17) ); - print(non_revertible.gas_used); assert_eq( - non_revertible.gas_used, Gas::new(4 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 0) + Gas::tx_overhead() + non_revertible.gas_used, Gas::new( + (4 * DA_BYTES_PER_FIELD + + non_revertible.encrypted_log_preimages_length as u32 + + non_revertible.unencrypted_log_preimages_length as u32) + * DA_GAS_PER_BYTE, + 0 + ) + + Gas::tx_overhead() ); } } @@ -353,6 +466,7 @@ impl Empty for PrivateAccumulatedDataBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, 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 518a24b1675..06f23069398 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,12 +1,12 @@ use crate::{ abis::{ call_request::CallRequest, public_data_update_request::PublicDataUpdateRequest, gas::Gas, - note_hash::NoteHash, nullifier::Nullifier, side_effect::SideEffect + note_hash::NoteHash, nullifier::Nullifier, log_hash::{LogHash, NoteLogHash} }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, PUBLIC_ACCUMULATED_DATA_LENGTH + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, PUBLIC_ACCUMULATED_DATA_LENGTH }, traits::{Empty, Serialize, Deserialize}, utils::reader::Reader }; @@ -16,8 +16,9 @@ struct PublicAccumulatedData { new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [LogHash; 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. @@ -37,8 +38,9 @@ impl Empty for PublicAccumulatedData { new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [0; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hashes: [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + note_encrypted_logs_hashes: [NoteLogHash::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], encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], @@ -62,6 +64,10 @@ impl Serialize for PublicAccumulatedData { fields.extend_from_array(self.new_l2_to_l1_msgs); + for i in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { + fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize()); + } + for i in 0..MAX_ENCRYPTED_LOGS_PER_TX { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } @@ -97,8 +103,9 @@ impl Deserialize for PublicAccumulatedData { new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX]), new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX]), new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_TX]), - encrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), - unencrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), + note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::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]), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), public_data_update_requests: reader.read_struct_array(PublicDataUpdateRequest::deserialize, [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]), @@ -115,6 +122,7 @@ impl Eq for PublicAccumulatedData { (self.new_note_hashes == other.new_note_hashes) & (self.new_nullifiers == other.new_nullifiers) & (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & 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 dcf35fcf50f..104458d673c 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,12 +2,12 @@ use crate::{ abis::{ gas::Gas, accumulated_data::public_accumulated_data::PublicAccumulatedData, call_request::CallRequest, note_hash::NoteHash, nullifier::Nullifier, - public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffect + public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash} }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, traits::Empty }; @@ -17,8 +17,9 @@ struct PublicAccumulatedDataBuilder { new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + note_encrypted_logs_hashes: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -38,6 +39,7 @@ impl PublicAccumulatedDataBuilder { new_note_hashes: self.new_note_hashes.storage, new_nullifiers: self.new_nullifiers.storage, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -55,6 +57,7 @@ impl Empty for PublicAccumulatedDataBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, 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 new file mode 100644 index 00000000000..a88bf41fa5c --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr @@ -0,0 +1,126 @@ +use crate::{ + abis::side_effect::{Ordered, OrderedValue}, constants::{LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH}, + traits::{Empty, Serialize, Deserialize} +}; + +struct LogHash { + value: Field, + counter: u32, + length: Field, +} + +impl Ordered for LogHash { + fn counter(self) -> u32 { + self.counter + } +} + +impl OrderedValue for LogHash { + fn value(self) -> Field { + self.value + } + fn counter(self) -> u32 { + self.counter + } +} + +impl Eq for LogHash { + fn eq(self, other: LogHash) -> bool { + (self.value == other.value) + & (self.counter == other.counter) + & (self.length == other.length) + } +} + +impl Empty for LogHash { + fn empty() -> Self { + LogHash { + value: 0, + counter: 0, + length: 0, + } + } +} + +impl Serialize for LogHash { + fn serialize(self) -> [Field; LOG_HASH_LENGTH] { + [self.value, self.counter as Field, self.length] + } +} + +impl Deserialize for LogHash { + fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self { + Self { + value: values[0], + counter: values[1] as u32, + length: values[2], + } + } +} + +struct NoteLogHash { + value: Field, + counter: u32, + length: Field, + note_hash_counter: u32, +} + +impl NoteLogHash { + pub fn expose_to_public(self) -> NoteLogHash { + // Hide the actual counter and note hash counter when exposing it to the public kernel. + // The counter is usually note_hash.counter + 1, so it can be revealing. + NoteLogHash { value: self.value, counter: 0, length: self.length, note_hash_counter: 0 } + } +} + +impl Ordered for NoteLogHash { + fn counter(self) -> u32 { + self.counter + } +} + +impl OrderedValue for NoteLogHash { + fn value(self) -> Field { + self.value + } + fn counter(self) -> u32 { + self.counter + } +} + +impl Eq for NoteLogHash { + fn eq(self, other: NoteLogHash) -> bool { + (self.value == other.value) + & (self.counter == other.counter) + & (self.length == other.length) + & (self.note_hash_counter == other.note_hash_counter) + } +} + +impl Empty for NoteLogHash { + fn empty() -> Self { + NoteLogHash { + value: 0, + counter: 0, + length: 0, + note_hash_counter: 0, + } + } +} + +impl Serialize for NoteLogHash { + fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] { + [self.value, self.counter as Field, self.length, self.note_hash_counter as Field] + } +} + +impl Deserialize for NoteLogHash { + fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self { + Self { + value: values[0], + counter: values[1] as u32, + length: values[2], + note_hash_counter: values[3] as u32, + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 6c9f5e003d7..a34738bc2d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x092493dbe24afc80afb32c5ba43dde1eb447a66f88a36676a63cdd04f21636ad; + let test_data_empty_hash = 0x23e9b31fb9659181d8e6d941e95cc88a6d4d43c6b6ee316351528db772f419c0; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index c9b97cbcc0a..849e0c82b47 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings, nullifier_key_validation_request::NullifierKeyValidationRequest, note_hash::NoteHash, - nullifier::Nullifier, read_request::ReadRequest, side_effect::SideEffect + nullifier::Nullifier, read_request::ReadRequest, log_hash::{LogHash, NoteLogHash} }, constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, @@ -10,7 +10,7 @@ use crate::{ MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL }, header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message, traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader, @@ -41,8 +41,9 @@ struct PrivateCircuitPublicInputs { start_side_effect_counter : u32, end_side_effect_counter : u32, - encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_CALL], - unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_CALL], + note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL], + encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -76,6 +77,7 @@ impl Eq for PrivateCircuitPublicInputs { (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & (self.start_side_effect_counter == other.start_side_effect_counter) & (self.end_side_effect_counter == other.end_side_effect_counter) & + (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & @@ -120,6 +122,9 @@ impl Serialize for PrivateCircuitPublicInp } fields.push(self.start_side_effect_counter as Field); fields.push(self.end_side_effect_counter as Field); + for i in 0..self.note_encrypted_logs_hashes.len() { + fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize()); + } for i in 0..self.encrypted_logs_hashes.len() { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } @@ -159,8 +164,9 @@ impl Deserialize for PrivateCircuitPublicI new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, - encrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]), - unencrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), + note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]), + encrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]), + unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), historical_header: reader.read_struct(Header::deserialize), @@ -198,8 +204,9 @@ impl Empty for PrivateCircuitPublicInputs { new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : 0 as u32, end_side_effect_counter : 0 as u32, - encrypted_logs_hashes: [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_CALL], - unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL], + encrypted_logs_hashes: [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, historical_header: Header::empty(), @@ -221,6 +228,6 @@ fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x2a6e17b55aa91be7eb562d5fcf1bd67a0abed9098ec2d1a9c7e68541e7518326; + let test_data_empty_hash = 0x04f513d6a85e9d0c994d3c3764732e4486264190b3bf285257f41180f09a0b58; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index 8c24533dd6b..5e43de3424b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x1177a69fbc37f0ebdf290025414ff72504497840f174896bd427d0f30ec21c55; + let test_data_call_stack_item_request_hash = 0x23066ad690c088120f8397cfeb2ef5608d4517342c7ff9fcb713009933ef1c61; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x0f7624c0d5ea65fcec318c4d34cb3fcbf9c67435aebbf1548b3c90ef641424f8; + let test_data_call_stack_item_hash = 0x1236612a9ec71bcc83af597d523f1d05df071565067bc23276a4e64b72882c22; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index aafdd024ec8..ca3b173a1ad 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest, - side_effect::SideEffect, gas::Gas, global_variables::GlobalVariables + gas::Gas, global_variables::GlobalVariables, log_hash::LogHash }, address::AztecAddress, constants::{ @@ -36,7 +36,7 @@ struct PublicCircuitPublicInputs { start_side_effect_counter: u32, end_side_effect_counter: u32, - unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -130,7 +130,7 @@ impl Deserialize for PublicCircuitPublicInp new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, - unencrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), + unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), unencrypted_log_preimages_length: reader.read(), historical_header: reader.read_struct(Header::deserialize), global_variables: reader.read_struct(GlobalVariables::deserialize), @@ -168,7 +168,7 @@ impl Empty for PublicCircuitPublicInputs { new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0 as u32, end_side_effect_counter: 0 as u32, - unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], unencrypted_log_preimages_length: 0, historical_header: Header::empty(), global_variables: GlobalVariables::empty(), @@ -195,6 +195,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x132559f41b7adc7388e0cd52b91fd6837c296b2f9ec1b6d2ed046f7a56db18f8; + let test_data_empty_hash = 0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f; assert_eq(hash, test_data_empty_hash); } 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 d6e99a66310..a39b851d223 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -32,7 +32,8 @@ global MAX_PUBLIC_DATA_READS_PER_CALL: u64 = 16; global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u64 = 32; global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u64 = 2; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u64 = 2; -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 16; // THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_CALL +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 16; +global MAX_NOTE_ENCRYPTED_LOGS_PER_CALL: u64 = 16; global MAX_ENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. @@ -47,7 +48,8 @@ global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u64 = 128; global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u64 = 8; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u64 = 8; -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 64; // THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_TX +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 64; +global MAX_NOTE_ENCRYPTED_LOGS_PER_TX: u64 = 64; global MAX_ENCRYPTED_LOGS_PER_TX: u64 = 8; global MAX_UNENCRYPTED_LOGS_PER_TX: u64 = 8; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; @@ -162,6 +164,8 @@ global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; global SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; global READ_REQUEST_LENGTH = 2; +global LOG_HASH_LENGTH = 3; +global NOTE_LOG_HASH_LENGTH = 4; global NOTE_HASH_LENGTH = 2; global SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; global NULLIFIER_LENGTH = 3; @@ -172,8 +176,8 @@ global STATE_REFERENCE_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_ global TX_CONTEXT_LENGTH: u64 = 2 + GAS_SETTINGS_LENGTH; global TX_REQUEST_LENGTH: u64 = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; global HEADER_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; global PUBLIC_CONTEXT_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + GAS_LENGTH + 2; @@ -182,15 +186,15 @@ 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_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; -global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; +global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 5 + (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; global CALLER_CONTEXT_LENGTH = 2 * AZTEC_ADDRESS_LENGTH; global CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; -global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); +global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + (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_NEW_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NEW_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_ENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH) + 2 + (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_NEW_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NEW_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + 2 + (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 6c3678b6bb3..c189a21d365 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -3,13 +3,13 @@ use crate::recursion::verification_key::VerificationKey; use crate::abis::function_selector::FunctionSelector; use crate::abis::contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage; use crate::contract_class_id::ContractClassId; -use crate::abis::side_effect::SideEffect; +use crate::abis::log_hash::{LogHash, NoteLogHash}; use crate::traits::is_empty; use crate::utils::{uint256::U256, field::field_from_bytes_32_trunc}; use crate::constants::{ FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH, - MAX_ENCRYPTED_LOGS_PER_TX + MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }; use crate::traits::Hash; use crate::messaging::l2_to_l1_message::L2ToL1Message; @@ -142,7 +142,7 @@ pub fn accumulate_sha256(input: [Field; 2]) -> Field { // Computes the final logs hash for a tx. // NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX // to avoid doubling code, since we can't define the byte len to be 32*N directly. -pub fn compute_tx_logs_hash(logs: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field { +pub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field { // Convert each field element into a byte array and append the bytes to `hash_input_flattened` let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32]; for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX { @@ -163,6 +163,27 @@ pub fn compute_tx_logs_hash(logs: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX]) -> Fi hash } +pub fn compute_tx_note_logs_hash(logs: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field { + // Convert each field element into a byte array and append the bytes to `hash_input_flattened` + let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32]; + for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { + let input_as_bytes = logs[offset].value.to_be_bytes(32); + for byte_index in 0..32 { + hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index]; + } + } + // Ideally we would push to a slice then hash, but there is no sha_slice + // Hardcode to 256 bytes for now + let mut hash = sha256_to_field(hash_input_flattened); + // Not having a 0 value hash for empty logs causes issues with empty txs + // used for padding. Returning early is currently unsupported. + // We always provide sorted logs here, so 0 being empty means all are empty. + if is_empty(logs[0]) { + hash = 0; + } + hash +} + pub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field { dep::std::hash::pedersen_hash_with_separator(inputs, hash_index) } 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 a1d2159d279..c27429ffbf2 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 @@ -10,7 +10,7 @@ use crate::{ nullifier::{Nullifier, ScopedNullifier}, nullifier_key_validation_request::{ScopedNullifierKeyValidationRequest, NullifierKeyValidationRequest}, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - read_request::{ReadRequest, ScopedReadRequest}, side_effect::SideEffect, + read_request::{ReadRequest, ScopedReadRequest}, log_hash::{LogHash, NoteLogHash}, validation_requests::{ValidationRequests, ValidationRequestsBuilder} }, address::{AztecAddress, EthAddress}, @@ -20,7 +20,8 @@ use crate::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - VK_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + VK_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, hash::silo_nullifier, header::Header, messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, @@ -44,8 +45,10 @@ struct FixtureBuilder { new_note_hashes: BoundedVec, new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + note_encrypted_logs_hashes: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, + note_encrypted_logs_hash: Field, encrypted_logs_hash: Field, unencrypted_logs_hash: Field, encrypted_log_preimages_length: Field, @@ -92,8 +95,10 @@ impl FixtureBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), + note_encrypted_logs_hash: 0, encrypted_logs_hash: 0, unencrypted_logs_hash: 0, encrypted_log_preimages_length: 0, @@ -135,6 +140,7 @@ impl FixtureBuilder { new_note_hashes: self.new_note_hashes, new_nullifiers: self.new_nullifiers, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes, encrypted_logs_hashes: self.encrypted_logs_hashes, unencrypted_logs_hashes: self.unencrypted_logs_hashes, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -150,6 +156,7 @@ impl FixtureBuilder { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash), new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -165,6 +172,7 @@ impl FixtureBuilder { new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), new_l2_to_l1_msgs: self.new_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, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -275,12 +283,24 @@ impl FixtureBuilder { self.new_note_hashes.push(NoteHash { value, counter: self.next_counter() }.scope(0, self.storage_contract_address)); } - pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u64) { + pub fn add_broadcast_new_note_hash(&mut self, value: Field) { + self.new_note_hashes.push(NoteHash { value, counter: self.next_counter() }.scope(0, self.storage_contract_address)); + self.note_encrypted_logs_hashes.push( + NoteLogHash { value: value + 1, counter: self.next_counter(), length: 64, note_hash_counter: self.counter - 2 } + ); + self.encrypted_log_preimages_length += 64; + } + + pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u64, broadcast: bool) { let index_offset = self.new_note_hashes.len(); for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { if i < num_new_note_hashes { let mocked_value = self.get_mocked_note_hash_value(index_offset + i); - self.add_new_note_hash(mocked_value); + if (broadcast) { + self.add_broadcast_new_note_hash(mocked_value); + } else { + self.add_new_note_hash(mocked_value); + } } } } @@ -408,13 +428,13 @@ impl FixtureBuilder { } pub fn set_encrypted_logs(&mut self, hash: Field, preimages_length: Field) { - let side_effect = SideEffect { value: hash, counter: self.next_counter() }; + let side_effect = LogHash { value: hash, counter: self.next_counter(), length: preimages_length }; self.encrypted_logs_hashes.push(side_effect); self.encrypted_log_preimages_length += preimages_length; } pub fn set_unencrypted_logs(&mut self, hash: Field, preimages_length: Field) { - let side_effect = SideEffect { value: hash, counter: self.next_counter() }; + let side_effect = LogHash { value: hash, counter: self.next_counter(), length: preimages_length }; self.unencrypted_logs_hashes.push(side_effect); self.unencrypted_log_preimages_length += preimages_length; } @@ -507,8 +527,10 @@ impl Empty for FixtureBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), + note_encrypted_logs_hash: 0, encrypted_logs_hash: 0, unencrypted_logs_hash: 0, encrypted_log_preimages_length: 0, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr index 5268ac1eea6..c3d29483cca 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr @@ -3,7 +3,7 @@ use crate::{ gas_settings::GasSettings, call_request::{CallerContext, CallRequest}, private_call_stack_item::PrivateCallStackItem, function_data::FunctionData, max_block_number::MaxBlockNumber, private_circuit_public_inputs::PrivateCircuitPublicInputs, - private_kernel::private_call_data::PrivateCallData, side_effect::SideEffect + private_kernel::private_call_data::PrivateCallData, log_hash::LogHash }, merkle_tree::membership::MembershipWitness, address::{AztecAddress, EthAddress, SaltedInitializationHash, PublicKeysHash}, @@ -130,7 +130,7 @@ impl PrivateCallDataBuilder { } } - pub fn add_teaddown_call_request(&mut self, is_delegate_call: bool) { + pub fn add_teardown_call_request(&mut self, is_delegate_call: bool) { let hash = 909090; self.public_teardown_call_request = self.public_inputs.generate_call_request(hash, is_delegate_call); self.public_inputs.add_teardown_call_request(hash); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr index 20dd2efc32e..edcab97af36 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -4,7 +4,7 @@ use crate::{ gas_settings::GasSettings, gas::Gas, max_block_number::MaxBlockNumber, note_hash::NoteHash, nullifier::Nullifier, nullifier_key_validation_request::NullifierKeyValidationRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs, read_request::ReadRequest, - side_effect::SideEffect + log_hash::{LogHash, NoteLogHash} }, address::{AztecAddress, compute_initialization_hash}, header::Header, messaging::l2_to_l1_message::L2ToL1Message, tests::fixtures, transaction::tx_context::TxContext @@ -15,7 +15,7 @@ use crate::{ MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL }, traits::Empty }; @@ -44,8 +44,9 @@ struct PrivateCircuitPublicInputsBuilder { public_teardown_function_hash: Field, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + note_encrypted_logs_hashes: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, @@ -153,13 +154,13 @@ impl PrivateCircuitPublicInputsBuilder { } pub fn add_encrypted_log(&mut self, hash: Field, preimages_length: Field) { - let side_effect = SideEffect { value: hash, counter: self.next_counter() }; + let side_effect = LogHash { value: hash, counter: self.next_counter(), length: preimages_length }; self.encrypted_logs_hashes.push(side_effect); self.encrypted_log_preimages_length += preimages_length; } pub fn add_unencrypted_log(&mut self, hash: Field, preimages_length: Field) { - let side_effect = SideEffect { value: hash, counter: self.next_counter() }; + let side_effect = LogHash { value: hash, counter: self.next_counter(), length: preimages_length }; self.unencrypted_logs_hashes.push(side_effect); self.unencrypted_log_preimages_length += preimages_length; } @@ -216,6 +217,7 @@ impl PrivateCircuitPublicInputsBuilder { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.counter_start, end_side_effect_counter: self.counter_end, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, @@ -251,6 +253,7 @@ impl Empty for PrivateCircuitPublicInputsBuilder { public_call_stack_hashes: BoundedVec::new(), public_teardown_function_hash: 0, new_l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 40c379f0d7c..9f66f8cf62e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -3,7 +3,7 @@ use crate::{ gas_settings::GasSettings, gas::Gas, call_context::CallContext, call_request::{CallerContext, CallRequest}, function_data::FunctionData, public_call_data::PublicCallData, public_call_stack_item::PublicCallStackItem, - public_circuit_public_inputs::PublicCircuitPublicInputs, side_effect::SideEffect + public_circuit_public_inputs::PublicCircuitPublicInputs, log_hash::LogHash }, address::{AztecAddress, EthAddress}, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, mocked::Proof, @@ -145,7 +145,7 @@ impl PublicCallDataBuilder { pub fn set_unencrypted_logs(&mut self, hash: Field, preimages_length: Field) { // Counter set as 0 for testing, like note read requests - let side_effect = SideEffect { value: hash, counter: 0 }; + let side_effect = LogHash { value: hash, counter: 0, length: preimages_length }; self.public_inputs.unencrypted_logs_hashes.push(side_effect); self.public_inputs.unencrypted_log_preimages_length += preimages_length; } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr index d18db5dca8b..0aba746f283 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ gas::Gas, call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest, - side_effect::SideEffect, global_variables::GlobalVariables + log_hash::LogHash, global_variables::GlobalVariables }, address::AztecAddress, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, header::Header, @@ -32,7 +32,7 @@ struct PublicCircuitPublicInputsBuilder { new_l2_to_l1_msgs: BoundedVec, start_side_effect_counter: u32, end_side_effect_counter: u32, - unencrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, unencrypted_log_preimages_length: Field, historical_header: Header, global_variables: GlobalVariables, diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index eb9a9661466..5cd1bc4d512 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -105,6 +105,15 @@ describe('Archiver', () => { } // Expect logs to correspond to what is set by L2Block.random(...) + const noteEncryptedLogs = await archiver.getLogs(1, 100, LogType.NOTEENCRYPTED); + expect(noteEncryptedLogs.length).toEqual(blockNumbers.length); + + for (const [index, x] of blockNumbers.entries()) { + const expectedTotalNumEncryptedLogs = 4 * x * 2; + const totalNumEncryptedLogs = EncryptedL2BlockL2Logs.unrollLogs([noteEncryptedLogs[index]]).length; + expect(totalNumEncryptedLogs).toEqual(expectedTotalNumEncryptedLogs); + } + const encryptedLogs = await archiver.getLogs(1, 100, LogType.ENCRYPTED); expect(encryptedLogs.length).toEqual(blockNumbers.length); diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 24069e5c1a0..b2b511b5531 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -265,10 +265,10 @@ export class Archiver implements ArchiveSource { await Promise.all( retrievedBlocks.retrievedData.map(block => { + const noteEncryptedLogs = block.body.noteEncryptedLogs; const encryptedLogs = block.body.encryptedLogs; const unencryptedLogs = block.body.unencryptedLogs; - - return this.store.addLogs(encryptedLogs, unencryptedLogs, block.number); + return this.store.addLogs(noteEncryptedLogs, encryptedLogs, unencryptedLogs, block.number); }), ); diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 0188575228f..b3d54af1d03 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -85,12 +85,14 @@ export interface ArchiverDataStore { /** * Append new logs to the store's list. + * @param noteEncryptedLogs - The note encrypted logs to be added to the store. * @param encryptedLogs - The encrypted logs to be added to the store. * @param unencryptedLogs - The unencrypted logs to be added to the store. * @param blockNumber - The block for which to add the logs. * @returns True if the operation is successful. */ addLogs( + noteEncryptedLogs: EncryptedL2BlockL2Logs | undefined, encryptedLogs: EncryptedL2BlockL2Logs | undefined, unencryptedLogs: UnencryptedL2BlockL2Logs | undefined, blockNumber: number, diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 24ef0228b5d..828567e36e3 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -122,6 +122,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch it('adds encrypted & unencrypted logs', async () => { await expect( store.addLogs( + blocks.retrievedData[0].body.noteEncryptedLogs, blocks.retrievedData[0].body.encryptedLogs, blocks.retrievedData[0].body.unencryptedLogs, blocks.retrievedData[0].number, @@ -131,23 +132,37 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); describe.each([ + ['note_encrypted', LogType.NOTEENCRYPTED], ['encrypted', LogType.ENCRYPTED], ['unencrypted', LogType.UNENCRYPTED], ])('getLogs (%s)', (_, logType) => { beforeEach(async () => { await Promise.all( blocks.retrievedData.map(block => - store.addLogs(block.body.encryptedLogs, block.body.unencryptedLogs, block.number), + store.addLogs( + block.body.noteEncryptedLogs, + block.body.encryptedLogs, + block.body.unencryptedLogs, + block.number, + ), ), ); }); it.each(blockTests)('retrieves previously stored logs', async (from, limit, getExpectedBlocks) => { - const expectedLogs = getExpectedBlocks().map(block => - logType === LogType.ENCRYPTED ? block.body.encryptedLogs : block.body.unencryptedLogs, - ); + const expectedLogs = getExpectedBlocks().map(block => { + switch (logType) { + case LogType.ENCRYPTED: + return block.body.encryptedLogs; + case LogType.NOTEENCRYPTED: + return block.body.noteEncryptedLogs; + case LogType.UNENCRYPTED: + default: + return block.body.unencryptedLogs; + } + }); const actualLogs = await store.getLogs(from, limit, logType); - expect(actualLogs).toEqual(expectedLogs); + expect(actualLogs[0].txLogs[0]).toEqual(expectedLogs[0].txLogs[0]); }); }); @@ -155,7 +170,12 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch beforeEach(async () => { await Promise.all( blocks.retrievedData.map(block => - store.addLogs(block.body.encryptedLogs, block.body.unencryptedLogs, block.number), + store.addLogs( + block.body.noteEncryptedLogs, + block.body.encryptedLogs, + block.body.unencryptedLogs, + block.number, + ), ), ); await store.addBlocks(blocks); @@ -319,7 +339,12 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch await Promise.all( blocks.retrievedData.map(block => - store.addLogs(block.body.encryptedLogs, block.body.unencryptedLogs, block.number), + store.addLogs( + block.body.noteEncryptedLogs, + block.body.encryptedLogs, + block.body.unencryptedLogs, + block.number, + ), ), ); }); diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index c01b8d2202b..a542e3dcc0b 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -153,11 +153,12 @@ export class KVArchiverDataStore implements ArchiverDataStore { * @returns True if the operation is successful. */ addLogs( + noteEncryptedLogs: EncryptedL2BlockL2Logs | undefined, encryptedLogs: EncryptedL2BlockL2Logs | undefined, unencryptedLogs: UnencryptedL2BlockL2Logs | undefined, blockNumber: number, ): Promise { - return this.#logStore.addLogs(encryptedLogs, unencryptedLogs, blockNumber); + return this.#logStore.addLogs(noteEncryptedLogs, encryptedLogs, unencryptedLogs, blockNumber); } /** diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts index 305c385d254..6724256d80f 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts @@ -20,12 +20,14 @@ import { type BlockStore } from './block_store.js'; * A store for logs */ export class LogStore { + #noteEncryptedLogs: AztecMap; #encryptedLogs: AztecMap; #unencryptedLogs: AztecMap; #logsMaxPageSize: number; #log = createDebugLogger('aztec:archiver:log_store'); constructor(private db: AztecKVStore, private blockStore: BlockStore, logsMaxPageSize: number = 1000) { + this.#noteEncryptedLogs = db.openMap('archiver_note_encrypted_logs'); this.#encryptedLogs = db.openMap('archiver_encrypted_logs'); this.#unencryptedLogs = db.openMap('archiver_unencrypted_logs'); @@ -40,11 +42,16 @@ export class LogStore { * @returns True if the operation is successful. */ addLogs( + noteEncryptedLogs: EncryptedL2BlockL2Logs | undefined, encryptedLogs: EncryptedL2BlockL2Logs | undefined, unencryptedLogs: UnencryptedL2BlockL2Logs | undefined, blockNumber: number, ): Promise { return this.db.transaction(() => { + if (noteEncryptedLogs) { + void this.#noteEncryptedLogs.set(blockNumber, noteEncryptedLogs.toBuffer()); + } + if (encryptedLogs) { void this.#encryptedLogs.set(blockNumber, encryptedLogs.toBuffer()); } @@ -69,8 +76,18 @@ export class LogStore { limit: number, logType: TLogType, ): IterableIterator>> { - const logMap = logType === LogType.ENCRYPTED ? this.#encryptedLogs : this.#unencryptedLogs; - const L2BlockL2Logs = logType === LogType.ENCRYPTED ? EncryptedL2BlockL2Logs : UnencryptedL2BlockL2Logs; + const logMap = (() => { + switch (logType) { + case LogType.ENCRYPTED: + return this.#encryptedLogs; + case LogType.NOTEENCRYPTED: + return this.#noteEncryptedLogs; + case LogType.UNENCRYPTED: + default: + return this.#unencryptedLogs; + } + })(); + const L2BlockL2Logs = logType === LogType.UNENCRYPTED ? UnencryptedL2BlockL2Logs : EncryptedL2BlockL2Logs; for (const buffer of logMap.values({ start, limit })) { yield L2BlockL2Logs.fromBuffer(buffer) as L2BlockL2Logs>; } diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts index 7c90a611c2f..51f93c71c86 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts @@ -27,7 +27,12 @@ describe('MemoryArchiverStore', () => { await archiverStore.addBlocks(blocks); await Promise.all( blocks.retrievedData.map(block => - archiverStore.addLogs(block.body.encryptedLogs, block.body.unencryptedLogs, block.number), + archiverStore.addLogs( + block.body.noteEncryptedLogs, + block.body.encryptedLogs, + block.body.unencryptedLogs, + block.number, + ), ), ); diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index 5c1292a000e..5f29df0a969 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -48,6 +48,12 @@ export class MemoryArchiverStore implements ArchiverDataStore { */ private txEffects: TxEffect[] = []; + /** + * An array containing all the encrypted logs that have been fetched so far. + * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM). + */ + private noteEncryptedLogsPerBlock: EncryptedL2BlockL2Logs[] = []; + /** * An array containing all the encrypted logs that have been fetched so far. * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM). @@ -185,10 +191,15 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns True if the operation is successful. */ addLogs( + noteEncryptedLogs: EncryptedL2BlockL2Logs, encryptedLogs: EncryptedL2BlockL2Logs, unencryptedLogs: UnencryptedL2BlockL2Logs, blockNumber: number, ): Promise { + if (noteEncryptedLogs) { + this.noteEncryptedLogsPerBlock[blockNumber - INITIAL_L2_BLOCK_NUM] = noteEncryptedLogs; + } + if (encryptedLogs) { this.encryptedLogsPerBlock[blockNumber - INITIAL_L2_BLOCK_NUM] = encryptedLogs; } @@ -308,9 +319,18 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (from < INITIAL_L2_BLOCK_NUM || limit < 1) { throw new Error(`Invalid limit: ${limit}`); } - const logs = ( - logType === LogType.ENCRYPTED ? this.encryptedLogsPerBlock : this.unencryptedLogsPerBlock - ) as L2BlockL2Logs>[]; + const logs = (() => { + switch (logType) { + case LogType.ENCRYPTED: + return this.encryptedLogsPerBlock; + case LogType.NOTEENCRYPTED: + return this.noteEncryptedLogsPerBlock; + case LogType.UNENCRYPTED: + default: + return this.unencryptedLogsPerBlock; + } + })() as L2BlockL2Logs>[]; + if (from > logs.length) { return Promise.resolve([]); } diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 6bb1146c395..967076a8247 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -76,6 +76,12 @@ export class Body { return computeRoot(leaves); } + get noteEncryptedLogs(): EncryptedL2BlockL2Logs { + const logs = this.txEffects.map(txEffect => txEffect.noteEncryptedLogs); + + return new EncryptedL2BlockL2Logs(logs); + } + get encryptedLogs(): EncryptedL2BlockL2Logs { const logs = this.txEffects.map(txEffect => txEffect.encryptedLogs); diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index 1b80876ebb5..ae44827cfcb 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -203,6 +203,14 @@ export class L2Block { */ getStats() { const logsStats = { + noteEncryptedLogLength: this.body.txEffects.reduce( + (logCount, txEffect) => logCount + txEffect.noteEncryptedLogs.getSerializedLength(), + 0, + ), + noteEncryptedLogCount: this.body.txEffects.reduce( + (logCount, txEffect) => logCount + txEffect.noteEncryptedLogs.getTotalLogCount(), + 0, + ), encryptedLogLength: this.body.txEffects.reduce( (logCount, txEffect) => logCount + txEffect.encryptedLogs.getSerializedLength(), 0, @@ -212,11 +220,11 @@ export class L2Block { 0, ), unencryptedLogCount: this.body.txEffects.reduce( - (logCount, txEffect) => logCount + txEffect.unencryptedLogs.getSerializedLength(), + (logCount, txEffect) => logCount + txEffect.unencryptedLogs.getTotalLogCount(), 0, ), unencryptedLogSize: this.body.txEffects.reduce( - (logCount, txEffect) => logCount + txEffect.unencryptedLogs.getTotalLogCount(), + (logCount, txEffect) => logCount + txEffect.unencryptedLogs.getSerializedLength(), 0, ), }; diff --git a/yarn-project/circuit-types/src/logs/log_type.ts b/yarn-project/circuit-types/src/logs/log_type.ts index 1f9c247cc4a..c5a4e666496 100644 --- a/yarn-project/circuit-types/src/logs/log_type.ts +++ b/yarn-project/circuit-types/src/logs/log_type.ts @@ -5,10 +5,11 @@ import { type UnencryptedL2Log } from './unencrypted_l2_log.js'; * Defines possible log types. */ export enum LogType { + NOTEENCRYPTED, ENCRYPTED, UNENCRYPTED, } -export type FromLogType = TLogType extends LogType.ENCRYPTED - ? EncryptedL2Log - : UnencryptedL2Log; +export type FromLogType = TLogType extends LogType.UNENCRYPTED + ? UnencryptedL2Log + : EncryptedL2Log; 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 c18bec7c3c5..86ad70a046b 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -1,4 +1,8 @@ -import { MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX } from '@aztec/circuits.js'; +import { + MAX_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, +} from '@aztec/circuits.js'; import { sha256Trunc } from '@aztec/foundation/crypto'; import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; @@ -6,6 +10,7 @@ import isEqual from 'lodash.isequal'; import { type EncryptedL2Log } from './encrypted_l2_log.js'; import { EncryptedFunctionL2Logs, type FunctionL2Logs, UnencryptedFunctionL2Logs } from './function_l2_logs.js'; +import { LogType } from './log_type.js'; import { type UnencryptedL2Log } from './unencrypted_l2_log.js'; /** @@ -83,7 +88,7 @@ export abstract class TxL2Logs { * Note: This is a TS implementation of `computeKernelLogsHash` function in Decoder.sol. See that function documentation * for more details. */ - public hash(): Buffer { + public hash(logType: LogType = LogType.ENCRYPTED): Buffer { if (this.unrollLogs().length == 0) { return Buffer.alloc(32); } @@ -94,7 +99,8 @@ export abstract class TxL2Logs { } // pad the end of logs with 0s // NB - This assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX - for (let i = 0; i < MAX_ENCRYPTED_LOGS_PER_TX - this.unrollLogs().length; i++) { + const pad = logType == LogType.NOTEENCRYPTED ? MAX_NOTE_ENCRYPTED_LOGS_PER_TX : MAX_ENCRYPTED_LOGS_PER_TX; + for (let i = 0; i < pad - this.unrollLogs().length; i++) { flattenedLogs = Buffer.concat([flattenedLogs, Buffer.alloc(32)]); } diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index dba3bca5427..2e21eac53b9 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -2,13 +2,13 @@ import { AztecAddress, CallRequest, GasSettings, + LogHash, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, Nullifier, PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, Proof, PublicCallRequest, - SideEffect, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js'; @@ -68,6 +68,7 @@ export const mockTx = ( const isForPublic = totalPublicCallRequests > 0; const data = PrivateKernelTailCircuitPublicInputs.empty(); const firstNullifier = new Nullifier(new Fr(seed + 1), 0, Fr.ZERO); + const noteEncryptedLogs = EncryptedTxL2Logs.empty(); // Mock seems to have no new notes => no note logs const encryptedLogs = hasLogs ? EncryptedTxL2Logs.random(2, 3) : EncryptedTxL2Logs.empty(); // 2 priv function invocations creating 3 encrypted logs each const unencryptedLogs = hasLogs ? UnencryptedTxL2Logs.random(2, 1) : UnencryptedTxL2Logs.empty(); // 2 priv function invocations creating 1 unencrypted log each data.constants.txContext.gasSettings = GasSettings.default(); @@ -102,17 +103,26 @@ export const mockTx = ( encryptedLogs.functionLogs.forEach((log, j) => { // ts complains if we dont check .forPublic here, even though it is defined ^ if (data.forPublic) { - data.forPublic.end.encryptedLogsHashes[j] = new SideEffect(Fr.fromBuffer(log.hash()), new Fr(i++)); + data.forPublic.end.encryptedLogsHashes[j] = new LogHash( + Fr.fromBuffer(log.hash()), + i++, + new Fr(log.toBuffer().length), + ); } }); unencryptedLogs.functionLogs.forEach((log, j) => { if (data.forPublic) { - data.forPublic.end.unencryptedLogsHashes[j] = new SideEffect(Fr.fromBuffer(log.hash()), new Fr(i++)); + data.forPublic.end.unencryptedLogsHashes[j] = new LogHash( + Fr.fromBuffer(log.hash()), + i++, + new Fr(log.toBuffer().length), + ); } }); } } else { data.forRollup!.end.newNullifiers[0] = firstNullifier.value; + data.forRollup!.end.noteEncryptedLogsHash = Fr.fromBuffer(noteEncryptedLogs.hash(0)); data.forRollup!.end.encryptedLogsHash = Fr.fromBuffer(encryptedLogs.hash()); data.forRollup!.end.unencryptedLogsHash = Fr.fromBuffer(unencryptedLogs.hash()); } @@ -120,6 +130,7 @@ export const mockTx = ( const tx = new Tx( data, new Proof(Buffer.alloc(0)), + noteEncryptedLogs, encryptedLogs, unencryptedLogs, publicCallRequests, diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index ca21b3b6704..7e78a0cba7c 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -165,10 +165,14 @@ export type TxStats = { size: number; /** Size of the proof. */ proofSize: number; + /** Number of note encrypted logs. */ + noteEncryptedLogCount: number; /** Number of encrypted logs. */ encryptedLogCount: number; /** Number of unencrypted logs. */ unencryptedLogCount: number; + /** Serialized size of note encrypted logs. */ + noteEncryptedLogSize: number; /** Serialized size of encrypted logs. */ encryptedLogSize: number; /** Serialized size of unencrypted logs. */ diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index 24a5265b305..4fad2f35652 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -46,7 +46,7 @@ export type PublicKernelRequest = PublicKernelTailRequest | PublicKernelNonTailR * Represents a tx that has been processed by the sequencer public processor, * so its kernel circuit public inputs are filled in. */ -export type ProcessedTx = Pick & { +export type ProcessedTx = Pick & { /** * Output of the private tail or public tail kernel circuit for this tx. */ @@ -134,6 +134,8 @@ export function makeProcessedTx( hash: tx.getTxHash(), data: kernelOutput, proof, + // TODO(4712): deal with non-revertible logs here + noteEncryptedLogs: revertReason ? EncryptedTxL2Logs.empty() : tx.noteEncryptedLogs, encryptedLogs: revertReason ? EncryptedTxL2Logs.empty() : tx.encryptedLogs, unencryptedLogs: revertReason ? UnencryptedTxL2Logs.empty() : tx.unencryptedLogs, isEmpty: false, @@ -157,6 +159,7 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr): const hash = new TxHash(Fr.ZERO.toBuffer()); return { hash, + noteEncryptedLogs: EncryptedTxL2Logs.empty(), encryptedLogs: EncryptedTxL2Logs.empty(), unencryptedLogs: UnencryptedTxL2Logs.empty(), data: emptyKernelOutput, @@ -178,6 +181,7 @@ export function toTxEffect(tx: ProcessedTx): TxEffect { tx.data.end.publicDataUpdateRequests .map(t => new PublicDataWrite(t.leafSlot, t.newValue)) .filter(h => !h.isEmpty()), + tx.noteEncryptedLogs || EncryptedTxL2Logs.empty(), tx.encryptedLogs || EncryptedTxL2Logs.empty(), tx.unencryptedLogs || UnencryptedTxL2Logs.empty(), ); diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index a07496a238c..44853dcd91e 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -25,6 +25,10 @@ export class Tx { * Proof from the private kernel circuit. */ public readonly proof: Proof, + /** + * Encrypted note logs generated by the tx. + */ + public readonly noteEncryptedLogs: EncryptedTxL2Logs, /** * Encrypted logs generated by the tx. */ @@ -67,6 +71,7 @@ export class Tx { reader.readObject(PrivateKernelTailCircuitPublicInputs), reader.readObject(Proof), reader.readObject(EncryptedTxL2Logs), + reader.readObject(EncryptedTxL2Logs), reader.readObject(UnencryptedTxL2Logs), reader.readArray(reader.readNumber(), PublicCallRequest), reader.readObject(PublicCallRequest), @@ -81,6 +86,7 @@ export class Tx { return serializeToBuffer([ this.data, this.proof, + this.noteEncryptedLogs, this.encryptedLogs, this.unencryptedLogs, this.enqueuedPublicFunctionCalls.length, @@ -96,6 +102,7 @@ export class Tx { public toJSON() { return { data: this.data.toBuffer().toString('hex'), + noteEncryptedLogs: this.noteEncryptedLogs.toBuffer().toString('hex'), encryptedLogs: this.encryptedLogs.toBuffer().toString('hex'), unencryptedLogs: this.unencryptedLogs.toBuffer().toString('hex'), proof: this.proof.toBuffer().toString('hex'), @@ -120,6 +127,7 @@ export class Tx { */ public static fromJSON(obj: any) { const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(Buffer.from(obj.data, 'hex')); + const noteEncryptedLogs = EncryptedTxL2Logs.fromBuffer(Buffer.from(obj.noteEncryptedLogs, 'hex')); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(Buffer.from(obj.encryptedLogs, 'hex')); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(Buffer.from(obj.unencryptedLogs, 'hex')); const proof = Buffer.from(obj.proof, 'hex'); @@ -130,6 +138,7 @@ export class Tx { return new Tx( publicInputs, Proof.fromBuffer(proof), + noteEncryptedLogs, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions, @@ -154,8 +163,10 @@ export class Tx { getStats(): TxStats { return { txHash: this.getTxHash().toString(), + noteEncryptedLogCount: this.noteEncryptedLogs.getTotalLogCount(), encryptedLogCount: this.encryptedLogs.getTotalLogCount(), unencryptedLogCount: this.unencryptedLogs.getTotalLogCount(), + noteEncryptedLogSize: this.noteEncryptedLogs.getSerializedLength(), encryptedLogSize: this.encryptedLogs.getSerializedLength(), unencryptedLogSize: this.unencryptedLogs.getSerializedLength(), @@ -208,6 +219,7 @@ export class Tx { static clone(tx: Tx): Tx { const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(tx.data.toBuffer()); const proof = Proof.fromBuffer(tx.proof.toBuffer()); + const noteEncryptedLogs = EncryptedTxL2Logs.fromBuffer(Buffer.from(tx.noteEncryptedLogs.toBuffer())); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(tx.encryptedLogs.toBuffer()); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(tx.unencryptedLogs.toBuffer()); const enqueuedPublicFunctions = tx.enqueuedPublicFunctionCalls.map(x => { @@ -217,6 +229,7 @@ export class Tx { return new Tx( publicInputs, proof, + noteEncryptedLogs, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions, diff --git a/yarn-project/circuit-types/src/tx_effect.test.ts b/yarn-project/circuit-types/src/tx_effect.test.ts index 0858dc1837f..82876e870aa 100644 --- a/yarn-project/circuit-types/src/tx_effect.test.ts +++ b/yarn-project/circuit-types/src/tx_effect.test.ts @@ -10,6 +10,6 @@ describe('TxEffect', () => { it('hash of empty tx effect matches snapshot', () => { const txEffectHash = TxEffect.empty().hash().toString('hex'); // If you change this you have to change the hardcoded value in TxsDecoder.sol! - expect(txEffectHash).toMatchInlineSnapshot(`"00822c2cdfbc7a6e5f4dd355251f4dfc9af1b1a64152464b9b83c5007eeed0f3"`); + expect(txEffectHash).toMatchInlineSnapshot(`"00543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7"`); }); }); diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index 4caaec8c57f..422727c5062 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -43,6 +43,7 @@ export class TxEffect { /** * The logs of the txEffect */ + public noteEncryptedLogs: EncryptedTxL2Logs, public encryptedLogs: EncryptedTxL2Logs, public unencryptedLogs: UnencryptedTxL2Logs, ) { @@ -95,6 +96,7 @@ export class TxEffect { serializeArrayOfBufferableToVector(this.nullifiers, 1), serializeArrayOfBufferableToVector(this.l2ToL1Msgs, 1), serializeArrayOfBufferableToVector(this.publicDataWrites, 1), + this.noteEncryptedLogs, this.encryptedLogs, this.unencryptedLogs, ]); @@ -116,6 +118,7 @@ export class TxEffect { reader.readVectorUint8Prefix(Fr), reader.readVectorUint8Prefix(PublicDataWrite), reader.readObject(EncryptedTxL2Logs), + reader.readObject(EncryptedTxL2Logs), reader.readObject(UnencryptedTxL2Logs), ); } @@ -145,6 +148,7 @@ export class TxEffect { PublicDataWrite.SIZE_IN_BYTES * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); + const noteEncryptedLogsHashKernel0 = this.noteEncryptedLogs.hash(0); const encryptedLogsHashKernel0 = this.encryptedLogs.hash(); const unencryptedLogsHashKernel0 = this.unencryptedLogs.hash(); @@ -155,6 +159,7 @@ export class TxEffect { nullifiersBuffer, l2ToL1MsgsBuffer, publicDataWritesBuffer, + noteEncryptedLogsHashKernel0, encryptedLogsHashKernel0, unencryptedLogsHashKernel0, ]); @@ -176,12 +181,23 @@ export class TxEffect { makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.random), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.random), EncryptedTxL2Logs.random(numPrivateCallsPerTx, numEncryptedLogsPerCall), + EncryptedTxL2Logs.random(numPrivateCallsPerTx, numEncryptedLogsPerCall), UnencryptedTxL2Logs.random(numPublicCallsPerTx, numUnencryptedLogsPerCall), ); } static empty(): TxEffect { - return new TxEffect(RevertCode.OK, Fr.ZERO, [], [], [], [], EncryptedTxL2Logs.empty(), UnencryptedTxL2Logs.empty()); + return new TxEffect( + RevertCode.OK, + Fr.ZERO, + [], + [], + [], + [], + EncryptedTxL2Logs.empty(), + EncryptedTxL2Logs.empty(), + UnencryptedTxL2Logs.empty(), + ); } isEmpty(): boolean { @@ -205,6 +221,7 @@ export class TxEffect { nullifiers: [${this.nullifiers.map(h => h.toString()).join(', ')}], l2ToL1Msgs: [${this.l2ToL1Msgs.map(h => h.toString()).join(', ')}], publicDataWrites: [${this.publicDataWrites.map(h => h.toString()).join(', ')}], + noteEncryptedLogs: ${JSON.stringify(this.noteEncryptedLogs.toJSON())}, encryptedLogs: ${JSON.stringify(this.encryptedLogs.toJSON())}, unencryptedLogs: ${JSON.stringify(this.unencryptedLogs.toJSON())} }`; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 5b4153088f7..563f1b3cb40 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -12,6 +12,7 @@ export const MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; export const MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 16; +export const MAX_NOTE_ENCRYPTED_LOGS_PER_CALL = 16; export const MAX_ENCRYPTED_LOGS_PER_CALL = 4; export const MAX_UNENCRYPTED_LOGS_PER_CALL = 4; export const MAX_NEW_NOTE_HASHES_PER_TX = 64; @@ -25,6 +26,7 @@ export const MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; export const MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 64; +export const MAX_NOTE_ENCRYPTED_LOGS_PER_TX = 64; export const MAX_ENCRYPTED_LOGS_PER_TX = 8; export const MAX_UNENCRYPTED_LOGS_PER_TX = 8; export const NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; @@ -105,6 +107,8 @@ export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; export const SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; export const READ_REQUEST_LENGTH = 2; +export const LOG_HASH_LENGTH = 3; +export const NOTE_LOG_HASH_LENGTH = 4; export const NOTE_HASH_LENGTH = 2; export const SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 2; export const NULLIFIER_LENGTH = 3; @@ -130,8 +134,9 @@ export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + 2 + - SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL + - SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + + NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL + + LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL + + LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; @@ -147,7 +152,7 @@ export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + 2 + - SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + + LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + @@ -173,7 +178,7 @@ export const COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + - 4 + + 5 + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH + GAS_LENGTH; export const COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; @@ -183,8 +188,9 @@ export const PRIVATE_ACCUMULATED_DATA_LENGTH = SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX + SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH + - SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX + - SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX + + NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX + + LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX + + LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX + 2 + CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX + CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX; @@ -199,8 +205,9 @@ export const PUBLIC_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH + MAX_NEW_NULLIFIERS_PER_TX * NULLIFIER_LENGTH + MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1 + - MAX_ENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH + - MAX_UNENCRYPTED_LOGS_PER_TX * SIDE_EFFECT_LENGTH + + NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX + + MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH + + MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH + 2 + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH + diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap index 37d75fc64af..2d413b4089c 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap @@ -1,7 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ContractAddress Public key hash matches Noir 1`] = `"0x22d83a089d7650514c2de24cd30185a414d943eaa19817c67bffe2c3183006a3"`; - exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x0bed63221d281713007bfb0c063e1f61d0646404fb3701b99bb92f41b6390604"`; exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x109865e4b959adba34b722e72a69baaf9ee78e31bb1042318f0d91006ed86780>`; diff --git a/yarn-project/circuits.js/src/contract/contract_address.test.ts b/yarn-project/circuits.js/src/contract/contract_address.test.ts index c83f7fdd928..e81eaebfc49 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -1,6 +1,6 @@ import { ABIParameterVisibility, type FunctionAbi, FunctionType } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; -import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { AztecAddress, deriveKeys } from '../index.js'; import { @@ -69,17 +69,4 @@ describe('ContractAddress', () => { expect(address).toMatchSnapshot(); }); - - it('Public key hash matches Noir', () => { - const secretKey = new Fr(2n); - const hash = deriveKeys(secretKey).publicKeys.hash().toString(); - expect(hash).toMatchSnapshot(); - - // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data - updateInlineTestData( - 'noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr', - 'expected_public_keys_hash', - hash.toString(), - ); - }); }); diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts index 783ea56c885..d72783914be 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts @@ -1,4 +1,12 @@ -import { AztecAddress, Fr, NoteHash, Nullifier, type ScopedNoteHash, type ScopedNullifier } from '@aztec/circuits.js'; +import { + AztecAddress, + Fr, + NoteHash, + NoteLogHash, + Nullifier, + type ScopedNoteHash, + type ScopedNullifier, +} from '@aztec/circuits.js'; import { buildTransientDataHints } from './build_transient_data_hints.js'; @@ -7,6 +15,7 @@ describe('buildTransientDataHints', () => { let noteHashes: ScopedNoteHash[]; let nullifiers: ScopedNullifier[]; + let logs: NoteLogHash[]; beforeEach(() => { noteHashes = [ @@ -20,27 +29,38 @@ describe('buildTransientDataHints', () => { new Nullifier(new Fr(66), 600, new Fr(0)).scope(contractAddress), new Nullifier(new Fr(77), 700, new Fr(11)).scope(contractAddress), ]; + logs = [ + new NoteLogHash(new Fr(88), 350, new Fr(64), 300), + new NoteLogHash(new Fr(99), 375, new Fr(64), 300), + new NoteLogHash(new Fr(111), 150, new Fr(64), 100), + new NoteLogHash(new Fr(122), 250, new Fr(64), 200), + ]; }); it('builds index hints that link transient note hashes and nullifiers', () => { - const [nullifierIndexes, noteHashIndexes] = buildTransientDataHints(noteHashes, nullifiers); + const [nullifierIndexes, noteHashIndexesForNullifiers, noteHashIndexesForLogs] = buildTransientDataHints( + noteHashes, + nullifiers, + logs, + ); expect(nullifierIndexes).toEqual([3, 4, 1]); - expect(noteHashIndexes).toEqual([3, 2, 3, 0]); + expect(noteHashIndexesForNullifiers).toEqual([3, 2, 3, 0]); + expect(noteHashIndexesForLogs).toEqual([2, 2, 0, 3]); }); it('throws if no matching nullifier', () => { noteHashes[0].nullifierCounter = 450; - expect(() => buildTransientDataHints(noteHashes, nullifiers)).toThrow('Unknown nullifier counter.'); + expect(() => buildTransientDataHints(noteHashes, nullifiers, logs)).toThrow('Unknown nullifier counter.'); }); it('throws if note hash does not match', () => { nullifiers[1].nullifier.noteHash = new Fr(11); - expect(() => buildTransientDataHints(noteHashes, nullifiers)).toThrow('Hinted note hash does not match.'); + expect(() => buildTransientDataHints(noteHashes, nullifiers, logs)).toThrow('Hinted note hash does not match.'); }); it('throws if contract address does not match', () => { nullifiers[1].contractAddress = AztecAddress.fromBigInt(123456n); - expect(() => buildTransientDataHints(noteHashes, nullifiers)).toThrow( + expect(() => buildTransientDataHints(noteHashes, nullifiers, logs)).toThrow( 'Contract address of hinted note hash does not match.', ); }); diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts index a9664d6e5ce..9eb26f51a4c 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts @@ -1,16 +1,27 @@ -import { type ScopedNoteHash, type ScopedNullifier, countAccumulatedItems } from '@aztec/circuits.js'; +import { type NoteLogHash, type ScopedNoteHash, type ScopedNullifier, countAccumulatedItems } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; -export function buildTransientDataHints( +export function buildTransientDataHints< + NOTE_HASHES_LEN extends number, + NULLIFIERS_LEN extends number, + LOGS_LEN extends number, +>( noteHashes: Tuple, nullifiers: Tuple, + noteLogs: Tuple, noteHashesLength: NOTE_HASHES_LEN = noteHashes.length as NOTE_HASHES_LEN, nullifiersLength: NULLIFIERS_LEN = nullifiers.length as NULLIFIERS_LEN, -): [Tuple, Tuple] { + logsLength: LOGS_LEN = noteLogs.length as LOGS_LEN, +): [Tuple, Tuple, Tuple] { const nullifierIndexMap: Map = new Map(); nullifiers.forEach((n, i) => nullifierIndexMap.set(n.counter, i)); + const logNoteHashMap: Map = new Map(); + noteLogs.forEach((n, i) => { + logNoteHashMap.set(n.noteHashCounter, (logNoteHashMap.get(n.noteHashCounter) || []).concat([i])); + }); + const nullifierIndexesForNoteHashes: Tuple = makeTuple( noteHashesLength, () => nullifiersLength, @@ -21,6 +32,8 @@ export function buildTransientDataHints noteHashesLength, ); + const noteHashIndexesForLogs: Tuple = makeTuple(logsLength, () => noteHashesLength); + const numNoteHashes = countAccumulatedItems(noteHashes); for (let i = 0; i < numNoteHashes; i++) { const noteHash = noteHashes[i]; @@ -38,10 +51,17 @@ export function buildTransientDataHints { + noteHashIndexesForLogs[logIndex] = i; + }); + } + nullifierIndexesForNoteHashes[i] = nullifierIndex; noteHashIndexesForNullifiers[nullifierIndex] = i; } } - return [nullifierIndexesForNoteHashes, noteHashIndexesForNullifiers]; + return [nullifierIndexesForNoteHashes, noteHashIndexesForNullifiers, noteHashIndexesForLogs]; } diff --git a/yarn-project/circuits.js/src/keys/index.test.ts b/yarn-project/circuits.js/src/keys/index.test.ts index 5f1d70705d2..de6d68d1610 100644 --- a/yarn-project/circuits.js/src/keys/index.test.ts +++ b/yarn-project/circuits.js/src/keys/index.test.ts @@ -23,7 +23,7 @@ describe('🔑', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( - 'noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr', + 'noir-projects/aztec-nr/aztec/src/keys/public_keys.nr', 'expected_public_keys_hash', expected.toString(), ); diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 161ec6eecc5..060f5e390d3 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x092493dbe24afc80afb32c5ba43dde1eb447a66f88a36676a63cdd04f21636ad>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x23e9b31fb9659181d8e6d941e95cc88a6d4d43c6b6ee316351528db772f419c0>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x0a3f795ce85d43fddedcde7711982cf50382e3da1c0ad7afbbc2cb7a219a46c3>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x03716c2dd42af2c14e1a871ef725775bd2ee0e7a606bb7882f15dc8cc49c2ad5>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index b741933be5b..1d79cf605e1 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2a6e17b55aa91be7eb562d5fcf1bd67a0abed9098ec2d1a9c7e68541e7518326>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x04f513d6a85e9d0c994d3c3764732e4486264190b3bf285257f41180f09a0b58>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x112e706493a7ca33bb253550f8c1e4822c8193e4e2367aefda0f40fba4063455>`; \ No newline at end of file +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0e2af4cfdb7eb8df296c5ca7c88141f821ef45800bd240026f151f7fa7bebba6>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index 0ccb386246e..94e1a8f18bd 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x0f7624c0d5ea65fcec318c4d34cb3fcbf9c67435aebbf1548b3c90ef641424f8"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1236612a9ec71bcc83af597d523f1d05df071565067bc23276a4e64b72882c22"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x1177a69fbc37f0ebdf290025414ff72504497840f174896bd427d0f30ec21c55"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x23066ad690c088120f8397cfeb2ef5608d4517342c7ff9fcb713009933ef1c61"`; -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x020b98dcc882881a349edfd43044d58c8703fdcfc9d4b250b799d951608dcd6b>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x0eef6f20d1f73de870f781dad46a843966eb560e2b684752c82cd2bd45f97a34>`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x18d2b726728360b534121bb15accd1059f7df38225e76768e64d3e3040122440>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x14dc282fc24629bcc16eab0264ce0bfffc01e433f307e3578c89d95337bc42b3>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index 834668caf75..19f80957d35 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x132559f41b7adc7388e0cd52b91fd6837c296b2f9ec1b6d2ed046f7a56db18f8>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x048912d56248af479f8d7ecedbba7092d27741b10075a989e040f8e3242a7a3f>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0ac3cb8eb6605fc7aa83e9420eb988c1f6c9a5dcc2457c133216624bc6932619>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x28a405c25dfa4ae5823506f7ad48e804d81b9f0fa57dc8fc43fbc0f804ee4514>`; diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 138baa2d6c9..8be49f1d142 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -34,6 +34,7 @@ export * from './kernel/public_kernel_tail_circuit_private_inputs.js'; export * from './kernel/kernel_circuit_public_inputs.js'; export * from './kernel/kernel_data.js'; export * from './l2_to_l1_message.js'; +export * from './log_hash.js'; export * from './max_block_number.js'; export * from './membership_witness.js'; export * from './non_existent_read_request_hints.js'; 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 ba1343f86a2..19f1460f973 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 @@ -31,6 +31,11 @@ export class CombinedAccumulatedData { * All the new L2 to L1 messages created in this transaction. */ public newL2ToL1Msgs: Tuple, + /** + * Accumulated encrypted note logs hash from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. + */ + public noteEncryptedLogsHash: Fr, /** * Accumulated encrypted logs hash from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. @@ -63,6 +68,7 @@ export class CombinedAccumulatedData { this.newNoteHashes, this.newNullifiers, this.newL2ToL1Msgs, + this.noteEncryptedLogsHash, this.encryptedLogsHash, this.unencryptedLogsHash, this.encryptedLogPreimagesLength, @@ -91,6 +97,7 @@ export class CombinedAccumulatedData { Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), + Fr.fromBuffer(reader), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readObject(Gas), ); @@ -114,6 +121,7 @@ export class CombinedAccumulatedData { Fr.zero(), Fr.zero(), Fr.zero(), + Fr.zero(), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), Gas.empty(), ); @@ -133,6 +141,7 @@ export class CombinedAccumulatedData { .filter(x => !x.isZero()) .map(x => inspect(x)) .join(', ')}], + noteEncryptedLogsHash: ${this.noteEncryptedLogsHash.toString()}, encryptedLogsHash: ${this.encryptedLogsHash.toString()}, unencryptedLogsHash: ${this.unencryptedLogsHash.toString()}, encryptedLogPreimagesLength: ${this.encryptedLogPreimagesLength.toString()}, diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index 3d0029b199b..0c83610688a 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -4,19 +4,19 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { MAX_ENCRYPTED_LOGS_PER_TX, - type MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; +import { LogHash, NoteLogHash } from '../log_hash.js'; import { ScopedNoteHash } from '../note_hash.js'; import { ScopedNullifier } from '../nullifier.js'; -import { SideEffect } from '../side_effects.js'; /** * Specific accumulated data structure for the final ordering private kernel circuit. It is included @@ -35,17 +35,22 @@ export class PrivateAccumulatedData { /** * All the new L2 to L1 messages created in this transaction. */ - public newL2ToL1Msgs: Tuple, + public newL2ToL1Msgs: Tuple, /** - * Accumulated encrypted logs hash from all the previous kernel iterations. - * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. + * Accumulated encrypted note logs hashes from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. */ - public encryptedLogsHashes: Tuple, + public noteEncryptedLogsHashes: Tuple, /** - * Accumulated unencrypted logs hash from all the previous kernel iterations. - * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. + * Accumulated encrypted logs hashes from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHashes: Tuple, + public encryptedLogsHashes: Tuple, + /** + * Accumulated unencrypted logs hashes from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. + */ + public unencryptedLogsHashes: Tuple, /** * Total accumulated length of the encrypted log preimages emitted in all the previous kernel iterations */ @@ -70,6 +75,7 @@ export class PrivateAccumulatedData { this.newNoteHashes, this.newNullifiers, this.newL2ToL1Msgs, + this.noteEncryptedLogsHashes, this.encryptedLogsHashes, this.unencryptedLogsHashes, this.encryptedLogPreimagesLength, @@ -94,8 +100,9 @@ export class PrivateAccumulatedData { reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), - reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, CallRequest), @@ -117,8 +124,9 @@ export class PrivateAccumulatedData { makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash.empty), makeTuple(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), - makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), - makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), + makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash.empty), + makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, LogHash.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash.empty), Fr.zero(), Fr.zero(), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts index 05da039bbe6..980af10d329 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts @@ -4,10 +4,12 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, } from '../../constants.gen.js'; import { type GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; import { countAccumulatedItems } from '../../utils/index.js'; +import { NoteLogHash } from '../log_hash.js'; import { ScopedNoteHash } from '../note_hash.js'; import { ScopedNullifier } from '../nullifier.js'; import { @@ -22,10 +24,11 @@ export class PrivateKernelResetOutputs { constructor( public noteHashes: Tuple, public nullifiers: Tuple, + public noteEncryptedLogHashes: Tuple, ) {} toBuffer() { - return serializeToBuffer(this.noteHashes, this.nullifiers); + return serializeToBuffer(this.noteHashes, this.nullifiers, this.noteEncryptedLogHashes); } static fromBuffer(buffer: Buffer | BufferReader) { @@ -33,6 +36,7 @@ export class PrivateKernelResetOutputs { return new PrivateKernelResetOutputs( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), ); } } @@ -47,6 +51,10 @@ export class PrivateKernelResetHints { * Contains hints for the transient nullifiers to locate corresponding note hashes. */ public transientNoteHashIndexesForNullifiers: Tuple, + /** + * Contains hints for the transient logs to locate corresponding note hashes. + */ + public transientNoteHashIndexesForLogs: Tuple, /** * Contains hints for the transient read requests to localize corresponding commitments. */ @@ -66,6 +74,7 @@ export class PrivateKernelResetHints { return serializeToBuffer( this.transientNullifierIndexesForNoteHashes, this.transientNoteHashIndexesForNullifiers, + this.transientNoteHashIndexesForLogs, this.noteHashReadRequestHints, this.nullifierReadRequestHints, this.masterNullifierSecretKeys, @@ -82,6 +91,7 @@ export class PrivateKernelResetHints { return new PrivateKernelResetHints( reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), + reader.readNumbers(MAX_NOTE_ENCRYPTED_LOGS_PER_TX), reader.readObject({ fromBuffer: noteHashReadRequestHintsFromBuffer }), reader.readObject({ fromBuffer: nullifierReadRequestHintsFromBuffer }), reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index a9d1be68988..f3015824a00 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -4,12 +4,13 @@ import { MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { countAccumulatedItems } from '../../utils/index.js'; +import { LogHash, NoteLogHash } from '../log_hash.js'; import { ScopedNoteHash } from '../note_hash.js'; import { ScopedNullifier } from '../nullifier.js'; -import { SideEffect } from '../side_effects.js'; import { PrivateKernelData } from './private_kernel_data.js'; export class PrivateKernelTailHints { @@ -30,10 +31,18 @@ export class PrivateKernelTailHints { * The sorted new nullifiers indexes. */ public sortedNewNullifiersIndexes: Tuple, + /** + * The sorted encrypted note log hashes. + */ + public sortedNoteEncryptedLogHashes: Tuple, + /** + * The sorted encrypted note log hashes indexes. Maps original to sorted. + */ + public sortedNoteEncryptedLogHashesIndexes: Tuple, /** * The sorted encrypted log hashes. */ - public sortedEncryptedLogHashes: Tuple, + public sortedEncryptedLogHashes: Tuple, /** * The sorted encrypted log hashes indexes. Maps original to sorted. */ @@ -41,7 +50,7 @@ export class PrivateKernelTailHints { /** * The sorted unencrypted log hashes. */ - public sortedUnencryptedLogHashes: Tuple, + public sortedUnencryptedLogHashes: Tuple, /** * The sorted encrypted log hashes indexes. Maps original to sorted. */ @@ -54,6 +63,8 @@ export class PrivateKernelTailHints { this.sortedNewNoteHashesIndexes, this.sortedNewNullifiers, this.sortedNewNullifiersIndexes, + this.sortedNoteEncryptedLogHashes, + this.sortedNoteEncryptedLogHashesIndexes, this.sortedEncryptedLogHashes, this.sortedEncryptedLogHashesIndexes, this.sortedUnencryptedLogHashes, @@ -73,9 +84,11 @@ export class PrivateKernelTailHints { reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), - reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), + reader.readNumbers(MAX_NOTE_ENCRYPTED_LOGS_PER_TX), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readNumbers(MAX_ENCRYPTED_LOGS_PER_TX), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), reader.readNumbers(MAX_UNENCRYPTED_LOGS_PER_TX), ); } 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 792891fc9c7..3843fe50efc 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 @@ -10,16 +10,17 @@ import { MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; +import { LogHash, NoteLogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { Nullifier } from '../nullifier.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; -import { SideEffect } from '../side_effects.js'; export class PublicAccumulatedData { constructor( @@ -36,15 +37,20 @@ export class PublicAccumulatedData { */ public newL2ToL1Msgs: Tuple, /** - * Accumulated encrypted logs hash from all the previous kernel iterations. - * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. + * Accumulated encrypted note logs hashes from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. */ - public encryptedLogsHashes: Tuple, + public noteEncryptedLogsHashes: Tuple, /** - * Accumulated unencrypted logs hash from all the previous kernel iterations. - * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. + * Accumulated encrypted logs hashes from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHashes: Tuple, + public encryptedLogsHashes: Tuple, + /** + * Accumulated unencrypted logs hashes from all the previous kernel iterations. + * Note: Truncated to 31 bytes to fit in Fr. + */ + public unencryptedLogsHashes: Tuple, /** * Total accumulated length of the encrypted log preimages emitted in all the previous kernel iterations */ @@ -71,6 +77,7 @@ export class PublicAccumulatedData { this.newNoteHashes, this.newNullifiers, this.newL2ToL1Msgs, + this.noteEncryptedLogsHashes, this.encryptedLogsHashes, this.unencryptedLogsHashes, this.encryptedLogPreimagesLength, @@ -90,6 +97,7 @@ export class PublicAccumulatedData { this.newNoteHashes.every(x => x.isEmpty()) && this.newNullifiers.every(x => x.isEmpty()) && this.newL2ToL1Msgs.every(x => x.isZero()) && + this.noteEncryptedLogsHashes.every(x => x.isEmpty()) && this.encryptedLogsHashes.every(x => x.isEmpty()) && this.unencryptedLogsHashes.every(x => x.isEmpty()) && this.encryptedLogPreimagesLength.isZero() && @@ -115,6 +123,10 @@ export class PublicAccumulatedData { .filter(x => !x.isZero()) .map(h => inspect(h)) .join(', ')}], + noteEncryptedLogsHashes: [${this.noteEncryptedLogsHashes + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], encryptedLogsHashes: [${this.encryptedLogsHashes .filter(x => !x.isEmpty()) .map(h => inspect(h)) @@ -148,8 +160,9 @@ export class PublicAccumulatedData { reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Nullifier), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), - reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), @@ -172,8 +185,9 @@ export class PublicAccumulatedData { makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash.empty), makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), - makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), - makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), + makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash.empty), + makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, LogHash.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash.empty), Fr.zero(), Fr.zero(), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), diff --git a/yarn-project/circuits.js/src/structs/log_hash.ts b/yarn-project/circuits.js/src/structs/log_hash.ts new file mode 100644 index 00000000000..7c1f0802217 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/log_hash.ts @@ -0,0 +1,72 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { type Ordered } from '../interfaces/index.js'; + +export class LogHash implements Ordered { + constructor(public value: Fr, public counter: number, public length: Fr) {} + + toFields(): Fr[] { + return [this.value, new Fr(this.counter), this.length]; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new LogHash(reader.readField(), reader.readU32(), reader.readField()); + } + + isEmpty() { + return this.value.isZero() && this.length.isZero() && !this.counter; + } + + static empty() { + return new LogHash(Fr.zero(), 0, Fr.zero()); + } + + toBuffer(): Buffer { + return serializeToBuffer(this.value, this.counter, this.length); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new LogHash(Fr.fromBuffer(reader), reader.readNumber(), Fr.fromBuffer(reader)); + } + + toString(): string { + return `value=${this.value} counter=${this.counter} length=${this.length}`; + } +} + +export class NoteLogHash implements Ordered { + constructor(public value: Fr, public counter: number, public length: Fr, public noteHashCounter: number) {} + + toFields(): Fr[] { + return [this.value, new Fr(this.counter), this.length, new Fr(this.noteHashCounter)]; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new NoteLogHash(reader.readField(), reader.readU32(), reader.readField(), reader.readU32()); + } + + isEmpty() { + return this.value.isZero() && this.length.isZero() && !this.counter && !this.noteHashCounter; + } + + static empty() { + return new NoteLogHash(Fr.zero(), 0, Fr.zero(), 0); + } + + toBuffer(): Buffer { + return serializeToBuffer(this.value, this.counter, this.length, this.noteHashCounter); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new NoteLogHash(Fr.fromBuffer(reader), reader.readNumber(), Fr.fromBuffer(reader), reader.readNumber()); + } + + toString(): string { + return `value=${this.value} counter=${this.counter} length=${this.length} noteHashCounter=${this.noteHashCounter}`; + } +} diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index 7c9da159b58..7eae5eedb78 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -17,6 +17,7 @@ import { MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, @@ -29,12 +30,12 @@ import { Header } from '../structs/header.js'; import { isEmptyArray } from '../utils/index.js'; import { CallContext } from './call_context.js'; import { L2ToL1Message } from './l2_to_l1_message.js'; +import { LogHash, NoteLogHash } from './log_hash.js'; import { MaxBlockNumber } from './max_block_number.js'; import { NoteHash } from './note_hash.js'; import { Nullifier } from './nullifier.js'; import { NullifierKeyValidationRequest } from './nullifier_key_validation_request.js'; import { ReadRequest } from './read_request.js'; -import { SideEffect } from './side_effects.js'; import { TxContext } from './tx_context.js'; /** @@ -113,16 +114,21 @@ export class PrivateCircuitPublicInputs { * The end side effect counter for this call. */ public endSideEffectCounter: Fr, + /** + * Hash of the encrypted note logs emitted in this function call. + * Note: Truncated to 31 bytes to fit in Fr. + */ + public noteEncryptedLogsHashes: Tuple, /** * Hash of the encrypted logs emitted in this function call. * Note: Truncated to 31 bytes to fit in Fr. */ - public encryptedLogsHashes: Tuple, + public encryptedLogsHashes: Tuple, /** * Hash of the unencrypted logs emitted in this function call. * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHashes: Tuple, + public unencryptedLogsHashes: Tuple, /** * Length of the encrypted log preimages emitted in this function call. * Note: Here so that the gas cost of this request can be measured by circuits, without actually needing to feed @@ -181,8 +187,9 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), - reader.readArray(MAX_ENCRYPTED_LOGS_PER_CALL, SideEffect), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, NoteLogHash), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_CALL, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), reader.readObject(Fr), reader.readObject(Fr), reader.readObject(Header), @@ -210,8 +217,9 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), - reader.readArray(MAX_ENCRYPTED_LOGS_PER_CALL, SideEffect), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, NoteLogHash), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_CALL, LogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), reader.readField(), reader.readField(), reader.readObject(Header), @@ -242,8 +250,9 @@ export class PrivateCircuitPublicInputs { makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, - makeTuple(MAX_ENCRYPTED_LOGS_PER_CALL, SideEffect.empty), - makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect.empty), + makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, NoteLogHash.empty), + makeTuple(MAX_ENCRYPTED_LOGS_PER_CALL, LogHash.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash.empty), Fr.ZERO, Fr.ZERO, Header.empty(), @@ -269,6 +278,7 @@ export class PrivateCircuitPublicInputs { isZeroArray(this.publicCallStackHashes) && this.publicTeardownFunctionHash.isZero() && isEmptyArray(this.newL2ToL1Msgs) && + isEmptyArray(this.noteEncryptedLogsHashes) && isEmptyArray(this.encryptedLogsHashes) && isEmptyArray(this.unencryptedLogsHashes) && this.encryptedLogPreimagesLength.isZero() && @@ -302,6 +312,7 @@ export class PrivateCircuitPublicInputs { fields.newL2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, + fields.noteEncryptedLogsHashes, fields.encryptedLogsHashes, fields.unencryptedLogsHashes, fields.encryptedLogPreimagesLength, diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index 77b4f05483c..0674dc53b56 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -33,11 +33,11 @@ import { Gas } from './gas.js'; import { GlobalVariables } from './global_variables.js'; import { Header } from './header.js'; import { L2ToL1Message } from './l2_to_l1_message.js'; +import { LogHash } from './log_hash.js'; import { NoteHash } from './note_hash.js'; import { Nullifier } from './nullifier.js'; import { ReadRequest } from './read_request.js'; import { RevertCode } from './revert_code.js'; -import { SideEffect } from './side_effects.js'; /** * Public inputs to a public circuit. @@ -106,7 +106,7 @@ export class PublicCircuitPublicInputs { * Hash of the unencrypted logs emitted in this function call. * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHashes: Tuple, + public unencryptedLogsHashes: Tuple, /** * Length of the unencrypted log preimages emitted in this function call. */ @@ -166,7 +166,7 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, - makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash.empty), Fr.ZERO, Header.empty(), GlobalVariables.empty(), @@ -277,7 +277,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), reader.readObject(Fr), reader.readObject(Header), reader.readObject(GlobalVariables), @@ -306,7 +306,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), reader.readField(), Header.fromFields(reader), GlobalVariables.fromFields(reader), diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 7cfc28ff701..49ccb6738b4 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -37,6 +37,7 @@ import { GrumpkinScalar, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, L2ToL1Message, + LogHash, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, @@ -45,6 +46,8 @@ import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, @@ -74,6 +77,7 @@ import { NUM_BASE_PARITY_PER_ROOT_PARITY, NUM_MSGS_PER_BASE_PARITY, NoteHash, + NoteLogHash, Nullifier, NullifierKeyValidationRequest, NullifierLeafPreimage, @@ -118,7 +122,6 @@ import { RootRollupPublicInputs, ScopedNullifierKeyValidationRequest, ScopedReadRequest, - SideEffect, StateDiffHints, StateReference, TxContext, @@ -147,8 +150,12 @@ import { ValidationRequests } from '../structs/validation_requests.js'; * @param seed - The seed to use for generating the object. * @returns A side effect object. */ -export function makeNewSideEffect(seed: number): SideEffect { - return new SideEffect(fr(seed), fr(seed + 1)); +function makeLogHash(seed: number) { + return new LogHash(fr(seed), seed + 1, fr(seed + 2)); +} + +function makeNoteLogHash(seed: number) { + return new NoteLogHash(fr(seed + 3), seed + 1, fr(seed + 2), seed); } function makeNoteHash(seed: number) { @@ -298,10 +305,11 @@ export function makeCombinedAccumulatedData(seed = 1, full = false): CombinedAcc tupleGenerator(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x120, Fr.zero), tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x200, Fr.zero), tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), - fr(seed + 0x700), // encrypted logs hash - fr(seed + 0x800), // unencrypted logs hash - fr(seed + 0x900), // encrypted_log_preimages_length - fr(seed + 0xa00), // unencrypted_log_preimages_length + fr(seed + 0x700), // note encrypted logs hash + fr(seed + 0x800), // encrypted logs hash + fr(seed + 0x900), // unencrypted logs hash + fr(seed + 0xa00), // encrypted_log_preimages_length + fr(seed + 0xb00), // unencrypted_log_preimages_length tupleGenerator( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, @@ -328,10 +336,11 @@ export function makePublicAccumulatedData(seed = 1, full = false): PublicAccumul tupleGenerator(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x120, NoteHash.empty), tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, makeNullifier, seed + 0x200, Nullifier.empty), tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), - tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, makeNewSideEffect, seed + 0x700, SideEffect.empty), // encrypted logs hashes - tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeNewSideEffect, seed + 0x800, SideEffect.empty), // unencrypted logs hashes - fr(seed + 0x900), // encrypted_log_preimages_length - fr(seed + 0xa00), // unencrypted_log_preimages_length + tupleGenerator(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, makeNoteLogHash, seed + 0x700, NoteLogHash.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 + fr(seed + 0xa00), // encrypted_log_preimages_length + fr(seed + 0xb00), // unencrypted_log_preimages_length tupleGenerator( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, @@ -407,7 +416,7 @@ export function makePublicCircuitPublicInputs( tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x900, L2ToL1Message.empty), fr(seed + 0xa00), fr(seed + 0xa01), - tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_CALL, makeNewSideEffect, seed + 0x901, SideEffect.empty), + tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_CALL, makeLogHash, seed + 0x901, LogHash.empty), fr(seed + 0x902), makeHeader(seed + 0xa00, undefined), makeGlobalVariables(seed + 0xa01), @@ -785,8 +794,9 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn newL2ToL1Msgs: makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), startSideEffectCounter: fr(seed + 0x849), endSideEffectCounter: fr(seed + 0x850), - encryptedLogsHashes: makeTuple(MAX_ENCRYPTED_LOGS_PER_CALL, makeNewSideEffect, seed + 0x900), - unencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, makeNewSideEffect, seed + 0xa00), + noteEncryptedLogsHashes: makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, makeNoteLogHash, seed + 0x875), + encryptedLogsHashes: makeTuple(MAX_ENCRYPTED_LOGS_PER_CALL, makeLogHash, seed + 0x900), + unencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, makeLogHash, seed + 0xa00), encryptedLogPreimagesLength: fr(seed + 0xb00), unencryptedLogPreimagesLength: fr(seed + 0xc00), historicalHeader: makeHeader(seed + 0xd00, undefined), diff --git a/yarn-project/end-to-end/src/benchmarks/bench_proving.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_proving.test.ts index 52f1d2f8826..b77ced7138c 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_proving.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_proving.test.ts @@ -11,7 +11,7 @@ import { getACVMConfig } from '../fixtures/get_acvm_config.js'; import { getBBConfig } from '../fixtures/get_bb_config.js'; import { type EndToEndContext, publicDeployAccounts, setup } from '../fixtures/utils.js'; -jest.setTimeout(600_000); +jest.setTimeout(900_000); const txTimeoutSec = 600; diff --git a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts index 26e03ead1e4..a73f08a32d2 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts @@ -67,28 +67,28 @@ describe('benchmarks/tx_size_fees', () => { 'native fee', () => NativeFeePaymentMethod.create(aliceWallet), // DA: - // non-rev: 1 nullifiers, overhead; rev: 2 note hashes, 1 nullifier, 624 B enc logs, 8 B unenc logs, teardown + // non-rev: 1 nullifiers, overhead; rev: 2 note hashes, 1 nullifier, 616 B enc logs, 0 B unenc logs, teardown // L2: // non-rev: 0; rev: 0 - 200012672n, + 200012416n, ], [ 'public fee', () => Promise.resolve(new PublicFeePaymentMethod(token.address, fpc.address, aliceWallet)), // DA: - // non-rev: 1 nullifiers, overhead; rev: 2 note hashes, 1 nullifier, 628 B enc logs, 12 B unenc logs, teardown + // non-rev: 1 nullifiers, overhead; rev: 2 note hashes, 1 nullifier, 616 B enc logs, 0 B unenc logs, teardown // L2: // non-rev: 0; rev: 0 - 200012800n, + 200012416n, ], [ 'private fee', () => Promise.resolve(new PrivateFeePaymentMethod(token.address, fpc.address, aliceWallet)), // DA: - // non-rev: 3 nullifiers, overhead; rev: 2 note hashes, 944 B enc logs, 20 B unenc logs, teardown + // non-rev: 3 nullifiers, overhead; rev: 2 note hashes, 616 B enc logs, 0 B unenc logs, teardown // L2: // non-rev: 0; rev: 0 - 200018496n, + 200012928n, ], ] as const)( 'sends a tx with a fee with %s payment method', diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index fcd544eecce..0e61140a4c8 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -16,7 +16,7 @@ import { ChildContract, TokenContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; -import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } from './fixtures/utils.js'; +import { expectsNumOfNoteEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } from './fixtures/utils.js'; const TIMEOUT = 120_000; @@ -132,7 +132,7 @@ describe('e2e_2_pxes', () => { // Check initial balances and logs are as expected await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); + await expectsNumOfNoteEncryptedLogsInTheLastBlockToBe(aztecNode, 1); // Transfer funds from A to B via PXE A const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); @@ -144,7 +144,7 @@ describe('e2e_2_pxes', () => { // Check balances and logs are as expected await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1); - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + await expectsNumOfNoteEncryptedLogsInTheLastBlockToBe(aztecNode, 2); // Transfer funds from B to A via PXE B const contractWithWalletB = await TokenContract.at(tokenAddress, walletB); @@ -161,7 +161,7 @@ describe('e2e_2_pxes', () => { initialBalance - transferAmount1 + transferAmount2, ); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1 - transferAmount2); - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + await expectsNumOfNoteEncryptedLogsInTheLastBlockToBe(aztecNode, 2); }); const deployChildContractViaServerA = async () => { @@ -276,7 +276,7 @@ describe('e2e_2_pxes', () => { await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); // don't check userB yet - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); + await expectsNumOfNoteEncryptedLogsInTheLastBlockToBe(aztecNode, 1); // Transfer funds from A to B via PXE A const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 0688b129d9d..f23dfb99b48 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -273,7 +273,7 @@ describe('e2e_block_building', () => { // compare logs expect(rct.status).toEqual('mined'); - const decryptedLogs = tx.encryptedLogs + const decryptedLogs = tx.noteEncryptedLogs .unrollLogs() .map(l => TaggedNote.fromEncryptedBuffer(l.data, keys.masterIncomingViewingSecretKey)); const notevalues = decryptedLogs.map(l => l?.notePayload.note.items[0]); diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 3f2a3dc22e7..06ec9e71473 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -19,7 +19,7 @@ import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-re import { jest } from '@jest/globals'; -import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } from './fixtures/utils.js'; +import { expectsNumOfNoteEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } from './fixtures/utils.js'; const TIMEOUT = 120_000; @@ -168,7 +168,7 @@ describe('e2e_key_rotation', () => { // Check balances and logs are as expected await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transfer1Amount); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transfer1Amount); - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + await expectsNumOfNoteEncryptedLogsInTheLastBlockToBe(aztecNode, 2); } // 3. Rotates B key diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index 25b146be25a..c993171e774 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -15,7 +15,7 @@ import { } from '@aztec/aztec.js'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; -import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup } from './fixtures/utils.js'; +import { expectsNumOfNoteEncryptedLogsInTheLastBlockToBe, setup } from './fixtures/utils.js'; describe('e2e_multiple_accounts_1_enc_key', () => { let aztecNode: AztecNode | undefined; @@ -109,7 +109,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { await expectBalance(i, expectedBalances[i]); } - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + await expectsNumOfNoteEncryptedLogsInTheLastBlockToBe(aztecNode, 2); logger.info(`Transfer ${transferAmount} from ${sender} to ${receiver} successful`); }; diff --git a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts index 4b49fa43f6b..ebfc03a48a3 100644 --- a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts @@ -1,6 +1,7 @@ import { type AztecAddress, type AztecNode, type DebugLogger, Fr, type Wallet } from '@aztec/aztec.js'; import { PendingNoteHashesContract } from '@aztec/noir-contracts.js/PendingNoteHashes'; +import { EncryptedTxL2Logs } from '../../circuit-types/src/logs/tx_l2_logs.js'; import { setup } from './fixtures/utils.js'; describe('e2e_pending_note_hashes_contract', () => { @@ -50,6 +51,20 @@ describe('e2e_pending_note_hashes_contract', () => { } }; + const expectNoteLogsSquashedExcept = async (exceptFirstFew: number) => { + const blockNum = await aztecNode.getBlockNumber(); + const block = (await aztecNode.getBlocks(blockNum, 1))[0]; + + const logArray = block.body.txEffects.flatMap(txEffect => txEffect.noteEncryptedLogs); + + for (let l = 0; l < exceptFirstFew + 1; l++) { + expect(logArray[l]).not.toEqual(EncryptedTxL2Logs.empty()); + } + for (let l = exceptFirstFew + 1; l < logArray.length; l++) { + expect(logArray[l]).toEqual(EncryptedTxL2Logs.empty()); + } + }; + const deployContract = async () => { logger.debug(`Deploying L2 contract...`); contract = await PendingNoteHashesContract.deploy(wallet).send().deployed(); @@ -87,6 +102,7 @@ describe('e2e_pending_note_hashes_contract', () => { await expectNoteHashesSquashedExcept(0); await expectNullifiersSquashedExcept(0); + await expectNoteLogsSquashedExcept(0); }); it('Squash! Aztec.nr function can "create" 2 notes and "nullify" both in the same TX', async () => { @@ -108,6 +124,7 @@ describe('e2e_pending_note_hashes_contract', () => { await expectNoteHashesSquashedExcept(0); await expectNullifiersSquashedExcept(0); + await expectNoteLogsSquashedExcept(0); }); it('Squash! Aztec.nr function can "create" 2 notes and "nullify" 1 in the same TX (kernel will squash one note + nullifier)', async () => { @@ -130,6 +147,7 @@ describe('e2e_pending_note_hashes_contract', () => { await expectNoteHashesSquashedExcept(1); await expectNullifiersSquashedExcept(0); + await expectNoteLogsSquashedExcept(1); }); it('Squash! Aztec.nr function can nullify a pending note and a persistent in the same TX', async () => { @@ -147,6 +165,7 @@ describe('e2e_pending_note_hashes_contract', () => { await expectNoteHashesSquashedExcept(1); // first TX just creates 1 persistent note await expectNullifiersSquashedExcept(0); + await expectNoteLogsSquashedExcept(1); // create another note, and nullify it and AND nullify the above-created note in the same TX await deployedContract.methods @@ -167,6 +186,7 @@ describe('e2e_pending_note_hashes_contract', () => { // the nullifier corresponding to this transient note is squashed, but the // other nullifier corresponding to the persistent note becomes persistent itself. await expectNullifiersSquashedExcept(1); + await expectNoteLogsSquashedExcept(0); }); it('get_notes function filters a nullified note created in a previous transaction', async () => { @@ -182,6 +202,7 @@ describe('e2e_pending_note_hashes_contract', () => { // There is a single new note hash. await expectNoteHashesSquashedExcept(1); + await expectNoteLogsSquashedExcept(1); await deployedContract.methods .test_insert_then_get_then_nullify_all_in_nested_calls( diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index f7bb329fd92..69773a10de4 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -490,7 +490,7 @@ export function getLogger() { * @param aztecNode - The instance of aztec node for retrieving the logs. * @param numEncryptedLogs - The number of expected logs. */ -export const expectsNumOfEncryptedLogsInTheLastBlockToBe = async ( +export const expectsNumOfNoteEncryptedLogsInTheLastBlockToBe = async ( aztecNode: AztecNode | undefined, numEncryptedLogs: number, ) => { @@ -500,7 +500,7 @@ export const expectsNumOfEncryptedLogsInTheLastBlockToBe = async ( return; } const l2BlockNum = await aztecNode.getBlockNumber(); - const encryptedLogs = await aztecNode.getLogs(l2BlockNum, 1, LogType.ENCRYPTED); + const encryptedLogs = await aztecNode.getLogs(l2BlockNum, 1, LogType.NOTEENCRYPTED); const unrolledLogs = EncryptedL2BlockL2Logs.unrollLogs(encryptedLogs); expect(unrolledLogs.length).toBe(numEncryptedLogs); }; 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 380d7ee8e0d..750d1909db5 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -29,10 +29,12 @@ import { type KernelData, L2ToL1Message, type LeafDataReadHint, + LogHash, MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, @@ -52,6 +54,7 @@ import { type NonMembershipHint, NoteHash, type NoteHashReadRequestHints, + NoteLogHash, Nullifier, NullifierKeyValidationRequest, type NullifierLeafPreimage, @@ -111,7 +114,6 @@ import { ScopedNullifierKeyValidationRequest, ScopedReadRequest, type SettledReadHint, - SideEffect, type StateDiffHints, StateReference, TxContext, @@ -148,6 +150,7 @@ import type { KernelData as KernelDataNoir, L2ToL1Message as L2ToL1MessageNoir, LeafDataReadHint as LeafDataReadHintNoir, + LogHash as LogHashNoir, MaxBlockNumber as MaxBlockNumberNoir, MembershipWitness as MembershipWitnessNoir, MergeRollupInputs as MergeRollupInputsNoir, @@ -159,6 +162,7 @@ import type { NoteHash as NoteHashNoir, NoteHashReadRequestHints as NoteHashReadRequestHintsNoir, NoteHashSettledReadHint as NoteHashSettledReadHintNoir, + NoteLogHash as NoteLogHashNoir, NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, NullifierLeafPreimage as NullifierLeafPreimageNoir, Nullifier as NullifierNoir, @@ -213,7 +217,6 @@ import type { ScopedNullifierKeyValidationRequest as ScopedNullifierKeyValidationRequestNoir, ScopedNullifier as ScopedNullifierNoir, ScopedReadRequest as ScopedReadRequestNoir, - SideEffect as SideEffectNoir, StateDiffHints as StateDiffHintsNoir, StateReference as StateReferenceNoir, StorageRead as StorageReadNoir, @@ -591,24 +594,57 @@ function mapScopedNullifierFromNoir(nullifier: ScopedNullifierNoir) { } /** - * Maps a SideEffect to a noir side effect. - * @param sideEffect - The SideEffect. + * Maps a LogHash to a noir LogHash. + * @param sideEffect - The LogHash. * @returns The noir side effect. */ -export function mapSideEffectToNoir(sideEffect: SideEffect): SideEffectNoir { +export function mapLogHashToNoir(logHash: LogHash): LogHashNoir { return { - value: mapFieldToNoir(sideEffect.value), - counter: mapFieldToNoir(sideEffect.counter), + value: mapFieldToNoir(logHash.value), + counter: mapNumberToNoir(logHash.counter), + length: mapFieldToNoir(logHash.length), }; } /** - * Maps a noir side effect to a SideEffect. - * @param sideEffect - The noir SideEffect. + * Maps a noir LogHash to a LogHash. + * @param sideEffect - The noir LogHash. * @returns The TS side effect. */ -export function mapSideEffectFromNoir(sideEffect: SideEffectNoir): SideEffect { - return new SideEffect(mapFieldFromNoir(sideEffect.value), mapFieldFromNoir(sideEffect.counter)); +export function mapLogHashFromNoir(logHash: LogHashNoir): LogHash { + return new LogHash( + mapFieldFromNoir(logHash.value), + mapNumberFromNoir(logHash.counter), + mapFieldFromNoir(logHash.length), + ); +} + +/** + * Maps a LogHash to a noir LogHash. + * @param sideEffect - The LogHash. + * @returns The noir side effect. + */ +export function mapNoteLogHashToNoir(noteLogHash: NoteLogHash): NoteLogHashNoir { + return { + value: mapFieldToNoir(noteLogHash.value), + counter: mapNumberToNoir(noteLogHash.counter), + length: mapFieldToNoir(noteLogHash.length), + note_hash_counter: mapNumberToNoir(noteLogHash.noteHashCounter), + }; +} + +/** + * Maps a noir LogHash to a LogHash. + * @param sideEffect - The noir LogHash. + * @returns The TS side effect. + */ +export function mapNoteLogHashFromNoir(noteLogHash: NoteLogHashNoir): NoteLogHash { + return new NoteLogHash( + mapFieldFromNoir(noteLogHash.value), + mapNumberFromNoir(noteLogHash.counter), + mapFieldFromNoir(noteLogHash.length), + mapNumberFromNoir(noteLogHash.note_hash_counter), + ); } /** @@ -759,8 +795,9 @@ export function mapPrivateCircuitPublicInputsToNoir( new_l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.endSideEffectCounter), - encrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.encryptedLogsHashes, mapSideEffectToNoir), - unencrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.unencryptedLogsHashes, mapSideEffectToNoir), + note_encrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.noteEncryptedLogsHashes, mapNoteLogHashToNoir), + encrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.encryptedLogsHashes, mapLogHashToNoir), + unencrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.unencryptedLogsHashes, mapLogHashToNoir), encrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.unencryptedLogPreimagesLength), historical_header: mapHeaderToNoir(privateCircuitPublicInputs.historicalHeader), @@ -1048,12 +1085,13 @@ export function mapPrivateAccumulatedDataFromNoir( MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapScopedL2ToL1MessageFromNoir, ), - mapTupleFromNoir(privateAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), mapTupleFromNoir( - privateAccumulatedData.unencrypted_logs_hashes, - MAX_UNENCRYPTED_LOGS_PER_TX, - mapSideEffectFromNoir, + privateAccumulatedData.note_encrypted_logs_hashes, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + mapNoteLogHashFromNoir, ), + mapTupleFromNoir(privateAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), + mapTupleFromNoir(privateAccumulatedData.unencrypted_logs_hashes, MAX_UNENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), mapFieldFromNoir(privateAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(privateAccumulatedData.unencrypted_log_preimages_length), mapTupleFromNoir( @@ -1074,8 +1112,9 @@ export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): P new_note_hashes: mapTuple(data.newNoteHashes, mapScopedNoteHashToNoir), new_nullifiers: mapTuple(data.newNullifiers, mapScopedNullifierToNoir), new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapScopedL2ToL1MessageToNoir), - encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapSideEffectToNoir), - unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapSideEffectToNoir), + note_encrypted_logs_hashes: mapTuple(data.noteEncryptedLogsHashes, mapNoteLogHashToNoir), + encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapLogHashToNoir), + unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapLogHashToNoir), encrypted_log_preimages_length: mapFieldToNoir(data.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(data.unencryptedLogPreimagesLength), private_call_stack: mapTuple(data.privateCallStack, mapCallRequestToNoir), @@ -1090,8 +1129,13 @@ export function mapPublicAccumulatedDataFromNoir( mapTupleFromNoir(publicAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapNoteHashFromNoir), mapTupleFromNoir(publicAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierFromNoir), mapTupleFromNoir(publicAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), - mapTupleFromNoir(publicAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), - mapTupleFromNoir(publicAccumulatedData.unencrypted_logs_hashes, MAX_UNENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), + mapTupleFromNoir( + publicAccumulatedData.note_encrypted_logs_hashes, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + mapNoteLogHashFromNoir, + ), + mapTupleFromNoir(publicAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), + mapTupleFromNoir(publicAccumulatedData.unencrypted_logs_hashes, MAX_UNENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), mapFieldFromNoir(publicAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(publicAccumulatedData.unencrypted_log_preimages_length), mapTupleFromNoir( @@ -1115,8 +1159,9 @@ export function mapPublicAccumulatedDataToNoir( new_note_hashes: mapTuple(publicAccumulatedData.newNoteHashes, mapNoteHashToNoir), new_nullifiers: mapTuple(publicAccumulatedData.newNullifiers, mapNullifierToNoir), new_l2_to_l1_msgs: mapTuple(publicAccumulatedData.newL2ToL1Msgs, mapFieldToNoir), - encrypted_logs_hashes: mapTuple(publicAccumulatedData.encryptedLogsHashes, mapSideEffectToNoir), - unencrypted_logs_hashes: mapTuple(publicAccumulatedData.unencryptedLogsHashes, mapSideEffectToNoir), + note_encrypted_logs_hashes: mapTuple(publicAccumulatedData.noteEncryptedLogsHashes, mapNoteLogHashToNoir), + encrypted_logs_hashes: mapTuple(publicAccumulatedData.encryptedLogsHashes, mapLogHashToNoir), + unencrypted_logs_hashes: mapTuple(publicAccumulatedData.unencryptedLogsHashes, mapLogHashToNoir), encrypted_log_preimages_length: mapFieldToNoir(publicAccumulatedData.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(publicAccumulatedData.unencryptedLogPreimagesLength), public_data_update_requests: mapTuple( @@ -1181,6 +1226,7 @@ export function mapCombinedAccumulatedDataFromNoir( mapTupleFromNoir(combinedAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapFieldFromNoir), mapTupleFromNoir(combinedAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapFieldFromNoir), mapTupleFromNoir(combinedAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), + mapFieldFromNoir(combinedAccumulatedData.note_encrypted_logs_hash), mapFieldFromNoir(combinedAccumulatedData.encrypted_logs_hash), mapFieldFromNoir(combinedAccumulatedData.unencrypted_logs_hash), mapFieldFromNoir(combinedAccumulatedData.encrypted_log_preimages_length), @@ -1201,6 +1247,7 @@ export function mapCombinedAccumulatedDataToNoir( new_note_hashes: mapTuple(combinedAccumulatedData.newNoteHashes, mapFieldToNoir), new_nullifiers: mapTuple(combinedAccumulatedData.newNullifiers, mapFieldToNoir), new_l2_to_l1_msgs: mapTuple(combinedAccumulatedData.newL2ToL1Msgs, mapFieldToNoir), + note_encrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.noteEncryptedLogsHash), encrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.encryptedLogsHash), unencrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.unencryptedLogsHash), encrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.encryptedLogPreimagesLength), @@ -1423,6 +1470,7 @@ function mapPrivateKernelResetOutputsToNoir(inputs: PrivateKernelResetOutputs): return { note_hashes: mapTuple(inputs.noteHashes, mapScopedNoteHashToNoir), nullifiers: mapTuple(inputs.nullifiers, mapScopedNullifierToNoir), + note_encrypted_log_hashes: mapTuple(inputs.noteEncryptedLogHashes, mapNoteLogHashToNoir), }; } @@ -1432,9 +1480,11 @@ function mapPrivateKernelTailHintsToNoir(inputs: PrivateKernelTailHints): Privat sorted_new_note_hashes_indexes: mapTuple(inputs.sortedNewNoteHashesIndexes, mapNumberToNoir), sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapScopedNullifierToNoir), sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), - sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapSideEffectToNoir), + sorted_note_encrypted_log_hashes: mapTuple(inputs.sortedNoteEncryptedLogHashes, mapNoteLogHashToNoir), + sorted_note_encrypted_log_hashes_indexes: mapTuple(inputs.sortedNoteEncryptedLogHashesIndexes, mapNumberToNoir), + sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapLogHashToNoir), sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), - sorted_unencrypted_log_hashes: mapTuple(inputs.sortedUnencryptedLogHashes, mapSideEffectToNoir), + sorted_unencrypted_log_hashes: mapTuple(inputs.sortedUnencryptedLogHashes, mapLogHashToNoir), sorted_unencrypted_log_hashes_indexes: mapTuple(inputs.sortedUnencryptedLogHashesIndexes, mapNumberToNoir), }; } @@ -1446,6 +1496,7 @@ function mapPrivateKernelResetHintsToNoir(inputs: PrivateKernelResetHints): Priv mapNumberToNoir, ), transient_note_hash_indexes_for_nullifiers: mapTuple(inputs.transientNoteHashIndexesForNullifiers, mapNumberToNoir), + transient_note_hash_indexes_for_logs: mapTuple(inputs.transientNoteHashIndexesForLogs, mapNumberToNoir), note_hash_read_request_hints: mapNoteHashReadRequestHintsToNoir(inputs.noteHashReadRequestHints), nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), @@ -1629,7 +1680,7 @@ export function mapPublicCircuitPublicInputsToNoir( new_l2_to_l1_msgs: mapTuple(publicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(publicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(publicInputs.endSideEffectCounter), - unencrypted_logs_hashes: mapTuple(publicInputs.unencryptedLogsHashes, mapSideEffectToNoir), + unencrypted_logs_hashes: mapTuple(publicInputs.unencryptedLogsHashes, mapLogHashToNoir), unencrypted_log_preimages_length: mapFieldToNoir(publicInputs.unencryptedLogPreimagesLength), historical_header: mapHeaderToNoir(publicInputs.historicalHeader), global_variables: mapGlobalVariablesToNoir(publicInputs.globalVariables), diff --git a/yarn-project/p2p/src/service/tx_messages.ts b/yarn-project/p2p/src/service/tx_messages.ts index c4ec54e5db0..418704d492a 100644 --- a/yarn-project/p2p/src/service/tx_messages.ts +++ b/yarn-project/p2p/src/service/tx_messages.ts @@ -68,6 +68,7 @@ export function toTxMessage(tx: Tx): Buffer { const messageBuffer = Buffer.concat([ createMessageComponent(tx.data), createMessageComponent(tx.proof), + createMessageComponent(tx.noteEncryptedLogs), createMessageComponent(tx.encryptedLogs), createMessageComponent(tx.unencryptedLogs), createMessageComponents(tx.enqueuedPublicFunctionCalls), @@ -114,7 +115,11 @@ export function fromTxMessage(buffer: Buffer): Tx { const publicInputs = toObject(buffer.subarray(4), PrivateKernelTailCircuitPublicInputs); const proof = toObject(publicInputs.remainingData, Proof); - const encryptedLogs = toObject(proof.remainingData, EncryptedTxL2Logs); + const noteEncryptedLogs = toObject(proof.remainingData, EncryptedTxL2Logs); + if (!noteEncryptedLogs.obj) { + noteEncryptedLogs.obj = new EncryptedTxL2Logs([]); + } + const encryptedLogs = toObject(noteEncryptedLogs.remainingData, EncryptedTxL2Logs); if (!encryptedLogs.obj) { encryptedLogs.obj = new EncryptedTxL2Logs([]); } @@ -129,6 +134,7 @@ export function fromTxMessage(buffer: Buffer): Tx { return new Tx( publicInputs.obj!, proof.obj!, + noteEncryptedLogs.obj, encryptedLogs.obj, unencryptedLogs.obj, publicCalls.objects, diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index 065c5296edf..74c4e2cb62b 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -119,6 +119,7 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se processedTx.data.end.newNullifiers[tx.data.forPublic!.end.newNullifiers.length - 1] = Fr.zero(); processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); + processedTx.data.end.noteEncryptedLogsHash = Fr.fromBuffer(processedTx.noteEncryptedLogs.hash(0)); processedTx.data.end.encryptedLogsHash = Fr.fromBuffer(processedTx.encryptedLogs.hash()); processedTx.data.end.unencryptedLogsHash = Fr.fromBuffer(processedTx.unencryptedLogs.hash()); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 302f35acd5c..48d144b05fd 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -408,6 +408,18 @@ export class ProvingOrchestrator { logger.debug('Not running base rollup, state invalid'); return; } + if ( + !tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHash + .toBuffer() + .equals(tx.processedTx.noteEncryptedLogs.hash(0)) + ) { + provingState.reject( + `Note encrypted logs hash mismatch: ${ + tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHash + } === ${Fr.fromBuffer(tx.processedTx.noteEncryptedLogs.hash(0))}`, + ); + return; + } if ( !tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash .toBuffer() diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index 99983a3bfb3..efbfafffe61 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -77,6 +77,7 @@ describe('Kernel Prover', () => { partialWitness: new Map(), enqueuedPublicFunctionCalls: [], publicTeardownFunctionCall: PublicCallRequest.empty(), + noteEncryptedLogs: [], encryptedLogs: [], unencryptedLogs: [], }; diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 5d3da7712c4..6c9f033c274 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -140,6 +140,7 @@ export class KernelProver { const expectedOutputs = buildPrivateKernelResetOutputs( output.publicInputs.end.newNoteHashes, output.publicInputs.end.newNullifiers, + output.publicInputs.end.noteEncryptedLogsHashes, ); output = await this.proofCreator.createProofReset( diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts index a38f81f292b..1449ceec2ac 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts @@ -3,6 +3,7 @@ import { GrumpkinScalar, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, type MAX_NULLIFIER_READ_REQUESTS_PER_TX, MembershipWitness, @@ -87,16 +88,23 @@ export async function buildPrivateKernelResetHints( oracle, ); - const [transientNullifierIndexesForNoteHashes, transientNoteHashIndexesForNullifiers] = buildTransientDataHints( + const [ + transientNullifierIndexesForNoteHashes, + transientNoteHashIndexesForNullifiers, + transientNoteHashIndexesForLogs, + ] = buildTransientDataHints( publicInputs.end.newNoteHashes, publicInputs.end.newNullifiers, + publicInputs.end.noteEncryptedLogsHashes, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, ); return new PrivateKernelResetHints( transientNullifierIndexesForNoteHashes, transientNoteHashIndexesForNullifiers, + transientNoteHashIndexesForLogs, noteHashReadRequestHints, nullifierReadRequestHints, masterNullifierSecretKeys, diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts index e2b80f6f0f2..7278cf72e80 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts @@ -1,6 +1,8 @@ import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + NoteLogHash, PrivateKernelResetOutputs, ScopedNoteHash, ScopedNullifier, @@ -11,6 +13,7 @@ import { type Tuple } from '@aztec/foundation/serialize'; export function buildPrivateKernelResetOutputs( prevNoteHashes: Tuple, prevNullifiers: Tuple, + prevLogs: Tuple, ) { // Propagate note hashes that are not linked to a nullifier. // Note that note hashes can't link to the first nullifier (counter == 0). @@ -26,5 +29,13 @@ export function buildPrivateKernelResetOutputs( MAX_NEW_NULLIFIERS_PER_TX, ); - return new PrivateKernelResetOutputs(noteHashes, nullifiers); + const nullifiedNotes = prevNoteHashes.filter(n => !n.isEmpty() && n.nullifierCounter).map(n => n.counter); + + const logs = padArrayEnd( + prevLogs.filter(l => !l.isEmpty() && !nullifiedNotes.includes(l.noteHashCounter)), + NoteLogHash.empty(), + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + ); + + return new PrivateKernelResetOutputs(noteHashes, nullifiers, logs); } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index 8b30244e83b..4a0781fdb8a 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -1,37 +1,13 @@ import { - type MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, - type MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, type PrivateKernelCircuitPublicInputs, PrivateKernelTailHints, - type SideEffect, - type SideEffectType, sortByCounterGetSortedHints, } from '@aztec/circuits.js'; -import { type Tuple } from '@aztec/foundation/serialize'; - -/** @deprecated Use sortByCounterGetSortedHints instead */ -function sortSideEffects( - sideEffects: Tuple, -): [Tuple, Tuple] { - const sorted = sideEffects - .map((sideEffect, index) => ({ sideEffect, index })) - .sort((a, b) => { - // Empty ones go to the right - if (a.sideEffect.isEmpty()) { - return 1; - } - return Number(a.sideEffect.counter.toBigInt() - b.sideEffect.counter.toBigInt()); - }); - - const originalToSorted = sorted.map(() => 0); - sorted.forEach(({ index }, i) => { - originalToSorted[index] = i; - }); - - return [sorted.map(({ sideEffect }) => sideEffect) as Tuple, originalToSorted as Tuple]; -} export function buildPrivateKernelTailHints(publicInputs: PrivateKernelCircuitPublicInputs) { const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( @@ -44,21 +20,28 @@ export function buildPrivateKernelTailHints(publicInputs: PrivateKernelCircuitPu MAX_NEW_NULLIFIERS_PER_TX, ); - const [sortedEncryptedLogHashes, sortedEncryptedLogHashesIndexes] = sortSideEffects< - SideEffect, - typeof MAX_ENCRYPTED_LOGS_PER_TX - >(publicInputs.end.encryptedLogsHashes); + const [sortedNoteEncryptedLogHashes, sortedNoteEncryptedLogHashesIndexes] = sortByCounterGetSortedHints( + publicInputs.end.noteEncryptedLogsHashes, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + ); + + const [sortedEncryptedLogHashes, sortedEncryptedLogHashesIndexes] = sortByCounterGetSortedHints( + publicInputs.end.encryptedLogsHashes, + MAX_ENCRYPTED_LOGS_PER_TX, + ); - const [sortedUnencryptedLogHashes, sortedUnencryptedLogHashesIndexes] = sortSideEffects< - SideEffect, - typeof MAX_UNENCRYPTED_LOGS_PER_TX - >(publicInputs.end.unencryptedLogsHashes); + const [sortedUnencryptedLogHashes, sortedUnencryptedLogHashesIndexes] = sortByCounterGetSortedHints( + publicInputs.end.unencryptedLogsHashes, + MAX_UNENCRYPTED_LOGS_PER_TX, + ); return new PrivateKernelTailHints( sortedNoteHashes, sortedNoteHashesIndexes, sortedNullifiers, sortedNullifiersIndexes, + sortedNoteEncryptedLogHashes, + sortedNoteEncryptedLogHashesIndexes, sortedEncryptedLogHashes, sortedEncryptedLogHashesIndexes, sortedUnencryptedLogHashes, diff --git a/yarn-project/pxe/src/note_processor/produce_note_dao.ts b/yarn-project/pxe/src/note_processor/produce_note_dao.ts index f22d17f63eb..d5de1d4dea9 100644 --- a/yarn-project/pxe/src/note_processor/produce_note_dao.ts +++ b/yarn-project/pxe/src/note_processor/produce_note_dao.ts @@ -107,25 +107,9 @@ async function findNoteIndexAndNullifier( } if (!nonce) { - let errorString; - if (siloedNoteHash == undefined) { - errorString = 'Cannot find a matching commitment for the note.'; - } else { - errorString = `We decrypted a log, but couldn't find a corresponding note in the tree. -This might be because the note was nullified in the same tx which created it. -In that case, everything is fine. To check whether this is the case, look back through -the logs for a notification -'important: chopped commitment for siloed inner hash note -${siloedNoteHash.toString()}'. -If you can see that notification. Everything's fine. -If that's not the case, and you can't find such a notification, something has gone wrong. -There could be a problem with the way you've defined a custom note, or with the way you're -serializing / deserializing / hashing / encrypting / decrypting that note. -Please see the following github issue to track an improvement that we're working on: -https://github.com/AztecProtocol/aztec-packages/issues/1641`; - } - - throw new Error(errorString); + // NB: this used to warn the user that a decrypted log didn't match any notes. + // This was previously fine as we didn't chop transient note logs, but now we do (#1641 complete). + throw new Error('Cannot find a matching commitment for the note.'); } return { diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 68f011b7f92..91c00795841 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -48,6 +48,7 @@ import { collectEnqueuedPublicFunctionCalls, collectPublicTeardownFunctionCall, collectSortedEncryptedLogs, + collectSortedNoteEncryptedLogs, collectSortedUnencryptedLogs, resolveOpcodeLocations, } from '@aztec/simulator'; @@ -661,6 +662,7 @@ export class PXEService implements PXE { this.log.debug(`Executing kernel prover...`); const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult); + const noteEncryptedLogs = new EncryptedTxL2Logs([collectSortedNoteEncryptedLogs(executionResult)]); const unencryptedLogs = new UnencryptedTxL2Logs([collectSortedUnencryptedLogs(executionResult)]); const encryptedLogs = new EncryptedTxL2Logs([collectSortedEncryptedLogs(executionResult)]); const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult); @@ -673,6 +675,7 @@ export class PXEService implements PXE { const tx = new Tx( publicInputs, proof.binaryProof, + noteEncryptedLogs, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions, diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index 527fe3d9a47..f85a7cf3a7d 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -105,18 +105,18 @@ export class Synchronizer { return false; } - const encryptedLogs = blocks.flatMap(block => block.body.encryptedLogs); + const noteEncryptedLogs = blocks.flatMap(block => block.body.noteEncryptedLogs); // Update latest tree roots from the most recent block const latestBlock = blocks[blocks.length - 1]; await this.setHeaderFromBlock(latestBlock); - const logCount = L2BlockL2Logs.getTotalLogCount(encryptedLogs); + const logCount = L2BlockL2Logs.getTotalLogCount(noteEncryptedLogs); this.log.debug( `Forwarding ${logCount} encrypted logs and blocks to ${this.noteProcessors.length} note processors`, ); for (const noteProcessor of this.noteProcessors) { - await noteProcessor.process(blocks, encryptedLogs); + await noteProcessor.process(blocks, noteEncryptedLogs); } return true; } catch (err) { @@ -182,9 +182,9 @@ export class Synchronizer { throw new Error('No blocks in processor catch up mode'); } - const encryptedLogs = blocks.flatMap(block => block.body.encryptedLogs); + const noteEncryptedLogs = blocks.flatMap(block => block.body.noteEncryptedLogs); - const logCount = L2BlockL2Logs.getTotalLogCount(encryptedLogs); + const logCount = L2BlockL2Logs.getTotalLogCount(noteEncryptedLogs); this.log.debug(`Forwarding ${logCount} encrypted logs and blocks to note processors in catch up mode`); for (const noteProcessor of catchUpGroup) { @@ -202,7 +202,7 @@ export class Synchronizer { blocks.length - index } blocks`, ); - await noteProcessor.process(blocks.slice(index), encryptedLogs.slice(index)); + await noteProcessor.process(blocks.slice(index), noteEncryptedLogs.slice(index)); if (noteProcessor.status.syncedToBlock === toBlockNumber) { // Note processor caught up, move it to `noteProcessors` from `noteProcessorsToCatchUp`. diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 94f764409bd..3017e1a7eaf 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -6,10 +6,10 @@ import { ContractStorageUpdateRequest, EthAddress, L2ToL1Message, + LogHash, NoteHash, Nullifier, ReadRequest, - SideEffect, } from '@aztec/circuits.js'; import { EventSelector } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; @@ -64,7 +64,7 @@ type PartialPublicExecutionResult = { newNullifiers: Nullifier[]; contractStorageReads: ContractStorageRead[]; contractStorageUpdateRequests: ContractStorageUpdateRequest[]; - unencryptedLogsHashes: SideEffect[]; + unencryptedLogsHashes: LogHash[]; unencryptedLogs: UnencryptedL2Log[]; unencryptedLogPreimagesLength: Fr; allUnencryptedLogs: UnencryptedL2Log[]; @@ -119,8 +119,7 @@ export class AvmPersistableStateManager { contractStorageUpdateRequests: [], unencryptedLogsHashes: [], unencryptedLogs: [], - // The length starts at 4 because it will always include the size. - unencryptedLogPreimagesLength: new Fr(4), + unencryptedLogPreimagesLength: Fr.ZERO, allUnencryptedLogs: [], nestedExecutions: [], }; @@ -311,12 +310,14 @@ export class AvmPersistableStateManager { this.transitionalExecutionResult.allUnencryptedLogs.push(ulog); // this duplicates exactly what happens in the trace just for the purpose of transitional integration with the kernel this.transitionalExecutionResult.unencryptedLogsHashes.push( - new SideEffect(logHash, new Fr(this.trace.accessCounter)), + new LogHash(logHash, this.trace.accessCounter, new Fr(ulog.length)), ); // Duplicates computation performed in public_context.nr::emit_unencrypted_log // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4). - this.transitionalExecutionResult.unencryptedLogPreimagesLength = new Fr( - this.transitionalExecutionResult.unencryptedLogPreimagesLength.toNumber() + 44 + log.length * Fr.SIZE_IN_BYTES, + // Note that ulog.length includes all the above bytes apart from processed log len + // Processed log len is added to replicate conversion to function_l2_logs at the end of exec. + this.transitionalExecutionResult.unencryptedLogPreimagesLength = new Fr(ulog.length + 4).add( + this.transitionalExecutionResult.unencryptedLogPreimagesLength, ); // TODO(6206): likely need to track this here and not just in the transitional logic. diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 6b381dd723c..6b5e75207ec 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -1,14 +1,13 @@ import { type AuthWitness, type AztecNode, - EncryptedFunctionL2Logs, EncryptedL2Log, L1NotePayload, Note, type NoteStatus, TaggedNote, - UnencryptedFunctionL2Logs, type UnencryptedL2Log, + encryptBuffer, } from '@aztec/circuit-types'; import { CallContext, @@ -20,18 +19,24 @@ import { type TxContext, } from '@aztec/circuits.js'; import { Aes128 } from '@aztec/circuits.js/barretenberg'; -import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; +import { + computeInnerNoteHash, + computeNoteContentHash, + computePublicDataTreeLeafSlot, + computeUniqueNoteHash, + siloNoteHash, +} from '@aztec/circuits.js/hash'; import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, type Point } from '@aztec/foundation/fields'; +import { Fr, GrumpkinScalar, type Point } from '@aztec/foundation/fields'; import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type NoteData, toACVMWitness } from '../acvm/index.js'; import { type PackedValuesCache } from '../common/packed_values_cache.js'; import { type DBOracle } from './db_oracle.js'; import { type ExecutionNoteCache } from './execution_note_cache.js'; import { CountedLog, type ExecutionResult, type NoteAndSlot } from './execution_result.js'; -import { type LogsCache } from './logs_cache.js'; import { pickNotes } from './pick_notes.js'; import { executePrivateFunction } from './private_execution.js'; import { ViewDataOracle } from './view_data_oracle.js'; @@ -59,6 +64,7 @@ export class ClientExecutionContext extends ViewDataOracle { */ private noteHashLeafIndexMap: Map = new Map(); private nullifiedNoteHashCounters: Map = new Map(); + private noteEncryptedLogs: CountedLog[] = []; private encryptedLogs: CountedLog[] = []; private unencryptedLogs: CountedLog[] = []; private nestedExecutions: ExecutionResult[] = []; @@ -76,7 +82,6 @@ export class ClientExecutionContext extends ViewDataOracle { authWitnesses: AuthWitness[], private readonly packedValuesCache: PackedValuesCache, private readonly noteCache: ExecutionNoteCache, - private readonly logsCache: LogsCache, db: DBOracle, private node: AztecNode, protected sideEffectCounter: number = 0, @@ -133,31 +138,51 @@ export class ClientExecutionContext extends ViewDataOracle { } /** - * Return the encrypted logs emitted during this execution. + * Return the note encrypted logs emitted during this execution. */ - public getEncryptedLogs() { - return this.encryptedLogs; + public getNoteEncryptedLogs() { + return this.noteEncryptedLogs; + } + + /** + * Sometimes notes can be chopped after a nested execution is complete. + * This means finished nested executions still hold transient logs. This method removes them. + * TODO(Miranda): is there a cleaner solution? + */ + public chopNoteEncryptedLogs() { + // Do not return logs that have been chopped in the cache + const allNoteLogs = this.noteCache.getLogs(); + this.noteEncryptedLogs = this.noteEncryptedLogs.filter(l => allNoteLogs.includes(l)); + const chop = (thing: any) => + thing.nestedExecutions.forEach((result: ExecutionResult) => { + if (!result.noteEncryptedLogs[0]?.isEmpty()) { + // The execution has note logs + result.noteEncryptedLogs = result.noteEncryptedLogs.filter(l => allNoteLogs.includes(l)); + } + chop(result); + }); + chop(this); } /** - * Return the encrypted logs emitted during this execution and nested executions. + * Return the note encrypted logs emitted during this execution and nested executions. */ - public getAllEncryptedLogs() { - return new EncryptedFunctionL2Logs(this.logsCache.getEncryptedLogs()); + public getAllNoteEncryptedLogs() { + return this.noteCache.getLogs(); } /** * Return the encrypted logs emitted during this execution. */ - public getUnencryptedLogs() { - return this.unencryptedLogs; + public getEncryptedLogs() { + return this.encryptedLogs; } /** - * Return the unencrypted logs emitted during this execution and nested executions. + * Return the encrypted logs emitted during this execution. */ - public getAllUnencryptedLogs() { - return new UnencryptedFunctionL2Logs(this.logsCache.getUnencryptedLogs()); + public getUnencryptedLogs() { + return this.unencryptedLogs; } /** @@ -352,14 +377,29 @@ export class ClientExecutionContext extends ViewDataOracle { log: Fr[], counter: number, ) { + // TODO(Miranda): This is a temporary solution until we encrypt logs in the circuit + // Then we require a new oracle that deals only with notes const note = new Note(log); - const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId); - const taggedNote = new TaggedNote(l1NotePayload); - const encryptedNote = taggedNote.toEncryptedBuffer(publicKey); - const encryptedLog = new EncryptedL2Log(encryptedNote); - this.encryptedLogs.push(new CountedLog(encryptedLog, counter)); - this.logsCache.addEncryptedLog(encryptedLog); - return encryptedNote; + const innerNoteHash = computeInnerNoteHash(storageSlot, computeNoteContentHash(log)); + const noteExists = this.noteCache.checkNoteExists(contractAddress, innerNoteHash); + if (noteExists) { + // Log linked to note + const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId); + const taggedNote = new TaggedNote(l1NotePayload); + const encryptedNote = taggedNote.toEncryptedBuffer(publicKey); + const encryptedLog = new CountedLog(new EncryptedL2Log(encryptedNote), counter); + this.noteEncryptedLogs.push(encryptedLog); + this.noteCache.addNewLog(encryptedLog, innerNoteHash); + return encryptedNote; + } else { + // Generic non-note log + // We assume only the log and address are required + const preimage = Buffer.concat([contractAddress.toBuffer(), serializeToBuffer(log)]); + const encryptedMsg = encryptBuffer(preimage, GrumpkinScalar.random(), publicKey); + const encryptedLog = new EncryptedL2Log(encryptedMsg); + this.encryptedLogs.push(new CountedLog(encryptedLog, counter)); + return encryptedMsg; + } } /** @@ -368,7 +408,6 @@ export class ClientExecutionContext extends ViewDataOracle { */ public override emitUnencryptedLog(log: UnencryptedL2Log, counter: number) { this.unencryptedLogs.push(new CountedLog(log, counter)); - this.logsCache.addUnencryptedLog(log); const text = log.toHumanReadable(); this.log.verbose(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`); } @@ -382,7 +421,6 @@ export class ClientExecutionContext extends ViewDataOracle { */ public override emitContractClassUnencryptedLog(log: UnencryptedL2Log, counter: number) { this.unencryptedLogs.push(new CountedLog(log, counter)); - this.logsCache.addUnencryptedLog(log); const text = log.toHumanReadable(); this.log.verbose( `Emitted unencrypted log from ContractClassRegisterer: "${ @@ -397,8 +435,8 @@ export class ClientExecutionContext extends ViewDataOracle { childExecutionResult.callStackItem.publicInputs.newNoteHashes.some(item => !item.isEmpty()) || childExecutionResult.callStackItem.publicInputs.newNullifiers.some(item => !item.isEmpty()) || childExecutionResult.callStackItem.publicInputs.newL2ToL1Msgs.some(item => !item.isEmpty()) || - !childExecutionResult.callStackItem.publicInputs.encryptedLogPreimagesLength.equals(new Fr(4)) || - !childExecutionResult.callStackItem.publicInputs.unencryptedLogPreimagesLength.equals(new Fr(4)) + !childExecutionResult.callStackItem.publicInputs.encryptedLogPreimagesLength.equals(Fr.ZERO) || + !childExecutionResult.callStackItem.publicInputs.unencryptedLogPreimagesLength.equals(Fr.ZERO) ) { throw new Error(`Static call cannot create new notes, emit L2->L1 messages or generate logs`); } @@ -450,7 +488,6 @@ export class ClientExecutionContext extends ViewDataOracle { this.authWitnesses, this.packedValuesCache, this.noteCache, - this.logsCache, this.db, this.node, sideEffectCounter, diff --git a/yarn-project/simulator/src/client/execution_note_cache.ts b/yarn-project/simulator/src/client/execution_note_cache.ts index 2166f317941..a9572810981 100644 --- a/yarn-project/simulator/src/client/execution_note_cache.ts +++ b/yarn-project/simulator/src/client/execution_note_cache.ts @@ -1,8 +1,10 @@ +import { type EncryptedL2Log } from '@aztec/circuit-types'; import { siloNullifier } from '@aztec/circuits.js/hash'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type NoteData } from '../acvm/index.js'; +import { type CountedLog } from './execution_result.js'; export interface PendingNote { note: NoteData; @@ -27,6 +29,13 @@ export class ExecutionNoteCache { */ private nullifiers: Map> = new Map(); + /** + * The list of encrypted logs linked to note hashes created in this transaction. + * This mapping maps from inner note hash to log(s) emitted for that note hash. + * Note that their value (bigint representation) is used because Frs cannot be looked up in Sets. + */ + private logs: Map[]> = new Map(); + /** * Add a new note to cache. * @param note - New note created during execution. @@ -37,6 +46,16 @@ export class ExecutionNoteCache { this.newNotes.set(note.contractAddress.toBigInt(), notes); } + /** + * Add a new note to cache. + * @param note - New note created during execution. + */ + public addNewLog(log: CountedLog, innerNoteHash: Fr) { + const logs = this.logs.get(innerNoteHash.toBigInt()) ?? []; + logs.push(log); + this.logs.set(innerNoteHash.toBigInt(), logs); + } + /** * Add a nullifier to cache. It could be for a db note or a new note created during execution. * @param contractAddress - Contract address of the note. @@ -52,7 +71,7 @@ export class ExecutionNoteCache { this.nullifiers.set(contractAddress.toBigInt(), nullifiers); let nullifiedNoteHashCounter: number | undefined = undefined; - // Find and remove the matching new note if the emitted innerNoteHash is not empty. + // Find and remove the matching new note and log(s) if the emitted innerNoteHash is not empty. if (!innerNoteHash.equals(Fr.ZERO)) { const notes = this.newNotes.get(contractAddress.toBigInt()) ?? []; const noteIndexToRemove = notes.findIndex(n => n.note.innerNoteHash.equals(innerNoteHash)); @@ -62,6 +81,8 @@ export class ExecutionNoteCache { const note = notes.splice(noteIndexToRemove, 1)[0]; nullifiedNoteHashCounter = note.counter; this.newNotes.set(contractAddress.toBigInt(), notes); + // If a log linked to the note hash does not exist, this method just does nothing + this.logs.delete(innerNoteHash.toBigInt()); } return nullifiedNoteHashCounter; @@ -96,4 +117,11 @@ export class ExecutionNoteCache { public getNullifiers(contractAddress: AztecAddress): Set { return this.nullifiers.get(contractAddress.toBigInt()) ?? new Set(); } + + /** + * Return all note logs emitted from a contract. + */ + public getLogs(): CountedLog[] { + return Array.from(this.logs.values()).flat(); + } } diff --git a/yarn-project/simulator/src/client/execution_result.test.ts b/yarn-project/simulator/src/client/execution_result.test.ts index 0da6182478d..6b6ee3ed913 100644 --- a/yarn-project/simulator/src/client/execution_result.test.ts +++ b/yarn-project/simulator/src/client/execution_result.test.ts @@ -19,6 +19,7 @@ function emptyExecutionResult(): ExecutionResult { nestedExecutions: [], enqueuedPublicFunctionCalls: [], publicTeardownFunctionCall: PublicCallRequest.empty(), + noteEncryptedLogs: [], encryptedLogs: [], unencryptedLogs: [], }; diff --git a/yarn-project/simulator/src/client/execution_result.ts b/yarn-project/simulator/src/client/execution_result.ts index a80b7713cd2..1a734146703 100644 --- a/yarn-project/simulator/src/client/execution_result.ts +++ b/yarn-project/simulator/src/client/execution_result.ts @@ -58,6 +58,11 @@ export interface ExecutionResult { enqueuedPublicFunctionCalls: PublicCallRequest[]; /** Public function execution requested for teardown */ publicTeardownFunctionCall: PublicCallRequest; + /** + * Encrypted note logs emitted during execution of this function call. + * Note: These are preimages to `noteEncryptedLogsHashes`. + */ + noteEncryptedLogs: CountedLog[]; /** * Encrypted logs emitted during execution of this function call. * Note: These are preimages to `encryptedLogsHashes`. @@ -82,13 +87,32 @@ export function collectNullifiedNoteHashCounters(execResult: ExecutionResult, ac return accum; } +/** + * Collect all encrypted logs across all nested executions. + * @param execResult - The topmost execution result. + * @returns All encrypted logs. + */ +function collectNoteEncryptedLogs(execResult: ExecutionResult): CountedLog[] { + return [execResult.noteEncryptedLogs, ...execResult.nestedExecutions.flatMap(collectNoteEncryptedLogs)].flat(); +} + +/** + * Collect all encrypted logs across all nested executions and sorts by counter. + * @param execResult - The topmost execution result. + * @returns All encrypted logs. + */ +export function collectSortedNoteEncryptedLogs(execResult: ExecutionResult): EncryptedFunctionL2Logs { + const allLogs = collectNoteEncryptedLogs(execResult); + const sortedLogs = sortByCounter(allLogs); + return new EncryptedFunctionL2Logs(sortedLogs.map(l => l.log)); +} /** * Collect all encrypted logs across all nested executions. * @param execResult - The topmost execution result. * @returns All encrypted logs. */ function collectEncryptedLogs(execResult: ExecutionResult): CountedLog[] { - return [execResult.encryptedLogs, ...[...execResult.nestedExecutions].flatMap(collectEncryptedLogs)].flat(); + return [execResult.encryptedLogs, ...execResult.nestedExecutions.flatMap(collectEncryptedLogs)].flat(); } /** @@ -108,7 +132,7 @@ export function collectSortedEncryptedLogs(execResult: ExecutionResult): Encrypt * @returns All unencrypted logs. */ function collectUnencryptedLogs(execResult: ExecutionResult): CountedLog[] { - return [execResult.unencryptedLogs, ...[...execResult.nestedExecutions].flatMap(collectUnencryptedLogs)].flat(); + return [execResult.unencryptedLogs, ...execResult.nestedExecutions.flatMap(collectUnencryptedLogs)].flat(); } /** diff --git a/yarn-project/simulator/src/client/logs_cache.ts b/yarn-project/simulator/src/client/logs_cache.ts deleted file mode 100644 index c1e52ae7d8e..00000000000 --- a/yarn-project/simulator/src/client/logs_cache.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { type EncryptedL2Log, type UnencryptedL2Log } from '@aztec/circuit-types'; - -/** - * Log data that's accessible by all the function calls in an execution. - * This class exists to: - * 1. Keep track of logs emitted through nested calls in the correct order. - * 2. TODO(1641): Remove encrypted logs based on notes nullified in the same scope. - */ -export class LogsCache { - /** - * Logs notes created in this transaction. - */ - private encryptedLogs: EncryptedL2Log[] = []; - private unencryptedLogs: UnencryptedL2Log[] = []; - - // TODO Separate encrypted logs linked to note hashes and arbitrary logs: - - // Maps from note hash to encrypted log - useful for removing transient logs - // private encryptedLogsLinkedToNotes: Map = new Map(); - - // /** - // * Remove the encrypted log for a nullified note. - // * This fn should only be called if the note's innerNoteHash != 0. - // * @param noteHashCounter - Side effect counter of the note. - // */ - // public nullifyNote(noteHashCounter: Fr) { - // // Find and remove the matching new note if the emitted innerNoteHash is not empty. - // const log = this.encryptedLogsLinkedToNotes.get(noteHashCounter.toBigInt()) ?? false; - // // TODO: throw here? Will the log always be here? - // if (!log) { - // throw new Error('Attempt to remove a pending note log that does not exist.'); - // } - // this.encryptedLogsLinkedToNotes.delete(noteHashCounter.toBigInt()); - // } - - /** - * Add a new encrypted log to cache. - * @param log - New log created during execution. - */ - public addEncryptedLog(log: EncryptedL2Log) { - this.encryptedLogs.push(log); - } - - /** - * Add a new unencrypted log to cache. - * @param log - New log created during execution. - */ - public addUnencryptedLog(log: UnencryptedL2Log) { - this.unencryptedLogs.push(log); - } - - /** - * Return the encrypted logs. - */ - public getEncryptedLogs() { - return this.encryptedLogs; - } - - /** - * Return the encrypted logs. - */ - public getUnencryptedLogs() { - return this.unencryptedLogs; - } -} diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index e3f6bd825f6..7750808fd5d 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -167,9 +167,10 @@ describe('Private Execution test suite', () => { return trees[name]; }; - const getEncryptedSerializedLength = (result: ExecutionResult) => { - const fnLogs = new EncryptedFunctionL2Logs(result.encryptedLogs.map(l => l.log)); - return fnLogs.getSerializedLength(); + const getEncryptedNoteSerializedLength = (result: ExecutionResult) => { + const fnLogs = new EncryptedFunctionL2Logs(result.noteEncryptedLogs.map(l => l.log)); + // We take 4 to avoid counting the extra 4 bytes used to store len for L1 + return fnLogs.getSerializedLength() - 4; }; beforeAll(() => { @@ -247,8 +248,9 @@ describe('Private Execution test suite', () => { const [unencryptedLog] = newUnencryptedLogs; expect(unencryptedLog.value).toEqual(Fr.fromBuffer(functionLogs.logs[0].hash())); + // We take 4 to avoid counting the extra 4 bytes used to store len for L1 expect(result.callStackItem.publicInputs.unencryptedLogPreimagesLength).toEqual( - new Fr(functionLogs.getSerializedLength()), + new Fr(functionLogs.getSerializedLength() - 4), ); // Test that the log payload (ie ignoring address, selector, and header) matches what we emitted expect(functionLogs.logs[0].data.subarray(-32).toString('hex')).toEqual(owner.toBuffer().toString('hex')); @@ -266,8 +268,9 @@ describe('Private Execution test suite', () => { const [unencryptedLog] = newUnencryptedLogs; expect(unencryptedLog.value).toEqual(Fr.fromBuffer(functionLogs.logs[0].hash())); + // We take 4 to avoid counting the extra 4 bytes used to store len for L1 expect(result.callStackItem.publicInputs.unencryptedLogPreimagesLength).toEqual( - new Fr(functionLogs.getSerializedLength()), + new Fr(functionLogs.getSerializedLength() - 4), ); // Test that the log payload (ie ignoring address, selector, and header) matches what we emitted const expected = Buffer.concat(args[0].map(arg => arg.toBuffer())).toString('hex'); @@ -339,13 +342,14 @@ describe('Private Execution test suite', () => { ), ); - const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.encryptedLogsHashes); + const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[0].log.hash())); + expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); expect(result.callStackItem.publicInputs.encryptedLogPreimagesLength).toEqual( - new Fr(getEncryptedSerializedLength(result)), + new Fr(getEncryptedNoteSerializedLength(result)), ); }); @@ -370,13 +374,14 @@ describe('Private Execution test suite', () => { ), ); - const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.encryptedLogsHashes); + const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[0].log.hash())); + expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); expect(result.callStackItem.publicInputs.encryptedLogPreimagesLength).toEqual( - new Fr(getEncryptedSerializedLength(result)), + new Fr(getEncryptedNoteSerializedLength(result)), ); }); @@ -419,24 +424,26 @@ describe('Private Execution test suite', () => { const newNoteHashes = getNonEmptyItems(result.callStackItem.publicInputs.newNoteHashes); expect(newNoteHashes).toHaveLength(2); const [changeNoteHash, recipientNoteHash] = newNoteHashes; - expect(recipientNoteHash.value).toEqual( + const [recipientInnerNoteHash, changeInnerNoteHash] = [ await acirSimulator.computeInnerNoteHash(contractAddress, recipientStorageSlot, noteTypeId, recipientNote.note), - ); - expect(changeNoteHash.value).toEqual( await acirSimulator.computeInnerNoteHash(contractAddress, storageSlot, noteTypeId, changeNote.note), - ); + ]; + expect(recipientNoteHash.value).toEqual(recipientInnerNoteHash); + expect(changeNoteHash.value).toEqual(changeInnerNoteHash); expect(recipientNote.note.items[0]).toEqual(new Fr(amountToTransfer)); expect(changeNote.note.items[0]).toEqual(new Fr(40n)); - const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.encryptedLogsHashes); + const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(2); const [encryptedChangeLog, encryptedRecipientLog] = newEncryptedLogs; - expect(encryptedChangeLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[0].log.hash())); - expect(encryptedRecipientLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[1].log.hash())); + expect(encryptedChangeLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); + expect(encryptedChangeLog.noteHashCounter).toEqual(changeNoteHash.counter); + expect(encryptedRecipientLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[1].log.hash())); + expect(encryptedRecipientLog.noteHashCounter).toEqual(recipientNoteHash.counter); expect(result.callStackItem.publicInputs.encryptedLogPreimagesLength).toEqual( - new Fr(getEncryptedSerializedLength(result)), + new Fr(getEncryptedNoteSerializedLength(result)), ); const readRequests = getNonEmptyItems(result.callStackItem.publicInputs.noteHashReadRequests).map(r => r.value); @@ -473,13 +480,15 @@ describe('Private Execution test suite', () => { expect(recipientNote.note.items[0]).toEqual(new Fr(amountToTransfer)); expect(changeNote.note.items[0]).toEqual(new Fr(balance - amountToTransfer)); - const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.encryptedLogsHashes); + const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(2); const [encryptedChangeLog, encryptedRecipientLog] = newEncryptedLogs; - expect(encryptedChangeLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[0].log.hash())); - expect(encryptedRecipientLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[1].log.hash())); + expect(encryptedChangeLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); + expect(encryptedChangeLog.noteHashCounter).toEqual(result.callStackItem.publicInputs.newNoteHashes[0].counter); + expect(encryptedRecipientLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[1].log.hash())); + expect(encryptedRecipientLog.noteHashCounter).toEqual(result.callStackItem.publicInputs.newNoteHashes[1].counter); expect(result.callStackItem.publicInputs.encryptedLogPreimagesLength).toEqual( - new Fr(getEncryptedSerializedLength(result)), + new Fr(getEncryptedNoteSerializedLength(result)), ); }); }); @@ -936,14 +945,14 @@ describe('Private Execution test suite', () => { ); expect(noteHash).toEqual(innerNoteHash); - const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.encryptedLogsHashes); + const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.encryptedLogs[0].log.hash())); - expect(result.callStackItem.publicInputs.encryptedLogPreimagesLength).toEqual( - new Fr(getEncryptedSerializedLength(result)), - ); + expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + // We expect the note log to be chopped in ts. + // (note logs are chopped in kernel tail, so will still exist in the call stack item) + expect(result.noteEncryptedLogs).toHaveLength(0); // read request should match innerNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) const readRequest = getNonEmptyItems(result.callStackItem.publicInputs.noteHashReadRequests)[0]; @@ -1015,14 +1024,14 @@ describe('Private Execution test suite', () => { ); expect(noteHash).toEqual(innerNoteHash); - const newEncryptedLogs = getNonEmptyItems(execInsert.callStackItem.publicInputs.encryptedLogsHashes); + const newEncryptedLogs = getNonEmptyItems(execInsert.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.value).toEqual(Fr.fromBuffer(execInsert.encryptedLogs[0].log.hash())); - expect(result.callStackItem.publicInputs.encryptedLogPreimagesLength).toEqual( - new Fr(getEncryptedSerializedLength(result)), - ); + expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + // We expect the note log to be chopped in ts. + // (note logs are chopped in kernel tail, so will still exist in the call stack item) + expect(execInsert.noteEncryptedLogs).toHaveLength(0); // read request should match innerNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) const readRequest = execGetThenNullify.callStackItem.publicInputs.noteHashReadRequests[0]; diff --git a/yarn-project/simulator/src/client/private_execution.ts b/yarn-project/simulator/src/client/private_execution.ts index abab2f2f46f..f774bf9208f 100644 --- a/yarn-project/simulator/src/client/private_execution.ts +++ b/yarn-project/simulator/src/client/private_execution.ts @@ -42,6 +42,8 @@ export async function executePrivateFunction( const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness); const publicInputs = PrivateCircuitPublicInputs.fromFields(returnWitness); + context.chopNoteEncryptedLogs(); + const noteEncryptedLogs = context.getNoteEncryptedLogs(); const encryptedLogs = context.getEncryptedLogs(); const unencryptedLogs = context.getUnencryptedLogs(); @@ -69,6 +71,7 @@ export async function executePrivateFunction( vk: Buffer.from(artifact.verificationKey!, 'hex'), nestedExecutions, enqueuedPublicFunctionCalls, + noteEncryptedLogs, publicTeardownFunctionCall, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 0eebf76e26a..1c3c8490f84 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -19,7 +19,6 @@ import { ClientExecutionContext } from './client_execution_context.js'; import { type DBOracle } from './db_oracle.js'; import { ExecutionNoteCache } from './execution_note_cache.js'; import { type ExecutionResult } from './execution_result.js'; -import { LogsCache } from './logs_cache.js'; import { executePrivateFunction } from './private_execution.js'; import { executeUnconstrainedFunction } from './unconstrained_execution.js'; import { ViewDataOracle } from './view_data_oracle.js'; @@ -101,7 +100,6 @@ export class AcirSimulator { request.authWitnesses, PackedValuesCache.create(request.argsOfCalls), new ExecutionNoteCache(), - new LogsCache(), this.db, this.node, startSideEffectCounter, diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index b39468eb94a..3da3ffa306e 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -18,6 +18,7 @@ import { type Header, type KernelCircuitPublicInputs, L2ToL1Message, + LogHash, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, @@ -44,7 +45,6 @@ import { PublicKernelData, ReadRequest, RevertCode, - SideEffect, VK_TREE_HEIGHT, VerificationKey, makeEmptyProof, @@ -451,11 +451,7 @@ export abstract class AbstractPhaseManager { MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ), publicCallStackHashes, - unencryptedLogsHashes: padArrayEnd( - result.unencryptedLogsHashes, - SideEffect.empty(), - MAX_UNENCRYPTED_LOGS_PER_CALL, - ), + unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL), unencryptedLogPreimagesLength: result.unencryptedLogPreimagesLength, historicalHeader: this.historicalHeader, globalVariables: this.globalVariables, diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index 2aaccc9ffd4..7f5a1303568 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -4,13 +4,13 @@ import { type ContractStorageUpdateRequest, type Fr, type L2ToL1Message, + type LogHash, type NoteHash, type Nullifier, type PublicCallRequest, PublicDataRead, PublicDataUpdateRequest, type ReadRequest, - type SideEffect, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot, computePublicDataTreeValue } from '@aztec/circuits.js/hash'; @@ -48,7 +48,7 @@ export interface PublicExecutionResult { * The hashed logs with side effect counter. * Note: required as we don't track the counter anywhere else. */ - unencryptedLogsHashes: SideEffect[]; + unencryptedLogsHashes: LogHash[]; /** * Unencrypted logs emitted during execution of this function call. * Note: These are preimages to `unencryptedLogsHashes`. diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 7404e15237a..c8ee7056014 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -185,7 +185,7 @@ async function executePublicFunctionAcvm( nestedExecutions: [], unencryptedLogsHashes: [], unencryptedLogs: UnencryptedFunctionL2Logs.empty(), - unencryptedLogPreimagesLength: new Fr(4n), // empty logs have len 4 + unencryptedLogPreimagesLength: Fr.ZERO, allUnencryptedLogs: UnencryptedFunctionL2Logs.empty(), reverted, revertReason, diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 76131633890..9b17a5908bf 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -338,8 +338,9 @@ describe('ACIR public execution simulator', () => { expect(Fr.fromBuffer(childExecutionResult.unencryptedLogs.logs[0].hash())).toEqual( childExecutionResult.unencryptedLogsHashes[0].value, ); + // We take 4 to avoid counting the extra 4 bytes used to store len for L1 expect(childExecutionResult.unencryptedLogPreimagesLength).toEqual( - new Fr(childExecutionResult.unencryptedLogs.getSerializedLength()), + new Fr(childExecutionResult.unencryptedLogs.getSerializedLength() - 4), ); expect(result.returnValues[0]).toEqual(new Fr(newValue)); }, 20_000); diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 5495342516e..2e51cd93f3a 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -102,6 +102,7 @@ describe('public_processor', () => { hash, data: tx.data.toKernelCircuitPublicInputs(), proof: tx.proof, + noteEncryptedLogs: tx.noteEncryptedLogs, encryptedLogs: tx.encryptedLogs, unencryptedLogs: tx.unencryptedLogs, isEmpty: false, diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 06b7f732b47..be324885e6f 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -1,9 +1,10 @@ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types'; import { - Fr, + type Fr, type GlobalVariables, type Header, type KernelCircuitPublicInputs, + type LogHash, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -12,7 +13,6 @@ import { type Proof, type PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, - SideEffect, makeEmptyProof, mergeAccumulatedData, sortByCounter, @@ -159,10 +159,8 @@ export class TailPhaseManager extends AbstractPhaseManager { return sortByCounter(noteHashes).map(n => n.value) as Tuple; } - private sortLogsHashes(unencryptedLogsHashes: Tuple): Tuple { + private sortLogsHashes(unencryptedLogsHashes: Tuple): Tuple { // TODO(6052): logs here may have duplicate counters from nested calls - return sortByCounter( - unencryptedLogsHashes.map(n => ({ ...n, counter: n.counter.toNumber(), isEmpty: () => n.isEmpty() })), - ).map(h => new SideEffect(h.value, new Fr(h.counter))) as Tuple; + return sortByCounter(unencryptedLogsHashes); } } diff --git a/yarn-project/simulator/src/public/utils.ts b/yarn-project/simulator/src/public/utils.ts index c48798ff350..f824cf9e92f 100644 --- a/yarn-project/simulator/src/public/utils.ts +++ b/yarn-project/simulator/src/public/utils.ts @@ -11,6 +11,7 @@ export function lastSideEffectCounter(tx: Tx): number { const sideEffectCounters = [ ...data.endNonRevertibleData.newNoteHashes, ...data.endNonRevertibleData.newNullifiers, + ...data.endNonRevertibleData.unencryptedLogsHashes, ...data.endNonRevertibleData.publicCallStack, ...data.end.newNoteHashes, ...data.end.newNullifiers, @@ -24,8 +25,7 @@ export function lastSideEffectCounter(tx: Tx): number { // look at both start and end counters because for enqueued public calls start > 0 while end === 0 max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber()); } else { - const counter = typeof sideEffect.counter === 'number' ? sideEffect.counter : sideEffect.counter.toNumber(); - max = Math.max(max, counter); + max = Math.max(max, sideEffect.counter); } }