diff --git a/barretenberg/cpp/pil/avm/constants_gen.pil b/barretenberg/cpp/pil/avm/constants_gen.pil index cb8f8952d8c..4a05fa76c78 100644 --- a/barretenberg/cpp/pil/avm/constants_gen.pil +++ b/barretenberg/cpp/pil/avm/constants_gen.pil @@ -10,7 +10,7 @@ namespace constants(256); pol MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 16; pol MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 16; pol MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL = 16; - pol MAX_UNENCRYPTED_LOGS_PER_CALL = 4; + pol MAX_PUBLIC_LOGS_PER_CALL = 4; pol MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 3000; pol MEM_TAG_FF = 0; pol MEM_TAG_U1 = 1; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index acbfdfeca82..7be9d1e7ab3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -1799,46 +1799,48 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) // EXPECT_EQ(emit_nullifier_kernel_out_row->main_kernel_side_effect_out, 1); // feed_output(emit_nullifier_out_offset, 1, 1, 0); + // TODO(#11124): Rewrite for field based public logs // CHECK EMIT UNENCRYPTED LOG // Unencrypted logs are hashed with sha256 and truncated to 31 bytes - and then padded back to 32 bytes - auto [contract_class_id, contract_instance] = gen_test_contract_hint(bytecode); - FF address = AvmBytecodeTraceBuilder::compute_address_from_instance(contract_instance); - - std::vector contract_address_bytes = address.to_buffer(); - // Test log is empty, so just have to hash the contract address with 0 - // - std::vector bytes_to_hash; - bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(contract_address_bytes.begin()), - std::make_move_iterator(contract_address_bytes.end())); - uint32_t num_bytes = 0; - std::vector log_size_bytes = to_buffer(num_bytes); - // Add the log size to the hash to bytes - bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(log_size_bytes.begin()), - std::make_move_iterator(log_size_bytes.end())); - - std::array output = crypto::sha256(bytes_to_hash); - // Truncate the hash to 31 bytes so it will be a valid field element - FF expected_hash = FF(from_buffer(output.data()) >> 8); - - auto emit_log_row = - std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_emit_unencrypted_log == 1; }); - ASSERT_TRUE(emit_log_row != trace.end()); - - EXPECT_EQ(emit_log_row->main_ia, expected_hash); - // EXPECT_EQ(emit_log_row->main_side_effect_counter, 2); - // Value is 40 = 32 * log_length + 40 (and log_length is 0 in this case). - EXPECT_EQ(emit_log_row->main_ib, 40); - - uint32_t emit_log_out_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET; - auto emit_log_kernel_out_row = - std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == emit_log_out_offset; }); - ASSERT_TRUE(emit_log_kernel_out_row != trace.end()); - EXPECT_EQ(emit_log_kernel_out_row->main_kernel_value_out, expected_hash); - EXPECT_EQ(emit_log_kernel_out_row->main_kernel_side_effect_out, 2); - EXPECT_EQ(emit_log_kernel_out_row->main_kernel_metadata_out, 40); - // feed_output(emit_log_out_offset, expected_hash, 2, 40); + // auto [contract_class_id, contract_instance] = gen_test_contract_hint(bytecode); + // FF address = AvmBytecodeTraceBuilder::compute_address_from_instance(contract_instance); + + // std::vector contract_address_bytes = address.to_buffer(); + // // Test log is empty, so just have to hash the contract address with 0 + // // + // std::vector bytes_to_hash; + // bytes_to_hash.insert(bytes_to_hash.end(), + // std::make_move_iterator(contract_address_bytes.begin()), + // std::make_move_iterator(contract_address_bytes.end())); + // uint32_t num_bytes = 0; + // std::vector log_size_bytes = to_buffer(num_bytes); + // // Add the log size to the hash to bytes + // bytes_to_hash.insert(bytes_to_hash.end(), + // std::make_move_iterator(log_size_bytes.begin()), + // std::make_move_iterator(log_size_bytes.end())); + + // std::array output = crypto::sha256(bytes_to_hash); + // // Truncate the hash to 31 bytes so it will be a valid field element + // FF expected_hash = FF(from_buffer(output.data()) >> 8); + + // auto emit_log_row = + // std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_emit_unencrypted_log == 1; + // }); + // ASSERT_TRUE(emit_log_row != trace.end()); + + // EXPECT_EQ(emit_log_row->main_ia, expected_hash); + // // EXPECT_EQ(emit_log_row->main_side_effect_counter, 2); + // // Value is 40 = 32 * log_length + 40 (and log_length is 0 in this case). + // EXPECT_EQ(emit_log_row->main_ib, 40); + + // uint32_t emit_log_out_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET; + // auto emit_log_kernel_out_row = + // std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == emit_log_out_offset; }); + // ASSERT_TRUE(emit_log_kernel_out_row != trace.end()); + // EXPECT_EQ(emit_log_kernel_out_row->main_kernel_value_out, expected_hash); + // EXPECT_EQ(emit_log_kernel_out_row->main_kernel_side_effect_out, 2); + // EXPECT_EQ(emit_log_kernel_out_row->main_kernel_metadata_out, 40); + // // feed_output(emit_log_out_offset, expected_hash, 2, 40); // CHECK SEND L2 TO L1 MSG auto send_row = diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp index 727e16ec95e..101487752f2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp @@ -151,7 +151,9 @@ template VmPublicInputs_ convert_public_inputs(std::vector log{}; }; -inline void read(uint8_t const*& it, ScopedLogHash& scoped_log_hash) +inline void read(uint8_t const*& it, PublicLog& public_log) { using serialize::read; - read(it, scoped_log_hash.log_hash); - read(it, scoped_log_hash.contract_address); + read(it, public_log.contract_address); + read(it, public_log.log); } struct PublicDataWrite { @@ -282,9 +268,9 @@ struct AvmAccumulatedData { */ std::array l2_to_l1_msgs{}; /** - * The unencrypted logs emitted from the AVM execution. + * The public logs emitted from the AVM execution. */ - std::array unencrypted_logs_hashes{}; + std::array public_logs{}; /** * The public data writes made in the AVM execution. */ @@ -298,7 +284,7 @@ inline void read(uint8_t const*& it, AvmAccumulatedData& accumulated_data) read(it, accumulated_data.note_hashes); read(it, accumulated_data.nullifiers); read(it, accumulated_data.l2_to_l1_msgs); - read(it, accumulated_data.unencrypted_logs_hashes); + read(it, accumulated_data.public_logs); read(it, accumulated_data.public_data_writes); }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index d1407928a19..c1cba7fe195 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -3612,7 +3612,7 @@ AvmError AvmTraceBuilder::op_get_contract_instance( AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset) { - std::vector bytes_to_hash; + // TODO(#11124): Check this aligns with new public logs // We keep the first encountered error AvmError error = AvmError::NO_ERROR; @@ -3627,12 +3627,6 @@ AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log // This is a hack to get the contract address from the first contract instance // Once we have 1-enqueued call and proper nested contexts, this should use that address of the current context FF contract_address = execution_hints.all_contract_bytecode.at(0).contract_instance.address; - std::vector contract_address_bytes = contract_address.to_buffer(); - - // Unencrypted logs are hashed with sha256 and truncated to 31 bytes - and then padded back to 32 bytes - bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(contract_address_bytes.begin()), - std::make_move_iterator(contract_address_bytes.end())); if (is_ok(error) && !(check_tag(AvmMemoryTag::FF, resolved_log_offset) && check_tag(AvmMemoryTag::U32, resolved_log_size_offset))) { @@ -3641,18 +3635,10 @@ AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log Row row; uint32_t log_size = 0; - uint32_t num_bytes = 0; if (is_ok(error)) { log_size = static_cast(unconstrained_read_from_memory(resolved_log_size_offset)); - - // The size is in fields of 32 bytes, the length used for the hash is in terms of bytes - num_bytes = log_size * 32; - std::vector log_size_bytes = to_buffer(num_bytes); - // Add the log size to the hash to bytes - bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(log_size_bytes.begin()), - std::make_move_iterator(log_size_bytes.end())); + ASSERT(log_size <= PUBLIC_LOG_DATA_SIZE_IN_FIELDS); if (!check_slice_mem_range(resolved_log_offset, log_size)) { error = AvmError::MEM_SLICE_OUT_OF_RANGE; @@ -3666,7 +3652,7 @@ AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log // Can't return earlier as we do elsewhere for side-effect-limit because we need // to at least retrieve log_size first to charge proper gas. // This means a tag error could occur before side-effect-limit first. - if (is_ok(error) && unencrypted_log_write_counter >= MAX_UNENCRYPTED_LOGS_PER_TX) { + if (is_ok(error) && unencrypted_log_write_counter >= MAX_PUBLIC_LOGS_PER_TX) { error = AvmError::SIDE_EFFECT_LIMIT_REACHED; auto row = Row{ .main_clk = clk, @@ -3681,39 +3667,27 @@ AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log return error; } unencrypted_log_write_counter++; + std::vector log_values{ contract_address }; if (is_ok(error)) { // We need to read the rest of the log_size number of elements for (uint32_t i = 0; i < log_size; i++) { FF log_value = unconstrained_read_from_memory(resolved_log_offset + i); - std::vector log_value_byte = log_value.to_buffer(); - bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(log_value_byte.begin()), - std::make_move_iterator(log_value_byte.end())); + log_values.emplace_back(log_value); } - - std::array output = crypto::sha256(bytes_to_hash); - // Truncate the hash to 31 bytes so it will be a valid field element - FF trunc_hash = FF(from_buffer(output.data()) >> 8); - - // The + 32 here is for the contract_address in bytes, the +4 is for the extra 4 bytes that contain log_size - // and is prefixed to message see toBuffer in unencrypted_l2_log.ts - FF length_of_preimage = num_bytes + 32 + 4; - // The + 4 is because the kernels store the length of the - // processed log as 4 bytes; thus for this length value to match the log length stored in the kernels, we - // need to add four to the length here. [Copied from unencrypted_l2_log.ts] - FF metadata_log_length = length_of_preimage + 4; + // Add 1 for the contract address (= PUBLIC_LOG_SIZE_IN_FIELDS) + log_values.resize(PUBLIC_LOG_DATA_SIZE_IN_FIELDS + 1, FF::zero()); row = Row{ .main_clk = clk, .main_call_ptr = call_ptr, - .main_ia = trunc_hash, - .main_ib = metadata_log_length, + // .main_ia = trunc_hash, + // .main_ib = metadata_log_length, .main_internal_return_ptr = internal_return_ptr, .main_pc = pc, + .main_sel_op_emit_unencrypted_log = FF(1), }; // Write to offset // kernel_trace_builder.op_emit_unencrypted_log(clk, side_effect_counter, trunc_hash, metadata_log_length); - row.main_sel_op_emit_unencrypted_log = FF(1); } else { row = Row{ .main_clk = clk, diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index 9ba67538e39..836a5fd2a2c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -11,13 +11,14 @@ #define MAX_NULLIFIER_READ_REQUESTS_PER_CALL 16 #define MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL 16 #define MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL 16 -#define MAX_UNENCRYPTED_LOGS_PER_CALL 4 +#define MAX_PUBLIC_LOGS_PER_CALL 4 #define MAX_NOTE_HASHES_PER_TX 64 #define MAX_NULLIFIERS_PER_TX 64 #define MAX_ENQUEUED_CALLS_PER_TX 32 #define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX 63 #define MAX_L2_TO_L1_MSGS_PER_TX 8 -#define MAX_UNENCRYPTED_LOGS_PER_TX 8 +#define MAX_PUBLIC_LOGS_PER_TX 8 +#define PUBLIC_LOG_DATA_SIZE_IN_FIELDS 13 #define MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS 3000 #define CANONICAL_AUTH_REGISTRY_ADDRESS 1 #define DEPLOYER_CONTRACT_ADDRESS 2 @@ -44,14 +45,14 @@ #define PUBLIC_INNER_CALL_REQUEST_LENGTH 13 #define STATE_REFERENCE_LENGTH 8 #define TOTAL_FEES_LENGTH 1 -#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 864 -#define AVM_ACCUMULATED_DATA_LENGTH 320 -#define AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH 1011 +#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 908 +#define AVM_ACCUMULATED_DATA_LENGTH 400 +#define AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH 1091 #define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 86 #define MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS 21 #define AVM_PROOF_LENGTH_IN_FIELDS 4154 #define AVM_PUBLIC_COLUMN_MAX_SIZE 1024 -#define AVM_PUBLIC_INPUTS_FLATTENED_SIZE 2912 +#define AVM_PUBLIC_INPUTS_FLATTENED_SIZE 2956 #define MEM_TAG_FF 0 #define MEM_TAG_U1 1 #define MEM_TAG_U8 2 diff --git a/barretenberg/cpp/src/barretenberg/vm/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/constants.hpp index 5efbbfd82dd..cd4957469c5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/constants.hpp @@ -12,7 +12,7 @@ inline const std::size_t KERNEL_OUTPUTS_LENGTH = MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + MAX_NULLIFIER_READ_REQUESTS_PER_CALL + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_NOTE_HASHES_PER_CALL + - MAX_NULLIFIERS_PER_CALL + MAX_L2_TO_L1_MSGS_PER_CALL + MAX_UNENCRYPTED_LOGS_PER_CALL; + MAX_NULLIFIERS_PER_CALL + MAX_L2_TO_L1_MSGS_PER_CALL + MAX_PUBLIC_LOGS_PER_CALL; static_assert(KERNEL_INPUTS_LENGTH < AVM_PUBLIC_COLUMN_MAX_SIZE, "The kernel inputs length cannot exceed the max size of a public column. This is a requirement for the " @@ -87,6 +87,7 @@ inline const uint32_t START_SIDE_EFFECT_COUNTER_PCPI_OFFSET = // START_SIDE_EFFECT_COUNTER // END_SIDE_EFFECT_COUNTER -> + 1 // NEW_UNENCRYPTED_LOGS -> + 2 +// TODO(#11124): Edit this in line with public logs? inline const uint32_t NEW_UNENCRYPTED_LOGS_PCPI_OFFSET = START_SIDE_EFFECT_COUNTER_PCPI_OFFSET + 2; // END INDEXES in the PUBLIC_CIRCUIT_PUBLIC_INPUTS diff --git a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md index 88e95a21d1e..de9d952892d 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md +++ b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md @@ -48,7 +48,7 @@ To emit unencrypted logs you don't need to import any library. You call the cont Once emitted, unencrypted events are stored in AztecNode and can be queried by anyone: -#include_code get_logs /yarn-project/end-to-end/src/fixtures/utils.ts typescript +#include_code get_logs /yarn-project/end-to-end/src/e2e_ordering.test.ts typescript ## Costs diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 667276a9fb0..e2f0eed3c34 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,7 +6,32 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. -## TBD +## 0.72.0 +### Public logs replace unencrypted logs +Any log emitted from public is now known as a public log, rather than an unencrypted log. This means methods relating to these logs have been renamed e.g. in the pxe, archiver, txe: +```diff +- getUnencryptedLogs(filter: LogFilter): Promise +- getUnencryptedEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number): Promise ++ getPublicLogs(filter: LogFilter): Promise ++ getPublicEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number): Promise +``` + +These logs were treated as bytes in the node and as hashes in the protocol circuits. Now, public logs are treated as fields everywhere: +```diff +- unencryptedLogs: UnencryptedTxL2Logs +- unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX] ++ publicLogs: PublicLog[] ++ public_logs: [PublicLog; MAX_PUBLIC_LOGS_PER_TX] +``` +A `PublicLog` contains the log (as an array of fields) and the app address. + +This PR also renamed encrypted events to private events: +```diff +- getEncryptedEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number, vpks: Point[]): Promise ++ getPrivateEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number, vpks: Point[]): Promise +``` + +## 0.70.0 ### [Aztec.nr] Removal of `getSiblingPath` oracle Use `getMembershipWitness` oracle instead that returns both the sibling path and index. diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 874b6dc7bf9..9afbae2cdc0 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -29,7 +29,7 @@ library Constants { uint256 internal constant MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_KEY_VALIDATION_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_PRIVATE_LOGS_PER_CALL = 16; - uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_CALL = 4; + uint256 internal constant MAX_PUBLIC_LOGS_PER_CALL = 4; uint256 internal constant MAX_CONTRACT_CLASS_LOGS_PER_CALL = 1; uint256 internal constant ARCHIVE_HEIGHT = 29; uint256 internal constant VK_TREE_HEIGHT = 6; @@ -67,7 +67,7 @@ library Constants { uint256 internal constant MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX = 64; uint256 internal constant MAX_KEY_VALIDATION_REQUESTS_PER_TX = 64; uint256 internal constant MAX_PRIVATE_LOGS_PER_TX = 32; - uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_TX = 8; + uint256 internal constant MAX_PUBLIC_LOGS_PER_TX = 8; uint256 internal constant MAX_CONTRACT_CLASS_LOGS_PER_TX = 1; uint256 internal constant NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; uint256 internal constant PRIVATE_KERNEL_INIT_INDEX = 0; @@ -91,6 +91,8 @@ library Constants { uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; uint256 internal constant FIELDS_PER_BLOB = 4096; uint256 internal constant BLOBS_PER_BLOCK = 3; + uint256 internal constant PUBLIC_LOG_DATA_SIZE_IN_FIELDS = 13; + uint256 internal constant PUBLIC_LOG_SIZE_IN_FIELDS = 14; uint256 internal constant PRIVATE_LOG_SIZE_IN_FIELDS = 18; uint256 internal constant AZTEC_MAX_EPOCH_DURATION = 48; uint256 internal constant GENESIS_BLOCK_HASH = @@ -188,7 +190,7 @@ library Constants { uint256 internal constant BLOCK_HEADER_LENGTH = 25; uint256 internal constant BLOCK_HEADER_LENGTH_BYTES = 648; uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 741; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 864; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 908; uint256 internal constant PRIVATE_CONTEXT_INPUTS_LENGTH = 40; uint256 internal constant FEE_RECIPIENT_LENGTH = 2; uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16; @@ -293,7 +295,7 @@ library Constants { uint256 internal constant L2_L1_MSGS_PREFIX = 5; uint256 internal constant PUBLIC_DATA_UPDATE_REQUESTS_PREFIX = 6; uint256 internal constant PRIVATE_LOGS_PREFIX = 7; - uint256 internal constant UNENCRYPTED_LOGS_PREFIX = 8; + uint256 internal constant PUBLIC_LOGS_PREFIX = 8; uint256 internal constant CONTRACT_CLASS_LOGS_PREFIX = 9; uint256 internal constant PROOF_TYPE_PLONK = 0; uint256 internal constant PROOF_TYPE_HONK = 1; 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 ccb3526e65d..cc633e723c4 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -16,7 +16,7 @@ impl PublicContext { pub fn new(compute_args_hash: fn() -> Field) -> Self { PublicContext { args_hash: Option::none(), compute_args_hash } } - + // TODO(MW): continue renaming unencrypted -> public pub fn emit_unencrypted_log(_self: &mut Self, log: T) where T: Serialize, diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index f570ffd16f9..6729087304a 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -66,16 +66,18 @@ pub fn compute_private_log_payload( array_concat([tag], bytes_to_fields(encrypted)) } +// We return [Field; 1 + (M + 30) / 31], where M is the byte length of output of encryption because +// each field (apart from the tag) contains 31 bytes so the length in fields is computed as ceil(setup_log_byte_length / 31) +// --> we achieve rounding by adding 30 and then dividing without remainder, then add one for the 32 byte tag pub fn compute_partial_public_log_payload( contract_address: AztecAddress, recipient: AztecAddress, sender: AztecAddress, plaintext: [u8; P], -) -> [u8; M] { +) -> [Field; 1 + (M + 30) / 31] { let extended_plaintext: [u8; P + PLAINTEXT_LENGTH_SIZE] = extend_private_log_plaintext(plaintext); - let encrypted: [u8; M - 32] = - compute_encrypted_log(contract_address, recipient, extended_plaintext); + let encrypted: [u8; M] = compute_encrypted_log(contract_address, recipient, extended_plaintext); /// Safety: We assume that the sender wants for the recipient to find the tagged note, and therefore that they /// will cooperate and use the correct tag. Usage of a bad tag will result in the recipient not being able to @@ -86,21 +88,9 @@ pub fn compute_partial_public_log_payload( // This is done by the kernel circuit to the private logs, but since the partial log will be finalized and emitted // in public as unencrypted log, its tag is not siloed at the moment. // To avoid querying logs using two types of tags, we silo the tag manually here. - // TODO(#10273) This should be done by the AVM when it's processing the raw logs instead of their hashes. - let siloed_tag_bytes: [u8; 32] = - poseidon2_hash([contract_address.to_field(), tag]).to_be_bytes(); - - // Temporary hack so that the partial public log remains the same format. - // It should return field array and make the tag the first field as compute_private_log_payload does. - let mut log_bytes = [0; M]; - for i in 0..32 { - log_bytes[i] = siloed_tag_bytes[i]; - } - for i in 0..encrypted.len() { - log_bytes[i + 32] = encrypted[i]; - } + let siloed_tag = poseidon2_hash([contract_address.to_field(), tag]); - log_bytes + array_concat([siloed_tag], bytes_to_fields(encrypted)) } fn compute_encrypted_log( @@ -112,7 +102,7 @@ fn compute_encrypted_log( let header = EncryptedLogHeader::new(contract_address); - let incoming_header_ciphertext: [u8; 48] = + let incoming_header_ciphertext: [u8; HEADER_SIZE] = header.compute_ciphertext(eph_sk, recipient.to_address_point()); let incoming_body_ciphertext = compute_incoming_body_ciphertext(plaintext, eph_sk, recipient.to_address_point()); diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index b454547e3ab..ce6a9f793f7 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -20,27 +20,6 @@ pub fn compute_secret_hash(secret: Field) -> Field { poseidon2_hash_with_separator([secret], GENERATOR_INDEX__SECRET_HASH) } -pub fn compute_unencrypted_log_hash( - contract_address: AztecAddress, - log: [u8; N], -) -> Field { - let mut hash_bytes = [0; N + 36]; - // Address is converted to 32 bytes in ts - let address_bytes: [u8; 32] = contract_address.to_field().to_be_bytes(); - for i in 0..32 { - hash_bytes[i] = address_bytes[i]; - } - let len_bytes: [u8; 4] = (N as Field).to_be_bytes(); - for i in 0..4 { - hash_bytes[32 + i] = len_bytes[i]; - } - for i in 0..N { - hash_bytes[36 + i] = log[i]; - } - - sha256_to_field(hash_bytes) -} - pub fn compute_l1_to_l2_message_hash( sender: EthAddress, chain_id: Field, @@ -129,55 +108,3 @@ unconstrained fn compute_var_args_hash() { dep::std::println(hash); assert(hash == 0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f); } - -#[test] -unconstrained fn compute_unenc_log_hash_array() { - let contract_address = AztecAddress::from_field( - 0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6, - ); - let log = [ - 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2, - 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c, - 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4, - 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2, - 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd, - ]; - let serialized_log = arr_to_be_bytes_arr(log); - let hash = compute_unencrypted_log_hash(contract_address, serialized_log); - assert(hash == 0x0095b2d17ab72f4b27a341f7ac63e49ec73935ae8c9181a0ac02023eb12f3284); -} - -#[test] -unconstrained fn compute_unenc_log_hash_addr() { - let contract_address = AztecAddress::from_field( - 0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6, - ); - let log = AztecAddress::from_field( - 0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303, - ); - let serialized_log: [u8; 32] = log.to_field().to_be_bytes(); - let hash = compute_unencrypted_log_hash(contract_address, serialized_log); - assert(hash == 0x0083ab647dfb26e7ddee90a0f4209d049d4660cab42000c544b986aaa84c55a3); -} - -#[test] -unconstrained fn compute_unenc_log_hash_str() { - let contract_address = AztecAddress::from_field( - 0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8, - ); - let log = "dummy"; - let serialized_log = str_to_be_bytes_arr(log); - let hash = compute_unencrypted_log_hash(contract_address, serialized_log); - assert(hash == 0x00629e88ebd6374f44aa6cfe07e251ecf07213ebc7267e8f6b578ae57ffd6c20); -} - -#[test] -unconstrained fn compute_unenc_log_hash_longer_str() { - let contract_address = AztecAddress::from_field( - 0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8, - ); - let log = "Hello this is a string"; - let serialized_log = str_to_be_bytes_arr(log); - let hash = compute_unencrypted_log_hash(contract_address, serialized_log); - assert(hash == 0x0098637962f7d34fa202b7ffad8a07a238c5d1fd897b82a108f7f467fa73b841); -} diff --git a/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr index 53efed5e62e..495dcb65049 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr @@ -437,14 +437,13 @@ comptime fn generate_setup_payload( get_setup_log_plaintext_body(s, log_plaintext_length, indexed_nullable_fields); // Then we compute values for `encrypt_log(...)` function - let encrypted_log_byte_length = 32 /* tag */ - + OVERHEAD_SIZE + let untagged_encrypted_log_byte_length = OVERHEAD_SIZE + log_plaintext_length /* log_plaintext */ + 2 /* log_plaintext_length */ + 14 /* AES padding */; - // Each field contains 31 bytes so the length in fields is computed as ceil(encrypted_log_byte_length / 31) - // --> we achieve rounding by adding 30 and then dividing without remainder - let encrypted_log_field_length = (encrypted_log_byte_length + 30) / 31; + // Each field (apart from the tag) contains 31 bytes so the length in fields is computed as ceil(encrypted_log_byte_length / 31) + // --> we achieve rounding by adding 30 and then dividing without remainder, then add one for the 32 byte tag + let encrypted_log_field_length = 1 + (untagged_encrypted_log_byte_length + 30) / 31; ( quote { @@ -469,14 +468,12 @@ comptime fn generate_setup_payload( } pub fn encrypt_log(self, context: &mut PrivateContext, recipient: aztec::protocol_types::address::AztecAddress, sender: aztec::protocol_types::address::AztecAddress) -> [Field; $encrypted_log_field_length] { - let encrypted_log_bytes: [u8; $encrypted_log_byte_length] = aztec::encrypted_logs::payload::compute_partial_public_log_payload( + aztec::encrypted_logs::payload::compute_partial_public_log_payload::<$log_plaintext_length, $untagged_encrypted_log_byte_length>( context.this_address(), recipient, sender, self.log_plaintext, - ); - - aztec::utils::bytes::bytes_to_fields(encrypted_log_bytes) + ) } } @@ -620,7 +617,7 @@ comptime fn generate_finalization_payload( let name = s.name(); let finalization_payload_name = f"{name}FinalizationPayload".quoted_contents(); - // We compute serialization of the nullable fields which are to be emitted as an unencrypted log. We do that by + // We compute serialization of the nullable fields which are to be emitted as a public log. We do that by // passing the whole note struct to the `flatten_to_fields(...)` function but we omit the `NoteHeader` and // the fixed fields. let to_omit = indexed_fixed_fields.map(|(name, _, _): (Quoted, Type, u32)| name).push_back( @@ -657,17 +654,14 @@ comptime fn generate_finalization_payload( // Then we compute values for `encrypt_log(...)` function let setup_log_plaintext_length = indexed_fixed_fields.len() * 32 + 64; - let setup_log_byte_length = 32 /* tag */ - + OVERHEAD_SIZE + let untagged_setup_log_byte_length = OVERHEAD_SIZE + setup_log_plaintext_length + 2 /* log_plaintext_length */ + 14 /* AES padding */; - // Each field contains 31 bytes so the length in fields is computed as ceil(setup_log_byte_length / 31) - // --> we achieve rounding by adding 30 and then dividing without remainder - let setup_log_field_length = (setup_log_byte_length + 30) / 31; - let public_values_field_length = public_values_length * 32; - let finalization_log_byte_length = - 1 /* public_values_length */ + setup_log_byte_length + public_values_field_length; + // Each field (apart from the tag) contains 31 bytes so the length in fields is computed as ceil(setup_log_byte_length / 31) + // --> we achieve rounding by adding 30 and then dividing without remainder, then add one for the 32 byte tag + let setup_log_field_length = 1 + (untagged_setup_log_byte_length + 30) / 31; + let finalization_log_field_length = 1 + setup_log_field_length + public_values_length; ( quote { @@ -718,32 +712,43 @@ comptime fn generate_finalization_payload( } pub fn emit_log(self) { + let max_log_len = aztec::protocol_types::constants::PUBLIC_LOG_DATA_SIZE_IN_FIELDS; + // Make sure we aren't overflowing the public log maximum + assert( + $finalization_log_field_length <= max_log_len, + f"finalization public log must not exceed {max_log_len} fields", + ); + // We load the setup log from storage let setup_log_fields: [Field; $setup_log_field_length] = self.context.storage_read(self.setup_log_slot); - // We convert the log from fields to bytes - let setup_log: [u8; $setup_log_byte_length] = aztec::utils::bytes::fields_to_bytes(setup_log_fields); - - // We append the public value to the log and emit it as unencrypted log - let mut finalization_log = [0; $finalization_log_byte_length]; + // We append the public value to the log and emit it as public log + let mut finalization_log = [0; $finalization_log_field_length]; // Iterate over the partial log and copy it to the final log - for i in 0..setup_log.len() { - finalization_log[i + 1] = setup_log[i]; + for i in 0..setup_log_fields.len() { + finalization_log[i + 1] = setup_log_fields[i]; } // Iterate over the public values and append them to the log - for i in 0..$public_values_length { - let public_value_bytes: [u8; 32] = self.public_values[i].to_be_bytes(); - for j in 0..public_value_bytes.len() { - finalization_log[1 + $setup_log_byte_length + i * 32 + j] = public_value_bytes[j]; - } + for i in 0..self.public_values.len() { + finalization_log[1 + $setup_log_field_length + i] = self.public_values[i]; } - // Populate the first byte with number of public values - finalization_log[0] = $public_values_length; - - // We emit the finalization log via the unencrypted logs stream + // Populate the first field with number of public values, private values, and ciphertext length + let ciphertext_bytes_length = $untagged_setup_log_byte_length - aztec::encrypted_logs::payload::OVERHEAD_SIZE; + finalization_log[0] = aztec::protocol_types::utils::field::field_from_bytes([ + ($public_values_length >> 8) as u8, + $public_values_length as u8, + 0, + ($setup_log_field_length >> 8) as u8, + $setup_log_field_length as u8, + 0, + (ciphertext_bytes_length >> 8) as u8, + ciphertext_bytes_length as u8, + ], true); + + // We emit the finalization log via the public logs stream self.context.emit_unencrypted_log(finalization_log); // We reset public storage to zero to achieve the effect of transient storage - kernels will squash diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 7644487cba7..03ef9725b26 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -105,7 +105,7 @@ contract Crowdfunding { Token::at(storage.donation_token.read()).transfer(operator_address, amount as Field).call( &mut context, ); - // 3) Emit an unencrypted event so that anyone can audit how much the operator has withdrawn + // 3) Emit a public event so that anyone can audit how much the operator has withdrawn Crowdfunding::at(context.this_address()) ._publish_donation_receipts(amount, operator_address) .enqueue(&mut context); diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index dc8b2a91766..535eb55c2ec 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -515,7 +515,7 @@ mod tests { tx_data.set_protocol_nullifier(); tx_data.append_nullifiers(50); tx_data.append_l2_to_l1_msgs(5); - tx_data.append_unencrypted_log_hashes(5); + tx_data.append_public_logs(5); let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; let blob_fields = tx_data.to_private_to_rollup_accumulated_data().serialize(); for i in 0..blob_fields.len() { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-base-public/Prover.toml b/noir-projects/noir-protocol-circuits/crates/rollup-base-public/Prover.toml index 2f4f4d81375..ce41159822f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-base-public/Prover.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-base-public/Prover.toml @@ -1,53 +1,53 @@ [inputs.tube_data.public_inputs.constants] -vk_tree_root = "0x130ae70545763dadb59caeb820400cffc41df59bcc2b8731917644f247717686" -protocol_contract_tree_root = "0x2f9edcbdd0cfc67764aa32cdef9ea44f2914b44bfd9cf77d518a5ac172e7f9e4" +vk_tree_root = "0x017fe601803e9cd0f1cdb04b5e585733948868629e9266c3097e47d0dba5e232" +protocol_contract_tree_root = "0x2e1f56195ba674b50fbc37b7663e60f0b4b17087e471c3ffce1e347bb820ef31" [inputs.tube_data.public_inputs.constants.historical_header] - total_fees = "0x0000000000000000000000000000000000000000000000000003a83222de8a00" - total_mana_used = "0x0000000000000000000000000000000000000000000000000000000000004a40" + total_fees = "0x0000000000000000000000000000000000000000000000000030ba27b3223042" + total_mana_used = "0x000000000000000000000000000000000000000000000000000000000003dd25" [inputs.tube_data.public_inputs.constants.historical_header.last_archive] - root = "0x082bf9a6382021ca9fa204bdbc71fd5536d84358e57a61f129fdf5bfb228c06f" - next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000008" + root = "0x260b714997b7d919326f4ca8e57608ca37e2f5b7aa3ea9e78ba2c43f2112f1fd" + next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000005" [inputs.tube_data.public_inputs.constants.historical_header.content_commitment] num_txs = "0x0000000000000000000000000000000000000000000000000000000000000001" - blobs_hash = "0x00310bb50f2202183669b8a85c09986fd69c203fee7d32e06dd1b46c84b20a7d" + blobs_hash = "0x00e810eace900a333fdaf449fde8f3d14d4899bc8d28ddefe0d3c7246984ad33" in_hash = "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c" out_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" [inputs.tube_data.public_inputs.constants.historical_header.state.l1_to_l2_message_tree] root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000080" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000050" [inputs.tube_data.public_inputs.constants.historical_header.state.partial.note_hash_tree] -root = "0x2596f3d6b05b7055c3c5ab89de6e270b653cb30c3dd6b9cfd230ff41b5ffa623" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000240" +root = "0x1efa12bb5ca2f30b14ea29ebdee79b6b0f3f99ab9be86966278dfb0f39c3f97c" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000180" [inputs.tube_data.public_inputs.constants.historical_header.state.partial.nullifier_tree] -root = "0x15205da8ec6fc0317cee4482de04084768078d73397e7f466c11c45c2cb66bac" -next_available_leaf_index = "0x00000000000000000000000000000000000000000000000000000000000002c0" +root = "0x2cc6c2f102077c6021dce4e4aa8be0b6ef78e7ed514406baa4176ea8d854e0d0" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000200" [inputs.tube_data.public_inputs.constants.historical_header.state.partial.public_data_tree] -root = "0x2841d0ae135bd8bf3761f919c16b9e5cf7ad4b3035328f65bf84ee2dc599aed6" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000097" +root = "0x1bad10ae89ea9ed06cdd47783782c468a44bbfca09a476a29f34fd778de862bb" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000096" [inputs.tube_data.public_inputs.constants.historical_header.global_variables] chain_id = "0x0000000000000000000000000000000000000000000000000000000000007a69" version = "0x0000000000000000000000000000000000000000000000000000000000000001" - block_number = "0x0000000000000000000000000000000000000000000000000000000000000008" - slot_number = "0x0000000000000000000000000000000000000000000000000000000000000022" - timestamp = "0x00000000000000000000000000000000000000000000000000000000678ac01a" + block_number = "0x0000000000000000000000000000000000000000000000000000000000000005" + slot_number = "0x0000000000000000000000000000000000000000000000000000000000000009" + timestamp = "0x000000000000000000000000000000000000000000000000000000006788483c" [inputs.tube_data.public_inputs.constants.historical_header.global_variables.coinbase] - inner = "0x00000000000000000000000017ad47b9f14dc201975cca47fea765e5d42f0b72" + inner = "0x0000000000000000000000007f3566e568179d1a145b3d9f81d9de12f4efb4ab" [inputs.tube_data.public_inputs.constants.historical_header.global_variables.fee_recipient] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" [inputs.tube_data.public_inputs.constants.historical_header.global_variables.gas_fees] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" - fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd3a5e8" + fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9c6e089a" [inputs.tube_data.public_inputs.constants.tx_context] chain_id = "0x0000000000000000000000000000000000000000000000000000000000007a69" @@ -63,7 +63,7 @@ l2_gas = "0x00000000000000000000000000000000000000000000000000000000005b8d80" [inputs.tube_data.public_inputs.constants.tx_context.gas_settings.max_fees_per_gas] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" -fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd0959c" +fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9be07ae8" [inputs.tube_data.public_inputs.constants.tx_context.gas_settings.max_priority_fees_per_gas] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" @@ -141,7 +141,7 @@ note_hashes = [ "0x0000000000000000000000000000000000000000000000000000000000000000" ] nullifiers = [ - "0x25114218b4f6581154ab0fe36b0f00e2673087524aebcbf520264c658e19709e", + "0x040396fdcbfd0dddc55e7d1c96ba452b023472647a8504438098d4bd99e600eb", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -2361,13 +2361,13 @@ inner = "0x0000000000000000000000000000000000000000000000000000000000000000" [[inputs.tube_data.public_inputs.revertible_accumulated_data.public_call_requests]] is_static_call = false - args_hash = "0x1417dba875e97577c7611de470c195f6b66ab7ca8ae1d2624ff593d6355a7a11" + args_hash = "0x06dd605db0b3af21ea3ec0d331ca35002313410c19287a52d09b6a71939c5877" [inputs.tube_data.public_inputs.revertible_accumulated_data.public_call_requests.msg_sender] - inner = "0x238db6644a299b7b33993c163a0b3f3f3aaeca32f9d0f9d0328c1615d7efb8a5" + inner = "0x1709ca99cef62ed7b9b94f09698c60d7bb915bfe1a39ca716e8c07dbb7f99d39" [inputs.tube_data.public_inputs.revertible_accumulated_data.public_call_requests.contract_address] - inner = "0x1f3f85b45ea6c7be79b6e4948002182167732a202d83e1dba67b53f676583c83" + inner = "0x08177e32f37fe903867e601bb59d88f578087570b6a462e9f283b980b3fd3396" [inputs.tube_data.public_inputs.revertible_accumulated_data.public_call_requests.function_selector] inner = "0x00000000000000000000000000000000000000000000000000000000d5441b0d" @@ -3341,192 +3341,192 @@ fields = [ vk_index = "0x0000000000000000000000000000000000000000000000000000000000000004" vk_path = [ "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x1c05dc5d161ea24cab9cfe0b25104cc245a1a3dc5781c35f4dc7da7abf056629", - "0x29948c9ec655993f09495cf6efa2c4f95db2e7e2e7a338ffba4777209340c832", - "0x2c8b742477af94eb3d371b8aeef0f9a8d930466cfe240ca1b7c504b0b4492d22", + "0x2f0277c34cb53036f76ac453e6a1df26d408fbb0dab1f01e4ed7442ea91905b9", + "0x2a1d8715fadb132857d65d080f973beed888cdff6ded60bef97ea97afcd69013", + "0x18e0298fd3f6bf4fcf17a2072d7082b36aa1d05d11189235ead00e2c75635db5", "0x126bb13ce4b07681f511f3a23d88cb7cfe082a76730abd5b4be5c4da3b5c51fb", "0x050dc6390aace9c6e873b762c65e7d6a21e78e64e5ad6cc7c8fd5e69315ab5fe" ] [inputs.tube_data.vk_data.vk] key = [ - "0x1d970eba2ffe0b6252f28b8389fd0a7a040f988eadae5e1285e800f5b1bdb474", - "0x2037f2a6f6e0a8d475ee19665fd1cf6640f27be7d9d685c7ccd100d62f897653", - "0x0b5a65ce5f20a7f6a5f2837edd33d1ed50111787cc99c0efe6b8fbdf0227b49e", - "0x0f2f94d15be9ae712c804c17d2f1fee4d875c1f4b59640400001b0142353f9b9", - "0x223683c1e926adcaa02be70869f13b7ea7bd0cca96bc2c39e575deab7b5f15cf", - "0x2347a0cda216dfc1811c8f9739623ecae5c9fb709c950fe8145f2b37dc706e9d", - "0x1d0f3d997eac74734108b37e316ffb946201703661dd25d0c8f06211bdc24a90", - "0x0ff0f610f5085c2e443537a1230d3d0c93d635c7196a7fcc1bb11fa389ee35f9", - "0x23a3e32d06b85a556d0c98247e79365bfa863a1268842ab1f96b5185026d94c7", - "0x0b5a8e70e02c077945d47d4716581111d0917f74200ed3ebcfd8a9af5f6ae480", - "0x064a7849a81b895e476629b0146336cfd15c23330666528272264614825c597e", - "0x05707087ed6444de9416a4e215a85adbe10826c4b26052c318ccc5ed8a9e0cbc", - "0x049b4d8e4501f4cda7796b7ddc9afa5c46c48736bde2390feb9a48ccaf3b15cb", - "0x304135e75c8eaa9b20fe4410d98f57d5670e34e2c838c813f098fa85f51e08d0", - "0x00efa1fa665d687e32b9ecfb8543ee3339d460a176af4c54b9aba661f05b92a3", - "0x16fdee07c656b08c6b0d2c1525422fd2d90e366c30e9f624adade02b8fc5979d", - "0x0e8be081ee19fa020a58a3b4c0ac67d4748f307308bf43230fbb60d97e0b4daf", - "0x12adefa76fd9db50053de303c608007e739ae0734ecf5065706722d446f8dac4", - "0x03c812fb386b20bbaf5b010c45ceb5e3d2bb8838e0e94536fe81a2e309da7ad7", - "0x275fbc814660335f5f14243a9c4bc63b891e31670e6f82c79283ada87ecad851", - "0x10e38f2d09cd798d45a42f269d7fa69dfed374c939a1785891b90def34b83dc8", - "0x2a4a369574fcd3ea3eb7555478dac21f9319da4f2c53214138431a980699ae83", - "0x2a27ea7ef22c7b5ffd7655eafe16c76c15b9541fece07bfe42eb3eb6a973d6fe", - "0x1d00276a978b569119ff0eb7c489d1a0d9eddb39c6bc8623e72d313b2bf47217", - "0x23dca229ef508e9c31d74f34f975d539e13f6868582507a5b99b9a9a8e92b68e", - "0x1e7fd05b4a5ec062a8f8ee67f6586e85989dea9717b2f7476ae2bc184a308b18", - "0x18cf5b995a49b30e549eac46dcbccf15046d21f1417e18eeec79e1dafcd7b842", - "0x117f0ed909addbee01b939352dccb0b93f0f7a0cc35c7987303b8dcee423e582", - "0x0a8c17835937bd9f34a5b7a743d96e3008ff2b9c1ee889225bb44c905a189d9f", - "0x2d3d931e7c62a7166df9dd446bb51270c0337f06daf1c688a7234fa6f728ccb8", - "0x0242fac3d1d73ee9b78106865d2ff88eccdb6a6db42781cb4dc9c407ccba9614", - "0x180b906c3d7e5283fa9672370e49940465729592063027c5503dd56d65b354ef", - "0x14ca1dd351d841a92ac87b8b415b7f575882320c35ea3166be84c572e56c6c9c", - "0x20015b76e8ed3f32efc6ff12ddc9874cfb7513de1493e6f251bf355eaf1aa232", - "0x16e0c535adac8aadd4e1781df356608685962b9b2f9147bd9c10f056759b87c5", - "0x0598a9c6ac08cd7547a76336833fb4a04ff9e547e679a6980e0ebb175611c940", - "0x0b1f966fe329891db65beb9851c7a66f0aa94477ee4a3422823868dd69bc2f30", - "0x1459b2c65baef319472f565331396b4bf60d8b327a5513fb62375df46cd5c19b", - "0x0c1d4bf6fbd192cb09795f81d197779372bb9f05bd6ea4d2dacffcefa452dd24", - "0x00f49c251278a7ecaaaf9a36b3336574c796a5d4e3a10363daa6a6d87410d0b1", - "0x18f8af11782c41f6952d708967479b920b284f765c906a28d7d6c5941aae7c86", - "0x224e8e23df6080a7ce4231739efa5a3e4fb9d6c57811fce457bdf2e2b6d1e1ec", - "0x01294772ca9fe9d1949d663df5077e2b6f7681ff715f250a7b68a329c2cc6b9e", - "0x15741f45c7cbf1a9c11cf45e0d40c80d026841d7de55d00100c83587246b9bed", - "0x1c4326aff4068a2d2ea89f58f5b5ec65785504aa16dbc0a2096d856d6c7aba5a", - "0x1c61cb98d931dc06f2c05b5f6ca2d363fe3a3d0cc81fdef25884b1f9957b6f9a", - "0x24335197ac2ea62a7206d6f0ad4f370a619af58bf8495f998d327a9d2421e69c", - "0x0af5e5ccff4c404e6de3f1f62b251b054d2fdd6af744bcaf51a29a86ef0251a4", - "0x01d6e7147f15bd6d793b662ebdde35511c8b53e0932ac8fc073894d6773bb6a0", - "0x1ae08f778934ef0e449d40e2c93c7fc615e7b31b3fa6297a33bf598f189e3c5e", - "0x2d7092522bb1473b02497d87aa1babe36c38667dcc392a068d1f0f0ddec57f73", - "0x1eade802e0439057bff80228673f787fd2be08d5612f0a36f3cf415f175f5e22", - "0x1d3b09a634d70c62f93c4143bd8fa0bf01e29679ccccf2fce1c9cb4478b630e9", - "0x1ca256638dd60b16e2820946c6ac9763a7dd09dc775c941d4a4ca0e794a524dd", - "0x18dc6604222946073a87b5685068765bb2b20b2107514c6dd85f948e651cfb3c", - "0x1681302bd1e658980cbddfd8db37a54c2ee49f9d0da428a720bf95e25bd97e0a", - "0x28b93a8317fcc607057a741ba3fe69b78dc7fe373e8616c1198e296ab80fb504", - "0x07808f80c5a68663fea32909b155587da7c52a3399f8734e44c220c51eb01dfc", - "0x1e0e3dc30c05b7404688f161dd888374252837759424f2c9c7205e7443bb52dd", - "0x2a5b1982448bed142158367a8a9dabd35c5c431c1a5786048e9591c1d6d16e88", - "0x07a4fd591e7aacf4efa866c6156125da0ffc7cd32a43b2aa3bdb16565a1531ff", - "0x0cc985fd4b463a1a02cd822122c8f5e6c33500d8eb62006509d52b1a5f0688f4", - "0x0f2c650cc51ae4a1f7912c3e2c0f99ec9bcb0128a21b8642368819656b920e65", - "0x11663a2e4608104b07ecc8dc44ffa6259988f50f0523a3c6fec2e33cfb7540d3", - "0x26361bcd9fe3e354cfd424bcf200afc2e9fb22df6b59a40443fff830963b5196", - "0x18571ce2f1bf124c806d32dbe245ec2c0daed40a3c2a5a1556a1975e437cf806", - "0x23442243b8216c5d646e5579a51f6740be29c128cb822e8ec90a6a5eedaf6ef5", - "0x120dd97058c315814012a05dd1f5f20a9013fb6df4cdd4a3969bd9c2bba29428", - "0x2cb314e8d4a1d61c57a662bb7273a6646cb034670d5386b2c38c7e66df44efd3", - "0x09e6bfa91207fa4ba2c9bfdac968789f3decdf1ad02ddf3cb285747ab1bca4ef", - "0x0700c2c93bafd120677b7d97d245193aea0c277b6c3ffb1195ace2110bc4a543", - "0x2e55657f5d80fd569f02dd3cf7249e0e47b42f37d199e9042e7e8da8f55fc8ec", - "0x2f44f799427fa24e36eb2e22e7197bd1ec0147eabf0edceec436da7325c03cd0", - "0x04b6741e087c66d3fd58e7e3d1bc8a54eda0dd188afa2dbbfa110d24fea5a855", - "0x0120c93ac72c44c2be67d8d9047204c96b8ebebf1a982e055e8ba7bbe8751956", - "0x1bb8e64dacf691570a67eb15f631cbd9d55b464eaeb65f50e3c6fa39263bb266", - "0x0cd92a4ca914cc46515051364d15d84bb8331c91bac7a185ab5eeecfc1e640a8", - "0x0cc63a70e0b16440c4c6d81fbe898cc1ea26f8b3cfca3ea5d0c8d448923171ef", - "0x008d6feeacaa89264f34de73614c9ac3ebf4a3e0b31461e27cc2610e3ba90d8a", - "0x01f29a2d37e5de7354cf4cb716807805cbdb8714d43157eddca90c9ea228695d", - "0x02ff4d92781ab98aa98f16c707a73b6c3387ee0e473b397b22be00763b067e42", - "0x0c238f627adfea25646d47f6f52340c05895b38f1b38ab0a850b00e42d4e37f5", - "0x21483bd03f969e29a05019691fee6c33486296d6b0d80877d92f36713ede3c1e", - "0x27f3b59548885abc20383f708cff90019308a33140b5b19532ad0339337d48a2", - "0x0ac3de0d525eb9bc4e8038ce039540be1cc9ef38551d56d42c1633a7fcb56e91", - "0x0b9f68ed9b30e90723baac449a27dfc4854004f2285714391da088ef9ed39e84", - "0x15dd073fd785e697f7d2d86c3830ddf4565a3055407bc359a73ef2bb7abe3896", - "0x2b2cce9658511b431a26b478f1e5f91f00a0c892e1044efe640aed3daf89b4d1", - "0x054ee8c73262b94a090286491443ce53c096ce3349405a47df925837dea3db5d", - "0x0bacf58738841ca70fc9ce524be3f05d4a9ff8be36709ed8a7e5113f13fa1d66", - "0x106494a9477a4ce6b1dc8713f411d46db207bf492672b3420dc9cbe23411d95d", - "0x12e582b8fa39330cca7f4cba87d7c16275a6ac761f56a7745b42317174bcf951", - "0x2bdda379f19f157ad4e076d666dccb70f16705aadaa5cd1d422225f01552d69a", - "0x2fbc63d7f921d3ec0bc0f73367c940464b83897eecd695e0346308d362bd0673", - "0x2a3acb918b091f93de0ef5fad0998659d2b8b174160321aef4902d4b34c50ef2", - "0x24a2e15702b6e67b1285b562b78d323a365db3fa1177a0e6dee5fc893317fc31", - "0x0ac55eaed1225fce8b23a9bdda2a5eb4cf9d4a068e82f7a70148201cacd8847d", - "0x2302c97d51581f3b2af1b221ba1f9ef54e0a3e0de02d2ecac41e5e3ca7a3cfd6", - "0x0ff0b11b8d26c6f8c40767ca458509a5efafcdcd7ca35afc182004f2264ecf15", - "0x1a82cc0a9c1c7973e8449b252a2e0702f37415feec75ec7bb8a3b2bdefe4fea8", - "0x2541ac83d02f0238284d75c31f33c95111b58069e3d0b6fc34f8042ba277723d", - "0x0c5ef3017b0df4f675b322fe66067c91f3299dd732144342ed30ff486658ea95", - "0x075fe97dac4c2de305ecc3b69fec1957d5c078d67fc3246617587c909b4a78ac", - "0x180971876225f8e6d39ba532fffc772aa656f8a22d95629f4d9e6f1b5c47a26b", - "0x03413ab230562028e43474a0a0aa6eb0c20953aad2aef576f3e59c4f5edd9fd5", - "0x298d27cba5daec3b6e64b380a7e91fe7b92d017c5394d076c9b9d722d0b6c4e6", - "0x2866ed16a6a231eab36688265762dc8eb761c996805113b77c059dedb8985d77", - "0x2c93d4a441e1f1b824ad22f76ee21645d3548a7ccbcb7990dd0623eeba71059e", - "0x150a19d41dd6389d0ab6030e86d78625fbe907d40d55c62212cc09318f1a4012", - "0x021595174b7df1b9a1ba7633baab41ab49a58bba6259f1aabcfe6878ee8917cb", - "0x012082c7ae7e7860335dd22e76c939caea358b26cbedcf09829a08f611176d34", - "0x01b78d0eb9850690df45981f7dcf323ae5b88829fdd1ade3d2b9ac556cc8636a", - "0x16ec5b58f89af4f19399d068d69377834d5c5a39cf77e8d71519be3b48254f37", - "0x2dcbb31bf1d4277516f680d09cddadd5c079554a7d84cf8c21f1ce9bb059f884", - "0x02fd597a0371588b974c365631b244bdb4d347b2c5b4866564d83e2477a5406a", - "0x2578c2e2806a44f00514d9e5eb90925ad624b0fb0f8c6f54f17119de63739c96", - "0x19d9ccf7786559f277b8a4a8a81e2a2982e811ae1f84dd47f733424d99e30b1a", - "0x305ee46abffe75b121bfd7f6cffdc1593042d3ea764edf18419cf1026923acb9", - "0x18d7430f4a9bb4d66732d7e88e3618e778fd0889fb74e079e30b078477b8006c", - "0x1e8dcde0d77cf2c287c26e63fddbd62cc7d52b6c947a2228adeb7c8b35310121", - "0x15853fdce46b41e0ba900262c342339ce54c957efe7b6ad80e373a8713a4b225", - "0x18996d4e4a268924392e4eefc37aa37da97e988f88d38ac0cbeb7bab0985a068", - "0x1c16a0d5a57e04694a23ff23ca4fa7cca64ccad23b4b16a87f341892242a3555", - "0x044045130f031a5f73cce1e9c81cb884dc406bdbb09e7bdabf736fafa5427279", - "0x193dc99c306b9c0611a779165808096dc2b777739061a83f816bd5f369a4536b", - "0x295b559bb172be8366351046cf1fd3176ec8decd6020497791cc5b472f3dea24", - "0x0e2a87206f2f05e95d7698f60a043ec9c1c1be2face80a9657e66b61d641fa42", - "0x07e8e616c779a33e13c131f2a31171201755735279bc7a2cabc22b2c0d3148ef", - "0x1c4da3930078d46995cff98cd34619acff086eb0b1d24f5e703c8252acef6e92", - "0x02a4c1e556bdc1ed095cab28ccfab8ed05ffc7d740eb8b1d5e8b76087c3de847", - "0x069ec6717f084a3e3799e413580dcced9527d26fdbdb2b601bae069d2527bbc6", - "0x17b6a7ad118d7e18fa2b4be98d82de82237bfbe5f47b24c24a6aefafb8d00de2", - "0x0b7a6c86eaad96bc87c07b74e232cf61275318c3a3174d7e07d1d7d4d38be226", - "0x09cee8a544c6893b61f178a5e5110255d91fd4ab062f9beca11c5952a7a71a85", - "0x16c98cbd6209fccc388e9f4ff7930be5f44a0ad8da8a20871789194604314c54", - "0x18bf22c151ee3780025cd38c6f95c834803ccb41ae21b9845b21afee7d8c823f", - "0x19c6a40cc9ee82855f8ea8501cbac1e490ddb621648f88c1bedbb7ee909d6bd5", - "0x1df884e3a1ec0038c338a1d7dbc54127327f7a3ab304fab7c3f68c7a2893cb41", - "0x1109c3469913cce27c5e6567901b424f49f7c47d31ca103e3825d35e1c658c7f" + "0x0b60054df618328b8cbe67d62b0c0b0f661ef28bbab19be34b22cf2d03663744", + "0x141e39b68fd80a899e865d27f05e7085974b139939ce0a0235614f49cc35a90c", + "0x2a5370a9ed8f587dfd973028b19d31a9aace617a4ee568032c0be3144dfff6fb", + "0x09ccd13a291c85d5b41b4c7b7624efad637b607b9934c01945b32fc693d83496", + "0x0dd52cf343daeb1708f4015d983b871e00567963d54def4af097d98092ee0e88", + "0x0c10ac1a2685d18f4ee3852f4997df380e591f580a3f6acc56f4fa4ebca9453a", + "0x0f44ebee4be2957b0279ffc5705fb2d4b34be22670410c07ce051cdfb69df491", + "0x13b4f2f5c9ca9b07905581bc8a97539c09f1972f8bdc1c4f034dd4a39619d4d6", + "0x0044c029b2869828abff6b99b4249ccb895e24ccec57332d45648b42099bc41f", + "0x1a09e54842c8327504b4c858be527180187b1a74be4b8e2198da65a0a7c2565e", + "0x2692ccdf0d0502a7fc40f68aae0d0df9ff3fddcf9201975f3713c067a905b53f", + "0x241218c1f4885d56ee465bbfd92ba8758c0d210365035c36b994a26389678f1f", + "0x2129d17f4f4f12dbd42ede4fdb9dbca1787181d25851de8cf10cdd1220e8f1c6", + "0x1d740899f909516eb03e077d264dfc79f4e315f6c7d0cbccfc288d0d1cca5000", + "0x0a21658395cd37cf30a122ab174c0ac8e105b7001594b06b7c40198202806cf1", + "0x10d19b45d46b4ba1868e115ac549b22f69478b8fa5ec3ff99fc56c14a63c2627", + "0x0524978a50b200e425a27c5d0c1570800f0b4ab3ca17e1ccfba774a09302dc5a", + "0x1360b1d829a4ea63035908f0cfaa046519029cc0b439f0c5fdfb226f66ec7600", + "0x2ebcbcdf94d6225f74112903d80a4e1e9a2cd81aea8808787abb81c199a27a5a", + "0x1f65e0752e35489439f8f5ad0e391a9302d5653e8bab6ac48ae1cb9bdefd836d", + "0x14c11bbf427dab1457719ef47efc296762e3d370ffbb174aed772c0893986575", + "0x07d37f1dddf4a94e7927ac8b81e4f0434651ec7786e2e7927e41f19b2683345e", + "0x2dfdde89b101623e690ba181673019267cabd74cc110f3f859a0d92df7e2599b", + "0x1ecbb7f41e44e02f7d9bab6eddba1332704025998a90c2a53c324615411e3d99", + "0x127800b635553c71544df9147513f81ef65f6fe02a69db579432a4abbae090f1", + "0x293790a4cdc4e8cd00124c625de9d60721dd35412ce62f0710acc414f6d98429", + "0x037d0a071b3db8d4a0f673003be636ac11069ed7e1ef4a981110e87072993585", + "0x190ceddfd758f70805af5c237e3d368d03b8ee94e770f8ff49f8fa687f174eb6", + "0x2704f3543ef000e297388138dedc688981601c786902e42ac18333729e1e6a09", + "0x296c288e1b227f8dff655f963f2207b648ac51ef9fc200b072575a47b2cf9d97", + "0x182f2cd115674609304246ad29458ad823923b43a555fc621d1e27d76e18d63d", + "0x20cb6c37a02541856c60be0df8f1b21f25290bb280a0c2293f550603f02a42ab", + "0x1d537b9dd6dc2254e721ee9183b91af9e8f6fbc7f1d688be0654aa4eb235be67", + "0x21b77a08810e0eac0e2b72344dd4b66c7d8fea9ff7d4ccfa3e336d2ba7cedf92", + "0x00a1ee795af6ba40737b70b9384d5b9ff85d1797e5d3ffc2f5ea2a6c007aca3c", + "0x0826e4e5570c4e14ccf2a70469096831871c7b95fcc0c504f743fbe5fef980dc", + "0x29e2c1c1e6dcb127106598ff3788fe1f415b926b367c5b7f8a19319c71221a91", + "0x1c8ea302814a9bcdc5674e3cf66c6b8706fffbedc32b7e7f03b55b1913e79f73", + "0x1d35057d0641224f674d986918d1a4ae4b64138fb13e319108248caccdab8fa2", + "0x18a5779195f8297b9fbbd2fddc0ff920aba5570461f66b439d3ebdbdcf75fec5", + "0x2f20e14b02402d2840eed3bc22c0aebb67e1c76f8dbf738743793b3201a32b35", + "0x28f091fe973d13b25e70b95e596554a15de34ce964f7461870816de0e1b33406", + "0x26bc8a6b3fdd9b66332aadc39d19d554e2e5c11adbe9d8580c04a885fddd556d", + "0x0f0b2e6ab4266a78ba8098dc4a3e9b66191749924ee0f4aefafd4d7c6f8fe594", + "0x1d56fca3b45bd7c466818f34746517e46a4db6a428f32fa53972baa32e530c18", + "0x2ec9fdcecf41b93f4bb8ba7ae4cd5a09d4a91628b6615c9975557f86ef59553a", + "0x0679f0bb89d859e01ddb968fdb80fe16b12ad014d3d1e4fd705ad8976784519a", + "0x04e728182614861085e07d24a453c2ba6351f0bc30df8571a5917798986241eb", + "0x2aa95a9e23ef19efe4195b0da3d22409e9d03370954c83b021cb00fe15185dba", + "0x0c3d0f6dec45253cdd16e4523d5f691af602f5bf04d583479d80a64c28952b86", + "0x057603e04fd10d91e965af3c3e13992d3734aa306658802569da82b6087b582e", + "0x288fd77beaad66798564e82276ef035c8cfb8f2510c84372aedbe450755f5ab8", + "0x276025428d3000180229ca9df6f2f7201349d18fbba77c64cf1fba61a45bd676", + "0x1315ae8c69d290107e64a6620c4f68412f221880eb2dedbde34323cf1490c784", + "0x274fa228134bb904317924c73167897bbee68c924a0be478d57d731ffe00eee3", + "0x30487e012a5011dff5af9f255204306dfde3f8b9a71c74784a44b0e5b657c909", + "0x11f853b877fc66ac1d7c9cbb185821fc3e651ef49de2cc6294afcf82f85bbf5d", + "0x0f19929f85000d5f5025543c0ac4297b4bd4d49436880d9e24168c8eb8b6f523", + "0x023827bdd0014d3b267992518e9538094cd1fcf2eda77e472b0948e68cbf393b", + "0x0dab1a427d6dcc1de10afa2a69c27ef218377aa952e725e8025ab4befc8578cd", + "0x189a11cecb55733bc1d12695596c644b3c64285234abf45fbca919d66670cd06", + "0x19116bd52b3da6335e1bee837b80441dc1f353700b1259131f8e41476901b1a5", + "0x18950c1267d83f02f1d6233f800ed405f7f2d6e63af3c37f3c7b6eb462c25dda", + "0x2b7d831a92e3b9306d2743b744ae117d89a6c981075bafc6b37786a4c5d0b474", + "0x2a63c998e0135c499f4d6d9dce109e2cdc93b0227b31135f75be063b3611910f", + "0x2248a94e3642e5872f46bb67cf9e3d122449601ee7fdfdb157e3f771fe64355c", + "0x0afe0465f1751fab7cc189e77a977aa34c9b7b90e8a4432bb6bfd371eae61f2c", + "0x1df9270f89163b17cdeec6bb8b046a69a9c9c9ff63bdb8b9c2fe648178c388c6", + "0x2b14041df3990c06ba5a169f5102d011b54b3042755116728a844de28ca52703", + "0x13e24c12ead34147027ed30ee5a6ad67283827ffd9b45ae9e2223fcddb7dfdbe", + "0x15c48ec672a6ca8c88404157c4c6107445785640bafd08e8a8d8ecbec6230b11", + "0x1991b49fb250d931979dca2fe9aa121e631fe8afa2891eeca001996fae86965b", + "0x032a72384b653b4eb1b9d613957e1689a1458dd85ca3bb814c248c9ccc3eafa5", + "0x0e0b497220aaeeaef278509347f9019ab4cdbcaebe279b34e5e181490d059248", + "0x0e175e9917f3551c23ae9dcd6add5aaf05bc094fa8b2d824f2c4a6f7c2302cc4", + "0x25a481021954c94ef810e4ee61048f7014b6aa8b8295e192284f4cf92ad365c3", + "0x09fc119b8186da94a8a3a1c0b09a9ff351091883a878a80773dc06e32118183b", + "0x1807c55d338c9ae3b139264153625440ba9cce613ec29613fb66ccac3b0b066e", + "0x299fa58c97c76840f8927c8ed08169eb3385bd7432f5208c806bba521e8ac3c4", + "0x24738ac616454e41c5ef51ecbc2a2fef9afecf1e599971626d4479872c7a849f", + "0x0bdbbce9f3e75c44f18e037de8de00c0493ace91ecd3fef1a3cd5b3574ffcf34", + "0x01b7c1b2183cd49cbff484a16cc5d037c70f8a1410dfc2be9ec6cf69eda41d29", + "0x1c30b3296b30012ba55b192bae01ceb28e5e92770a45c069d27585e847a3e7f3", + "0x0ed4459861f5d76a2f1fdf2077bf01b7cf59df9e631be0376502ad474b445bd3", + "0x277b6f1b8078bcbd92b115e91e79a7d4a49c5499a1a79681bbbe333cf5092205", + "0x11447356f5ccb20ad37fa5f251f4b328b25967c3ab8389ace0db1dc747eee31b", + "0x16b92b49cd277fce17a8f0486f5f249b9d6e215c69b8c747fd502af092da8b78", + "0x19c8ecee0a5e3d34f11321d8b2a9fd7e92447c5b5008433ec2d9ebe429630f81", + "0x19cf19e98d7c330e9c4dfc005a84202ba2af13bb697cb0c38b3f0e47db0aa4da", + "0x1cac825062db92bab0caff7d39314c804c7571fff121c92640ca94c302c87312", + "0x0576dfb291906938ee8884e30ea9a072412b8892e3c86f3eec7e42008dbb8888", + "0x09f25f07ca1437e39af4b889bd5c2ed1372273eac84e0bbc29801d734430439a", + "0x134ad130f9e0b7c61c1a7b350b26e2fa158b5adc75c66c1960f6be12c752c34c", + "0x2838c4c11d1073656d0dd5a0d18b53c357bee321ceaaed66d20dba36e129eb72", + "0x2868f1ca22f8e28572c3a240c69c4152edc4d1772124eadc62cf3ee34b3d327e", + "0x2d7229eb9011c9282c0c90a852560d1d8c6550f47f74b8332b96a30ddef52395", + "0x224186ced6f398c14966c0705099b12959d997b1904f6855ed4c15a28a7a9dfa", + "0x0643598f994283d1edd575040a13f4a10129135dc97958eae26eb68792f90d5d", + "0x26eeb4dae00d98958dc0f93bd1495fba401b0a38512f747cab1124dd00708dcd", + "0x2116b4632243cc447d351528742b6ad889205bf857c621afd5de61eda274d50c", + "0x1828ca6899114e467eb0811e66565f9621821d27bcbce6a2b178f64896ada6b8", + "0x03ef5a64f5414049103c8449e9ad75b8369e4d615d70864d23b6728ceaf38fa3", + "0x1b1d2fae344322370c2cc22892e3158a455cfd1e90cfe2cc314b9810a12e5427", + "0x1e4e0967df365342f0011bd955c4f528900108335802f83324e1372d3c543b57", + "0x0a37a7bcfda3929816400d6da9e24be9f61eeb5980b66abb5305594525d0ce59", + "0x2887774ae0bcb8500de85edfb45e0d0152cef2ec95134c6a1a3e1c703ff97fa5", + "0x14a564157c4639b4283aecb8f7d728a01ca07af6b5c922fb2ee31af80ee46f8d", + "0x297b6714646992ee86bd665a07654aa49c5f090abd58268784f2f91859ee35e1", + "0x04059cb11550e2c49047a05f5c25dd13e78345cfd963a057bcac40a9c8b83da1", + "0x24a483b39d24ab055e3cf04456d72006d96cf9e0108b48a347f44b61f5ca7685", + "0x0d9f3d401f9d2adb26bc7c493eb7d8732ac8946babe7b3c83e563ab3d7bd20c9", + "0x2f2285de493b0cf6643169031a1b74ac8e809ca0f1f334cb841c7ce1d068da80", + "0x1b1e3c61b30e3b583a1b3bc0965b534a05ee56c36e301b141048e4585d6566ce", + "0x2c8bdbbf6c153ad461f429ddc6c3dca367e3348e9cb5234a32a3ab95d8d14788", + "0x2448b8629b8a188a745b9146dede4537d924e56ce5e47d022a91f9580064f9d9", + "0x21553b5f27c38563500c0d239b01f7655cf9b59699cabbfccc5281ebe47b5df2", + "0x2deb94006ca91c8ce3d0090d0473f531b4b3d675549e5c9f56e2629d4e4a83ba", + "0x262c69b259b25d4b8280c370f22377076d5f10c94f637902592c3d72ee721579", + "0x1ab36860b9be8f784cbdf88c7c357113ac573fee6c5a2912a006d0e92802853f", + "0x0f4aef840b0c4bf138700983bb3868fdf2492047aca1a856f7e98bea2bfb8bc6", + "0x2c771bb2fcd4a0c4c32129ae41236c3518acb4e8ca2c377054b28974ad27f277", + "0x1076ff6d5439acc86c81743a4afc840b52783572d63e0f806ab3b105392c064d", + "0x12a751cc203c990337f162dd88433b77e93ec66ac62d19438e3d2c5f8e140505", + "0x009af618fde42ffd69370d4b10381fb88a4a7289937fa8c2d4829668ece86d02", + "0x044f9a44db753321c604ddddbaf0d551dcab31237cc019ec3a497f71486dba6d", + "0x3053eea9d3d1adae32322b4027ad77fe062faeced6d26195d81066a86d801437", + "0x286a2e1e11c2fc1f2c92e6c3756403d96b8b1ffa1cbd900b8023266914d6c59c", + "0x24528098e994cb54e130389971491eda1ec75fc565691e42e389a1a9752b181d", + "0x142ecd9e65307df2247858c8e4dfdb967bef5638ee64530a6af65a4d0ca053b5", + "0x10ffbdbc2962d0ba3ede5d6e32429c70fcda9a2a0d1e73391cc4b09dfc619fc2", + "0x271f8791adc0e7849d618430c132e10e18da1ebb334b6328c59e74e11b944ae0", + "0x12976b85da48d33d4f474d7b43605613a5c5bb2ef66c3049ab51da046f923b53", + "0x104a950e669562a3da1d9790820f6a56d8422caa03ba7396568833a2e7c2af5d", + "0x20048f655b89f361aa91d7d0cdf6e0e276a099f008ffe9501e7f826b1d474f8d", + "0x204f493b3e2d2f8261bf56ee4a2608787809edc901d2e139df6be6308c40db09", + "0x08c9bbb8f9c24359690a1bc1378df6b732aeff87ae0d4012c9a1ddd31d6b3b4a", + "0x267c8fc553bd1ffedf114ad037508020d95e7ded62b2400adb65929eb97c60d9", + "0x16ed935a90a982e354b2a51cb8d544593abaa345edf8f6fdc07e4a39f9467c9e", + "0x247c6473d95d05265fc05023b65d8450a47af3d77e056d7b81ce953bbb6e2e1a" ] - hash = "0x1eabb66968894d3d2190f84f2c6b0b36642235e5163e4981f3edee6fed86a308" + hash = "0x261c6abffc4da04fb346aabc3b2f9769122c0ce56914e9ad95f1026c2c65bfdd" [inputs.avm_proof_data.public_inputs] -transaction_fee = "0x000000000000000000000000000000000000000000000000001057ce828b6df8" +transaction_fee = "0x000000000000000000000000000000000000000000000000001057d279f6f1a4" reverted = false [inputs.avm_proof_data.public_inputs.global_variables] chain_id = "0x0000000000000000000000000000000000000000000000000000000000007a69" version = "0x0000000000000000000000000000000000000000000000000000000000000001" - block_number = "0x000000000000000000000000000000000000000000000000000000000000000b" - slot_number = "0x0000000000000000000000000000000000000000000000000000000000000026" - timestamp = "0x00000000000000000000000000000000000000000000000000000000678ac07a" + block_number = "0x0000000000000000000000000000000000000000000000000000000000000008" + slot_number = "0x0000000000000000000000000000000000000000000000000000000000000015" + timestamp = "0x000000000000000000000000000000000000000000000000000000006788495c" [inputs.avm_proof_data.public_inputs.global_variables.coinbase] - inner = "0x00000000000000000000000017ad47b9f14dc201975cca47fea765e5d42f0b72" + inner = "0x0000000000000000000000007f3566e568179d1a145b3d9f81d9de12f4efb4ab" [inputs.avm_proof_data.public_inputs.global_variables.fee_recipient] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" [inputs.avm_proof_data.public_inputs.global_variables.gas_fees] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" - fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd0959c" + fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd3a502" [inputs.avm_proof_data.public_inputs.start_tree_snapshots.l1_to_l2_message_tree] root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6" -next_available_leaf_index = "0x00000000000000000000000000000000000000000000000000000000000000a0" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000070" [inputs.avm_proof_data.public_inputs.start_tree_snapshots.note_hash_tree] -root = "0x2da60f40a9ef5e4c47aca72c089ac5b94fdf0ca8508a087a870f6cf78be61ab0" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000340" +root = "0x056ca30ab1b6906ad9d426b78f692d9ac647b5f07c4369a226707ed7ec360888" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000280" [inputs.avm_proof_data.public_inputs.start_tree_snapshots.nullifier_tree] -root = "0x131203acd06b2aa044635e82926db8136be60f87105a5cd2ab3e3478f746e4fb" -next_available_leaf_index = "0x00000000000000000000000000000000000000000000000000000000000003c0" +root = "0x18ea098e0d64e5e63f40ff1a271bb52be59981b3bd0b1b1e93a4c7c50c9877b0" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000300" [inputs.avm_proof_data.public_inputs.start_tree_snapshots.public_data_tree] -root = "0x26a07a87a1e647dd19bbe8564b54cf38675311165bd5f0daf95794ee3a3b362f" +root = "0x0b76b6036daf5e3d44fdd8eae825b5177ea51a483d4f5e1d3be77b892c906504" next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000097" [inputs.avm_proof_data.public_inputs.start_gas_used] @@ -3543,7 +3543,7 @@ l2_gas = "0x00000000000000000000000000000000000000000000000000000000005b8d80" [inputs.avm_proof_data.public_inputs.gas_settings.max_fees_per_gas] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" -fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd0959c" +fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9be07ae8" [inputs.avm_proof_data.public_inputs.gas_settings.max_priority_fees_per_gas] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" @@ -3970,13 +3970,13 @@ fee_per_l2_gas = "0x000000000000000000000000000000000000000000000000000000000000 [[inputs.avm_proof_data.public_inputs.public_app_logic_call_requests]] is_static_call = false - args_hash = "0x1417dba875e97577c7611de470c195f6b66ab7ca8ae1d2624ff593d6355a7a11" + args_hash = "0x06dd605db0b3af21ea3ec0d331ca35002313410c19287a52d09b6a71939c5877" [inputs.avm_proof_data.public_inputs.public_app_logic_call_requests.msg_sender] - inner = "0x238db6644a299b7b33993c163a0b3f3f3aaeca32f9d0f9d0328c1615d7efb8a5" + inner = "0x1709ca99cef62ed7b9b94f09698c60d7bb915bfe1a39ca716e8c07dbb7f99d39" [inputs.avm_proof_data.public_inputs.public_app_logic_call_requests.contract_address] - inner = "0x1f3f85b45ea6c7be79b6e4948002182167732a202d83e1dba67b53f676583c83" + inner = "0x08177e32f37fe903867e601bb59d88f578087570b6a462e9f283b980b3fd3396" [inputs.avm_proof_data.public_inputs.public_app_logic_call_requests.function_selector] inner = "0x00000000000000000000000000000000000000000000000000000000d5441b0d" @@ -4475,7 +4475,7 @@ fee_per_l2_gas = "0x000000000000000000000000000000000000000000000000000000000000 "0x0000000000000000000000000000000000000000000000000000000000000000" ] nullifiers = [ - "0x25114218b4f6581154ab0fe36b0f00e2673087524aebcbf520264c658e19709e", + "0x040396fdcbfd0dddc55e7d1c96ba452b023472647a8504438098d4bd99e600eb", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -4853,18 +4853,18 @@ inner = "0x0000000000000000000000000000000000000000000000000000000000000000" [inputs.avm_proof_data.public_inputs.end_tree_snapshots.l1_to_l2_message_tree] root = "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6" -next_available_leaf_index = "0x00000000000000000000000000000000000000000000000000000000000000a0" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000070" [inputs.avm_proof_data.public_inputs.end_tree_snapshots.note_hash_tree] -root = "0x2da60f40a9ef5e4c47aca72c089ac5b94fdf0ca8508a087a870f6cf78be61ab0" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000380" +root = "0x056ca30ab1b6906ad9d426b78f692d9ac647b5f07c4369a226707ed7ec360888" +next_available_leaf_index = "0x00000000000000000000000000000000000000000000000000000000000002c0" [inputs.avm_proof_data.public_inputs.end_tree_snapshots.nullifier_tree] -root = "0x2cc27cfcfe9e60bf1bc9e3212a28070c4d996a984960f7606378e58a64ef58c6" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000400" +root = "0x2383abf2c7c0e28619a04f3b323ae5ef4ceceb7a263eddb72f0b5e9b292a4a96" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000340" [inputs.avm_proof_data.public_inputs.end_tree_snapshots.public_data_tree] -root = "0x249acb9798196b9577b04cc2e50a622c905187712d3f709cbbbcc19e5069bf54" +root = "0x078573b48988d9d29d2e54525b718d7e7d72c4f0657809a391b8dd79afb510e7" next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000097" [inputs.avm_proof_data.public_inputs.end_gas_used] @@ -4939,7 +4939,7 @@ next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000 "0x0000000000000000000000000000000000000000000000000000000000000000" ] nullifiers = [ - "0x25114218b4f6581154ab0fe36b0f00e2673087524aebcbf520264c658e19709e", + "0x040396fdcbfd0dddc55e7d1c96ba452b023472647a8504438098d4bd99e600eb", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -5093,85 +5093,181 @@ counter = "0x0000000000000000000000000000000000000000000000000000000000000000" [inputs.avm_proof_data.public_inputs.accumulated_data.l2_to_l1_msgs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" - -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" - [[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes]] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.log_hash] -value = "0x0000000000000000000000000000000000000000000000000000000000000000" -counter = "0x0000000000000000000000000000000000000000000000000000000000000000" -length = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] -[inputs.avm_proof_data.public_inputs.accumulated_data.unencrypted_logs_hashes.contract_address] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs]] +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.contract_address] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" +[inputs.avm_proof_data.public_inputs.accumulated_data.public_logs.log] +fields = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" +] + [[inputs.avm_proof_data.public_inputs.accumulated_data.public_data_writes]] - leaf_slot = "0x2f8385e78ace4abbc53c1bfbf40ef7715cd880840c847185777d88fca876a219" - value = "0x0000000000000000000000000000000000000000000000000000000000001c20" + leaf_slot = "0x12ad17af8a38f05e90ea0bc5763b218de1af0dd7e560f9f89bdf547f54021770" + value = "0x0000000000000000000000000000000000000000000000000000000000001f40" [[inputs.avm_proof_data.public_inputs.accumulated_data.public_data_writes]] - leaf_slot = "0x0f357862441fae6179c82cce01aa0db970a894ddacc647bc736ddb7c39c7cf07" - value = "0x0000000000000000000000000000000000000000000000000000000000000af0" + leaf_slot = "0x2c63ea85756369773789f2b69553411d0380416053ff57588301d2ee56bbe778" + value = "0x00000000000000000000000000000000000000000000000000000000000007d0" [[inputs.avm_proof_data.public_inputs.accumulated_data.public_data_writes]] leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" @@ -9582,115 +9678,115 @@ fields = [ [inputs.avm_proof_data.vk_data] vk_index = "0x0000000000000000000000000000000000000000000000000000000000000005" vk_path = [ - "0x17b251cff9b750d9d4c87bcc4b9ef84a2f85ab7486cf17129bd3e7ead90394f7", - "0x1c05dc5d161ea24cab9cfe0b25104cc245a1a3dc5781c35f4dc7da7abf056629", - "0x29948c9ec655993f09495cf6efa2c4f95db2e7e2e7a338ffba4777209340c832", - "0x2c8b742477af94eb3d371b8aeef0f9a8d930466cfe240ca1b7c504b0b4492d22", + "0x1b6a6b12cc77facce066474069e4eca636cadadd5d8c892cc883f32aace95b1f", + "0x2f0277c34cb53036f76ac453e6a1df26d408fbb0dab1f01e4ed7442ea91905b9", + "0x2a1d8715fadb132857d65d080f973beed888cdff6ded60bef97ea97afcd69013", + "0x18e0298fd3f6bf4fcf17a2072d7082b36aa1d05d11189235ead00e2c75635db5", "0x126bb13ce4b07681f511f3a23d88cb7cfe082a76730abd5b4be5c4da3b5c51fb", "0x050dc6390aace9c6e873b762c65e7d6a21e78e64e5ad6cc7c8fd5e69315ab5fe" ] [inputs.avm_proof_data.vk_data.vk] key = [ - "0x2d3ca6414aaff508686f12adc64a6eef95db1ec05a9685106241fc08ae4ceb58", - "0x1dd5a0331ae1ee0c5159c257b5a50ba048a629aaf92fb9924eafb17cc65ffc35", - "0x243d13a4ec5e0c1a1e7867ed26815c14203b6bb5b7b678823e76950b5990a143", - "0x294ce6215ac17666059ff568ae975fc8572f4c84571e1d86e17f54c7a87e5a7b", - "0x276c8f3bbcbafa886286bef2516d3c35ce38574d61e328082c784eccbdfc7b49", - "0x1f06386e009cb413671937e8ec50149723bec6a0eec130909d008b776fbf4d78", - "0x00ed49f139f920df7b0561ad0b3da6da6c7e3edacc9bf94634e19a79aef6aa34", - "0x16ad0b175ae0851c88bcae7f9afb524ea6454cd3d099102e5f2fb7f641db1371", - "0x25c2265efb170c48fce46c5c7dfb3b1d044400694857168c209afab16c06bb9c", - "0x06f2cb6f6b6a3ee34e3f9cd777a7a798eb0d7c0939e9c8a0b6fd299fc88d2e61", - "0x1aca00cde7f9797178b2bc11a3e9357e9eff887f5ddece80dd4c4992717f587d", - "0x01d15ca81a5b7f17c86e959b3269ead49483411515df7eb8f5da8e0458b2e597", - "0x16addafc044222fdc5a2f8c39781733afc156a46d4eee694a7ea715e62b56670", - "0x07abdd9e71cf1a0818fa7571e0e4fd1482fba0e68a39bc0706a317d742700260", - "0x057f3ccaf700ef0d9a4eba94566b732f4808eaa1a5db71c2b15dc5c52735d8b5", - "0x1990b2e94edc6c155f84e1d6ae586b84f8ee2a803c89574825e977476b5a5c5c", - "0x0e8b955cec332c82dcb16012ebea8641ff3e807981c3c39a71464d2d94e02028", - "0x16dca52c6babe42484c999d780439527de30c2b9f82943f4b8cea573511b3da1", - "0x042f01811e4f40316ada58a49b13c38ed0a44cff519a30377d4c5a7bc417c440", - "0x030f5fbf90b39b87402f8febf336e811562465b824c4d6160e77427cc84d2265", - "0x1635eda784d5c9236c8db964acf119214ccf765704056af70ef4ba1285a7574e", - "0x05cba9590fab41b0af5eadcbcc34842e16dc42700bb8f17b8beb508f238e4154", - "0x1556fc97dca79598152112214fec9e11e9f16ab8615edc5728170a2ebb1347be", - "0x201ed47763d989047bdf54f5da84abb2089fdacab6c03182e1126d8f7b1088b1", - "0x25f09658ed032a76b0939c2a1f63eaef0a7c41293b484f2fe28b83418f8a678e", - "0x0e224a637cbd4cb6ead95b427f78dd1442066261e6c74f018b6f122c4e00ea28", - "0x17ac2169ae1fe84a864dbdf5d91016a830915c9ef91ada258aa46f5f57897a3f", - "0x009d86b9cef76329b3b4dac4442eb25e7721f80a3cd895a72f34881d2e348dc8", - "0x095a914037e8b66fa988b2d796c559a6dcba0fe365fc392a97e9f7d621f4af39", - "0x1289cad89ec3a0676c0768e2ba2e29600d91deea95718e81cd1c3b4087c4d852", - "0x237df16d4582c9e1c01f35ef18e6f889a41336a8ca44ccec073cd0ccd35cc793", - "0x2fb4b116ef62d595058452cc1cc6eea0197fecd27cd55daa9452493fe9864281", - "0x2165757e9459bb23513d097680b6a302376a0db512f2b4f0568d781ee3e1a20b", - "0x0e0c2c59ba6b011b92eef4752610bcdae1862d35f8f59e679e5427b829afcd8b", - "0x2a68422f1b2876b87a98cdf1f77413eb37adfc2373977baa024c7f29596159a4", - "0x02453bc976b1ece0a8ead88e60bcee8d4d393eb8e204ab79ace58e654e748638", - "0x0b64a61212e3239ed1b7574432def381de0fed3081a411c172941e86bd42b25d", - "0x04d9bd0701d55ea64fc226c3442da6b658e378676885ddfec326d78d345c322e", - "0x178db9a01549eec7529e6111d585b50545e07733605580484afe43b62a97cd5f", - "0x2a9acdf9dc041f79f3cf4306ab0fa9ef9ffc2de88792aba120a5f3c2557b8046", - "0x0977b57c102356cb0887d98d3ece6cf9426db32525293059c842b0f689de3a2d", - "0x251e142fd8fafb852a5feb9a7625cc41d555d2750f3f516a69c35baecb272e0c", - "0x29a6a49e3f12d6563a8dad273cdf98b62e86dc925f054ab5cbd1d25ebad5f06d", - "0x1c5c2d1be2dbfb0ffc90813ba046d160a01c4c155033a77f530b64b5cd80283c", - "0x1588d837c195c131d25dae4d72b17be5be9a788b8b64122c1fb6b427d75773f1", - "0x24b01f3b5b5f5322f927e90c60e28d9cef5a69c8b5ce816ccd6f46faa74c3f2e", - "0x159b9958c8beafcea5507142194ca7e06c85d8edbb84dbeee2051d15b0923d3f", - "0x16bc6a44ea6d2f0f1c35c8c899b930b63a2b5e6a1055af14a7a2218a5e4cff5a", - "0x081a40dac0ba2905b42f63f03ad93eae18163ccb943dc669344ceac26f9575f9", - "0x0ef3f6f6dd86abac0b89eb5e5ead1758d87e3c21bfd09d87acb2766f0ecf69a1", - "0x21dfcabe38ea1bf53182d99ae6d7cb87e540a9d15848c0d8a6c86a91372a91b4", - "0x2ac7b90ae5830a8ba42eca7c51330bbb5dbc3ce86c5e027ab47065545928d456", - "0x19a1d03e6c7ba4d8b9552d4a114dd79d266e63f14982c744940819005599935e", - "0x21897c8f645fb5d19dbbf8343d3a68797cdca628b64048f1d94ce22639f38c10", - "0x093c5f0a8eed767e8b3e1ba748de039efc7016efe80d8bad79cd8a276110342b", - "0x20138d0b29a67c057e8359106066b75385daf45a7778508a79593ed02cac73aa", - "0x1ca1f2e9a9a28bcc0a6d786c1e380655db9a8fa04255c5863b451f2bb4496199", - "0x2cb11b0148b6ac22f20659d2d93d8f02c019e8253aa3fa9d79be92dea0baad8f", - "0x1cfe9cc006d80e3d1ed19b1dc1cfb29d97c5bcef7e5b64c620d56d2f24a43ffe", - "0x2e38b93463e06b4374080583d54da6c2023e8ac6e0f47f9d2ca7816174869863", - "0x17e414acde9261ed51e826ee772c1e5e214ce58493a39af3409a7b9adcba0114", - "0x271eb98e8ab8964131c693534ad413354fa59eb82fe9442e358965bbdf69348a", - "0x28a4d8394ca140a516e2f9312615638aaece3ce9066bf7fbc4c77cf373323b76", - "0x078b576e3742ec9d9e34efdabdec0a043142663fea7cdc99a2310d99efd35306", - "0x1f45b850677e6d8b55e311edf6037210dafa6c3a769596797d6afd72f297bbed", - "0x175884c6ff48110e2bc62cac532c5baa5a138429ef5b0ec786aed58be36eb0f8", - "0x04104fdf07c29dfe79631228aa9bb03a8ccfd86f4e84f5a1ae82d84ce05926e4", - "0x1186ae1943803e8ec155fdb91ac33064513aba01a2b35dbd7894c6b41f6429d9", - "0x2750c3d313a642071f798c85f8ae87836dd03b0a702499824a10a70c9991b984", - "0x185b6dd9c6d7138c241a83c803ad7c22884dcf6b8f28c7a1da8c854560b5b7b4", - "0x2b214842010d42555d6a67727067b2e502448f80420cc1c4fcf6379ef6c48c88", - "0x1af1c66b438f5f50b822fb0e6e42162d553279a72f5deea89c6dd9b01a94285b", - "0x22178c6413e0e86329d229fb1a2af9eb6d5a48ee9d6cbddf03cfd05b04161734", - "0x027e424fc31dfa11fdc26ea90234e269ba42d08eed689de332b023ecf468860c", - "0x0477535d7798a3c6bfa4c586ce23457a532ccff311834c658ad44bef7b189ccb", - "0x0a112f0f6420def1f74449bd6459dbc3e8a62488fa57d81219eec44427fb2864", - "0x0b36bbfefd70305159c214d220114a21384578e067ab9741d37479276392bfa7", - "0x218c9c333ba9d1c782df3fa3481b23efb3fe8db06526fdaf0adf2c54b0b776b0", - "0x027dda74e6edffc463600ef9d114e7abd7c5be33a5d34d4bf1193d647b3ed242", - "0x135ca23cd7fb49ed95ca7135a2b13f053d4f8d643f5dcc524779d3769c296e1a", - "0x19624a452ab6988efbcea48e7cbb9e1b14827d38028718b4cbcffde6654c69bd", - "0x2c60b2a6128cf8f76d3c0e15d0bed830a5fe44587bb88664c9e34d4ab8017a1a", - "0x2a6fed6db9dc5ceaf3614b360fb8db59c94420e8b219f2402b54af1dacb8a1e8", - "0x1237359ef73003a04f18ac42951ac95fbf7aaa5ab4c09eb22072ef4f13a0c388", - "0x1d4a3b0b7f1cb9d4f5a0be75a8689319e7319d6bf54c125e04fea3e6dc33aef4", - "0x12cfbb155bdfb9c726102ff17b0499bd3c7616bb0af3df96c468cca2953cc663" + "0x0cc8e5a76ff899ca9bc72679a935bf3bd7a3a86f3b400879e64911f52e7822ea", + "0x2ff2342711cb975b785784818ee476c6d1ffe2a4b05fc2b334049909fa99172e", + "0x0fab3a958a2d10924cb172af183e153d98b63c8e16d77efa95dd67afb84b4593", + "0x119547a14bc23b53dfe01867b667f72edd87ca60f51c7e2fe1ae11763799c950", + "0x14bc6e4a290f6807777c36e7268e0a553455b388fbcc64756566a5f90af74ab9", + "0x1023dab9bad68e39426d84d01fee41a44c1f0318bbd2e2fe075ac2462465bec9", + "0x2bbd69dbfd6463075fd06482454b52af18747dfe0381e1bc568f33e6536187a9", + "0x1c4829d7c16128cb7a0479a2ff14c5deb52e06a44184d3bc052936019adec8b1", + "0x2dc1b7a6912db9bbc202f6d5bfba94bbf0fb57381c9af0a82091b2b3a8335583", + "0x2f5b019c02636a1f2aab1be232768f8d2f1e9e3d7caaa172c4b2ed3ee46b01c0", + "0x1f23dd8fe7a9307ace3c6c5c8579006964a1b9c7e45d627b67470e6d39de4be9", + "0x24be596a5333b3ce0bfb64c695469ad2334532b051b9ab0b7293fa0590bb2b50", + "0x111848d48434189cec2c5f4cfbef054e519c9b6cc9b68c856863e6a8d93f3e70", + "0x1e1dd1d99535f8fb4bd7b6141204658ac03fc00ae8d01ecdc8e00508206c1062", + "0x08b56bb7da67ee509e39e85aaf2a4bd5933a541ede9cb5c9682884fc5a25d0b7", + "0x2d3f99ff8cf0567527252cb9fadd7aceeb08e4afa67186b95a2a87a03f9108f1", + "0x255e4a4044a91b7cfe2d075147f80995e144492dd98ef9381f7374f6e0267266", + "0x1fb7a021f4ad385b85135d916d46d1c9a876913546f7e48650b874e53347fe9e", + "0x1ac62e52e97656780a185fbb5ca5aba699057c2cc8e0f9e1824905893d64e525", + "0x032bd443b8bd29e083e1bbeb27d1df74f07c7a0ddf1fdcd0ae721ad9edef1371", + "0x1923973fee7b0fefa54d91753845f9515da272ddeff01e01a358172c19654558", + "0x13053bc6e7388b2680431b490ff6c82a020b5402b8adbca5ff17536b7bdf8986", + "0x1b70ea28bb2005d6a614cc0fa31fd8ab4dbdb2234cb1fcd1306ec6d4baf90d6f", + "0x28d63ddcdfcac8118c61a81856c411f91e7c55ab8279fac8bf23d4377b53be8a", + "0x226a0022be55d9e558d0fdd60017979ddac0d9a5d51f2d80e55dcb21e7ed5185", + "0x101e78aec83b15f871e0841445a543044cc7fca7a50b79d144a8274785f9641e", + "0x2142eb325c02c87f5eaed910095d3f1ca6b7eabe0cd14536584501e98b25ba14", + "0x2ca03b8917ce345b433c03c53eb55cdeda364d18e5f9b5e7aff218a7f11c4bc8", + "0x05ea6d9aae4ada0d8530337ed2e3a41d103659646b76a7be80f548664f51c7b1", + "0x09b03860f1f187ef8b96c691d4f128ca990aee90b3b8ad598ab10a08a366c14e", + "0x2190d99fc9f81bba1d975a6edc65781970ee6e3013d51ccaa0d06f2c7300c534", + "0x1db3bfdaa46745b14d6ceb9d70a527b8d193a6f582e5690afc8d93711d64bbf3", + "0x13423ca166149fdf2545e4bf70da6dfb1beac8dea212d630613514fee945196a", + "0x10370911421dc1168d958554dd5b7e753ea80f08984a09e6f82c573e1f4918cc", + "0x1fdda227f7877ab5573333d39d1728a5fbfe9844346540abe5beca0206e7f3aa", + "0x1dfbaa8c2adb53b712f14d912a8ab158c6c43ffd009e4c71cfc88a83cf32787e", + "0x03ffde8b3bfec49287bff716ad43747d3f4229cd6a15e23c80dc0cb610c3413b", + "0x2263776d9d7ca4aeb7b324210c8a1aeb6e312693d4a4533899149132835cc81c", + "0x19f05665ef19e92c9c24a68b3cf60329db85e88032e101289a4f1aca0b5cc64c", + "0x061b5b3469ac6859763f7b5a6cac450bbe5c25d2adbdb416a698cc0da60aed9e", + "0x302bd88507ea94d5789df29c2bad84a999e6a37794aaf209aa0de3e91dc2034c", + "0x25b605d6790a51a417418adf23420b6610cd19db005199ea4a4c58ead6cfcb6c", + "0x0a38a8618e8af990f0d9bf816681ac23a26af1fd134cd2b262c9da9be26cd0ed", + "0x2512eca30adc84ce48a198c6b337eaa901e272509181e27a64aa9158a1f0926e", + "0x0da4b7447b8210d4136ff35d7e094700f0a1add00dd0afe44f0880cee4714573", + "0x1af36f48e68d41ad8c3d87a6bbc35894ce5bd84d1311c52df959975908264de6", + "0x18280a6ffa972193fbf10c3905e14a2e4b6e9d82b6037ad2f880d575efd3e84d", + "0x2463b02da9ee0c8fedbd42afa4a7544dfb4c58ad0cf70b66d71e64c77c1b1065", + "0x2a415cd15d951294db8e737933485326487de57218a4e63722fcc60af41c81d4", + "0x28a3bd36f30a63536ab8c1bd101d63c62979ceca0490e3db028611b45d984ca8", + "0x237f4e769ab34a0eebc5c90acf64855073b6a38364974d8a393ab89d3f02a601", + "0x046256f7e5d661e9c96c1ab9ea552aba4e22511d52ab3fb22e7760f5addc8e29", + "0x170ceddcfe4b88d6e6a8b7d509e2451b77c30d14d375b623573d901a7d556b01", + "0x060b1adaee1057c85b386cf1feaceb24c2c67b173889128e5bcd3c2128d71d42", + "0x2b1b799934ffe55adfee8c0e62ea0ebc022b225f76bf6b2228f165cc40810db5", + "0x264703c72b96e07373b4495693ccdce7fd955997d86285d4cf059f5b91e51551", + "0x19fcbf07b26ab5a2d9ae5b0f4ede219732b380082639de4dc8b3b888487f01a1", + "0x1a46997aecf662b6c00ff9962f214917cf8e50bef1fa30db53f520c98cf00536", + "0x08356705c226f57753194edb0e804f2ec2d5b190597f9e05cfc22d804074a9ef", + "0x1aff9ca30708fd4574cb59826a749ae555bb59220e138bfb3e1a69d99144946e", + "0x0456e47e7ddacc871101f0b30be54f1c52f085948e275ae42f138d1305361df3", + "0x2a676b6618dfbb61079ffae210b2b8e0bfcdb9543ed8df345fc3dc22b7d67ce1", + "0x0f007b229d2b96b4338db8b75f5e3296dfa5567ae2cc5243fc8bc15b26fd7b33", + "0x1872635239d42659858979c541af41f5d3a784a744ec33f0acb44bd82429da6e", + "0x07cd564339b31d6228852ec9152757d6848d72e75e087801c3d57981f23a31ba", + "0x2cf626793b51bf09416076f90ab55c267e1da7f06cc31857d7d77f4d30e407a6", + "0x2224130f6ee0df2f46ef615bcbc0509eb100fcc1fac9626c867a5f4bd907f69f", + "0x2d767962be73a78674a60185873c8a762aa2d041407d1eb1ea6f1bd73506ea34", + "0x16e27c15f85cfe19fc10a161fd2e48ef461252813d8153f2da8f01ec0c7820e7", + "0x2c0cb892b278887da2e3f062422ac9c177d632b5b6be249393e4f2bbfb61e5e6", + "0x22a2cbde167898aa1edd77109b6e654269ec46f70ca8b83e57bbf9e1e9eeca6c", + "0x02968e72590f90b21d2695104c48edb3fe7a217cf5a3fa82724b12aa035abea6", + "0x0bac9c75179de6d28a459b64ec6253a68890baf03fd8501d26f59e466464b541", + "0x1037bd2c80982b7c15354cc85a51441e0bae25a3b0f5b38f9b24e0bb8d30ff5d", + "0x12c6b0e0b8f09a296fd495a886981a33ded171d1bacae2638f087306e887d573", + "0x18167507f28a3d3dbc9d74a4ef1492c8b436c8832667a270d0efaa537fe276d6", + "0x2a0b11de7d3cbb5e67419590349c0ee8c141f447c61eef2158ed7880291ff897", + "0x251757a32978ce5f8c5fcad0c3f6f2d872cd30be6fb0578a3d52671d23d24433", + "0x01e85d0845754d0f4272a8e20577bf56405f30a5a544bf952684aaaf71b5d975", + "0x2b34818b87aace57c2953c9b4b8b5a120ef144dde7fb6bfc9f3f1737c64e82e1", + "0x03327834459cd3fae72937e3a48d1d54c373c18ce59733138f9b53739b34683c", + "0x2f8da6bd261dc9d0fe7e6937dcce7861f706e5e3e84f179bbcaf2bb5dfe15c1c", + "0x1a469e54743b46a1a9443d8906119e76503ad65fe64573f1017e74f0593118b2", + "0x1fcf0ea8bae6a8a3f5225c9c9ec0a4a4e5fe0cafc0ca68d33e79399eef164dff", + "0x00ec55620462f539077a9017c8859e82327f3d76b29abc2859fd077299e02c9a", + "0x00175734c4a8a10a453f0ba1dbca0e4d7c99ef6dc3190471c88e3d08bca94872" ] - hash = "0x1bda2aa33ce414576cc9ef41f23b3a0f421f4a1f53feb4de0435507e40f49f1a" + hash = "0x2df14edfe4cb500fd1838a13b46d166b7ac1eb91d0f3cd51986d08206c4e0751" [inputs.start.note_hash_tree] -root = "0x2da60f40a9ef5e4c47aca72c089ac5b94fdf0ca8508a087a870f6cf78be61ab0" -next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000340" +root = "0x056ca30ab1b6906ad9d426b78f692d9ac647b5f07c4369a226707ed7ec360888" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000280" [inputs.start.nullifier_tree] -root = "0x131203acd06b2aa044635e82926db8136be60f87105a5cd2ab3e3478f746e4fb" -next_available_leaf_index = "0x00000000000000000000000000000000000000000000000000000000000003c0" +root = "0x18ea098e0d64e5e63f40ff1a271bb52be59981b3bd0b1b1e93a4c7c50c9877b0" +next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000300" [inputs.start.public_data_tree] -root = "0x26a07a87a1e647dd19bbe8564b54cf38675311165bd5f0daf95794ee3a3b362f" +root = "0x0b76b6036daf5e3d44fdd8eae825b5177ea51a483d4f5e1d3be77b892c906504" next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000097" [inputs.start_sponge_blob] @@ -9714,7 +9810,7 @@ expected_fields = "0x00000000000000000000000000000000000000000000000000000000000 [inputs.state_diff_hints] sorted_nullifiers = [ - "0x25114218b4f6581154ab0fe36b0f00e2673087524aebcbf520264c658e19709e", + "0x040396fdcbfd0dddc55e7d1c96ba452b023472647a8504438098d4bd99e600eb", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -9847,9 +9943,9 @@ sorted_nullifier_indexes = [ ] note_hash_subtree_sibling_path = [ "0x01c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76", - "0x2d78ed82f93b61ba718b17c2dfe5b52375b4d37cbbed6f1fc98b47614b0cf21b", - "0x07c98f46a1b09569547657a89851f2b21e85eb3397e6b38f445476be6a4e8fd7", - "0x2808a667d2e7759fd284cb5dcc74819ddce7465d1b3862c2bd75a18a1623911b", + "0x2ad7d6937411adb3ba77e69b0ba4353e6ec7b9ab800c3a5f7b5a18f845830f58", + "0x067243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1", + "0x0c51fb841ad70f4ce99e3d92a5491de2e5cabc0a2f94951cad51f41d08444710", "0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686", "0x0f320b0703439a8114f81593de99cd0b8f3b9bf854601abb5b2ea0e8a3dda4a7", "0x0d07f6e7a8a0e9199d6d92801fff867002ff5b4808962f9da2ba5ce1bdd26a73", @@ -9882,10 +9978,10 @@ note_hash_subtree_sibling_path = [ "0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6" ] nullifier_subtree_sibling_path = [ - "0x2db0d201470e5a2d3938eb9dd607400190ab93c93f6f4bd9559f6aa1de4775d9", - "0x14e9a69853dc2f1c59571067a6392d4825235b19227e316c4352aa8ec583fe77", - "0x2e3f737e1f96fbda4b3bce4f0898dcc4b7dc999540d79246d8d60b3315023741", - "0x10ee5b4c7f7d4a3ed023d9149925ab4e3dd432b089e62f4cdb67a998eb2f11fb", + "0x01c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76", + "0x2d78ed82f93b61ba718b17c2dfe5b52375b4d37cbbed6f1fc98b47614b0cf21b", + "0x0a0fb685a3dbd49fe4a5a35c35bd2669f5d81c268a9bdc6b64e3375d01d5953c", + "0x1d22424e0480355cc461cc8e3600c982c31e82b92930a2a60f6ea7d1bbb64d17", "0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686", "0x0f320b0703439a8114f81593de99cd0b8f3b9bf854601abb5b2ea0e8a3dda4a7", "0x0d07f6e7a8a0e9199d6d92801fff867002ff5b4808962f9da2ba5ce1bdd26a73", @@ -12609,9 +12705,9 @@ public_data_tree_sibling_paths = [ ] [[inputs.state_diff_hints.nullifier_predecessor_preimages]] - nullifier = "0x241c57d7380a9bf497314b53ee8d437ccce4947d81c0af799bcaa15e3af1b5f1" - next_nullifier = "0x26504d8b41bb532e2cba8230215b27d85f59d116da4d32f18443431df90a33bf" - next_index = "0x0000000000000000000000000000000000000000000000000000000000000141" + nullifier = "0x021e8d1e6a2000176f32501470ae610e91e4fc6b91eb85c6fde5e36952546370" + next_nullifier = "0x08a1df051f7fdae813d58ede99af2ec8a1e34803e4c26ab1600559df2594ecec" + next_index = "0x00000000000000000000000000000000000000000000000000000000000000c1" [[inputs.state_diff_hints.nullifier_predecessor_preimages]] nullifier = "0x0000000000000000000000000000000000000000000000000000000000000000" @@ -12929,7 +13025,7 @@ public_data_tree_sibling_paths = [ next_index = "0x0000000000000000000000000000000000000000000000000000000000000000" [[inputs.state_diff_hints.nullifier_predecessor_membership_witnesses]] - leaf_index = "832" + leaf_index = "576" sibling_path = [ "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0b63a53787021a4a962a452c2921b3663aff1ffd8d5510540f8e659e782956f1", @@ -12937,10 +13033,10 @@ public_data_tree_sibling_paths = [ "0x21f9172d72fdcdafc312eee05cf5092980dda821da5b760a9fb8dbdf607c8a20", "0x2373ea368857ec7af97e7b470d705848e2bf93ed7bef142a490f2119bcf82d8e", "0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf", - "0x1dbf60317e0f4cb2b00dab0e9a3b844b47fa086e4b07bc3b8eeb8344454206e0", - "0x24405c6f455180b6e3dcd9484d97b4bccb61adec42bcd1a50d19930148c9416c", - "0x2e3f737e1f96fbda4b3bce4f0898dcc4b7dc999540d79246d8d60b3315023741", - "0x10ee5b4c7f7d4a3ed023d9149925ab4e3dd432b089e62f4cdb67a998eb2f11fb", + "0x0e872bb58eba8f3795d06bc53a7f4f19b904658e3a5fbd5eb35a3dce7bb41669", + "0x11b036eec5b39fe3f05288a9df9db6430c5ea5d1a5f2de112e6ba09f6627b1aa", + "0x067243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1", + "0x1d22424e0480355cc461cc8e3600c982c31e82b92930a2a60f6ea7d1bbb64d17", "0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686", "0x0f320b0703439a8114f81593de99cd0b8f3b9bf854601abb5b2ea0e8a3dda4a7", "0x0d07f6e7a8a0e9199d6d92801fff867002ff5b4808962f9da2ba5ce1bdd26a73", @@ -15809,16 +15905,16 @@ public_data_tree_sibling_paths = [ ] [[inputs.state_diff_hints.low_public_data_writes_preimages]] - slot = "0x2f8385e78ace4abbc53c1bfbf40ef7715cd880840c847185777d88fca876a219" - value = "0x0000000000000000000000000000000000000000000000000000000000001fa4" - next_slot = "0x2f9b1ce749ed119d6f0b62b72a39fa93e164a82c2503ef4741638cd44a7ec5c8" - next_index = "0x0000000000000000000000000000000000000000000000000000000000000090" + slot = "0x12ad17af8a38f05e90ea0bc5763b218de1af0dd7e560f9f89bdf547f54021770" + value = "0x0000000000000000000000000000000000000000000000000000000000002328" + next_slot = "0x14767c960c38cb153d720187942e7928268896f5ff3a539bcc854e5ee17cf27c" + next_index = "0x0000000000000000000000000000000000000000000000000000000000000087" [[inputs.state_diff_hints.low_public_data_writes_preimages]] - slot = "0x0f357862441fae6179c82cce01aa0db970a894ddacc647bc736ddb7c39c7cf07" - value = "0x000000000000000000000000000000000000000000000000000000000000076c" - next_slot = "0x0fefcd4bb173774ae6f0f8eae2b9fe2bb41798a660d0c69740cb1570afecd5b3" - next_index = "0x000000000000000000000000000000000000000000000000000000000000008b" + slot = "0x2c63ea85756369773789f2b69553411d0380416053ff57588301d2ee56bbe778" + value = "0x00000000000000000000000000000000000000000000000000000000000003e8" + next_slot = "0x2e084a6aadebb0d5276b4231c9f98db307a8b2af3998e2b9c655853afce090a4" + next_index = "0x000000000000000000000000000000000000000000000000000000000000008d" [[inputs.state_diff_hints.low_public_data_writes_preimages]] slot = "0x0000000000000000000000000000000000000000000000000000000000000000" @@ -16195,14 +16291,14 @@ public_data_tree_sibling_paths = [ [[inputs.state_diff_hints.low_public_data_writes_witnesses]] leaf_index = "136" sibling_path = [ - "0x170c1fa8afb2e161f87af67655946dcbfb1547791656b59eb13ac918b81e3132", - "0x1d5b41cc9ed7a46cc703aea0ca99c2e786d25ea942046b1b7046d5481c8a377a", - "0x29c147a74c7f99998c309d95b03d8ba84be1ecc275cb1fa6564bc4c8b4c72772", - "0x2ff8d7ffd6c933b1a18f79d90cfecdc3cf2504823519f29c98ca4b1d5af67517", - "0x18cb7601e0086c856969f3bd7eb0cc01df85ae48659028294f095dcba98da109", + "0x2db362cbdff0d0699d70b03a172312cf00f2a5d32c2bba8a0f217256f6d47506", + "0x0c2dd9098a8a65d6b72020bfeb8c045018839d7767fe27d921872be4332cdb58", + "0x0decf0c47e417d14d637698783006a4ba82aeabdbc2235937297dd9200af326f", + "0x07d6f32e6444d7ba46c3d5a4693453fd1659b4908198b7541bf087460082ec36", + "0x0b918bd4d3781b9219a3d33fe0363eab6a7bfb361cb2c2094cd87eb188114847", "0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf", "0x01c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76", - "0x1fa1bfa71554795b73d5ad1b4b53068958a6701ce6376f7df5214d9e6d1bdaca", + "0x28e791da5fd9e1db9304b1d9acb98d4c1577d41117b204e049ccc7bee635847f", "0x067243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1", "0x1849b85f3c693693e732dfc4577217acc18295193bede09ce8b97ad910310972", "0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686", @@ -16241,13 +16337,13 @@ public_data_tree_sibling_paths = [ leaf_index = "150" sibling_path = [ "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x288fece8c5e9d3852869d2fb7ed922f2eab11d5516dbe73426ea63dc6048c8bc", - "0x2c3f40c21bd62e902be503a7e8757f8e42f82338a5dac2ad8050908cba877f0e", + "0x1cb94e72b49625f6e071cbe836b308ce051804bf56d7d3288349770314d30e33", + "0x118f2584cd5be1fde22874dca4c9368a68d875fbefc63dc6e5492107a9692e4b", "0x21f9172d72fdcdafc312eee05cf5092980dda821da5b760a9fb8dbdf607c8a20", - "0x02aa52cbfbcfb1e75324a377d2eca725ec04f0f8202bffd3bb2ac271f5ca36c8", + "0x2489d21ac0f8bde63395da67f64c76e60352bb6498cf84bb577cde4eedb4b209", "0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf", "0x01c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76", - "0x1fa1bfa71554795b73d5ad1b4b53068958a6701ce6376f7df5214d9e6d1bdaca", + "0x28e791da5fd9e1db9304b1d9acb98d4c1577d41117b204e049ccc7bee635847f", "0x067243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1", "0x1849b85f3c693693e732dfc4577217acc18295193bede09ce8b97ad910310972", "0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686", @@ -19073,12 +19169,12 @@ public_data_tree_sibling_paths = [ ] [inputs.archive_root_membership_witness] -leaf_index = "8" +leaf_index = "5" sibling_path = [ - "0x190e7dc0a4fcb9c317c351190ee064f5cd8a5f575da0377390f8add3c5d5d4d9", - "0x0186a873772f6337a7539a2062dd2e501cf9a991df463cee3e9e068fe8058d98", - "0x0e34ac2c09f45a503d2908bcb12f1cbae5fa4065759c88d501c097506a8b2290", - "0x1cbbb3258721361f03964fdb821edaab3a5c2cb609ddee8e0668b04af5562206", + "0x07530f21b1b32d696b7639c2e9605ca262cae8a348251ee468008b0b88de9f0b", + "0x164ce14a0c70e941b0340a4593f324b17dbfb33052bd4720fb724f0328cf936a", + "0x1cfdef454315ecedac57329e1764e464d640c31f82d6d3c76991701a53b4a3d2", + "0x21f9172d72fdcdafc312eee05cf5092980dda821da5b760a9fb8dbdf607c8a20", "0x2373ea368857ec7af97e7b470d705848e2bf93ed7bef142a490f2119bcf82d8e", "0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf", "0x01c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76", @@ -19107,26 +19203,26 @@ sibling_path = [ ] [inputs.constants] -vk_tree_root = "0x130ae70545763dadb59caeb820400cffc41df59bcc2b8731917644f247717686" -protocol_contract_tree_root = "0x2f9edcbdd0cfc67764aa32cdef9ea44f2914b44bfd9cf77d518a5ac172e7f9e4" +vk_tree_root = "0x017fe601803e9cd0f1cdb04b5e585733948868629e9266c3097e47d0dba5e232" +protocol_contract_tree_root = "0x2e1f56195ba674b50fbc37b7663e60f0b4b17087e471c3ffce1e347bb820ef31" [inputs.constants.last_archive] - root = "0x1f2b5d6be05472c95d11b367ea0597914f71b480fe3eb93b1beaffd9b65ed6d1" - next_available_leaf_index = "0x000000000000000000000000000000000000000000000000000000000000000b" + root = "0x13b0813d5c178ae2f5856ea42f3ab0094c933f88c5a864dcad13fe78a24426c3" + next_available_leaf_index = "0x0000000000000000000000000000000000000000000000000000000000000008" [inputs.constants.global_variables] chain_id = "0x0000000000000000000000000000000000000000000000000000000000007a69" version = "0x0000000000000000000000000000000000000000000000000000000000000001" - block_number = "0x000000000000000000000000000000000000000000000000000000000000000b" - slot_number = "0x0000000000000000000000000000000000000000000000000000000000000026" - timestamp = "0x00000000000000000000000000000000000000000000000000000000678ac07a" + block_number = "0x0000000000000000000000000000000000000000000000000000000000000008" + slot_number = "0x0000000000000000000000000000000000000000000000000000000000000015" + timestamp = "0x000000000000000000000000000000000000000000000000000000006788495c" [inputs.constants.global_variables.coinbase] - inner = "0x00000000000000000000000017ad47b9f14dc201975cca47fea765e5d42f0b72" + inner = "0x0000000000000000000000007f3566e568179d1a145b3d9f81d9de12f4efb4ab" [inputs.constants.global_variables.fee_recipient] inner = "0x0000000000000000000000000000000000000000000000000000000000000000" [inputs.constants.global_variables.gas_fees] fee_per_da_gas = "0x0000000000000000000000000000000000000000000000000000000000000000" - fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd0959c" + fee_per_l2_gas = "0x0000000000000000000000000000000000000000000000000000000c9bd3a502" diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/tx_effect.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/tx_effect.nr index fe5f3cab437..c0e2da5c616 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/tx_effect.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/tx_effect.nr @@ -1,9 +1,12 @@ use types::{ - abis::{log_hash::ScopedLogHash, private_log::PrivateLog, public_data_write::PublicDataWrite}, + abis::{ + log_hash::ScopedLogHash, private_log::PrivateLog, public_data_write::PublicDataWrite, + public_log::PublicLog, + }, constants::{ MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, MAX_PUBLIC_LOGS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, }, traits::Empty, }; @@ -17,8 +20,7 @@ pub(crate) struct TxEffect { pub(crate) l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], pub(crate) public_data_writes: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], pub(crate) private_logs: [PrivateLog; MAX_PRIVATE_LOGS_PER_TX], - pub(crate) unencrypted_log_preimages_length: Field, - pub(crate) unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + pub(crate) public_logs: [PublicLog; MAX_PUBLIC_LOGS_PER_TX], pub(crate) contract_class_log_preimages_length: Field, pub(crate) contract_class_logs_hashes: [ScopedLogHash; MAX_CONTRACT_CLASS_LOGS_PER_TX], } @@ -36,8 +38,7 @@ impl Empty for TxEffect { PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX ], private_logs: [PrivateLog::empty(); MAX_PRIVATE_LOGS_PER_TX], - unencrypted_log_preimages_length: 0, - unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + public_logs: [PublicLog::empty(); MAX_PUBLIC_LOGS_PER_TX], contract_class_log_preimages_length: 0, contract_class_logs_hashes: [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr index f2ecd16eb0d..71813404daa 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr @@ -19,11 +19,11 @@ use super::components::constants::validate_tx_constant_data; use dep::types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, constant_rollup_data::ConstantRollupData, - log_hash::ScopedLogHash, nullifier_leaf_preimage::NullifierLeafPreimage, - public_data_write::PublicDataWrite, sponge_blob::SpongeBlob, tube::PrivateTubeData, + nullifier_leaf_preimage::NullifierLeafPreimage, public_data_write::PublicDataWrite, + public_log::PublicLog, sponge_blob::SpongeBlob, tube::PrivateTubeData, }, constants::{ - ARCHIVE_HEIGHT, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + ARCHIVE_HEIGHT, MAX_PUBLIC_LOGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, TUBE_VK_INDEX, }, data::{hash::compute_public_data_tree_value, public_data_hint::PublicDataHint}, @@ -120,8 +120,7 @@ impl PrivateBaseRollupInputs { l2_to_l1_msgs: siloed_l2_to_l1_msgs, public_data_writes: all_public_data_update_requests, private_logs: self.tube_data.public_inputs.end.private_logs, - unencrypted_log_preimages_length: 0, - unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + public_logs: [PublicLog::empty(); MAX_PUBLIC_LOGS_PER_TX], contract_class_log_preimages_length: self .tube_data .public_inputs @@ -940,7 +939,7 @@ mod tests { reconstructed_tx_effects[offset] = contract_class_logs_prefix; offset += 1; for i in 0..NUM_CC_LOGS { - reconstructed_tx_effects[offset + i] = types::hash::silo_unencrypted_log_hash( + reconstructed_tx_effects[offset + i] = types::hash::silo_contract_class_log_hash( builder.tube_data.contract_class_logs_hashes.storage()[i], ); } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr index 0ecd03c2636..91076f4bf68 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr @@ -81,10 +81,6 @@ impl PublicBaseRollupInputs { }; let contract_class_log_preimages_length = contract_class_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); - let unencrypted_log_preimages_length = from_public - .accumulated_data - .unencrypted_logs_hashes - .fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); TxEffect { tx_hash: self.tube_data.public_inputs.hash(), @@ -95,8 +91,7 @@ impl PublicBaseRollupInputs { l2_to_l1_msgs: siloed_l2_to_l1_msgs, public_data_writes: from_public.accumulated_data.public_data_writes, private_logs, - unencrypted_logs_hashes: from_public.accumulated_data.unencrypted_logs_hashes, - unencrypted_log_preimages_length, + public_logs: from_public.accumulated_data.public_logs, contract_class_log_preimages_length, contract_class_logs_hashes, } @@ -298,8 +293,8 @@ mod tests { NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, NOTES_PREFIX, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NULLIFIERS_PREFIX, PRIVATE_LOG_SIZE_IN_FIELDS, PRIVATE_LOGS_PREFIX, - PUBLIC_DATA_TREE_HEIGHT, PUBLIC_DATA_UPDATE_REQUESTS_PREFIX, REVERT_CODE_PREFIX, - TUBE_VK_INDEX, TX_FEE_PREFIX, TX_START_PREFIX, UNENCRYPTED_LOGS_PREFIX, + PUBLIC_DATA_TREE_HEIGHT, PUBLIC_DATA_UPDATE_REQUESTS_PREFIX, PUBLIC_LOG_SIZE_IN_FIELDS, + PUBLIC_LOGS_PREFIX, REVERT_CODE_PREFIX, TUBE_VK_INDEX, TX_FEE_PREFIX, TX_START_PREFIX, }, data::{PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, hash::silo_l2_to_l1_message, @@ -954,7 +949,7 @@ mod tests { let NUM_NULLIFIERS = 3; let NUM_MSGS = 5; let NUM_PRIV_EVENT_LOGS = 4; - let NUM_UNENC_LOGS = 6; + let NUM_PUB_LOGS = 6; let NUM_CC_LOGS = 1; let PUB_DATA_SLOT = 25; let PUB_DATA_VALUE = 60; @@ -965,8 +960,8 @@ mod tests { + 1 // nullifiers and prefix + NUM_MSGS + 1 // L2 to L1 msgs and prefix - + NUM_UNENC_LOGS - + 1 // unenc. logs and prefix + + NUM_PUB_LOGS * PUBLIC_LOG_SIZE_IN_FIELDS + + 1 // public logs and prefix + NUM_CC_LOGS + 1 // contract class logs and prefix + 2 @@ -995,7 +990,7 @@ mod tests { 0, PublicDataTreeLeaf { slot: PUB_DATA_SLOT, value: PUB_DATA_VALUE }, )); builder.tube_data.append_private_logs(NUM_PRIV_EVENT_LOGS); - builder.avm_data.append_unencrypted_log_hashes(NUM_UNENC_LOGS); + builder.avm_data.append_public_logs(NUM_PUB_LOGS); // Below will only work with NUM_CC_LOGS=1 builder.tube_data.add_contract_class_log_hash(1, 2); let inputs = builder.build_inputs(); @@ -1077,24 +1072,25 @@ mod tests { } } offset += total_private_logs_len; - // TODO(#8954): The below will change with log deconstruction - // unenc logs - let unencrypted_logs_prefix = encode_blob_prefix(UNENCRYPTED_LOGS_PREFIX, NUM_UNENC_LOGS); - reconstructed_tx_effects[offset] = unencrypted_logs_prefix; + // public logs + let public_logs_prefix = + encode_blob_prefix(PUBLIC_LOGS_PREFIX, NUM_PUB_LOGS * PUBLIC_LOG_SIZE_IN_FIELDS); + reconstructed_tx_effects[offset] = public_logs_prefix; offset += 1; - for i in 0..NUM_UNENC_LOGS { - reconstructed_tx_effects[offset + i] = types::hash::silo_unencrypted_log_hash( - builder.avm_data.unencrypted_logs_hashes.storage()[i], - ); + for i in 0..NUM_PUB_LOGS { + let log = builder.avm_data.public_logs.storage()[i].serialize(); + for j in 0..PUBLIC_LOG_SIZE_IN_FIELDS { + reconstructed_tx_effects[offset + i * PUBLIC_LOG_SIZE_IN_FIELDS + j] = log[j]; + } } - offset += NUM_UNENC_LOGS; + offset += NUM_PUB_LOGS * PUBLIC_LOG_SIZE_IN_FIELDS; // cc logs let contract_class_logs_prefix = encode_blob_prefix(CONTRACT_CLASS_LOGS_PREFIX, NUM_CC_LOGS); reconstructed_tx_effects[offset] = contract_class_logs_prefix; offset += 1; for i in 0..NUM_CC_LOGS { - reconstructed_tx_effects[offset + i] = types::hash::silo_unencrypted_log_hash( + reconstructed_tx_effects[offset + i] = types::hash::silo_contract_class_log_hash( builder.tube_data.contract_class_logs_hashes.storage()[i], ); } 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 918fdc52510..776ee6e8851 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 @@ -6,20 +6,20 @@ use super::abis::tx_effect::TxEffect; use dep::types::{ abis::{ log::Log, log_hash::ScopedLogHash, public_data_write::PublicDataWrite, - sponge_blob::SpongeBlob, + public_log::PublicLog, sponge_blob::SpongeBlob, }, constants::{ AZTEC_MAX_EPOCH_DURATION, CONTRACT_CLASS_LOGS_PREFIX, L2_L1_MSGS_PREFIX, MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NOTES_PREFIX, - NULLIFIERS_PREFIX, PRIVATE_LOG_SIZE_IN_FIELDS, PRIVATE_LOGS_PREFIX, - PUBLIC_DATA_UPDATE_REQUESTS_PREFIX, REVERT_CODE_PREFIX, TX_FEE_PREFIX, TX_START_PREFIX, - UNENCRYPTED_LOGS_PREFIX, + MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, MAX_PUBLIC_LOGS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTES_PREFIX, NULLIFIERS_PREFIX, + PRIVATE_LOG_SIZE_IN_FIELDS, PRIVATE_LOGS_PREFIX, PUBLIC_DATA_UPDATE_REQUESTS_PREFIX, + PUBLIC_LOG_SIZE_IN_FIELDS, PUBLIC_LOGS_PREFIX, REVERT_CODE_PREFIX, TX_FEE_PREFIX, + TX_START_PREFIX, }, - hash::{accumulate_sha256, silo_unencrypted_log_hash}, + hash::{accumulate_sha256, silo_contract_class_log_hash}, merkle_tree::VariableMerkleTree, - traits::{Empty, is_empty}, + traits::{Empty, is_empty, Serialize}, utils::arrays::{array_length, array_merge}, }; use blob::blob_public_inputs::BlockBlobPublicInputs; @@ -152,7 +152,7 @@ pub fn encode_blob_prefix(input_type: u8, array_len: u32) -> Field { // MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX public data update requests -> MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 fields // TODO(#8954): When logs are refactored into fields, we will append the values here, for now appending the log hashes: // MAX_PRIVATE_LOGS_PER_TX * PRIVATE_LOG_SIZE_IN_FIELDS fields for private logs -// MAX_UNENCRYPTED_LOGS_PER_TX fields for unencrypted logs +// MAX_PUBLIC_LOGS_PER_TX * PUBLIC_LOG_SIZE_IN_FIELDS fields for public logs // MAX_CONTRACT_CLASS_LOGS_PER_TX fields for contract class logs // 7 fields for prefixes for each of the above categories pub(crate) global TX_EFFECTS_BLOB_HASH_INPUT_FIELDS: u32 = 1 @@ -163,7 +163,7 @@ pub(crate) global TX_EFFECTS_BLOB_HASH_INPUT_FIELDS: u32 = 1 + MAX_L2_TO_L1_MSGS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + MAX_PRIVATE_LOGS_PER_TX * PRIVATE_LOG_SIZE_IN_FIELDS - + MAX_UNENCRYPTED_LOGS_PER_TX + + MAX_PUBLIC_LOGS_PER_TX * PUBLIC_LOG_SIZE_IN_FIELDS + MAX_CONTRACT_CLASS_LOGS_PER_TX + 7; @@ -202,10 +202,9 @@ fn get_tx_effects_hash_input( let public_data_update_requests = get_all_update_requests_for_tx_effects(tx_effect.public_data_writes); let private_logs = tx_effect.private_logs; - let unencrypted_logs = - tx_effect.unencrypted_logs_hashes.map(|log: ScopedLogHash| silo_unencrypted_log_hash(log)); + let public_logs = tx_effect.public_logs; let contract_class_logs = tx_effect.contract_class_logs_hashes.map(|log: ScopedLogHash| { - silo_unencrypted_log_hash(log) + silo_contract_class_log_hash(log) }); /// Safety: This constructs the array of effects and is constrained below. @@ -218,7 +217,7 @@ fn get_tx_effects_hash_input( tx_effect.l2_to_l1_msgs, public_data_update_requests, private_logs, - unencrypted_logs, + public_logs, contract_class_logs, tx_effect.revert_code as Field, ) @@ -330,23 +329,26 @@ fn get_tx_effects_hash_input( offset += array_len; } - // TODO(#8954): When logs are refactored into fields, we will append the values here - // Currently appending the single log hash as an interim solution - // UNENCRYPTED LOGS - array_len = array_length(unencrypted_logs); + // PUBLIC LOGS + array_len = array_length(public_logs) * PUBLIC_LOG_SIZE_IN_FIELDS; if array_len != 0 { - let unencrypted_logs_prefix = encode_blob_prefix(UNENCRYPTED_LOGS_PREFIX, array_len); - assert_eq(tx_effects_hash_input[offset], unencrypted_logs_prefix); + let public_logs_prefix = encode_blob_prefix(PUBLIC_LOGS_PREFIX, array_len); + assert_eq(tx_effects_hash_input[offset], public_logs_prefix); offset += 1; - - for j in 0..MAX_UNENCRYPTED_LOGS_PER_TX { - if j < array_len { - assert_eq(tx_effects_hash_input[offset + j], unencrypted_logs[j]); + for j in 0..MAX_PUBLIC_LOGS_PER_TX { + let log = public_logs[j].serialize(); + for k in 0..PUBLIC_LOG_SIZE_IN_FIELDS { + let index = offset + j * PUBLIC_LOG_SIZE_IN_FIELDS + k; + if index < array_len { + assert_eq(tx_effects_hash_input[index], log[k]); + } } } offset += array_len; } + // TODO(#8954): When logs are refactored into fields, we will append the values here + // Currently appending the single log hash as an interim solution // CONTRACT CLASS LOGS array_len = array_length(contract_class_logs); if array_len != 0 { @@ -389,7 +391,7 @@ unconstrained fn get_tx_effects_hash_input_helper( l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], public_data_update_requests: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], private_logs: [Log; MAX_PRIVATE_LOGS_PER_TX], - unencrypted_logs: [Field; MAX_UNENCRYPTED_LOGS_PER_TX], + public_logs: [PublicLog; MAX_PUBLIC_LOGS_PER_TX], contract_class_logs: [Field; MAX_CONTRACT_CLASS_LOGS_PER_TX], revert_code: Field, ) -> [Field; TX_EFFECTS_BLOB_HASH_INPUT_FIELDS] { @@ -480,21 +482,25 @@ unconstrained fn get_tx_effects_hash_input_helper( offset += array_len; } - // TODO(#8954): When logs are refactored into fields, we will append the values here - // Currently appending the single log hash as an interim solution - // UNENCRYPTED LOGS - let array_len = array_length(unencrypted_logs); - if array_len != 0 { - let unencrypted_logs_prefix = encode_blob_prefix(UNENCRYPTED_LOGS_PREFIX, array_len); - tx_effects_hash_input[offset] = unencrypted_logs_prefix; + // PUBLIC LOGS + let num_public_logs = array_length(public_logs); + if num_public_logs != 0 { + let array_len = num_public_logs * PUBLIC_LOG_SIZE_IN_FIELDS; + let public_logs_prefix = encode_blob_prefix(PUBLIC_LOGS_PREFIX, array_len); + tx_effects_hash_input[offset] = public_logs_prefix; offset += 1; - - for j in 0..array_len { - tx_effects_hash_input[offset + j] = unencrypted_logs[j]; + for j in 0..num_public_logs { + let log = public_logs[j].serialize(); + for k in 0..PUBLIC_LOG_SIZE_IN_FIELDS { + let index = offset + j * PUBLIC_LOG_SIZE_IN_FIELDS + k; + tx_effects_hash_input[index] = log[k]; + } } offset += array_len; } + // TODO(#8954): When logs are refactored into fields, we will append the values here + // Currently appending the single log hash as an interim solution // CONTRACT CLASS LOGS let array_len = array_length(contract_class_logs); if array_len != 0 { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr index 6108c987133..3e200f004e4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr @@ -1,9 +1,8 @@ use crate::{ - abis::{log_hash::ScopedLogHash, public_data_write::PublicDataWrite}, + abis::{public_data_write::PublicDataWrite, public_log::PublicLog}, constants::{ AVM_ACCUMULATED_DATA_LENGTH, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_LOGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Deserialize, Empty, Serialize}, @@ -17,9 +16,8 @@ pub struct AvmAccumulatedData { pub nullifiers: [Field; MAX_NULLIFIERS_PER_TX], // The L2 to L1 messages from private combining with those made in the AVM execution. pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], - // TODO(#9589): This should only contain logs emitted from public. - // The unencrypted logs emitted from private combining with those made in the AVM execution. - pub unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + // The public logs emitted from the AVM execution. + pub public_logs: [PublicLog; MAX_PUBLIC_LOGS_PER_TX], // The public data writes made in the AVM execution. pub public_data_writes: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], } @@ -30,7 +28,7 @@ impl Empty for AvmAccumulatedData { note_hashes: [0; MAX_NOTE_HASHES_PER_TX], nullifiers: [0; MAX_NULLIFIERS_PER_TX], l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + public_logs: [PublicLog::empty(); MAX_PUBLIC_LOGS_PER_TX], public_data_writes: [ PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX ], @@ -54,8 +52,8 @@ impl Serialize for AvmAccumulatedData { fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); } - for i in 0..self.unencrypted_logs_hashes.len() { - fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + for i in 0..self.public_logs.len() { + fields.extend_from_array(self.public_logs[i].serialize()); } for i in 0..self.public_data_writes.len() { @@ -79,9 +77,9 @@ impl Deserialize for AvmAccumulatedData { ScopedL2ToL1Message::deserialize, [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], ), - unencrypted_logs_hashes: reader.read_struct_array( - ScopedLogHash::deserialize, - [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + public_logs: reader.read_struct_array( + PublicLog::deserialize, + [PublicLog::empty(); MAX_PUBLIC_LOGS_PER_TX], ), public_data_writes: reader.read_struct_array( PublicDataWrite::deserialize, @@ -98,7 +96,7 @@ impl Eq for AvmAccumulatedData { (self.note_hashes == other.note_hashes) & (self.nullifiers == other.nullifiers) & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) - & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.public_logs == other.public_logs) & (self.public_data_writes == other.public_data_writes) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr index ff429eefad6..76d414f3a99 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr @@ -19,6 +19,7 @@ pub mod side_effect; pub mod read_request; pub mod log; pub mod private_log; +pub mod public_log; pub mod log_hash; pub mod note_hash; pub mod nullifier; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_log.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_log.nr new file mode 100644 index 00000000000..7fd46356ea2 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_log.nr @@ -0,0 +1,58 @@ +use crate::{ + abis::{log::Log, side_effect::Scoped}, + address::AztecAddress, + constants::{PUBLIC_LOG_DATA_SIZE_IN_FIELDS, PUBLIC_LOG_SIZE_IN_FIELDS}, + traits::{Deserialize, Empty, Serialize}, + utils::{arrays::array_concat, reader::Reader}, +}; + +pub struct PublicLog { + pub log: Log, + pub contract_address: AztecAddress, +} + +impl Scoped> for PublicLog { + fn inner(self) -> Log { + self.log + } + fn contract_address(self) -> AztecAddress { + self.contract_address + } +} + +impl Eq for PublicLog { + fn eq(self, other: PublicLog) -> bool { + (self.log == other.log) & (self.contract_address == other.contract_address) + } +} + +impl Empty for PublicLog { + fn empty() -> Self { + PublicLog { log: Log::empty(), contract_address: AztecAddress::empty() } + } +} + +impl Serialize for PublicLog { + fn serialize(self) -> [Field; PUBLIC_LOG_SIZE_IN_FIELDS] { + // Note: we ensure that the address of a public log goes first, unlike generic Scoped impls + array_concat([self.contract_address.to_field()], self.log.serialize()) + } +} + +impl Deserialize for PublicLog { + fn deserialize(fields: [Field; PUBLIC_LOG_SIZE_IN_FIELDS]) -> Self { + let mut reader = Reader::new(fields); + Self { + contract_address: reader.read_struct(AztecAddress::deserialize), + log: reader.read_struct(Log::deserialize), + } + } +} + +#[test] +fn serialization_of_empty_public_log() { + let item = PublicLog::empty(); + let serialized = item.serialize(); + let deserialized = PublicLog::deserialize(serialized); + assert(item.eq(deserialized)); +} 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 0d9b549c1b4..3e157e86998 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -39,7 +39,7 @@ pub global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u32 = 16; pub global MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL: u32 = 16; pub global MAX_KEY_VALIDATION_REQUESTS_PER_CALL: u32 = 16; pub global MAX_PRIVATE_LOGS_PER_CALL: u32 = 16; -pub global MAX_UNENCRYPTED_LOGS_PER_CALL: u32 = 4; +pub global MAX_PUBLIC_LOGS_PER_CALL: u32 = 4; pub global MAX_CONTRACT_CLASS_LOGS_PER_CALL: u32 = 1; // TREES RELATED CONSTANTS @@ -91,7 +91,7 @@ pub global MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX: u32 = 64; // databus will hopefully make the issue go away. pub global MAX_KEY_VALIDATION_REQUESTS_PER_TX: u32 = 64; pub global MAX_PRIVATE_LOGS_PER_TX: u32 = 32; -pub global MAX_UNENCRYPTED_LOGS_PER_TX: u32 = 8; +pub global MAX_PUBLIC_LOGS_PER_TX: u32 = 8; pub global MAX_CONTRACT_CLASS_LOGS_PER_TX: u32 = 1; // docs:end:constants @@ -128,6 +128,8 @@ pub global INITIALIZATION_SLOT_SEPARATOR: Field = 1000_000_000; pub global INITIAL_L2_BLOCK_NUM: Field = 1; pub global FIELDS_PER_BLOB: u32 = 4096; pub global BLOBS_PER_BLOCK: u32 = 3; +pub global PUBLIC_LOG_DATA_SIZE_IN_FIELDS: u32 = 13; +pub global PUBLIC_LOG_SIZE_IN_FIELDS: u32 = PUBLIC_LOG_DATA_SIZE_IN_FIELDS + 1; // This includes the contract address, since it is always emitted with a public log pub global PRIVATE_LOG_SIZE_IN_FIELDS: u32 = 18; // This is currently affected by the size of the log overhead defined in aztec-nr/aztec/src/encrypted_logs/payload.nr. pub global AZTEC_MAX_EPOCH_DURATION: u32 = 48; // The following genesis values are taken from world_state.test.cpp > WorldStateTest.GetInitialTreeInfoForAllTrees @@ -312,7 +314,7 @@ pub global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + (NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) + 2 - + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + + (PUBLIC_LOG_SIZE_IN_FIELDS * MAX_PUBLIC_LOGS_PER_CALL) + BLOCK_HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH @@ -378,7 +380,7 @@ pub global NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS: u32 = 3; pub global AVM_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) - + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + + (MAX_PUBLIC_LOGS_PER_TX * PUBLIC_LOG_SIZE_IN_FIELDS) + (MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); pub global PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = TX_CONSTANT_DATA_LENGTH @@ -743,7 +745,7 @@ pub global NULLIFIERS_PREFIX: u8 = 4; pub global L2_L1_MSGS_PREFIX: u8 = 5; pub global PUBLIC_DATA_UPDATE_REQUESTS_PREFIX: u8 = 6; pub global PRIVATE_LOGS_PREFIX: u8 = 7; -pub global UNENCRYPTED_LOGS_PREFIX: u8 = 8; +pub global PUBLIC_LOGS_PREFIX: u8 = 8; pub global CONTRACT_CLASS_LOGS_PREFIX: u8 = 9; // Constants related to proof type of a recursive proof verification. 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 d73964db0db..879851e1a3c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -117,15 +117,15 @@ pub fn silo_private_log(private_log: Scoped) -> PrivateLog { } } -fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field { +fn compute_siloed_contract_class_log_hash(address: AztecAddress, log_hash: Field) -> Field { accumulate_sha256([address.to_field(), log_hash]) } -pub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field { +pub fn silo_contract_class_log_hash(log_hash: ScopedLogHash) -> Field { if log_hash.contract_address.is_zero() { 0 } else { - compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value()) + compute_siloed_contract_class_log_hash(log_hash.contract_address, log_hash.value()) } } 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 e875144327d..a043820e186 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 @@ -30,6 +30,7 @@ use crate::{ private_log::PrivateLogData, public_call_request::PublicCallRequest, public_data_write::PublicDataWrite, + public_log::PublicLog, read_request::{ReadRequest, ScopedReadRequest}, side_effect::{Counted, OrderedValue, scoped::Scoped}, tube::{PrivateTubeData, PublicTubeData}, @@ -47,10 +48,10 @@ use crate::{ MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - PRIVATE_CALL_REQUEST_LENGTH, PRIVATE_LOG_SIZE_IN_FIELDS, PROTOCOL_CONTRACT_TREE_HEIGHT, - PUBLIC_CALL_REQUEST_LENGTH, VK_TREE_HEIGHT, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PRIVATE_LOGS_PER_TX, MAX_PUBLIC_LOGS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PRIVATE_CALL_REQUEST_LENGTH, + PRIVATE_LOG_SIZE_IN_FIELDS, PROTOCOL_CONTRACT_TREE_HEIGHT, PUBLIC_CALL_REQUEST_LENGTH, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, VK_TREE_HEIGHT, }, hash::{ compute_l2_to_l1_hash, compute_siloed_nullifier, compute_siloed_private_log_field, @@ -115,9 +116,8 @@ pub struct FixtureBuilder { pub nullifiers: BoundedVec, pub l2_to_l1_msgs: BoundedVec, pub private_logs: BoundedVec, MAX_PRIVATE_LOGS_PER_TX>, - pub unencrypted_logs_hashes: BoundedVec, + pub public_logs: BoundedVec, pub contract_class_logs_hashes: BoundedVec, - pub unencrypted_log_preimages_length: Field, pub contract_class_log_preimages_length: Field, pub public_data_writes: BoundedVec, pub private_call_requests: BoundedVec, @@ -558,7 +558,7 @@ impl FixtureBuilder { note_hashes: self.note_hashes.storage().map(|n: ScopedNoteHash| n.note_hash.value), nullifiers: self.nullifiers.storage().map(|n: ScopedNullifier| n.nullifier.value), l2_to_l1_msgs: self.l2_to_l1_msgs.storage(), - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage(), + public_logs: self.public_logs.storage(), public_data_writes: self.public_data_writes.storage(), } } @@ -869,18 +869,19 @@ impl FixtureBuilder { } } - pub fn add_unencrypted_log_hash(&mut self, hash: Field, length: Field) { - let log_hash = LogHash { value: hash, counter: self.next_counter(), length }; - self.unencrypted_logs_hashes.push(log_hash.scope(self.contract_address)); - self.unencrypted_log_preimages_length += length; + pub fn add_public_log(&mut self, fields: [Field; PUBLIC_LOG_DATA_SIZE_IN_FIELDS]) { + let inner = Log { fields }; + let log = PublicLog { log: inner, contract_address: self.contract_address }; + let _ = self.next_counter(); + self.public_logs.push(log); } - pub fn append_unencrypted_log_hashes(&mut self, num: u32) { - let index_offset = self.unencrypted_logs_hashes.len(); - for i in 0..self.unencrypted_logs_hashes.max_len() { - if i < num { - let (log_hash, length) = self.mock_unencrypted_log(index_offset + i); - self.add_unencrypted_log_hash(log_hash, length); + pub fn append_public_logs(&mut self, num_logs: u32) { + let index_offset = self.public_logs.len(); + for i in 0..self.public_logs.max_len() { + if i < num_logs { + let fields = self.mock_public_log_fields(index_offset + i); + self.add_public_log(fields); } } } @@ -1035,20 +1036,18 @@ impl FixtureBuilder { fields } - fn mock_private_log_randomness(self, index: u32) -> Field { - 579579 + self.value_offset + index as Field - } - - fn mock_encrypted_log(self, index: u32) -> (Field, Field) { - let log_hash = 50403 + self.value_offset + index as Field; - let length = 3 + index as Field; - (log_hash, length) + fn mock_public_log_fields(self, index: u32) -> [Field; PUBLIC_LOG_DATA_SIZE_IN_FIELDS] { + let value_offset = + 199199 + self.value_offset + (index * PUBLIC_LOG_DATA_SIZE_IN_FIELDS) as Field; + let mut fields = [0; PUBLIC_LOG_DATA_SIZE_IN_FIELDS]; + for i in 0..PUBLIC_LOG_DATA_SIZE_IN_FIELDS { + fields[i] = value_offset + i as Field; + } + fields } - fn mock_unencrypted_log(self, index: u32) -> (Field, Field) { - let log_hash = 199199 + self.value_offset + index as Field; - let length = 1 + index as Field; - (log_hash, length) + fn mock_private_log_randomness(self, index: u32) -> Field { + 579579 + self.value_offset + index as Field } fn mock_private_call_request(self, index: u32) -> PrivateCallRequest { @@ -1108,9 +1107,8 @@ impl Empty for FixtureBuilder { nullifiers: BoundedVec::new(), l2_to_l1_msgs: BoundedVec::new(), private_logs: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), + public_logs: BoundedVec::new(), contract_class_logs_hashes: BoundedVec::new(), - unencrypted_log_preimages_length: 0, contract_class_log_preimages_length: 0, public_data_writes: BoundedVec::new(), private_call_requests: BoundedVec::new(), diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 03d24c096a2..00d1813d86f 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -218,10 +218,9 @@ describe('Archiver', () => { const privateLogs = await archiver.getPrivateLogs(blockNumber, 1); expect(privateLogs.length).toBe(getNumPrivateLogsForBlock(blockNumber)); - const unencryptedLogs = (await archiver.getUnencryptedLogs({ fromBlock: blockNumber, toBlock: blockNumber + 1 })) - .logs; - const expectedTotalNumUnencryptedLogs = 4 * (blockNumber + 1) * 2; - expect(unencryptedLogs.length).toEqual(expectedTotalNumUnencryptedLogs); + const publicLogs = (await archiver.getPublicLogs({ fromBlock: blockNumber, toBlock: blockNumber + 1 })).logs; + const expectedTotalNumPublicLogs = 4 * (blockNumber + 1) * 2; + expect(publicLogs.length).toEqual(expectedTotalNumPublicLogs); } blockNumbers.forEach(async x => { @@ -377,7 +376,7 @@ describe('Archiver', () => { expect(await archiver.getBlock(2)).resolves.toBeUndefined; expect(await archiver.getPrivateLogs(2, 1)).toEqual([]); - expect((await archiver.getUnencryptedLogs({ fromBlock: 2, toBlock: 3 })).logs).toEqual([]); + expect((await archiver.getPublicLogs({ fromBlock: 2, toBlock: 3 })).logs).toEqual([]); expect((await archiver.getContractClassLogs({ fromBlock: 2, toBlock: 3 })).logs).toEqual([]); }, 10_000); diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 012ddd9c5d9..410110d51e4 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -1,6 +1,7 @@ import { type BlobSinkClientInterface } from '@aztec/blob-sink/client'; import { - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, type InboxLeaf, type L1RollupConstants, @@ -717,12 +718,12 @@ export class Archiver implements ArchiveSource, Traceable { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { - return this.store.getUnencryptedLogs(filter); + getPublicLogs(filter: LogFilter): Promise { + return this.store.getPublicLogs(filter); } /** @@ -730,7 +731,7 @@ export class Archiver implements ArchiveSource, Traceable { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { return this.store.getContractClassLogs(filter); } @@ -1067,10 +1068,10 @@ class ArchiverStoreHelper findNullifiersIndexesWithBlock(blockNumber: number, nullifiers: Fr[]): Promise<(InBlock | undefined)[]> { return this.store.findNullifiersIndexesWithBlock(blockNumber, nullifiers); } - getUnencryptedLogs(filter: LogFilter): Promise { - return this.store.getUnencryptedLogs(filter); + getPublicLogs(filter: LogFilter): Promise { + return this.store.getPublicLogs(filter); } - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { return this.store.getContractClassLogs(filter); } getSynchedL2BlockNumber(): Promise { diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index a68798c2d34..596f7818a66 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -1,5 +1,6 @@ import { - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, type InboxLeaf, type L2Block, @@ -156,18 +157,18 @@ export interface ArchiverDataStore { getLogsByTags(tags: Fr[]): Promise; /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getPublicLogs(filter: LogFilter): Promise; /** * Gets contract class logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise; + getContractClassLogs(filter: LogFilter): Promise; /** * Gets the number of the latest L2 block processed. 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 5f9cd2f6b0b..1892ecb4bcb 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -1,14 +1,4 @@ -import { - InboxLeaf, - L2Block, - LogId, - TxEffect, - TxHash, - UnencryptedFunctionL2Logs, - UnencryptedL2Log, - UnencryptedTxL2Logs, - wrapInBlock, -} from '@aztec/circuit-types'; +import { InboxLeaf, L2Block, LogId, TxEffect, TxHash, wrapInBlock } from '@aztec/circuit-types'; import '@aztec/circuit-types/jest'; import { AztecAddress, @@ -19,7 +9,9 @@ import { L1_TO_L2_MSG_SUBTREE_HEIGHT, MAX_NULLIFIERS_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, PrivateLog, + PublicLog, SerializableContractInstance, computePublicBytecodeCommitment, } from '@aztec/circuits.js'; @@ -166,14 +158,14 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); describe('addLogs', () => { - it('adds private & unencrypted logs', async () => { + it('adds private & public logs', async () => { const block = blocks[0].data; await expect(store.addLogs([block])).resolves.toEqual(true); }); }); describe('deleteLogs', () => { - it('deletes private & unencrypted logs', async () => { + it('deletes private & public logs', async () => { const block = blocks[0].data; await store.addBlocks([blocks[0]]); await expect(store.addLogs([block])).resolves.toEqual(true); @@ -181,15 +173,15 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch expect((await store.getPrivateLogs(1, 1)).length).toEqual( block.body.txEffects.map(txEffect => txEffect.privateLogs).flat().length, ); - expect((await store.getUnencryptedLogs({ fromBlock: 1 })).logs.length).toEqual( - block.body.unencryptedLogs.getTotalLogCount(), + expect((await store.getPublicLogs({ fromBlock: 1 })).logs.length).toEqual( + block.body.txEffects.map(txEffect => txEffect.publicLogs).flat().length, ); // This one is a pain for memory as we would never want to just delete memory in the middle. await store.deleteLogs([block]); expect((await store.getPrivateLogs(1, 1)).length).toEqual(0); - expect((await store.getUnencryptedLogs({ fromBlock: 1 })).logs.length).toEqual(0); + expect((await store.getPublicLogs({ fromBlock: 1 })).logs.length).toEqual(0); }); }); @@ -373,18 +365,34 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const numBlocks = 3; const numTxsPerBlock = 4; const numPrivateLogsPerTx = 3; - const numUnencryptedLogsPerTx = 2; + const numPublicLogsPerTx = 2; let blocks: L1Published[]; const makeTag = (blockNumber: number, txIndex: number, logIndex: number, isPublic = false) => new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1)); + // See parseLogFromPublic + const makeLengthsField = (publicValuesLen: number, privateValuesLen: number, ciphertextLen: number) => { + const buf = Buffer.alloc(32); + buf.writeUint16BE(publicValuesLen, 24); + buf.writeUint16BE(privateValuesLen, 27); + buf.writeUint16BE(ciphertextLen, 30); + return Fr.fromBuffer(buf); + }; + const makePrivateLog = (tag: Fr) => PrivateLog.fromFields([tag, ...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i))]); + // The tag lives in field 1, not 0, of a public log + // See extractTaggedLogsFromPublic and noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr -> emit_log const makePublicLog = (tag: Fr) => - Buffer.concat([tag.toBuffer(), ...times(tag.toNumber() % 60, i => new Fr(tag.toNumber() + i).toBuffer())]); + PublicLog.fromFields([ + AztecAddress.fromNumber(1).toField(), // log address + makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 3, 42), // field 0 + tag, // field 1 + ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 2 to end + ]); const mockPrivateLogs = (blockNumber: number, txIndex: number) => { return times(numPrivateLogsPerTx, (logIndex: number) => { @@ -393,13 +401,11 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); }; - const mockUnencryptedLogs = (blockNumber: number, txIndex: number) => { - const logs = times(numUnencryptedLogsPerTx, (logIndex: number) => { + const mockPublicLogs = (blockNumber: number, txIndex: number) => { + return times(numPublicLogsPerTx, (logIndex: number) => { const tag = makeTag(blockNumber, txIndex, logIndex, /* isPublic */ true); - const log = makePublicLog(tag); - return new UnencryptedL2Log(AztecAddress.fromNumber(txIndex), log); + return makePublicLog(tag); }); - return new UnencryptedTxL2Logs([new UnencryptedFunctionL2Logs(logs)]); }; const mockBlockWithLogs = (blockNumber: number): L1Published => { @@ -409,7 +415,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch block.body.txEffects = times(numTxsPerBlock, (txIndex: number) => { const txEffect = TxEffect.random(); txEffect.privateLogs = mockPrivateLogs(blockNumber, txIndex); - txEffect.unencryptedLogs = mockUnencryptedLogs(blockNumber, txIndex); + txEffect.publicLogs = mockPublicLogs(blockNumber, txIndex); return txEffect; }); @@ -449,9 +455,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch ]); }); - // TODO: Allow this test when #9835 is fixed and tags can be correctly decoded - it.skip('is possible to batch request all logs (private and unencrypted) via tags', async () => { - // Tag(0, 0, 0) is shared with the first private log and the first unencrypted log. + it('is possible to batch request all logs (private and public) via tags', async () => { + // Tag(0, 0, 0) is shared with the first private log and the first public log. const tags = [makeTag(0, 0, 0)]; const logsByTags = await store.getLogsByTags(tags); @@ -465,7 +470,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }), expect.objectContaining({ blockNumber: 0, - logData: makePublicLog(tags[0]), + logData: makePublicLog(tags[0]).toBuffer(), isFromPublic: true, }), ], @@ -520,18 +525,48 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch ], ]); }); + + it('is not possible to add public logs by tag if they are invalid', async () => { + const tag = makeTag(99, 88, 77); + const invalidLogs = [ + PublicLog.fromFields([ + AztecAddress.fromNumber(1).toField(), + makeLengthsField(2, 3, 42), // This field claims we have 5 items, but we actually have more + tag, + ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), + ]), + PublicLog.fromFields([ + AztecAddress.fromNumber(1).toField(), + makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS, 42), // This field claims we have more than the max items + tag, + ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), + ]), + ]; + + // Create a block containing these invalid logs + const newBlockNumber = numBlocks; + const newBlock = mockBlockWithLogs(newBlockNumber); + newBlock.data.body.txEffects[0].publicLogs = invalidLogs; + await store.addBlocks([newBlock]); + await store.addLogs([newBlock.data]); + + const logsByTags = await store.getLogsByTags([tag]); + + // Neither of the logs should have been added: + expect(logsByTags).toEqual([[]]); + }); }); - describe('getUnencryptedLogs', () => { + describe('getPublicLogs', () => { const txsPerBlock = 4; const numPublicFunctionCalls = 3; - const numUnencryptedLogs = 2; + const numPublicLogs = 2; const numBlocks = 10; let blocks: L1Published[]; beforeEach(async () => { blocks = times(numBlocks, (index: number) => ({ - data: L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numUnencryptedLogs), + data: L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs), l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) }, })); @@ -550,7 +585,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch store.deleteLogs(blocks.map(b => b.data)), ]); - const response = await store.getUnencryptedLogs({ txHash: targetTxHash }); + const response = await store.getPublicLogs({ txHash: targetTxHash }); const logs = response.logs; expect(response.maxLogsHit).toBeFalsy(); @@ -563,12 +598,12 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const targetTxIndex = randomInt(txsPerBlock); const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash; - const response = await store.getUnencryptedLogs({ txHash: targetTxHash }); + const response = await store.getPublicLogs({ txHash: targetTxHash }); const logs = response.logs; expect(response.maxLogsHit).toBeFalsy(); - const expectedNumLogs = numPublicFunctionCalls * numUnencryptedLogs; + const expectedNumLogs = numPublicFunctionCalls * numPublicLogs; expect(logs.length).toEqual(expectedNumLogs); const targeBlockNumber = targetBlockIndex + INITIAL_L2_BLOCK_NUM; @@ -583,12 +618,12 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const fromBlock = 3; const toBlock = 7; - const response = await store.getUnencryptedLogs({ fromBlock, toBlock }); + const response = await store.getPublicLogs({ fromBlock, toBlock }); const logs = response.logs; expect(response.maxLogsHit).toBeFalsy(); - const expectedNumLogs = txsPerBlock * numPublicFunctionCalls * numUnencryptedLogs * (toBlock - fromBlock); + const expectedNumLogs = txsPerBlock * numPublicFunctionCalls * numPublicLogs * (toBlock - fromBlock); expect(logs.length).toEqual(expectedNumLogs); for (const log of logs) { @@ -602,14 +637,11 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // Get a random contract address from the logs const targetBlockIndex = randomInt(numBlocks); const targetTxIndex = randomInt(txsPerBlock); - const targetFunctionLogIndex = randomInt(numPublicFunctionCalls); - const targetLogIndex = randomInt(numUnencryptedLogs); + const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls); const targetContractAddress = - blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].unencryptedLogs.functionLogs[ - targetFunctionLogIndex - ].logs[targetLogIndex].contractAddress; + blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress; - const response = await store.getUnencryptedLogs({ contractAddress: targetContractAddress }); + const response = await store.getPublicLogs({ contractAddress: targetContractAddress }); expect(response.maxLogsHit).toBeFalsy(); @@ -622,11 +654,11 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // Get a random log as reference const targetBlockIndex = randomInt(numBlocks); const targetTxIndex = randomInt(txsPerBlock); - const targetLogIndex = randomInt(numUnencryptedLogs); + const targetLogIndex = randomInt(numPublicLogs); const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex); - const response = await store.getUnencryptedLogs({ afterLog }); + const response = await store.getPublicLogs({ afterLog }); const logs = response.logs; expect(response.maxLogsHit).toBeFalsy(); @@ -648,40 +680,40 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const txHash = TxHash.random(); const afterLog = new LogId(1, 0, 0); - const response = await store.getUnencryptedLogs({ txHash, afterLog }); + const response = await store.getPublicLogs({ txHash, afterLog }); expect(response.logs.length).toBeGreaterThan(1); }); it('intersecting works', async () => { - let logs = (await store.getUnencryptedLogs({ fromBlock: -10, toBlock: -5 })).logs; + let logs = (await store.getPublicLogs({ fromBlock: -10, toBlock: -5 })).logs; expect(logs.length).toBe(0); // "fromBlock" gets correctly trimmed to range and "toBlock" is exclusive - logs = (await store.getUnencryptedLogs({ fromBlock: -10, toBlock: 5 })).logs; + logs = (await store.getPublicLogs({ fromBlock: -10, toBlock: 5 })).logs; let blockNumbers = new Set(logs.map(log => log.id.blockNumber)); expect(blockNumbers).toEqual(new Set([1, 2, 3, 4])); // "toBlock" should be exclusive - logs = (await store.getUnencryptedLogs({ fromBlock: 1, toBlock: 1 })).logs; + logs = (await store.getPublicLogs({ fromBlock: 1, toBlock: 1 })).logs; expect(logs.length).toBe(0); - logs = (await store.getUnencryptedLogs({ fromBlock: 10, toBlock: 5 })).logs; + logs = (await store.getPublicLogs({ fromBlock: 10, toBlock: 5 })).logs; expect(logs.length).toBe(0); // both "fromBlock" and "toBlock" get correctly capped to range and logs from all blocks are returned - logs = (await store.getUnencryptedLogs({ fromBlock: -100, toBlock: +100 })).logs; + logs = (await store.getPublicLogs({ fromBlock: -100, toBlock: +100 })).logs; blockNumbers = new Set(logs.map(log => log.id.blockNumber)); expect(blockNumbers.size).toBe(numBlocks); // intersecting with "afterLog" works - logs = (await store.getUnencryptedLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(4, 0, 0) })).logs; + logs = (await store.getPublicLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(4, 0, 0) })).logs; blockNumbers = new Set(logs.map(log => log.id.blockNumber)); expect(blockNumbers).toEqual(new Set([4])); - logs = (await store.getUnencryptedLogs({ toBlock: 5, afterLog: new LogId(5, 1, 0) })).logs; + logs = (await store.getPublicLogs({ toBlock: 5, afterLog: new LogId(5, 1, 0) })).logs; expect(logs.length).toBe(0); - logs = (await store.getUnencryptedLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(100, 0, 0) })).logs; + logs = (await store.getPublicLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(100, 0, 0) })).logs; expect(logs.length).toBe(0); }); @@ -689,11 +721,11 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // Get a random log as reference const targetBlockIndex = randomInt(numBlocks); const targetTxIndex = randomInt(txsPerBlock); - const targetLogIndex = randomInt(numUnencryptedLogs); + const targetLogIndex = randomInt(numPublicLogs); const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex); - const response = await store.getUnencryptedLogs({ afterLog, fromBlock: afterLog.blockNumber }); + const response = await store.getPublicLogs({ afterLog, fromBlock: afterLog.blockNumber }); const logs = response.logs; expect(response.maxLogsHit).toBeFalsy(); diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index 25a41108cf9..3f86dd1c12b 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -36,7 +36,7 @@ export type ArchiverConfig = { /** The deployed L1 contract addresses */ l1Contracts: L1ContractAddresses; - /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */ + /** The max number of logs that can be obtained in 1 "getPublicLogs" call. */ maxLogs?: number; } & L1ReaderConfig & L1ContractsConfig; @@ -64,7 +64,7 @@ export const archiverConfigMappings: ConfigMappingsType = { }, maxLogs: { env: 'ARCHIVER_MAX_LOGS', - description: 'The max number of logs that can be obtained in 1 "getUnencryptedLogs" call.', + description: 'The max number of logs that can be obtained in 1 "getPublicLogs" call.', ...numberConfigHelper(1_000), }, ...l1ReaderConfigMappings, diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index 1b6d2bf02a0..ccd3a44b80b 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -165,7 +165,7 @@ async function getBlockFromRollupTx( // TODO(#9101): The below reconstruction is currently redundant, but once we extract blobs will be the way to construct blocks. // The blob source will give us blockFields, and we must construct the body from them: // TODO(#8954): When logs are refactored into fields, we won't need to inject them here. - const reconstructedBlock = Body.fromBlobFields(blockFields, blockBody.unencryptedLogs, blockBody.contractClassLogs); + const reconstructedBlock = Body.fromBlobFields(blockFields, blockBody.contractClassLogs); if (!reconstructedBlock.toBuffer().equals(blockBody.toBuffer())) { // TODO(#9101): Remove below check (without calldata there will be nothing to check against) 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 85b670c5483..d14260a5957 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 @@ -1,5 +1,6 @@ import { - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, type InboxLeaf, type L2Block, @@ -290,13 +291,13 @@ export class KVArchiverDataStore implements ArchiverDataStore { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getPublicLogs(filter: LogFilter): Promise { try { - return Promise.resolve(this.#logStore.getUnencryptedLogs(filter)); + return Promise.resolve(this.#logStore.getPublicLogs(filter)); } catch (err) { return Promise.reject(err); } @@ -307,7 +308,7 @@ export class KVArchiverDataStore implements ArchiverDataStore { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { try { return Promise.resolve(this.#logStore.getContractClassLogs(filter)); } catch (err) { 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 be9675651d4..7cce768918f 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 @@ -1,18 +1,23 @@ import { ContractClass2BlockL2Logs, + ExtendedPublicLog, ExtendedUnencryptedL2Log, - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type L2Block, type LogFilter, LogId, TxScopedL2Log, - UnencryptedL2BlockL2Logs, - type UnencryptedL2Log, + UnencryptedL2Log, } from '@aztec/circuit-types'; -import { Fr, PrivateLog } from '@aztec/circuits.js'; -import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/circuits.js/constants'; +import { type Fr, PrivateLog, PublicLog } from '@aztec/circuits.js'; +import { + INITIAL_L2_BLOCK_NUM, + MAX_NOTE_HASHES_PER_TX, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, +} from '@aztec/circuits.js/constants'; import { createLogger } from '@aztec/foundation/log'; -import { BufferReader } from '@aztec/foundation/serialize'; +import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize'; import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; import { type BlockStore } from './block_store.js'; @@ -24,7 +29,7 @@ export class LogStore { #logsByTag: AztecMap; #logTagsByBlock: AztecMap; #privateLogsByBlock: AztecMap; - #unencryptedLogsByBlock: AztecMap; + #publicLogsByBlock: AztecMap; #contractClassLogsByBlock: AztecMap; #logsMaxPageSize: number; #log = createLogger('archiver:log_store'); @@ -33,7 +38,7 @@ export class LogStore { this.#logsByTag = db.openMap('archiver_tagged_logs_by_tag'); this.#logTagsByBlock = db.openMap('archiver_log_tags_by_block'); this.#privateLogsByBlock = db.openMap('archiver_private_logs_by_block'); - this.#unencryptedLogsByBlock = db.openMap('archiver_unencrypted_logs_by_block'); + this.#publicLogsByBlock = db.openMap('archiver_public_logs_by_block'); this.#contractClassLogsByBlock = db.openMap('archiver_contract_class_logs_by_block'); this.#logsMaxPageSize = logsMaxPageSize; @@ -70,39 +75,48 @@ export class LogStore { const dataStartIndexForBlock = block.header.state.partial.noteHashTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX; - block.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => { - const txHash = block.body.txEffects[txIndex].txHash; + block.body.txEffects.forEach((txEffect, txIndex) => { + const txHash = txEffect.txHash; const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; - const logs = txLogs.unrollLogs(); - logs.forEach(log => { - if (log.data.length < 32 * 33) { - // TODO remove when #9835 and #9836 are fixed - this.#log.warn(`Skipping unencrypted log with insufficient data length: ${log.data.length}`); + txEffect.publicLogs.forEach(log => { + // Check that each log stores 3 lengths in its first field. If not, it's not a tagged log: + const firstFieldBuf = log.log[0].toBuffer(); + if ( + !firstFieldBuf.subarray(0, 24).equals(Buffer.alloc(24)) || + firstFieldBuf[26] !== 0 || + firstFieldBuf[29] !== 0 + ) { + // See parseLogFromPublic - the first field of a tagged log is 8 bytes structured: + // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]] + this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`); return; } - try { - // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields. - // This means that for every 32 bytes of payload, we only have 1 byte of data. - // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32. - const correctedBuffer = Buffer.alloc(32); - const initialOffset = 32; - for (let i = 0; i < 32; i++) { - const byte = Fr.fromBuffer( - log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset), - ).toNumber(); - correctedBuffer.writeUInt8(byte, i); - } - const tag = new Fr(correctedBuffer); - - this.#log.debug(`Found tagged unencrypted log with tag ${tag.toString()} in block ${block.number}`); - const currentLogs = taggedLogs.get(tag.toString()) ?? []; - currentLogs.push( - new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.data).toBuffer(), - ); - taggedLogs.set(tag.toString(), currentLogs); - } catch (err) { - this.#log.warn(`Failed to add tagged log to store: ${err}`); + // Check that the length values line up with the log contents + const publicValuesLength = firstFieldBuf.subarray(-8).readUint16BE(); + const privateValuesLength = firstFieldBuf.subarray(-8).readUint16BE(3); + // Add 1 for the first field holding lengths + const totalLogLength = 1 + publicValuesLength + privateValuesLength; + // Note that zeroes can be valid log values, so we can only assert that we do not go over the given length + if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find(f => !f.isZero())) { + this.#log.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`); + return; } + + // The first elt stores lengths as above => tag is in fields[1] + const tag = log.log[1]; + + this.#log.debug(`Found tagged public log with tag ${tag.toString()} in block ${block.number}`); + const currentLogs = taggedLogs.get(tag.toString()) ?? []; + currentLogs.push( + new TxScopedL2Log( + txHash, + dataStartIndexForTx, + block.number, + /* isFromPublic */ true, + log.toBuffer(), + ).toBuffer(), + ); + taggedLogs.set(tag.toString(), currentLogs); }); }); return taggedLogs; @@ -150,7 +164,17 @@ export class LogStore { .map(log => log.toBuffer()); void this.#privateLogsByBlock.set(block.number, Buffer.concat(privateLogsInBlock)); - void this.#unencryptedLogsByBlock.set(block.number, block.body.unencryptedLogs.toBuffer()); + const publicLogsInBlock = block.body.txEffects + .map((txEffect, txIndex) => + [ + numToUInt32BE(txIndex), + numToUInt32BE(txEffect.publicLogs.length), + txEffect.publicLogs.map(log => log.toBuffer()), + ].flat(), + ) + .flat(); + + void this.#publicLogsByBlock.set(block.number, Buffer.concat(publicLogsInBlock)); void this.#contractClassLogsByBlock.set(block.number, block.body.contractClassLogs.toBuffer()); }); @@ -165,7 +189,7 @@ export class LogStore { return this.db.transaction(() => { blocks.forEach(block => { void this.#privateLogsByBlock.delete(block.number); - void this.#unencryptedLogsByBlock.delete(block.number); + void this.#publicLogsByBlock.delete(block.number); void this.#logTagsByBlock.delete(block.number); }); @@ -209,21 +233,21 @@ export class LogStore { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): GetUnencryptedLogsResponse { + getPublicLogs(filter: LogFilter): GetPublicLogsResponse { if (filter.afterLog) { - return this.#filterUnencryptedLogsBetweenBlocks(filter); + return this.#filterPublicLogsBetweenBlocks(filter); } else if (filter.txHash) { - return this.#filterUnencryptedLogsOfTx(filter); + return this.#filterPublicLogsOfTx(filter); } else { - return this.#filterUnencryptedLogsBetweenBlocks(filter); + return this.#filterPublicLogsBetweenBlocks(filter); } } - #filterUnencryptedLogsOfTx(filter: LogFilter): GetUnencryptedLogsResponse { + #filterPublicLogsOfTx(filter: LogFilter): GetPublicLogsResponse { if (!filter.txHash) { throw new Error('Missing txHash'); } @@ -233,18 +257,27 @@ export class LogStore { return { logs: [], maxLogsHit: false }; } - const buffer = this.#unencryptedLogsByBlock.get(blockNumber) ?? Buffer.alloc(0); - const unencryptedLogsInBlock = UnencryptedL2BlockL2Logs.fromBuffer(buffer); + const buffer = this.#publicLogsByBlock.get(blockNumber) ?? Buffer.alloc(0); + const publicLogsInBlock: [PublicLog[]] = [[]]; + const reader = new BufferReader(buffer); + while (reader.remainingBytes() > 0) { + const indexOfTx = reader.readNumber(); + const numLogsInTx = reader.readNumber(); + publicLogsInBlock[indexOfTx] = []; + for (let i = 0; i < numLogsInTx; i++) { + publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog)); + } + } - const txLogs = unencryptedLogsInBlock.txLogs[txIndex].unrollLogs(); + const txLogs = publicLogsInBlock[txIndex]; - const logs: ExtendedUnencryptedL2Log[] = []; + const logs: ExtendedPublicLog[] = []; const maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter); return { logs, maxLogsHit }; } - #filterUnencryptedLogsBetweenBlocks(filter: LogFilter): GetUnencryptedLogsResponse { + #filterPublicLogsBetweenBlocks(filter: LogFilter): GetPublicLogsResponse { const start = filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM); const end = filter.toBlock; @@ -256,13 +289,22 @@ export class LogStore { }; } - const logs: ExtendedUnencryptedL2Log[] = []; + const logs: ExtendedPublicLog[] = []; let maxLogsHit = false; - loopOverBlocks: for (const [blockNumber, logBuffer] of this.#unencryptedLogsByBlock.entries({ start, end })) { - const unencryptedLogsInBlock = UnencryptedL2BlockL2Logs.fromBuffer(logBuffer); - for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < unencryptedLogsInBlock.txLogs.length; txIndex++) { - const txLogs = unencryptedLogsInBlock.txLogs[txIndex].unrollLogs(); + loopOverBlocks: for (const [blockNumber, logBuffer] of this.#publicLogsByBlock.entries({ start, end })) { + const publicLogsInBlock: [PublicLog[]] = [[]]; + const reader = new BufferReader(logBuffer); + while (reader.remainingBytes() > 0) { + const indexOfTx = reader.readNumber(); + const numLogsInTx = reader.readNumber(); + publicLogsInBlock[indexOfTx] = []; + for (let i = 0; i < numLogsInTx; i++) { + publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog)); + } + } + for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < publicLogsInBlock.length; txIndex++) { + const txLogs = publicLogsInBlock[txIndex]; maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter); if (maxLogsHit) { this.#log.debug(`Max logs hit at block ${blockNumber}`); @@ -279,7 +321,7 @@ export class LogStore { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): GetUnencryptedLogsResponse { + getContractClassLogs(filter: LogFilter): GetContractClassLogsResponse { if (filter.afterLog) { return this.#filterContractClassLogsBetweenBlocks(filter); } else if (filter.txHash) { @@ -289,7 +331,7 @@ export class LogStore { } } - #filterContractClassLogsOfTx(filter: LogFilter): GetUnencryptedLogsResponse { + #filterContractClassLogsOfTx(filter: LogFilter): GetContractClassLogsResponse { if (!filter.txHash) { throw new Error('Missing txHash'); } @@ -310,7 +352,7 @@ export class LogStore { return { logs, maxLogsHit }; } - #filterContractClassLogsBetweenBlocks(filter: LogFilter): GetUnencryptedLogsResponse { + #filterContractClassLogsBetweenBlocks(filter: LogFilter): GetContractClassLogsResponse { const start = filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM); const end = filter.toBlock; @@ -341,10 +383,10 @@ export class LogStore { } #accumulateLogs( - results: ExtendedUnencryptedL2Log[], + results: (ExtendedUnencryptedL2Log | ExtendedPublicLog)[], blockNumber: number, txIndex: number, - txLogs: UnencryptedL2Log[], + txLogs: (UnencryptedL2Log | PublicLog)[], filter: LogFilter, ): boolean { let maxLogsHit = false; @@ -352,7 +394,12 @@ export class LogStore { for (; logIndex < txLogs.length; logIndex++) { const log = txLogs[logIndex]; if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) { - results.push(new ExtendedUnencryptedL2Log(new LogId(blockNumber, txIndex, logIndex), log)); + if (log instanceof UnencryptedL2Log) { + results.push(new ExtendedUnencryptedL2Log(new LogId(blockNumber, txIndex, logIndex), log)); + } else { + results.push(new ExtendedPublicLog(new LogId(blockNumber, txIndex, logIndex), log)); + } + if (results.length >= this.#logsMaxPageSize) { maxLogsHit = true; break; 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 c74b572761d..125a6132bc9 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 @@ -14,7 +14,7 @@ describe('MemoryArchiverStore', () => { describeArchiverDataStore('implements ArchiverStore', () => archiverStore); - describe('getUnencryptedLogs config', () => { + describe('getPublicLogs config', () => { it('does not return more than "maxLogs" logs', async () => { const maxLogs = 5; archiverStore = new MemoryArchiverStore(maxLogs); @@ -26,7 +26,7 @@ describe('MemoryArchiverStore', () => { await archiverStore.addBlocks(blocks); await archiverStore.addLogs(blocks.map(b => b.data)); - const response = await archiverStore.getUnencryptedLogs({}); + const response = await archiverStore.getPublicLogs({}); expect(response.maxLogsHit).toBeTruthy(); expect(response.logs.length).toEqual(maxLogs); 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 a5d5ed7c242..cf4de2ae1ad 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 @@ -1,7 +1,9 @@ import { type ContractClass2BlockL2Logs, + ExtendedPublicLog, ExtendedUnencryptedL2Log, - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, type InboxLeaf, type L2Block, @@ -12,7 +14,6 @@ import { type TxHash, TxReceipt, TxScopedL2Log, - type UnencryptedL2BlockL2Logs, wrapInBlock, } from '@aztec/circuit-types'; import { @@ -25,7 +26,9 @@ import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, type PrivateLog, + type PublicLog, type UnconstrainedFunctionWithMembershipProof, } from '@aztec/circuits.js'; import { FunctionSelector } from '@aztec/foundation/abi'; @@ -57,7 +60,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { private privateLogsPerBlock: Map = new Map(); - private unencryptedLogsPerBlock: Map = new Map(); + private publicLogsPerBlock: Map = new Map(); private contractClassLogsPerBlock: Map = new Map(); @@ -89,7 +92,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { #log = createLogger('archiver:data-store'); constructor( - /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */ + /** The max number of logs that can be obtained in 1 "getPublicLogs" call. */ public readonly maxLogs: number, ) {} @@ -249,43 +252,43 @@ export class MemoryArchiverStore implements ArchiverDataStore { const dataStartIndexForBlock = block.header.state.partial.noteHashTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX; - block.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => { - const txHash = block.body.txEffects[txIndex].txHash; + block.body.txEffects.forEach((txEffect, txIndex) => { + const txHash = txEffect.txHash; const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; - const logs = txLogs.unrollLogs(); - logs.forEach(log => { + txEffect.publicLogs.forEach(log => { + // Check that each log stores 3 lengths in its first field. If not, it's not a tagged log: + const firstFieldBuf = log.log[0].toBuffer(); if ( - // TODO remove when #9835 and #9836 are fixed - log.data.length < - 32 * 33 + !firstFieldBuf.subarray(0, 24).equals(Buffer.alloc(24)) || + firstFieldBuf[26] !== 0 || + firstFieldBuf[29] !== 0 ) { - this.#log.warn(`Skipping unencrypted log with invalid data length: ${log.data.length}`); + // See parseLogFromPublic - the first field of a tagged log is 8 bytes structured: + // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]] + this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`); return; } - try { - // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields. - // This means that for every 32 bytes of payload, we only have 1 byte of data. - // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32. - const correctedBuffer = Buffer.alloc(32); - const initialOffset = 32; - for (let i = 0; i < 32; i++) { - const byte = Fr.fromBuffer( - log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset), - ).toNumber(); - correctedBuffer.writeUInt8(byte, i); - } - const tag = new Fr(correctedBuffer); - this.#log.verbose(`Storing unencrypted tagged log with tag ${tag.toString()} in block ${block.number}`); - const currentLogs = this.taggedLogs.get(tag.toString()) || []; - this.taggedLogs.set(tag.toString(), [ - ...currentLogs, - new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.data), - ]); - const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || []; - this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]); - } catch (err) { - this.#log.warn(`Failed to add tagged log to store: ${err}`); + // Check that the length values line up with the log contents + const publicValuesLength = firstFieldBuf.subarray(-8).readUint16BE(); + const privateValuesLength = firstFieldBuf.subarray(-8).readUint16BE(3); + // Add 1 for the first field holding lengths + const totalLogLength = 1 + publicValuesLength + privateValuesLength; + // Note that zeroes can be valid log values, so we can only assert that we do not go over the given length + if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find(f => !f.isZero())) { + this.#log.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`); + return; } + + // The first elt stores lengths => tag is in fields[1] + const tag = log.log[1]; + this.#log.verbose(`Storing public tagged log with tag ${tag.toString()} in block ${block.number}`); + const currentLogs = this.taggedLogs.get(tag.toString()) || []; + this.taggedLogs.set(tag.toString(), [ + ...currentLogs, + new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.toBuffer()), + ]); + const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || []; + this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]); }); }); } @@ -300,7 +303,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { void this.#storeTaggedLogsFromPrivate(block); void this.#storeTaggedLogsFromPublic(block); this.privateLogsPerBlock.set(block.number, block.body.txEffects.map(txEffect => txEffect.privateLogs).flat()); - this.unencryptedLogsPerBlock.set(block.number, block.body.unencryptedLogs); + this.publicLogsPerBlock.set(block.number, block.body.txEffects.map(txEffect => txEffect.publicLogs).flat()); this.contractClassLogsPerBlock.set(block.number, block.body.contractClassLogs); }); return Promise.resolve(true); @@ -316,7 +319,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { blocks.forEach(block => { this.privateLogsPerBlock.delete(block.number); - this.unencryptedLogsPerBlock.delete(block.number); + this.publicLogsPerBlock.delete(block.number); this.logTagsPerBlock.delete(block.number); this.contractClassLogsPerBlock.delete(block.number); }); @@ -518,12 +521,12 @@ export class MemoryArchiverStore implements ArchiverDataStore { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. * @remarks Works by doing an intersection of all params in the filter. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getPublicLogs(filter: LogFilter): Promise { let txHash: TxHash | undefined; let fromBlock = 0; let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM; @@ -564,34 +567,34 @@ export class MemoryArchiverStore implements ArchiverDataStore { const contractAddress = filter.contractAddress; - const logs: ExtendedUnencryptedL2Log[] = []; + const logs: ExtendedPublicLog[] = []; for (; fromBlock < toBlock; fromBlock++) { const block = this.l2Blocks[fromBlock - INITIAL_L2_BLOCK_NUM]; - const blockLogs = this.unencryptedLogsPerBlock.get(fromBlock); + const blockLogs = this.publicLogsPerBlock.get(fromBlock); if (blockLogs) { - for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) { - const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs(); - for (; logIndexInTx < txLogs.length; logIndexInTx++) { - const log = txLogs[logIndexInTx]; - if ( - (!txHash || block.data.body.txEffects[txIndexInBlock].txHash.equals(txHash)) && - (!contractAddress || log.contractAddress.equals(contractAddress)) - ) { - logs.push(new ExtendedUnencryptedL2Log(new LogId(block.data.number, txIndexInBlock, logIndexInTx), log)); - if (logs.length === this.maxLogs) { - return Promise.resolve({ - logs, - maxLogsHit: true, - }); - } + for (let logIndex = 0; logIndex < blockLogs.length; logIndex++) { + const log = blockLogs[logIndex]; + const thisTxEffect = block.data.body.txEffects.filter(effect => effect.publicLogs.includes(log))[0]; + const thisTxIndexInBlock = block.data.body.txEffects.indexOf(thisTxEffect); + const thisLogIndexInTx = thisTxEffect.publicLogs.indexOf(log); + if ( + (!txHash || thisTxEffect.txHash.equals(txHash)) && + (!contractAddress || log.contractAddress.equals(contractAddress)) && + thisTxIndexInBlock >= txIndexInBlock && + thisLogIndexInTx >= logIndexInTx + ) { + logs.push(new ExtendedPublicLog(new LogId(block.data.number, thisTxIndexInBlock, thisLogIndexInTx), log)); + if (logs.length === this.maxLogs) { + return Promise.resolve({ + logs, + maxLogsHit: true, + }); } } - logIndexInTx = 0; } } - txIndexInBlock = 0; } return Promise.resolve({ @@ -607,7 +610,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns The requested logs. * @remarks Works by doing an intersection of all params in the filter. */ - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { let txHash: TxHash | undefined; let fromBlock = 0; let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM; diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 83a73c1335e..62a075c88c1 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -5,7 +5,8 @@ import { type AztecNode, type ClientProtocolCircuitVerifier, type EpochProofQuote, - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, type L1ToL2MessageSource, type L2Block, @@ -402,12 +403,12 @@ export class AztecNodeService implements AztecNode, Traceable { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { - return this.logsSource.getUnencryptedLogs(filter); + getPublicLogs(filter: LogFilter): Promise { + return this.logsSource.getPublicLogs(filter); } /** @@ -415,7 +416,7 @@ export class AztecNodeService implements AztecNode, Traceable { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { return this.logsSource.getContractClassLogs(filter); } diff --git a/yarn-project/aztec.js/src/contract/proven_tx.ts b/yarn-project/aztec.js/src/contract/proven_tx.ts index bb22cc14ddb..b024d4ca86e 100644 --- a/yarn-project/aztec.js/src/contract/proven_tx.ts +++ b/yarn-project/aztec.js/src/contract/proven_tx.ts @@ -11,7 +11,6 @@ export class ProvenTx extends Tx { super( tx.data, tx.clientIvcProof, - tx.unencryptedLogs, tx.contractClassLogs, tx.enqueuedPublicFunctionCalls, tx.publicTeardownFunctionCall, @@ -23,7 +22,6 @@ export class ProvenTx extends Tx { return new Tx( this.data, this.clientIvcProof, - this.unencryptedLogs, this.contractClassLogs, this.enqueuedPublicFunctionCalls, this.publicTeardownFunctionCall, diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index 99c4eec8650..6d9ad2ddc32 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -1,4 +1,4 @@ -import { type GetUnencryptedLogsResponse, type PXE, type TxHash, type TxReceipt, TxStatus } from '@aztec/circuit-types'; +import { type GetPublicLogsResponse, type PXE, type TxHash, type TxReceipt, TxStatus } from '@aztec/circuit-types'; import { retryUntil } from '@aztec/foundation/retry'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -87,13 +87,13 @@ export class SentTx { } /** - * Gets unencrypted logs emitted by this tx. + * Gets public logs emitted by this tx. * @remarks This function will wait for the tx to be mined if it hasn't been already. * @returns The requested logs. */ - public async getUnencryptedLogs(): Promise { + public async getPublicLogs(): Promise { await this.wait(); - return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() }); + return this.pxe.getPublicLogs({ txHash: await this.getTxHash() }); } protected async waitForReceipt(opts?: WaitOpts): Promise { diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index fc1a49e5adb..8e066e7412d 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -117,7 +117,6 @@ export { TxHash, TxReceipt, TxStatus, - UnencryptedL2BlockL2Logs, UnencryptedL2Log, UniqueNote, createAztecNodeClient, diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 47b431f4ae2..9c40a53412d 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -2,7 +2,8 @@ import { type AuthWitness, type EventMetadataDefinition, type ExtendedNote, - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type L2Block, type LogFilter, type NotesFilter, @@ -160,10 +161,10 @@ export abstract class BaseWallet implements Wallet { ): Promise { return this.pxe.simulateUnconstrained(functionName, args, to, from); } - getUnencryptedLogs(filter: LogFilter): Promise { - return this.pxe.getUnencryptedLogs(filter); + getPublicLogs(filter: LogFilter): Promise { + return this.pxe.getPublicLogs(filter); } - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { return this.pxe.getContractClassLogs(filter); } getBlockNumber(): Promise { @@ -193,16 +194,16 @@ export abstract class BaseWallet implements Wallet { getPXEInfo(): Promise { return this.pxe.getPXEInfo(); } - getEncryptedEvents( + getPrivateEvents( event: EventMetadataDefinition, from: number, limit: number, vpks: Point[] = [this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey], ): Promise { - return this.pxe.getEncryptedEvents(event, from, limit, vpks); + return this.pxe.getPrivateEvents(event, from, limit, vpks); } - getUnencryptedEvents(event: EventMetadataDefinition, from: number, limit: number): Promise { - return this.pxe.getUnencryptedEvents(event, from, limit); + getPublicEvents(event: EventMetadataDefinition, from: number, limit: number): Promise { + return this.pxe.getPublicEvents(event, from, limit); } public getL1ToL2MembershipWitness( contractAddress: AztecAddress, diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index feb7581be9e..b2532672786 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -4,7 +4,7 @@ import { MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_PUBLIC_LOGS_PER_TX, VerificationKeyData, } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; @@ -93,12 +93,12 @@ describe('AVM WitGen, "check circuit" tests', () => { TIMEOUT, ); it( - 'create too many unencrypted logs and revert', + 'create too many public logs and revert', async () => { await proveAndVerifyAvmTestContractSimple( /*checkCircuitOnly=*/ true, // quick 'n_new_unencrypted_logs', - /*args=*/ [new Fr(MAX_UNENCRYPTED_LOGS_PER_TX + 1)], + /*args=*/ [new Fr(MAX_PUBLIC_LOGS_PER_TX + 1)], /*expectRevert=*/ true, ); }, diff --git a/yarn-project/bb-prover/src/test/test_avm.ts b/yarn-project/bb-prover/src/test/test_avm.ts index b94488520cd..a45710afb87 100644 --- a/yarn-project/bb-prover/src/test/test_avm.ts +++ b/yarn-project/bb-prover/src/test/test_avm.ts @@ -6,7 +6,6 @@ import { Gas, GlobalVariables, L2ToL1Message, - LogHash, MAX_ENQUEUED_CALLS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, @@ -17,11 +16,12 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL, + MAX_PUBLIC_LOGS_PER_CALL, NoteHash, Nullifier, PublicCircuitPublicInputs, PublicInnerCallRequest, + PublicLog, ReadRequest, RevertCode, TreeLeafReadRequest, @@ -73,7 +73,7 @@ export function getPublicInputs(result: PublicFunctionCallResult): PublicCircuit MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ), publicCallRequests: padArrayEnd([], PublicInnerCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_CALL), - unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL), + publicLogs: padArrayEnd(result.publicLogs, PublicLog.empty(), MAX_PUBLIC_LOGS_PER_CALL), historicalHeader: BlockHeader.empty(), globalVariables: GlobalVariables.empty(), startGasLeft: Gas.from(result.startGasLeft), diff --git a/yarn-project/circuit-types/src/body.test.ts b/yarn-project/circuit-types/src/body.test.ts index e5b3eb52698..d28ae42c478 100644 --- a/yarn-project/circuit-types/src/body.test.ts +++ b/yarn-project/circuit-types/src/body.test.ts @@ -13,7 +13,7 @@ describe('Body', () => { const body = Body.random(); const fields = body.toBlobFields(); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here - expect(Body.fromBlobFields(fields, body.unencryptedLogs, body.contractClassLogs)).toEqual(body); + expect(Body.fromBlobFields(fields, body.contractClassLogs)).toEqual(body); }); it('converts empty to and from fields', () => { diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 23247071c15..5722e1405e9 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -5,7 +5,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { inspect } from 'util'; import { z } from 'zod'; -import { ContractClass2BlockL2Logs, UnencryptedL2BlockL2Logs } from './logs/index.js'; +import { ContractClass2BlockL2Logs } from './logs/index.js'; import { TxEffect } from './tx_effect.js'; export class Body { @@ -59,11 +59,7 @@ export class Body { * TODO(#8954): When logs are refactored into fields, we won't need to inject them here, instead just reading from fields in TxEffect.fromBlobFields. * Logs are best input by gathering from the getters below, as they don't remove empty log arrays. */ - static fromBlobFields( - fields: Fr[], - unencryptedLogs?: UnencryptedL2BlockL2Logs, - contractClassLogs?: ContractClass2BlockL2Logs, - ) { + static fromBlobFields(fields: Fr[], contractClassLogs?: ContractClass2BlockL2Logs) { const txEffectsFields: Fr[][] = []; let checkedFields = 0; while (checkedFields !== fields.length) { @@ -76,7 +72,7 @@ export class Body { } const txEffects = txEffectsFields .filter(effect => effect.length) - .map((effect, i) => TxEffect.fromBlobFields(effect, unencryptedLogs?.txLogs[i], contractClassLogs?.txLogs[i])); + .map((effect, i) => TxEffect.fromBlobFields(effect, contractClassLogs?.txLogs[i])); return new this(txEffects); } @@ -86,22 +82,14 @@ export class Body { }`; } - get unencryptedLogs(): UnencryptedL2BlockL2Logs { - const logs = this.txEffects.map(txEffect => txEffect.unencryptedLogs); - - return new UnencryptedL2BlockL2Logs(logs); - } - get contractClassLogs(): ContractClass2BlockL2Logs { const logs = this.txEffects.map(txEffect => txEffect.contractClassLogs); return new ContractClass2BlockL2Logs(logs); } - static random(txsPerBlock = 4, numPublicCallsPerTx = 3, numUnencryptedLogsPerCall = 1) { - const txEffects = [...new Array(txsPerBlock)].map(_ => - TxEffect.random(numPublicCallsPerTx, numUnencryptedLogsPerCall), - ); + static random(txsPerBlock = 4, numPublicCallsPerTx = 3, numPublicLogsPerCall = 1) { + const txEffects = [...new Array(txsPerBlock)].map(_ => TxEffect.random(numPublicCallsPerTx, numPublicLogsPerCall)); return new Body(txEffects); } diff --git a/yarn-project/circuit-types/src/interfaces/archiver.test.ts b/yarn-project/circuit-types/src/interfaces/archiver.test.ts index de3c342927d..8f522fe4cfd 100644 --- a/yarn-project/circuit-types/src/interfaces/archiver.test.ts +++ b/yarn-project/circuit-types/src/interfaces/archiver.test.ts @@ -25,8 +25,13 @@ import { EmptyL1RollupConstants, type L1RollupConstants } from '../epoch-helpers import { type InBlock, randomInBlock } from '../in_block.js'; import { L2Block } from '../l2_block.js'; import { type L2Tips } from '../l2_block_source.js'; +import { ExtendedPublicLog } from '../logs/extended_public_log.js'; import { ExtendedUnencryptedL2Log } from '../logs/extended_unencrypted_l2_log.js'; -import { type GetUnencryptedLogsResponse, TxScopedL2Log } from '../logs/get_logs_response.js'; +import { + type GetContractClassLogsResponse, + type GetPublicLogsResponse, + TxScopedL2Log, +} from '../logs/get_logs_response.js'; import { type LogFilter } from '../logs/log_filter.js'; import { TxHash } from '../tx/tx_hash.js'; import { TxReceipt } from '../tx/tx_receipt.js'; @@ -161,12 +166,12 @@ describe('ArchiverApiSchema', () => { expect(result).toEqual([[expect.any(TxScopedL2Log)]]); }); - it('getUnencryptedLogs', async () => { - const result = await context.client.getUnencryptedLogs({ + it('getPublicLogs', async () => { + const result = await context.client.getPublicLogs({ txHash: TxHash.random(), contractAddress: AztecAddress.random(), }); - expect(result).toEqual({ logs: [expect.any(ExtendedUnencryptedL2Log)], maxLogsHit: true }); + expect(result).toEqual({ logs: [expect.any(ExtendedPublicLog)], maxLogsHit: true }); }); it('getContractClassLogs', async () => { @@ -326,12 +331,12 @@ class MockArchiver implements ArchiverApi { expect(tags[0]).toBeInstanceOf(Fr); return Promise.resolve([Array.from({ length: tags.length }, () => TxScopedL2Log.random())]); } - getUnencryptedLogs(filter: LogFilter): Promise { + getPublicLogs(filter: LogFilter): Promise { expect(filter.txHash).toBeInstanceOf(TxHash); expect(filter.contractAddress).toBeInstanceOf(AztecAddress); - return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); + return Promise.resolve({ logs: [ExtendedPublicLog.random()], maxLogsHit: true }); } - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { expect(filter.txHash).toBeInstanceOf(TxHash); expect(filter.contractAddress).toBeInstanceOf(AztecAddress); return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); diff --git a/yarn-project/circuit-types/src/interfaces/archiver.ts b/yarn-project/circuit-types/src/interfaces/archiver.ts index e610fb7de81..9dee18253a7 100644 --- a/yarn-project/circuit-types/src/interfaces/archiver.ts +++ b/yarn-project/circuit-types/src/interfaces/archiver.ts @@ -14,7 +14,11 @@ import { L1RollupConstantsSchema } from '../epoch-helpers/index.js'; import { inBlockSchemaFor } from '../in_block.js'; import { L2Block } from '../l2_block.js'; import { type L2BlockSource, L2TipsSchema } from '../l2_block_source.js'; -import { GetUnencryptedLogsResponseSchema, TxScopedL2Log } from '../logs/get_logs_response.js'; +import { + GetContractClassLogsResponseSchema, + GetPublicLogsResponseSchema, + TxScopedL2Log, +} from '../logs/get_logs_response.js'; import { type L2LogsSource } from '../logs/l2_logs_source.js'; import { LogFilterSchema } from '../logs/log_filter.js'; import { type L1ToL2MessageSource } from '../messaging/l1_to_l2_message_source.js'; @@ -59,8 +63,8 @@ export const ArchiverApiSchema: ApiSchemaFor = { .function() .args(z.number(), z.array(schemas.Fr)) .returns(z.array(optional(inBlockSchemaFor(schemas.BigInt)))), - getUnencryptedLogs: z.function().args(LogFilterSchema).returns(GetUnencryptedLogsResponseSchema), - getContractClassLogs: z.function().args(LogFilterSchema).returns(GetUnencryptedLogsResponseSchema), + getPublicLogs: z.function().args(LogFilterSchema).returns(GetPublicLogsResponseSchema), + getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), getPublicFunction: z .function() .args(schemas.AztecAddress, schemas.FunctionSelector) diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts index b55f7275803..c7276545234 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts @@ -33,8 +33,13 @@ import { resolve } from 'path'; import { type InBlock, randomInBlock } from '../in_block.js'; import { L2Block } from '../l2_block.js'; import { type L2Tips } from '../l2_block_source.js'; +import { ExtendedPublicLog } from '../logs/extended_public_log.js'; import { ExtendedUnencryptedL2Log } from '../logs/extended_unencrypted_l2_log.js'; -import { type GetUnencryptedLogsResponse, TxScopedL2Log } from '../logs/get_logs_response.js'; +import { + type GetContractClassLogsResponse, + type GetPublicLogsResponse, + TxScopedL2Log, +} from '../logs/get_logs_response.js'; import { type LogFilter } from '../logs/log_filter.js'; import { MerkleTreeId } from '../merkle_tree_id.js'; import { EpochProofQuote } from '../prover_coordination/epoch_proof_quote.js'; @@ -233,9 +238,9 @@ describe('AztecNodeApiSchema', () => { expect(response).toEqual([expect.any(PrivateLog)]); }); - it('getUnencryptedLogs', async () => { - const response = await context.client.getUnencryptedLogs({ contractAddress: AztecAddress.random() }); - expect(response).toEqual({ logs: [expect.any(ExtendedUnencryptedL2Log)], maxLogsHit: true }); + it('getPublicLogs', async () => { + const response = await context.client.getPublicLogs({ contractAddress: AztecAddress.random() }); + expect(response).toEqual({ logs: [expect.any(ExtendedPublicLog)], maxLogsHit: true }); }); it('getContractClassLogs', async () => { @@ -516,11 +521,11 @@ class MockAztecNode implements AztecNode { getPrivateLogs(_from: number, _limit: number): Promise { return Promise.resolve([PrivateLog.random()]); } - getUnencryptedLogs(filter: LogFilter): Promise { + getPublicLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); - return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); + return Promise.resolve({ logs: [ExtendedPublicLog.random()], maxLogsHit: true }); } - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); } diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 621c3636e44..ac2fa964de7 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -28,8 +28,10 @@ import { type InBlock, inBlockSchemaFor } from '../in_block.js'; import { L2Block } from '../l2_block.js'; import { type L2BlockSource, type L2Tips, L2TipsSchema } from '../l2_block_source.js'; import { - type GetUnencryptedLogsResponse, - GetUnencryptedLogsResponseSchema, + type GetContractClassLogsResponse, + GetContractClassLogsResponseSchema, + type GetPublicLogsResponse, + GetPublicLogsResponseSchema, type LogFilter, LogFilterSchema, TxScopedL2Log, @@ -304,18 +306,18 @@ export interface AztecNode getPrivateLogs(from: number, limit: number): Promise; /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getPublicLogs(filter: LogFilter): Promise; /** * Gets contract class logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise; + getContractClassLogs(filter: LogFilter): Promise; /** * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag). @@ -544,9 +546,9 @@ export const AztecNodeApiSchema: ApiSchemaFor = { getPrivateLogs: z.function().args(z.number(), z.number()).returns(z.array(PrivateLog.schema)), - getUnencryptedLogs: z.function().args(LogFilterSchema).returns(GetUnencryptedLogsResponseSchema), + getPublicLogs: z.function().args(LogFilterSchema).returns(GetPublicLogsResponseSchema), - getContractClassLogs: z.function().args(LogFilterSchema).returns(GetUnencryptedLogsResponseSchema), + getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), getLogsByTags: z .function() diff --git a/yarn-project/circuit-types/src/interfaces/pxe.test.ts b/yarn-project/circuit-types/src/interfaces/pxe.test.ts index 8cd0b35ee90..af272a58f0b 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.test.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.test.ts @@ -33,7 +33,13 @@ import { resolve } from 'path'; import { AuthWitness } from '../auth_witness.js'; import { type InBlock } from '../in_block.js'; import { L2Block } from '../l2_block.js'; -import { ExtendedUnencryptedL2Log, type GetUnencryptedLogsResponse, type LogFilter } from '../logs/index.js'; +import { + ExtendedPublicLog, + ExtendedUnencryptedL2Log, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, + type LogFilter, +} from '../logs/index.js'; import { ExtendedNote, UniqueNote } from '../notes/index.js'; import { type NotesFilter } from '../notes/notes_filter.js'; import { PrivateExecutionResult } from '../private_execution_result.js'; @@ -228,9 +234,9 @@ describe('PXESchema', () => { expect(result).toEqual(10n); }); - it('getUnencryptedLogs', async () => { - const result = await context.client.getUnencryptedLogs({ contractAddress: address }); - expect(result).toEqual({ logs: [expect.any(ExtendedUnencryptedL2Log)], maxLogsHit: true }); + it('getPublicLogs', async () => { + const result = await context.client.getPublicLogs({ contractAddress: address }); + expect(result).toEqual({ logs: [expect.any(ExtendedPublicLog)], maxLogsHit: true }); }); it('getContractClassLogs', async () => { @@ -289,8 +295,8 @@ describe('PXESchema', () => { expect(result).toBe(true); }); - it('getEncryptedEvents', async () => { - const result = await context.client.getEncryptedEvents( + it('getPrivateEvents', async () => { + const result = await context.client.getPrivateEvents( { abiType: { kind: 'boolean' }, eventSelector: EventSelector.random(), fieldNames: ['name'] }, 1, 1, @@ -299,8 +305,8 @@ describe('PXESchema', () => { expect(result).toEqual([{ value: 1n }]); }); - it('getUnencryptedEvents', async () => { - const result = await context.client.getUnencryptedEvents( + it('getPublicEvents', async () => { + const result = await context.client.getPublicEvents( { abiType: { kind: 'boolean' }, eventSelector: EventSelector.random(), fieldNames: ['name'] }, 1, 1, @@ -460,11 +466,11 @@ class MockPXE implements PXE { expect(scopes).toEqual([this.address]); return Promise.resolve(10n); } - getUnencryptedLogs(filter: LogFilter): Promise { + getPublicLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toEqual(this.address); - return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); + return Promise.resolve({ logs: [ExtendedPublicLog.random()], maxLogsHit: true }); } - getContractClassLogs(filter: LogFilter): Promise { + getContractClassLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toEqual(this.address); return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); } @@ -523,7 +529,7 @@ class MockPXE implements PXE { expect(address).toEqual(this.address); return Promise.resolve(true); } - getEncryptedEvents( + getPrivateEvents( _eventMetadata: EventMetadataDefinition, from: number, limit: number, @@ -534,7 +540,7 @@ class MockPXE implements PXE { expect(vpks[0]).toBeInstanceOf(Point); return Promise.resolve([{ value: 1n } as T]); } - getUnencryptedEvents(_eventMetadata: EventMetadataDefinition, from: number, limit: number): Promise { + getPublicEvents(_eventMetadata: EventMetadataDefinition, from: number, limit: number): Promise { expect(from).toBe(1); expect(limit).toBe(1); return Promise.resolve([{ value: 1n } as T]); diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 1cfaa5af4e9..f25b8249bc6 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -31,8 +31,10 @@ import { AuthWitness } from '../auth_witness.js'; import { type InBlock, inBlockSchemaFor } from '../in_block.js'; import { L2Block } from '../l2_block.js'; import { - type GetUnencryptedLogsResponse, - GetUnencryptedLogsResponseSchema, + type GetContractClassLogsResponse, + GetContractClassLogsResponseSchema, + type GetPublicLogsResponse, + GetPublicLogsResponseSchema, type LogFilter, LogFilterSchema, } from '../logs/index.js'; @@ -313,18 +315,18 @@ export interface PXE { ): Promise; /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getPublicLogs(filter: LogFilter): Promise; /** * Gets contract class logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise; + getContractClassLogs(filter: LogFilter): Promise; /** * Fetches the current block number. @@ -396,28 +398,23 @@ export interface PXE { isContractInitialized(address: AztecAddress): Promise; /** - * Returns the encrypted events given search parameters. + * Returns the private events given search parameters. * @param eventMetadata - Metadata of the event. This should be the class generated from the contract. e.g. Contract.events.Event * @param from - The block number to search from. * @param limit - The amount of blocks to search. * @param vpks - The incoming viewing public keys that can decrypt the log. * @returns - The deserialized events. */ - getEncryptedEvents( - eventMetadata: EventMetadataDefinition, - from: number, - limit: number, - vpks: Point[], - ): Promise; + getPrivateEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number, vpks: Point[]): Promise; /** - * Returns the unencrypted events given search parameters. + * Returns the public events given search parameters. * @param eventMetadata - Metadata of the event. This should be the class generated from the contract. e.g. Contract.events.Event * @param from - The block number to search from. * @param limit - The amount of blocks to search. * @returns - The deserialized events. */ - getUnencryptedEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number): Promise; + getPublicEvents(eventMetadata: EventMetadataDefinition, from: number, limit: number): Promise; } // docs:end:pxe-interface @@ -518,8 +515,8 @@ export const PXESchema: ApiSchemaFor = { optional(z.array(schemas.AztecAddress)), ) .returns(AbiDecodedSchema), - getUnencryptedLogs: z.function().args(LogFilterSchema).returns(GetUnencryptedLogsResponseSchema), - getContractClassLogs: z.function().args(LogFilterSchema).returns(GetUnencryptedLogsResponseSchema), + getPublicLogs: z.function().args(LogFilterSchema).returns(GetPublicLogsResponseSchema), + getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), getBlockNumber: z.function().returns(z.number()), getProvenBlockNumber: z.function().returns(z.number()), getNodeInfo: z.function().returns(NodeInfoSchema), @@ -539,11 +536,11 @@ export const PXESchema: ApiSchemaFor = { isContractClassPubliclyRegistered: z.function().args(schemas.Fr).returns(z.boolean()), isContractPubliclyDeployed: z.function().args(schemas.AztecAddress).returns(z.boolean()), isContractInitialized: z.function().args(schemas.AztecAddress).returns(z.boolean()), - getEncryptedEvents: z + getPrivateEvents: z .function() .args(EventMetadataDefinitionSchema, z.number(), z.number(), z.array(schemas.Point)) .returns(z.array(AbiDecodedSchema)), - getUnencryptedEvents: z + getPublicEvents: z .function() .args(EventMetadataDefinitionSchema, z.number(), z.number()) .returns(z.array(AbiDecodedSchema)), diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index 3f60c192461..5ae6db38f4f 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -75,7 +75,7 @@ export class L2Block { * @param l2BlockNum - The number of the L2 block. * @param txsPerBlock - The number of transactions to include in the block. * @param numPublicCallsPerTx - The number of public function calls to include in each transaction. - * @param numUnencryptedLogsPerCall - The number of unencrypted logs per 1 public function invocation. + * @param numPublicLogsPerCall - The number of public logs per 1 public function invocation. * @param inHash - The hash of the L1 to L2 messages subtree which got inserted in this block. * @returns The L2 block. */ @@ -83,11 +83,11 @@ export class L2Block { l2BlockNum: number, txsPerBlock = 4, numPublicCallsPerTx = 3, - numUnencryptedLogsPerCall = 1, + numPublicLogsPerCall = 1, inHash: Buffer | undefined = undefined, slotNumber: number | undefined = undefined, ): L2Block { - const body = Body.random(txsPerBlock, numPublicCallsPerTx, numUnencryptedLogsPerCall); + const body = Body.random(txsPerBlock, numPublicCallsPerTx, numPublicLogsPerCall); return new L2Block( makeAppendOnlyTreeSnapshot(l2BlockNum + 1), @@ -181,14 +181,8 @@ export class L2Block { */ getStats() { const logsStats = { - unencryptedLogCount: this.body.txEffects.reduce( - (logCount, txEffect) => logCount + txEffect.unencryptedLogs.getTotalLogCount(), - 0, - ), - unencryptedLogSize: this.body.txEffects.reduce( - (logCount, txEffect) => logCount + txEffect.unencryptedLogs.getSerializedLength(), - 0, - ), + privateLogCount: this.body.txEffects.reduce((logCount, txEffect) => logCount + txEffect.privateLogs.length, 0), + publicLogCount: this.body.txEffects.reduce((logCount, txEffect) => logCount + txEffect.publicLogs.length, 0), contractClassLogCount: this.body.txEffects.reduce( (logCount, txEffect) => logCount + txEffect.contractClassLogs.getTotalLogCount(), 0, diff --git a/yarn-project/circuit-types/src/logs/event_metadata.ts b/yarn-project/circuit-types/src/logs/event_metadata.ts index e5b4a89f221..523cbe623dd 100644 --- a/yarn-project/circuit-types/src/logs/event_metadata.ts +++ b/yarn-project/circuit-types/src/logs/event_metadata.ts @@ -1,17 +1,16 @@ +import { type PublicLog } from '@aztec/circuits.js'; import { type AbiType, AbiTypeSchema, type EventSelector, decodeFromAbi } from '@aztec/foundation/abi'; -import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { z } from 'zod'; import { L1EventPayload } from './l1_payload/l1_event_payload.js'; -import { type UnencryptedL2Log } from './unencrypted_l2_log.js'; /** * Represents metadata for an event decoder, including all information needed to reconstruct it. */ export class EventMetadata { - public readonly decode: (payload: L1EventPayload | UnencryptedL2Log) => T | undefined; + public readonly decode: (payload: L1EventPayload | PublicLog) => T | undefined; public readonly eventSelector: EventSelector; public readonly abiType: AbiType; @@ -27,8 +26,8 @@ export class EventMetadata { public static decodeEvent( eventSelector: EventSelector, abiType: AbiType, - ): (payload: L1EventPayload | UnencryptedL2Log | undefined) => T | undefined { - return (payload: L1EventPayload | UnencryptedL2Log | undefined): T | undefined => { + ): (payload: L1EventPayload | PublicLog | undefined) => T | undefined { + return (payload: L1EventPayload | PublicLog | undefined): T | undefined => { if (payload === undefined) { return undefined; } @@ -39,12 +38,7 @@ export class EventMetadata { } return decodeFromAbi([abiType], payload.event.items) as T; } else { - const items = []; - for (let i = 0; i < payload.data.length; i += 32) { - items.push(new Fr(payload.data.subarray(i, i + 32))); - } - - return decodeFromAbi([abiType], items) as T; + return decodeFromAbi([abiType], payload.log) as T; } }; } diff --git a/yarn-project/circuit-types/src/logs/extended_public_log.ts b/yarn-project/circuit-types/src/logs/extended_public_log.ts new file mode 100644 index 00000000000..30230aaa48d --- /dev/null +++ b/yarn-project/circuit-types/src/logs/extended_public_log.ts @@ -0,0 +1,94 @@ +import { PublicLog } from '@aztec/circuits.js'; +import { BufferReader } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import isEqual from 'lodash.isequal'; +import { z } from 'zod'; + +import { LogId } from './log_id.js'; + +/** + * Represents an individual public log entry extended with info about the block and tx it was emitted in. + */ +export class ExtendedPublicLog { + constructor( + /** Globally unique id of the log. */ + public readonly id: LogId, + /** The data contents of the log. */ + public readonly log: PublicLog, + ) {} + + static random() { + return new ExtendedPublicLog(LogId.random(), PublicLog.random()); + } + + static get schema() { + return z + .object({ + id: LogId.schema, + log: PublicLog.schema, + }) + .transform(ExtendedPublicLog.from); + } + + static from(fields: FieldsOf) { + return new ExtendedPublicLog(fields.id, fields.log); + } + + /** + * Serializes log to a buffer. + * @returns A buffer containing the serialized log. + */ + public toBuffer(): Buffer { + return Buffer.concat([this.id.toBuffer(), this.log.toBuffer()]); + } + + /** + * Serializes log to a string. + * @returns A string containing the serialized log. + */ + public toString(): string { + return bufferToHex(this.toBuffer()); + } + + /** + * Serializes log to a human readable string. + * @returns A human readable representation of the log. + */ + public toHumanReadable(): string { + return `${this.id.toHumanReadable()}, ${this.log.toHumanReadable()}`; + } + + /** + * Checks if two ExtendedPublicLog objects are equal. + * @param other - Another ExtendedPublicLog object to compare with. + * @returns True if the two objects are equal, false otherwise. + */ + public equals(other: ExtendedPublicLog): boolean { + return isEqual(this, other); + } + + /** + * Deserializes log from a buffer. + * @param buffer - The buffer or buffer reader containing the log. + * @returns Deserialized instance of `Log`. + */ + public static fromBuffer(buffer: Buffer | BufferReader): ExtendedPublicLog { + const reader = BufferReader.asReader(buffer); + + const logId = LogId.fromBuffer(reader); + const log = PublicLog.fromBuffer(reader); + + return new ExtendedPublicLog(logId, log); + } + + /** + * Deserializes `ExtendedPublicLog` object from a hex string representation. + * @param data - A hex string representation of the log. + * @returns An `ExtendedPublicLog` object. + */ + public static fromString(data: string): ExtendedPublicLog { + return ExtendedPublicLog.fromBuffer(hexToBuffer(data)); + } +} diff --git a/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts index 9bdab9deeb4..e218b50b43f 100644 --- a/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts @@ -10,6 +10,7 @@ import { UnencryptedL2Log } from './unencrypted_l2_log.js'; /** * Represents an individual unencrypted log entry extended with info about the block and tx it was emitted in. + * TODO(#8945): Currently only used for contract class logs. When these are fields, delete this class. */ export class ExtendedUnencryptedL2Log { constructor( diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts index a4039913e9b..7826499292c 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts @@ -5,7 +5,7 @@ import { UnencryptedFunctionL2Logs } from './function_l2_logs.js'; function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFunctionL2Logs) { describe(FunctionL2Logs.name, () => { it('can encode L2Logs to buffer and back', () => { - const l2Logs = FunctionL2Logs.random(3); + const l2Logs = FunctionL2Logs.random(1); const buffer = l2Logs.toBuffer(); const recovered = FunctionL2Logs.fromBuffer(buffer); @@ -14,7 +14,7 @@ function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFuncti }); it('can encode L2Logs to JSON and back', () => { - const l2Logs = FunctionL2Logs.random(3); + const l2Logs = FunctionL2Logs.random(1); const buffer = jsonStringify(l2Logs); const recovered = FunctionL2Logs.schema.parse(JSON.parse(buffer)); @@ -23,7 +23,7 @@ function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFuncti }); it('getSerializedLength returns the correct length', () => { - const l2Logs = FunctionL2Logs.random(3); + const l2Logs = FunctionL2Logs.random(1); const buffer = l2Logs.toBuffer(); const recovered = FunctionL2Logs.fromBuffer(buffer); @@ -37,7 +37,7 @@ function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFuncti }); it('getKernelLength returns the correct length', () => { - const l2Logs = FunctionL2Logs.random(3); + const l2Logs = FunctionL2Logs.random(1); const expectedLength = l2Logs.logs.map(l => l.length).reduce((a, b) => a + b + 4, 0); diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.ts index 668661924cd..5e9b6bf64c1 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.ts @@ -1,4 +1,4 @@ -import { MAX_UNENCRYPTED_LOGS_PER_CALL } from '@aztec/circuits.js'; +import { MAX_CONTRACT_CLASS_LOGS_PER_CALL } from '@aztec/circuits.js'; import { sha256Trunc } from '@aztec/foundation/crypto'; import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; @@ -92,8 +92,8 @@ export class UnencryptedFunctionL2Logs { * @returns A new UnencryptedFunctionL2Logs object. */ public static random(numLogs: number): UnencryptedFunctionL2Logs { - if (numLogs > MAX_UNENCRYPTED_LOGS_PER_CALL) { - throw new Error(`Trying to create ${numLogs} logs for one call (max: ${MAX_UNENCRYPTED_LOGS_PER_CALL})`); + if (numLogs > MAX_CONTRACT_CLASS_LOGS_PER_CALL) { + throw new Error(`Trying to create ${numLogs} logs for one call (max: ${MAX_CONTRACT_CLASS_LOGS_PER_CALL})`); } const logs: UnencryptedL2Log[] = []; for (let i = 0; i < numLogs; i++) { diff --git a/yarn-project/circuit-types/src/logs/get_logs_response.ts b/yarn-project/circuit-types/src/logs/get_logs_response.ts index 13aab991d0d..2beb8480504 100644 --- a/yarn-project/circuit-types/src/logs/get_logs_response.ts +++ b/yarn-project/circuit-types/src/logs/get_logs_response.ts @@ -5,20 +5,34 @@ import { BufferReader, boolToBuffer, numToUInt32BE } from '@aztec/foundation/ser import { z } from 'zod'; import { TxHash } from '../tx/tx_hash.js'; +import { ExtendedPublicLog } from './extended_public_log.js'; import { ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js'; -/** Response for the getUnencryptedLogs archiver call. */ -export type GetUnencryptedLogsResponse = { +/** Response for the getContractClassLogs archiver call. */ +export type GetContractClassLogsResponse = { /** An array of ExtendedUnencryptedL2Log elements. */ logs: ExtendedUnencryptedL2Log[]; /** Indicates if a limit has been reached. */ maxLogsHit: boolean; }; -export const GetUnencryptedLogsResponseSchema = z.object({ +export const GetContractClassLogsResponseSchema = z.object({ logs: z.array(ExtendedUnencryptedL2Log.schema), maxLogsHit: z.boolean(), -}) satisfies ZodFor; +}) satisfies ZodFor; + +/** Response for the getPublicLogs archiver call. */ +export type GetPublicLogsResponse = { + /** An array of ExtendedPublicLog elements. */ + logs: ExtendedPublicLog[]; + /** Indicates if a limit has been reached. */ + maxLogsHit: boolean; +}; + +export const GetPublicLogsResponseSchema = z.object({ + logs: z.array(ExtendedPublicLog.schema), + maxLogsHit: z.boolean(), +}) satisfies ZodFor; export class TxScopedL2Log { constructor( @@ -36,7 +50,7 @@ export class TxScopedL2Log { */ public blockNumber: number, /* - * Indicates if the log comes from the unencrypted logs stream (partial note) + * Indicates if the log comes from the public logs stream (partial note) */ public isFromPublic: boolean, /* diff --git a/yarn-project/circuit-types/src/logs/index.ts b/yarn-project/circuit-types/src/logs/index.ts index cee3f87433b..97dd524ca9b 100644 --- a/yarn-project/circuit-types/src/logs/index.ts +++ b/yarn-project/circuit-types/src/logs/index.ts @@ -9,3 +9,4 @@ export * from './l1_payload/index.js'; export * from './tx_l2_logs.js'; export * from './unencrypted_l2_log.js'; export * from './extended_unencrypted_l2_log.js'; +export * from './extended_public_log.js'; diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts index 8fa34784694..467db1d4ce4 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts @@ -42,7 +42,7 @@ describe('EncryptedLogPayload', () => { it('decrypt a log as incoming', () => { const addressSecret = computeAddressSecret(completeAddress.getPreaddress(), ivskM); - const recreated = EncryptedLogPayload.decryptAsIncoming(payload, addressSecret); + const recreated = EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); expect(recreated?.toBuffer()).toEqual(original.toBuffer()); }); @@ -90,7 +90,7 @@ describe('EncryptedLogPayload', () => { const ivskM = new GrumpkinScalar(0x0d6e27b21c89a7632f7766e35cc280d43f75bea3898d7328400a5fefc804d462n); const addressSecret = computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM); - const recreated = EncryptedLogPayload.decryptAsIncoming(payload, addressSecret); + const recreated = EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); expect(recreated?.toBuffer()).toEqual(log.toBuffer()); }); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts index 1b17fc0552f..0906f368f58 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts @@ -45,6 +45,20 @@ function fieldsToEncryptedBytes(fields: Fr[]) { return Buffer.concat(fields.map(f => f.toBuffer().subarray(1))); } +function trimCiphertext(buf: Buffer, ciphertextLength: number) { + // bytes_to_fields in nr pads fields smaller than 31 bytes, meaning fieldsToEncryptedBytes can give incorrect ciphertext + // e.g. input + // Fr<0x003b1cb893d1fdab1d55420181669aa5251acc8beaed8438dca7960f217cfe1f>, + // Fr<0x00000000000000000000a3a3d57e7221e9bb201917f09caa475f2d00658e8f5e> + // becomes: 3b1cb893d1fdab1d55420181669aa5251acc8beaed8438dca7960f217cfe1f00000000000000000a3a3d57e7221e9bb201917f09caa475f2d00658e8f5e + // but should be: 3b1cb893d1fdab1d55420181669aa5251acc8beaed8438dca7960f217cfe1fa3a3d57e7221e9bb201917f09caa475f2d00658e8f5e + // This fn trims the correct number of zeroes. + const zeroesToTrim = buf.length - ciphertextLength; + const finalFieldBytes = buf.subarray(-31).subarray(zeroesToTrim); + const ciphertextBytes = Buffer.concat([buf.subarray(0, -31), finalFieldBytes]); + return ciphertextBytes; +} + class Overhead { constructor(public ephPk: Point, public incomingHeader: Buffer) {} @@ -135,49 +149,25 @@ export class EncryptedLogPayload { * * @param payload - The payload for the log * @param addressSecret - The address secret, used to decrypt the logs + * @param ciphertextLength - Optionally supply the ciphertext length (see trimCiphertext()) * @returns The decrypted log payload */ - public static decryptAsIncoming(payload: PrivateLog, addressSecret: GrumpkinScalar): EncryptedLogPayload | undefined { - try { - const logFields = payload.fields; - const tag = logFields[0]; - const reader = BufferReader.asReader(fieldsToEncryptedBytes(logFields.slice(1))); - - const overhead = Overhead.fromBuffer(reader); - const { contractAddress } = this.#decryptOverhead(overhead, { addressSecret }); - - const ciphertext = reader.readToEnd(); - const incomingBodyPlaintext = this.#decryptIncomingBody(ciphertext, addressSecret, overhead.ephPk); - - return new EncryptedLogPayload(tag, contractAddress, incomingBodyPlaintext); - } catch (e: any) { - // Following error messages are expected to occur when decryption fails - if (!this.isAcceptableError(e)) { - // If we encounter an unexpected error, we rethrow it - throw e; - } - return; - } - } - - /** - * Similar to `decryptAsIncoming`. Except that this is for the payload coming from public, which has tightly packed - * bytes that don't have 0 byte at the beginning of every 32 bytes. - * And the incoming body is of variable size. - */ - public static decryptAsIncomingFromPublic( - payload: Buffer, + public static decryptAsIncoming( + payload: Fr[], addressSecret: GrumpkinScalar, + ciphertextLength?: number, ): EncryptedLogPayload | undefined { try { - const reader = BufferReader.asReader(payload); - const tag = reader.readObject(Fr); + const tag = payload[0]; + const reader = BufferReader.asReader(fieldsToEncryptedBytes(payload.slice(1))); const overhead = Overhead.fromBuffer(reader); const { contractAddress } = this.#decryptOverhead(overhead, { addressSecret }); - // The incoming can be of variable size, so we read until the end - const ciphertext = reader.readToEnd(); + let ciphertext = reader.readToEnd(); + if (ciphertextLength && ciphertext.length !== ciphertextLength) { + ciphertext = trimCiphertext(ciphertext, ciphertextLength); + } const incomingBodyPlaintext = this.#decryptIncomingBody(ciphertext, addressSecret, overhead.ephPk); return new EncryptedLogPayload(tag, contractAddress, incomingBodyPlaintext); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts index b573027a594..1d4b577726a 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts @@ -47,7 +47,7 @@ export class L1EventPayload { } static decryptAsIncoming(log: PrivateLog, sk: Fq): L1EventPayload | undefined { - const decryptedLog = EncryptedLogPayload.decryptAsIncoming(log, sk); + const decryptedLog = EncryptedLogPayload.decryptAsIncoming(log.fields, sk); if (!decryptedLog) { return undefined; } diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 70b8628ecfd..3f36fd4841a 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -1,4 +1,4 @@ -import { AztecAddress, type PrivateLog, Vector } from '@aztec/circuits.js'; +import { AztecAddress, type PrivateLog, type PublicLog, Vector } from '@aztec/circuits.js'; import { NoteSelector } from '@aztec/foundation/abi'; import { randomInt } from '@aztec/foundation/crypto'; import { type Fq, Fr } from '@aztec/foundation/fields'; @@ -60,7 +60,7 @@ export class L1NotePayload { } static decryptAsIncoming(log: PrivateLog, sk: Fq): L1NotePayload | undefined { - const decryptedLog = EncryptedLogPayload.decryptAsIncoming(log, sk); + const decryptedLog = EncryptedLogPayload.decryptAsIncoming(log.fields, sk); if (!decryptedLog) { return undefined; } @@ -72,13 +72,13 @@ export class L1NotePayload { ); } - static decryptAsIncomingFromPublic(log: Buffer, sk: Fq): L1NotePayload | undefined { - const { privateValues, publicValues } = parseLogFromPublic(log); + static decryptAsIncomingFromPublic(log: PublicLog, sk: Fq): L1NotePayload | undefined { + const { privateValues, publicValues, ciphertextLength } = parseLogFromPublic(log); if (!privateValues) { return undefined; } - const decryptedLog = EncryptedLogPayload.decryptAsIncomingFromPublic(privateValues, sk); + const decryptedLog = EncryptedLogPayload.decryptAsIncoming(privateValues, sk, ciphertextLength); if (!decryptedLog) { return undefined; } @@ -150,50 +150,23 @@ export class L1NotePayload { * Parse the given log into an array of public values and an encrypted log. * * @param log - Log to be parsed. - * @returns An object containing the public values and the encrypted log. + * @returns An object containing the public values, encrypted log, and ciphertext length. */ -function parseLogFromPublic(log: Buffer) { - // First we remove padding bytes - const processedLog = removePaddingBytes(log); - if (!processedLog) { - return {}; - } - - const reader = new BufferReader(processedLog); - - // Then we extract public values from the log - const numPublicValues = reader.readUInt8(); - - const publicValuesLength = numPublicValues * Fr.SIZE_IN_BYTES; - const privateValuesLength = reader.remainingBytes() - publicValuesLength; - - // Now we get the buffer corresponding to the values generated from private. - const privateValues = reader.readBytes(privateValuesLength); +function parseLogFromPublic(log: PublicLog) { + // Extract lengths from the log + // Each length is stored in 2 bytes with a 0 separator byte between them: + // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]] + const lengths = log.log[0].toBuffer().subarray(-8); + const publicValuesLength = lengths.readUint16BE(); + const privateValuesLength = lengths.readUint16BE(3); + const ciphertextLength = lengths.readUint16BE(6); + + // Now we get the fields corresponding to the values generated from private. + // Note: +1 for the length values in position 0 + const privateValues = log.log.slice(1, privateValuesLength + 1); // At last we load the public values - const publicValues = reader.readArray(numPublicValues, Fr); - - return { publicValues, privateValues }; -} - -/** - * When a log is emitted via the unencrypted log channel each field contains only 1 byte. OTOH when a log is emitted - * via the encrypted log channel there are no empty bytes. This function removes the padding bytes. - * @param unprocessedLog - Log to be processed. - * @returns Log with padding bytes removed. - */ -function removePaddingBytes(unprocessedLog: Buffer) { - // Determine whether first 31 bytes of each 32 bytes block of bytes are 0 - const is1FieldPerByte = unprocessedLog.every((byte, index) => index % 32 === 31 || byte === 0); - if (!is1FieldPerByte) { - return; - } - - // We take every 32nd byte from the log and return the result - const processedLog = Buffer.alloc(unprocessedLog.length / 32); - for (let i = 0; i < processedLog.length; i++) { - processedLog[i] = unprocessedLog[31 + i * 32]; - } + const publicValues = log.log.slice(privateValuesLength + 1, privateValuesLength + 1 + publicValuesLength); - return processedLog; + return { publicValues, privateValues, ciphertextLength }; } diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts index bc5f1a2e7fb..9d1a579ff53 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts @@ -1,17 +1,11 @@ import { jsonStringify } from '@aztec/foundation/json-rpc'; -import { ContractClass2BlockL2Logs, UnencryptedL2BlockL2Logs } from './l2_block_l2_logs.js'; +import { ContractClass2BlockL2Logs } from './l2_block_l2_logs.js'; -function shouldBehaveLikeL2BlockL2Logs( - L2BlockL2Logs: typeof UnencryptedL2BlockL2Logs | typeof ContractClass2BlockL2Logs, -) { +function shouldBehaveLikeL2BlockL2Logs(L2BlockL2Logs: typeof ContractClass2BlockL2Logs) { describe(L2BlockL2Logs.name, () => { it('can encode L2Logs to buffer and back', () => { - const l2Logs = - L2BlockL2Logs.name == 'ContractClass2BlockL2Logs' - ? L2BlockL2Logs.random(3, 1, 1) - : L2BlockL2Logs.random(3, 4, 2); - + const l2Logs = L2BlockL2Logs.random(3, 1, 1); const buffer = l2Logs.toBuffer(); const recovered = L2BlockL2Logs.fromBuffer(buffer); @@ -19,27 +13,14 @@ function shouldBehaveLikeL2BlockL2Logs( }); it('getSerializedLength returns the correct length', () => { - const l2Logs = - L2BlockL2Logs.name == 'ContractClass2BlockL2Logs' - ? L2BlockL2Logs.random(3, 1, 1) - : L2BlockL2Logs.random(3, 4, 2); - + const l2Logs = L2BlockL2Logs.random(3, 1, 1); const buffer = l2Logs.toBuffer(); const recovered = L2BlockL2Logs.fromBuffer(buffer); - if (L2BlockL2Logs.name == 'EncryptedL2BlockL2Logs') { - // For event logs, we don't 'count' the maskedContractAddress as part of the - // log length, since it's just for siloing later on - expect(recovered.getSerializedLength()).toEqual(buffer.length - 24 * 32); - } else { - expect(recovered.getSerializedLength()).toEqual(buffer.length); - } + expect(recovered.getSerializedLength()).toEqual(buffer.length); }); it('serializes to and from JSON via schema', () => { - const l2Logs = - L2BlockL2Logs.name == 'ContractClass2BlockL2Logs' - ? L2BlockL2Logs.random(3, 1, 1) - : L2BlockL2Logs.random(3, 4, 2); + const l2Logs = L2BlockL2Logs.random(3, 1, 1); const json = jsonStringify(l2Logs); const recovered = L2BlockL2Logs.schema.parse(JSON.parse(json)); expect(recovered).toEqual(l2Logs); @@ -48,5 +29,4 @@ function shouldBehaveLikeL2BlockL2Logs( }); } -shouldBehaveLikeL2BlockL2Logs(UnencryptedL2BlockL2Logs); shouldBehaveLikeL2BlockL2Logs(ContractClass2BlockL2Logs); diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts index 4620740544b..a0f5e275e06 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts @@ -4,7 +4,7 @@ import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import isEqual from 'lodash.isequal'; import { z } from 'zod'; -import { ContractClassTxL2Logs, type TxL2Logs, UnencryptedTxL2Logs } from './tx_l2_logs.js'; +import { ContractClassTxL2Logs, type TxL2Logs } from './tx_l2_logs.js'; import { type UnencryptedL2Log } from './unencrypted_l2_log.js'; /** @@ -70,75 +70,6 @@ abstract class L2BlockL2Logs { } } -export class UnencryptedL2BlockL2Logs extends L2BlockL2Logs { - static get schema() { - return z - .object({ txLogs: z.array(UnencryptedTxL2Logs.schema) }) - .transform(({ txLogs }) => new UnencryptedL2BlockL2Logs(txLogs)); - } - - public get type() { - return 'Unencrypted'; - } - - /** - * Deserializes logs from a buffer. - * @param buffer - The buffer containing the serialized logs. - * @returns A new `L2BlockL2Logs` object. - */ - public static fromBuffer(buffer: Buffer | BufferReader): UnencryptedL2BlockL2Logs { - const reader = BufferReader.asReader(buffer); - - const logsBufLength = reader.readNumber(); - const serializedTxLogs = reader.readBufferArray(logsBufLength); - - const txLogs = serializedTxLogs.map(logs => UnencryptedTxL2Logs.fromBuffer(logs, false)); - return new UnencryptedL2BlockL2Logs(txLogs); - } - - /** - * Deserializes logs from a string. - * @param data - The string containing the serialized logs. - * @returns A new `L2BlockL2Logs` object. - */ - public static fromString(data: string): UnencryptedL2BlockL2Logs { - return UnencryptedL2BlockL2Logs.fromBuffer(hexToBuffer(data)); - } - - /** - * Creates a new `L2BlockL2Logs` object with `numCalls` function logs and `numLogsPerCall` logs in each function - * call. - * @param numTxs - The number of txs in the block. - * @param numCalls - The number of function calls in the tx. - * @param numLogsPerCall - The number of logs emitted in each function call. - * @returns A new `L2BlockL2Logs` object. - */ - public static random(numTxs: number, numCalls: number, numLogsPerCall: number): UnencryptedL2BlockL2Logs { - const txLogs: UnencryptedTxL2Logs[] = []; - for (let i = 0; i < numTxs; i++) { - txLogs.push(UnencryptedTxL2Logs.random(numCalls, numLogsPerCall)); - } - return new UnencryptedL2BlockL2Logs(txLogs); - } - - /** - * Unrolls logs from a set of blocks. - * @param blockLogs - Input logs from a set of blocks. - * @returns Unrolled logs. - */ - public static unrollLogs(blockLogs: (UnencryptedL2BlockL2Logs | undefined)[]): UnencryptedL2Log[] { - const logs: UnencryptedL2Log[] = []; - for (const blockLog of blockLogs) { - if (blockLog) { - for (const txLog of blockLog.txLogs) { - logs.push(...txLog.unrollLogs()); - } - } - } - return logs; - } -} - export class ContractClass2BlockL2Logs extends L2BlockL2Logs { // This class is identical in methods to UnencryptedL2BlockL2Logs, but its // consistuent ContractClassTxL2Logs must be treated differently, hence new class. diff --git a/yarn-project/circuit-types/src/logs/l2_logs_source.ts b/yarn-project/circuit-types/src/logs/l2_logs_source.ts index 766eb84cb94..c0b818b5319 100644 --- a/yarn-project/circuit-types/src/logs/l2_logs_source.ts +++ b/yarn-project/circuit-types/src/logs/l2_logs_source.ts @@ -1,6 +1,10 @@ import { type Fr, type PrivateLog } from '@aztec/circuits.js'; -import { type GetUnencryptedLogsResponse, type TxScopedL2Log } from './get_logs_response.js'; +import { + type GetContractClassLogsResponse, + type GetPublicLogsResponse, + type TxScopedL2Log, +} from './get_logs_response.js'; import { type LogFilter } from './log_filter.js'; /** @@ -24,18 +28,18 @@ export interface L2LogsSource { getLogsByTags(tags: Fr[]): Promise; /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getPublicLogs(filter: LogFilter): Promise; /** * Gets contract class logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(filter: LogFilter): Promise; + getContractClassLogs(filter: LogFilter): Promise; /** * Gets the number of the latest L2 block processed by the implementation. diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts index 9397740891d..767b0c93371 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts @@ -1,12 +1,11 @@ import { jsonStringify } from '@aztec/foundation/json-rpc'; -import { ContractClassTxL2Logs, UnencryptedTxL2Logs } from './tx_l2_logs.js'; +import { ContractClassTxL2Logs } from './tx_l2_logs.js'; -function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof UnencryptedTxL2Logs | typeof ContractClassTxL2Logs) { +function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof ContractClassTxL2Logs) { describe(TxL2Logs.name, () => { it('can encode TxL2Logs to buffer and back', () => { - const l2Logs = TxL2Logs.name == 'ContractClassTxL2Logs' ? TxL2Logs.random(1, 1) : TxL2Logs.random(4, 2); - + const l2Logs = TxL2Logs.random(1, 1); const buffer = l2Logs.toBuffer(); const recovered = TxL2Logs.fromBuffer(buffer); @@ -14,8 +13,7 @@ function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof UnencryptedTxL2Logs | typeof }); it('can encode TxL2Logs to JSON and back', () => { - const l2Logs = TxL2Logs.name == 'ContractClassTxL2Logs' ? TxL2Logs.random(1, 1) : TxL2Logs.random(4, 2); - + const l2Logs = TxL2Logs.random(1, 1); const buffer = jsonStringify(l2Logs); const recovered = TxL2Logs.schema.parse(JSON.parse(buffer)); @@ -23,16 +21,14 @@ function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof UnencryptedTxL2Logs | typeof }); it('getSerializedLength returns the correct length', () => { - const l2Logs = TxL2Logs.name == 'ContractClassTxL2Logs' ? TxL2Logs.random(1, 1) : TxL2Logs.random(4, 2); - + const l2Logs = TxL2Logs.random(1, 1); const buffer = l2Logs.toBuffer(); const recovered = TxL2Logs.fromBuffer(buffer); expect(recovered.getSerializedLength()).toEqual(buffer.length); }); it('getKernelLength returns the correct length', () => { - const l2Logs = TxL2Logs.name == 'ContractClassTxL2Logs' ? TxL2Logs.random(1, 1) : TxL2Logs.random(4, 2); - + const l2Logs = TxL2Logs.random(1, 1); const expectedLength = l2Logs.functionLogs.map(l => l.getKernelLength()).reduce((a, b) => a + b, 0); expect(l2Logs.getKernelLength()).toEqual(expectedLength); @@ -40,5 +36,4 @@ function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof UnencryptedTxL2Logs | typeof }); } -shouldBehaveLikeTxL2Logs(UnencryptedTxL2Logs); shouldBehaveLikeTxL2Logs(ContractClassTxL2Logs); 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 299513de970..fab163a3ac9 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -1,10 +1,4 @@ -import { - Fr, - type LogHash, - MAX_CONTRACT_CLASS_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, - type ScopedLogHash, -} from '@aztec/circuits.js'; +import { Fr, type LogHash, MAX_CONTRACT_CLASS_LOGS_PER_TX, type ScopedLogHash } from '@aztec/circuits.js'; import { sha256Trunc } from '@aztec/foundation/crypto'; import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; @@ -16,6 +10,7 @@ import { type UnencryptedL2Log } from './unencrypted_l2_log.js'; /** * Data container of logs emitted in 1 tx. + * TODO(#8945): Currently only used for contract class logs. When these are fields, delete this class. */ export abstract class TxL2Logs { abstract hash(): Buffer; @@ -138,89 +133,6 @@ export abstract class TxL2Logs { } } -export class UnencryptedTxL2Logs extends TxL2Logs { - static get schema() { - return z - .object({ functionLogs: z.array(UnencryptedFunctionL2Logs.schema) }) - .transform(({ functionLogs }) => new UnencryptedTxL2Logs(functionLogs)); - } - - /** Creates an empty instance. */ - public static empty() { - return new UnencryptedTxL2Logs([]); - } - - /** - * Deserializes logs from a buffer. - * @param buf - The buffer containing the serialized logs. - * @param isLengthPrefixed - Whether the buffer is prefixed with 4 bytes for its total length. - * @returns A new L2Logs object. - */ - public static fromBuffer(buf: Buffer | BufferReader, isLengthPrefixed = true): UnencryptedTxL2Logs { - const reader = BufferReader.asReader(buf); - - // If the buffer is length prefixed use the length to read the array. Otherwise, the entire buffer is consumed. - const logsBufLength = isLengthPrefixed ? reader.readNumber() : -1; - const serializedFunctionLogs = reader.readBufferArray(logsBufLength); - - const functionLogs = serializedFunctionLogs.map(logs => UnencryptedFunctionL2Logs.fromBuffer(logs, false)); - return new UnencryptedTxL2Logs(functionLogs); - } - - /** - * Creates a new `TxL2Logs` object with `numCalls` function logs and `numLogsPerCall` logs in each invocation. - * @param numCalls - The number of function calls in the tx. - * @param numLogsPerCall - The number of logs emitted in each function call. - * @returns A new `TxL2Logs` object. - */ - public static random(numCalls: number, numLogsPerCall: number): UnencryptedTxL2Logs { - if (numCalls * numLogsPerCall > MAX_UNENCRYPTED_LOGS_PER_TX) { - throw new Error( - `Trying to create ${numCalls * numLogsPerCall} logs for one tx (max: ${MAX_UNENCRYPTED_LOGS_PER_TX})`, - ); - } - const functionLogs: UnencryptedFunctionL2Logs[] = []; - for (let i = 0; i < numCalls; i++) { - functionLogs.push(UnencryptedFunctionL2Logs.random(numLogsPerCall)); - } - return new UnencryptedTxL2Logs(functionLogs); - } - - /** - * Computes unencrypted logs hash as is done in the kernel and decoder contract. - * @param logs - Logs to be hashed. - * @returns The hash of the logs. - * Note: This is a TS implementation of `computeKernelUnencryptedLogsHash` function in Decoder.sol. See that function documentation - * for more details. - */ - public override hash(): Buffer { - const unrolledLogs = this.unrollLogs(); - return UnencryptedTxL2Logs.hashSiloedLogs(unrolledLogs.map(log => log.getSiloedHash())); - } - - /** - * Hashes siloed unencrypted logs as in the same way as the base rollup would. - * @param siloedLogHashes - The siloed log hashes - * @returns The hash of the logs. - */ - public static hashSiloedLogs(siloedLogHashes: Buffer[]): Buffer { - if (siloedLogHashes.length == 0) { - return Buffer.alloc(32); - } - - let allSiloedLogHashes = Buffer.alloc(0); - for (const siloedLogHash of siloedLogHashes) { - allSiloedLogHashes = Buffer.concat([allSiloedLogHashes, siloedLogHash]); - } - // pad the end of logs with 0s - for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX - siloedLogHashes.length; i++) { - allSiloedLogHashes = Buffer.concat([allSiloedLogHashes, Buffer.alloc(32)]); - } - - return sha256Trunc(allSiloedLogHashes); - } -} - export class ContractClassTxL2Logs extends TxL2Logs { static get schema() { return z diff --git a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts index 942dad32db2..472905de196 100644 --- a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts @@ -7,6 +7,7 @@ import { z } from 'zod'; /** * Represents an individual unencrypted log entry. + * TODO(#8945): Currently only used for contract class logs. When these are fields, delete this class. */ export class UnencryptedL2Log { constructor( diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 4b09e99ffc5..51797673d04 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -25,7 +25,7 @@ import { randomBigInt, randomBytes, randomInt } from '@aztec/foundation/crypto'; import { Signature } from '@aztec/foundation/eth-signature'; import { Fr } from '@aztec/foundation/fields'; -import { ContractClassTxL2Logs, Note, UnencryptedTxL2Logs } from './logs/index.js'; +import { ContractClassTxL2Logs, Note } from './logs/index.js'; import { ExtendedNote, UniqueNote } from './notes/index.js'; import { CountedPublicExecutionRequest, @@ -151,7 +151,6 @@ export const mockTx = ( const tx = new Tx( data, ClientIvcProof.empty(), - UnencryptedTxL2Logs.empty(), ContractClassTxL2Logs.empty(), enqueuedPublicFunctionCalls, publicTeardownFunctionCall, diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index e874bbea9f4..dafea919ab3 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -16,10 +16,8 @@ export type L2BlockStats = { txCount: number; /** Number of the L2 block. */ blockNumber: number; - /** Number of unencrypted logs. */ - unencryptedLogCount?: number; - /** Serialized size of unencrypted logs. */ - unencryptedLogSize?: number; + /** Number of public logs. */ + publicLogCount?: number; }; /** Stats logged for each L1 publish tx.*/ @@ -212,10 +210,6 @@ export type TxStats = { size: number; /** Size of the proof. */ proofSize: number; - /** Number of unencrypted logs. */ - unencryptedLogCount: number; - /** Serialized size of unencrypted logs. */ - unencryptedLogSize: number; /** Number of note hashes */ noteHashCount: number; /** Number of nullifiers */ diff --git a/yarn-project/circuit-types/src/test/factories.ts b/yarn-project/circuit-types/src/test/factories.ts index 21367837a22..bfd6e6e2dbf 100644 --- a/yarn-project/circuit-types/src/test/factories.ts +++ b/yarn-project/circuit-types/src/test/factories.ts @@ -14,6 +14,7 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicCircuitPublicInputs, PublicDataWrite, + PublicLog, RevertCode, ScopedLogHash, TxConstantData, @@ -140,7 +141,7 @@ export function makeBloatedProcessedTx({ } // Remove all logs as it's ugly to mock them at the moment and we are going to change it to have the preimages be part of the public inputs soon. -function clearLogs(data: { unencryptedLogsHashes?: ScopedLogHash[]; contractClassLogsHashes: ScopedLogHash[] }) { - data.unencryptedLogsHashes?.forEach((_, i) => (data.unencryptedLogsHashes![i] = ScopedLogHash.empty())); +function clearLogs(data: { publicLogs?: PublicLog[]; contractClassLogsHashes: ScopedLogHash[] }) { + data.publicLogs?.forEach((_, i) => (data.publicLogs![i] = PublicLog.empty())); data.contractClassLogsHashes.forEach((_, i) => (data.contractClassLogsHashes[i] = ScopedLogHash.empty())); } diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index 38e857e1a4f..85f0640c099 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -98,9 +98,8 @@ export function makeProcessedTxFromPrivateOnlyTx( .filter(h => !h.isZero()), publicDataWrites, data.end.privateLogs.filter(l => !l.isEmpty()), - Fr.ZERO, + [], data.end.contractClassLogPreimagesLength, - tx.unencryptedLogs, tx.contractClassLogs, ); @@ -146,8 +145,6 @@ export function makeProcessedTxFromTxWithPublicCalls( ...(revertCode.isOK() ? tx.data.forPublic!.revertibleAccumulatedData.privateLogs : []), ].filter(l => !l.isEmpty()); - // Unencrypted logs emitted from public functions are inserted to tx.unencryptedLogs directly :( - const unencryptedLogPreimagesLength = tx.unencryptedLogs.getKernelLength(); const contractClassLogPreimagesLength = tx.contractClassLogs.getKernelLength(); const txEffect = new TxEffect( @@ -161,9 +158,8 @@ export function makeProcessedTxFromTxWithPublicCalls( .filter(h => !h.isZero()), publicDataWrites, privateLogs, - new Fr(unencryptedLogPreimagesLength), + avmOutput.accumulatedData.publicLogs.filter(l => !l.isEmpty()), new Fr(contractClassLogPreimagesLength), - tx.unencryptedLogs, tx.contractClassLogs, ); diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.ts b/yarn-project/circuit-types/src/tx/simulated_tx.ts index b1ae9f789b8..737f3d45d2b 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.ts @@ -7,7 +7,7 @@ import { type PrivateKernelProverProfileResult, PrivateKernelProverProfileResultSchema, } from '../interfaces/private_kernel_prover.js'; -import { ContractClassTxL2Logs, UnencryptedTxL2Logs } from '../logs/tx_l2_logs.js'; +import { ContractClassTxL2Logs } from '../logs/tx_l2_logs.js'; import { type PrivateCallExecutionResult, PrivateExecutionResult, @@ -34,11 +34,9 @@ export class PrivateSimulationResult { const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(this.privateExecutionResult); const teardownPublicFunction = collectPublicTeardownFunctionCall(this.privateExecutionResult); - // NB: no unencrypted logs* come from private, but we keep the property on Tx so enqueued_calls_processor.ts can accumulate public logs const tx = new Tx( this.publicInputs, ClientIvcProof.empty(), - UnencryptedTxL2Logs.empty(), // *unencrypted logs contractClassLogs, enqueuedPublicFunctions, teardownPublicFunction, @@ -125,11 +123,9 @@ export class TxProvingResult { const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(this.privateExecutionResult); const teardownPublicFunction = collectPublicTeardownFunctionCall(this.privateExecutionResult); - // NB: no unencrypted logs* come from private, but we keep the property on Tx so enqueued_calls_processor.ts can accumulate public logs const tx = new Tx( this.publicInputs, this.clientIvcProof, - UnencryptedTxL2Logs.empty(), // *unencrypted logs contractClassLogs, enqueuedPublicFunctions, teardownPublicFunction, diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 87768204e1a..0ed741bdf7a 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -5,18 +5,17 @@ import { PrivateKernelTailCircuitPublicInputs, PrivateLog, type PrivateToPublicAccumulatedData, - type ScopedLogHash, } from '@aztec/circuits.js'; import { Buffer32 } from '@aztec/foundation/buffer'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; -import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeArrayOfBufferableToVector, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; -import { type GetUnencryptedLogsResponse } from '../logs/get_logs_response.js'; +import { type GetPublicLogsResponse } from '../logs/get_logs_response.js'; import { type L2LogsSource } from '../logs/l2_logs_source.js'; -import { ContractClassTxL2Logs, UnencryptedTxL2Logs } from '../logs/tx_l2_logs.js'; +import { ContractClassTxL2Logs } from '../logs/tx_l2_logs.js'; import { Gossipable } from '../p2p/gossipable.js'; import { TopicType, createTopicString } from '../p2p/topic_type.js'; import { PublicExecutionRequest } from '../public_execution_request.js'; @@ -42,11 +41,6 @@ export class Tx extends Gossipable { * */ public readonly clientIvcProof: ClientIvcProof, - /** - * Unencrypted logs generated by the tx. - * NOTE: These do not get filled, but remain here so enqueued_calls_processor.ts can accumulate public logs - */ - public unencryptedLogs: UnencryptedTxL2Logs, /** * Contract class logs generated by the tx. */ @@ -105,9 +99,8 @@ export class Tx extends Gossipable { return new Tx( reader.readObject(PrivateKernelTailCircuitPublicInputs), reader.readObject(ClientIvcProof), - reader.readObject(UnencryptedTxL2Logs), reader.readObject(ContractClassTxL2Logs), - reader.readArray(reader.readNumber(), PublicExecutionRequest), + reader.readVectorUint8Prefix(PublicExecutionRequest), reader.readObject(PublicExecutionRequest), ); } @@ -119,7 +112,6 @@ export class Tx extends Gossipable { return new Tx( data, ClientIvcProof.empty(), - UnencryptedTxL2Logs.empty(), ContractClassTxL2Logs.empty(), [], publicTeardownExecutionRequest ? publicTeardownExecutionRequest : PublicExecutionRequest.empty(), @@ -134,10 +126,8 @@ export class Tx extends Gossipable { return serializeToBuffer([ this.data, this.clientIvcProof, - this.unencryptedLogs, this.contractClassLogs, - this.enqueuedPublicFunctionCalls.length, - this.enqueuedPublicFunctionCalls, + serializeArrayOfBufferableToVector(this.enqueuedPublicFunctionCalls, 1), this.publicTeardownFunctionCall, ]); } @@ -147,7 +137,6 @@ export class Tx extends Gossipable { .object({ data: PrivateKernelTailCircuitPublicInputs.schema, clientIvcProof: ClientIvcProof.schema, - unencryptedLogs: UnencryptedTxL2Logs.schema, contractClassLogs: ContractClassTxL2Logs.schema, enqueuedPublicFunctionCalls: z.array(PublicExecutionRequest.schema), publicTeardownFunctionCall: PublicExecutionRequest.schema, @@ -159,7 +148,6 @@ export class Tx extends Gossipable { return new Tx( fields.data, fields.clientIvcProof, - fields.unencryptedLogs, fields.contractClassLogs, fields.enqueuedPublicFunctionCalls, fields.publicTeardownFunctionCall, @@ -167,12 +155,12 @@ export class Tx extends Gossipable { } /** - * Gets unencrypted logs emitted by this tx. + * Gets public logs emitted by this tx. * @param logsSource - An instance of `L2LogsSource` which can be used to obtain the logs. * @returns The requested logs. */ - public getUnencryptedLogs(logsSource: L2LogsSource): Promise { - return logsSource.getUnencryptedLogs({ txHash: this.getTxHash() }); + public getPublicLogs(logsSource: L2LogsSource): Promise { + return logsSource.getPublicLogs({ txHash: this.getTxHash() }); } /** @@ -203,8 +191,6 @@ export class Tx extends Gossipable { getStats(): TxStats { return { txHash: this.getTxHash().toString(), - unencryptedLogCount: this.unencryptedLogs.getTotalLogCount(), - unencryptedLogSize: this.unencryptedLogs.getSerializedLength(), noteHashCount: this.data.getNonEmptyNoteHashes().length, nullifierCount: this.data.getNonEmptyNullifiers().length, @@ -234,7 +220,6 @@ export class Tx extends Gossipable { return ( this.data.getSize() + this.clientIvcProof.clientIvcProofBuffer.length + - this.unencryptedLogs.getSerializedLength() + this.contractClassLogs.getSerializedLength() + arraySerializedSizeOfNonEmpty(this.enqueuedPublicFunctionCalls) + arraySerializedSizeOfNonEmpty([this.publicTeardownFunctionCall]) @@ -247,7 +232,6 @@ export class Tx extends Gossipable { */ getEstimatedPrivateTxEffectsSize() { return ( - this.unencryptedLogs.getSerializedLength() + this.contractClassLogs.getSerializedLength() + this.data.getNonEmptyNoteHashes().length * Fr.SIZE_IN_BYTES + this.data.getNonEmptyNullifiers().length * Fr.SIZE_IN_BYTES + @@ -281,7 +265,6 @@ export class Tx extends Gossipable { static clone(tx: Tx): Tx { const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(tx.data.toBuffer()); const clientIvcProof = ClientIvcProof.fromBuffer(tx.clientIvcProof.toBuffer()); - const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(tx.unencryptedLogs.toBuffer()); const contractClassLogs = ContractClassTxL2Logs.fromBuffer(tx.contractClassLogs.toBuffer()); const enqueuedPublicFunctionCalls = tx.enqueuedPublicFunctionCalls.map(x => PublicExecutionRequest.fromBuffer(x.toBuffer()), @@ -290,7 +273,6 @@ export class Tx extends Gossipable { const clonedTx = new Tx( publicInputs, clientIvcProof, - unencryptedLogs, contractClassLogs, enqueuedPublicFunctionCalls, publicTeardownFunctionCall, @@ -306,7 +288,6 @@ export class Tx extends Gossipable { return new Tx( PrivateKernelTailCircuitPublicInputs.emptyWithNullifier(), ClientIvcProof.empty(), - UnencryptedTxL2Logs.random(1, 1), ContractClassTxL2Logs.random(1, 1), [PublicExecutionRequest.random()], PublicExecutionRequest.random(), @@ -327,16 +308,11 @@ export class Tx extends Gossipable { * @param logHashes the individual log hashes we want to keep * @param out the output to put passing logs in, to keep this function abstract */ - public filterRevertedLogs( - privateNonRevertible: PrivateToPublicAccumulatedData, - unencryptedLogsHashes: ScopedLogHash[], - ) { + public filterRevertedLogs(privateNonRevertible: PrivateToPublicAccumulatedData) { this.contractClassLogs = this.contractClassLogs.filterScoped( privateNonRevertible.contractClassLogsHashes, ContractClassTxL2Logs.empty(), ); - - this.unencryptedLogs = this.unencryptedLogs.filterScoped(unencryptedLogsHashes, UnencryptedTxL2Logs.empty()); } } diff --git a/yarn-project/circuit-types/src/tx_effect.test.ts b/yarn-project/circuit-types/src/tx_effect.test.ts index 41c9502b0d2..c2c0b54d48d 100644 --- a/yarn-project/circuit-types/src/tx_effect.test.ts +++ b/yarn-project/circuit-types/src/tx_effect.test.ts @@ -13,7 +13,7 @@ describe('TxEffect', () => { const txEffect = TxEffect.random(); const fields = txEffect.toBlobFields(); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here - expect(TxEffect.fromBlobFields(fields, txEffect.unencryptedLogs, txEffect.contractClassLogs)).toEqual(txEffect); + expect(TxEffect.fromBlobFields(fields, txEffect.contractClassLogs)).toEqual(txEffect); }); it('converts empty to and from fields', () => { @@ -34,9 +34,7 @@ describe('TxEffect', () => { // Add an extra field fields.push(new Fr(7)); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here - expect(() => TxEffect.fromBlobFields(fields, txEffect.unencryptedLogs, txEffect.contractClassLogs)).toThrow( - 'Too many fields', - ); + expect(() => TxEffect.fromBlobFields(fields, txEffect.contractClassLogs)).toThrow('Too many fields'); txEffect = TxEffect.random(); fields = txEffect.toBlobFields(); @@ -47,8 +45,6 @@ describe('TxEffect', () => { const fakePrefix = new Fr(buf); fields.push(fakePrefix); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here - expect(() => TxEffect.fromBlobFields(fields, txEffect.unencryptedLogs, txEffect.contractClassLogs)).toThrow( - 'Invalid fields', - ); + expect(() => TxEffect.fromBlobFields(fields, txEffect.contractClassLogs)).toThrow('Invalid fields'); }); }); diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index a5995915736..1bd8f6713c2 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -12,13 +12,15 @@ import { PRIVATE_LOGS_PREFIX, PRIVATE_LOG_SIZE_IN_FIELDS, PUBLIC_DATA_UPDATE_REQUESTS_PREFIX, + PUBLIC_LOGS_PREFIX, + PUBLIC_LOG_SIZE_IN_FIELDS, PrivateLog, PublicDataWrite, + PublicLog, REVERT_CODE_PREFIX, RevertCode, TX_FEE_PREFIX, TX_START_PREFIX, - UNENCRYPTED_LOGS_PREFIX, } from '@aztec/circuits.js'; import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; @@ -37,7 +39,7 @@ import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; import { z } from 'zod'; -import { ContractClassTxL2Logs, type TxL2Logs, UnencryptedTxL2Logs } from './logs/index.js'; +import { ContractClassTxL2Logs, type TxL2Logs } from './logs/index.js'; import { TxHash } from './tx/tx_hash.js'; export { RevertCodeEnum } from '@aztec/circuits.js'; @@ -82,12 +84,14 @@ export class TxEffect { * The private logs. */ public privateLogs: PrivateLog[], + /** + * The public logs. + */ + public publicLogs: PublicLog[], /** * The logs and logs lengths of the txEffect */ - public unencryptedLogsLength: Fr, public contractClassLogsLength: Fr, - public unencryptedLogs: UnencryptedTxL2Logs, public contractClassLogs: ContractClassTxL2Logs, ) { // TODO(#4638): Clean this up once we have isDefault() everywhere --> then we don't have to deal with 2 different @@ -150,9 +154,8 @@ export class TxEffect { serializeArrayOfBufferableToVector(this.l2ToL1Msgs, 1), serializeArrayOfBufferableToVector(this.publicDataWrites, 1), serializeArrayOfBufferableToVector(this.privateLogs, 1), - this.unencryptedLogsLength, + serializeArrayOfBufferableToVector(this.publicLogs, 1), this.contractClassLogsLength, - this.unencryptedLogs, this.contractClassLogs, ]); } @@ -179,9 +182,8 @@ export class TxEffect { reader.readVectorUint8Prefix(Fr), reader.readVectorUint8Prefix(PublicDataWrite), reader.readVectorUint8Prefix(PrivateLog), + reader.readVectorUint8Prefix(PublicLog), Fr.fromBuffer(reader), - Fr.fromBuffer(reader), - reader.readObject(UnencryptedTxL2Logs), reader.readObject(ContractClassTxL2Logs), ); } @@ -214,8 +216,7 @@ export class TxEffect { return thisLayer[0]; } - static random(numPublicCallsPerTx = 3, numUnencryptedLogsPerCall = 1): TxEffect { - const unencryptedLogs = UnencryptedTxL2Logs.random(numPublicCallsPerTx, numUnencryptedLogsPerCall); + static random(numPublicCallsPerTx = 3, numPublicLogsPerCall = 1): TxEffect { const contractClassLogs = ContractClassTxL2Logs.random(1, 1); return new TxEffect( RevertCode.random(), @@ -226,9 +227,8 @@ export class TxEffect { makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.random), makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, () => new PublicDataWrite(Fr.random(), Fr.random())), makeTuple(MAX_PRIVATE_LOGS_PER_TX, () => new PrivateLog(makeTuple(PRIVATE_LOG_SIZE_IN_FIELDS, Fr.random))), - new Fr(unencryptedLogs.getKernelLength()), + makeTuple(numPublicCallsPerTx * numPublicLogsPerCall, PublicLog.random), new Fr(contractClassLogs.getKernelLength()), - unencryptedLogs, contractClassLogs, ); } @@ -243,9 +243,8 @@ export class TxEffect { [], [], [], + [], Fr.ZERO, - Fr.ZERO, - UnencryptedTxL2Logs.empty(), ContractClassTxL2Logs.empty(), ); } @@ -375,12 +374,12 @@ export class TxEffect { flattened.push(this.toPrefix(PRIVATE_LOGS_PREFIX, this.privateLogs.length * PRIVATE_LOG_SIZE_IN_FIELDS)); flattened.push(...this.privateLogs.map(l => l.fields).flat()); } + if (this.publicLogs.length) { + flattened.push(this.toPrefix(PUBLIC_LOGS_PREFIX, this.publicLogs.length * PUBLIC_LOG_SIZE_IN_FIELDS)); + flattened.push(...this.publicLogs.map(l => l.toFields()).flat()); + } // TODO(#8954): When logs are refactored into fields, we will append the values here // Currently appending the single log hash as an interim solution - if (this.unencryptedLogs.unrollLogs().length) { - flattened.push(this.toPrefix(UNENCRYPTED_LOGS_PREFIX, this.unencryptedLogs.unrollLogs().length)); - flattened.push(...this.unencryptedLogs.unrollLogs().map(log => Fr.fromBuffer(log.getSiloedHash()))); - } if (this.contractClassLogs.unrollLogs().length) { flattened.push(this.toPrefix(CONTRACT_CLASS_LOGS_PREFIX, this.contractClassLogs.unrollLogs().length)); flattened.push(...this.contractClassLogs.unrollLogs().map(log => Fr.fromBuffer(log.getSiloedHash()))); @@ -398,11 +397,7 @@ export class TxEffect { * Decodes a flat packed array of prefixed fields to TxEffect * TODO(#8954): When logs are refactored into fields, we won't need to inject them here, instead just reading from fields as below */ - static fromBlobFields( - fields: Fr[] | FieldReader, - unencryptedLogs?: UnencryptedTxL2Logs, - contractClassLogs?: ContractClassTxL2Logs, - ) { + static fromBlobFields(fields: Fr[] | FieldReader, contractClassLogs?: ContractClassTxL2Logs) { const ensureEmpty = (arr: Array) => { if (arr.length) { throw new Error('Invalid fields given to TxEffect.fromBlobFields(): Attempted to assign property twice.'); @@ -458,17 +453,15 @@ export class TxEffect { } break; } - // TODO(#8954): When logs are refactored into fields, we will append the read fields here - case UNENCRYPTED_LOGS_PREFIX: - // effect.unencryptedLogs = UnencryptedTxL2Logs.fromFields(reader.readFieldArray(length)); - ensureEmpty(effect.unencryptedLogs.functionLogs); - if (!unencryptedLogs) { - throw new Error(`Tx effect has unencrypted logs, but they were not passed raw to .fromBlobFields()`); + case PUBLIC_LOGS_PREFIX: { + ensureEmpty(effect.publicLogs); + const flatPublicLogs = reader.readFieldArray(length); + for (let i = 0; i < length; i += PUBLIC_LOG_SIZE_IN_FIELDS) { + effect.publicLogs.push(PublicLog.fromFields(flatPublicLogs.slice(i, i + PUBLIC_LOG_SIZE_IN_FIELDS))); } - this.checkInjectedLogs(unencryptedLogs, reader.readFieldArray(length)); - effect.unencryptedLogs = unencryptedLogs; - effect.unencryptedLogsLength = new Fr(unencryptedLogs.getKernelLength()); break; + } + // TODO(#8954): When logs are refactored into fields, we will append the read fields here case CONTRACT_CLASS_LOGS_PREFIX: // effect.contractClassLogs = ContractClassTxL2Logs.fromFields(reader.readFieldArray(length)); ensureEmpty(effect.contractClassLogs.functionLogs); @@ -486,8 +479,6 @@ export class TxEffect { } // If the input fields have no logs, ensure we match the original struct by reassigning injected logs - effect.unencryptedLogs = - !effect.unencryptedLogs.getTotalLogCount() && unencryptedLogs ? unencryptedLogs : effect.unencryptedLogs; effect.contractClassLogs = !effect.contractClassLogs.getTotalLogCount() && contractClassLogs ? contractClassLogs : effect.contractClassLogs; return effect; @@ -517,9 +508,8 @@ export class TxEffect { fields.l2ToL1Msgs, fields.publicDataWrites, fields.privateLogs, - fields.unencryptedLogsLength, + fields.publicLogs, fields.contractClassLogsLength, - fields.unencryptedLogs, fields.contractClassLogs, ); } @@ -535,9 +525,8 @@ export class TxEffect { l2ToL1Msgs: z.array(schemas.Fr), publicDataWrites: z.array(PublicDataWrite.schema), privateLogs: z.array(PrivateLog.schema), - unencryptedLogsLength: schemas.Fr, + publicLogs: z.array(PublicLog.schema), contractClassLogsLength: schemas.Fr, - unencryptedLogs: UnencryptedTxL2Logs.schema, contractClassLogs: ContractClassTxL2Logs.schema, }) .transform(TxEffect.from); @@ -553,9 +542,8 @@ export class TxEffect { l2ToL1Msgs: [${this.l2ToL1Msgs.map(h => h.toString()).join(', ')}], publicDataWrites: [${this.publicDataWrites.map(h => h.toString()).join(', ')}], privateLogs: [${this.privateLogs.map(l => l.toString()).join(', ')}], - unencryptedLogsLength: ${this.unencryptedLogsLength}, + publicLogs: [${this.publicLogs.map(l => l.toString()).join(', ')}], contractClassLogsLength: ${this.contractClassLogsLength}, - unencryptedLogs: ${jsonStringify(this.unencryptedLogs)} contractClassLogs: ${jsonStringify(this.contractClassLogs)} }`; } diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 057ef714e61..f9ca211665a 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -15,7 +15,7 @@ export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 16; export const MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL = 16; export const MAX_KEY_VALIDATION_REQUESTS_PER_CALL = 16; export const MAX_PRIVATE_LOGS_PER_CALL = 16; -export const MAX_UNENCRYPTED_LOGS_PER_CALL = 4; +export const MAX_PUBLIC_LOGS_PER_CALL = 4; export const MAX_CONTRACT_CLASS_LOGS_PER_CALL = 1; export const ARCHIVE_HEIGHT = 29; export const VK_TREE_HEIGHT = 6; @@ -53,7 +53,7 @@ export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 64; export const MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX = 64; export const MAX_KEY_VALIDATION_REQUESTS_PER_TX = 64; export const MAX_PRIVATE_LOGS_PER_TX = 32; -export const MAX_UNENCRYPTED_LOGS_PER_TX = 8; +export const MAX_PUBLIC_LOGS_PER_TX = 8; export const MAX_CONTRACT_CLASS_LOGS_PER_TX = 1; export const NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; export const PRIVATE_KERNEL_INIT_INDEX = 0; @@ -78,6 +78,8 @@ export const INITIALIZATION_SLOT_SEPARATOR = 1000000000; export const INITIAL_L2_BLOCK_NUM = 1; export const FIELDS_PER_BLOB = 4096; export const BLOBS_PER_BLOCK = 3; +export const PUBLIC_LOG_DATA_SIZE_IN_FIELDS = 13; +export const PUBLIC_LOG_SIZE_IN_FIELDS = 14; export const PRIVATE_LOG_SIZE_IN_FIELDS = 18; export const AZTEC_MAX_EPOCH_DURATION = 48; export const GENESIS_BLOCK_HASH = 20646204262468251631976884937192820660867507115079672078981654411421834866549n; @@ -165,7 +167,7 @@ export const TOTAL_MANA_USED_LENGTH = 1; export const BLOCK_HEADER_LENGTH = 25; export const BLOCK_HEADER_LENGTH_BYTES = 648; export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 741; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 864; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 908; export const PRIVATE_CONTEXT_INPUTS_LENGTH = 40; export const FEE_RECIPIENT_LENGTH = 2; export const AGGREGATION_OBJECT_LENGTH = 16; @@ -181,10 +183,10 @@ export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2230; export const PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH = 900; export const PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH = 160; export const NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS = 3; -export const AVM_ACCUMULATED_DATA_LENGTH = 320; +export const AVM_ACCUMULATED_DATA_LENGTH = 400; export const PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1847; export const PRIVATE_TO_ROLLUP_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 783; -export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1011; +export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1091; export const CONSTANT_ROLLUP_DATA_LENGTH = 13; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 52; export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 986; @@ -215,7 +217,7 @@ export const MAX_PUBLIC_BYTECODE_SIZE_IN_BYTES = 96000; export const MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS = 21; export const AVM_PROOF_LENGTH_IN_FIELDS = 4154; export const AVM_PUBLIC_COLUMN_MAX_SIZE = 1024; -export const AVM_PUBLIC_INPUTS_FLATTENED_SIZE = 2912; +export const AVM_PUBLIC_INPUTS_FLATTENED_SIZE = 2956; export const MEM_TAG_FF = 0; export const MEM_TAG_U1 = 1; export const MEM_TAG_U8 = 2; @@ -337,7 +339,7 @@ export const NULLIFIERS_PREFIX = 4; export const L2_L1_MSGS_PREFIX = 5; export const PUBLIC_DATA_UPDATE_REQUESTS_PREFIX = 6; export const PRIVATE_LOGS_PREFIX = 7; -export const UNENCRYPTED_LOGS_PREFIX = 8; +export const PUBLIC_LOGS_PREFIX = 8; export const CONTRACT_CLASS_LOGS_PREFIX = 9; export const PROOF_TYPE_PLONK = 0; export const PROOF_TYPE_HONK = 1; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index acf5a3a0181..419daa59e69 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -27,10 +27,10 @@ const CPP_CONSTANTS = [ 'MAX_NOTE_HASHES_PER_TX', 'MAX_NULLIFIERS_PER_TX', 'MAX_L2_TO_L1_MSGS_PER_TX', - 'MAX_UNENCRYPTED_LOGS_PER_TX', + 'MAX_PUBLIC_LOGS_PER_TX', + 'PUBLIC_LOG_DATA_SIZE_IN_FIELDS', 'MAX_NOTE_HASH_READ_REQUESTS_PER_CALL', 'MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX', - 'MAX_UNENCRYPTED_LOGS_PER_TX', 'MAX_NULLIFIER_READ_REQUESTS_PER_CALL', 'MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL', 'MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL', @@ -47,7 +47,7 @@ const CPP_CONSTANTS = [ 'L2_TO_L1_MESSAGE_LENGTH', 'MAX_L2_TO_L1_MSGS_PER_CALL', 'LOG_HASH_LENGTH', - 'MAX_UNENCRYPTED_LOGS_PER_CALL', + 'MAX_PUBLIC_LOGS_PER_CALL', 'HEADER_LENGTH', 'GLOBAL_VARIABLES_LENGTH', 'AZTEC_ADDRESS_LENGTH', @@ -117,7 +117,7 @@ const PIL_CONSTANTS = [ 'MAX_NOTE_HASHES_PER_CALL', 'MAX_NULLIFIERS_PER_CALL', 'MAX_L2_TO_L1_MSGS_PER_CALL', - 'MAX_UNENCRYPTED_LOGS_PER_CALL', + 'MAX_PUBLIC_LOGS_PER_CALL', 'START_NOTE_HASH_EXISTS_WRITE_OFFSET', 'START_NULLIFIER_EXISTS_OFFSET', 'START_NULLIFIER_NON_EXISTS_OFFSET', diff --git a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts index 6b64b79fb06..ba3b8f0c908 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts @@ -10,12 +10,12 @@ import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_PUBLIC_LOGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; -import { ScopedLogHash } from '../log_hash.js'; import { PublicDataWrite } from '../public_data_write.js'; +import { PublicLog } from '../public_log.js'; export class AvmAccumulatedData { constructor( @@ -32,9 +32,9 @@ export class AvmAccumulatedData { */ public l2ToL1Msgs: Tuple, /** - * The unencrypted logs emitted from the AVM execution. + * The public logs emitted from the AVM execution. */ - public unencryptedLogsHashes: Tuple, + public publicLogs: Tuple, /** * The public data writes made in the AVM execution. */ @@ -46,7 +46,7 @@ export class AvmAccumulatedData { arraySerializedSizeOfNonEmpty(this.noteHashes) + arraySerializedSizeOfNonEmpty(this.nullifiers) + arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + - arraySerializedSizeOfNonEmpty(this.unencryptedLogsHashes) + + arraySerializedSizeOfNonEmpty(this.publicLogs) + arraySerializedSizeOfNonEmpty(this.publicDataWrites) ); } @@ -57,19 +57,13 @@ export class AvmAccumulatedData { reader.readArray(MAX_NOTE_HASHES_PER_TX, Fr), reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_PUBLIC_LOGS_PER_TX, PublicLog), reader.readArray(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), ); } toBuffer() { - return serializeToBuffer( - this.noteHashes, - this.nullifiers, - this.l2ToL1Msgs, - this.unencryptedLogsHashes, - this.publicDataWrites, - ); + return serializeToBuffer(this.noteHashes, this.nullifiers, this.l2ToL1Msgs, this.publicLogs, this.publicDataWrites); } static fromFields(fields: Fr[] | FieldReader) { @@ -78,7 +72,7 @@ export class AvmAccumulatedData { reader.readFieldArray(MAX_NOTE_HASHES_PER_TX), reader.readFieldArray(MAX_NULLIFIERS_PER_TX), reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_PUBLIC_LOGS_PER_TX, PublicLog), reader.readArray(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), ); } @@ -96,7 +90,7 @@ export class AvmAccumulatedData { makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.zero), makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), - makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), + makeTuple(MAX_PUBLIC_LOGS_PER_TX, PublicLog.empty), makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), ); } @@ -106,7 +100,7 @@ export class AvmAccumulatedData { this.noteHashes.every(x => x.isZero()) && this.nullifiers.every(x => x.isZero()) && this.l2ToL1Msgs.every(x => x.isEmpty()) && - this.unencryptedLogsHashes.every(x => x.isEmpty()) && + this.publicLogs.every(x => x.isEmpty()) && this.publicDataWrites.every(x => x.isEmpty()) ); } @@ -126,7 +120,7 @@ export class AvmAccumulatedData { .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}], - unencryptedLogsHashes: [${this.unencryptedLogsHashes + publicLogs: [${this.publicLogs .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}], diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 8da2960cd5e..7a727fcff51 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -63,6 +63,7 @@ export * from './public_data_read.js'; export * from './public_data_update_request.js'; export * from './public_data_write.js'; export * from './public_inner_call_request.js'; +export * from './public_log.js'; export * from './read_request.js'; export * from './read_request_hints/index.js'; export * from './recursive_proof.js'; diff --git a/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts b/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts index 37b98d62282..0fd04cda28c 100644 --- a/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts +++ b/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts @@ -29,13 +29,13 @@ export class IndexedTaggingSecret { } /** - * Computes the tag as it is submitted on-chain. + * Computes the siloed tag. * @dev We do this second layer of siloing (one was already done as the tagging secret is app-siloed) because kernels * do that to protect against contract impersonation attacks. This extra layer of siloing in kernels ensures that * a malicious contract cannot emit a note with a tag corresponding to another contract. * @param recipient The recipient of the note * @param app The app address - * @returns The tag as it is submitted on-chain in a log. + * @returns The siloed tag. */ computeSiloedTag(recipient: AztecAddress, app: AztecAddress) { const tag = this.computeTag(recipient); 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 9834e2f4cb9..21105d11047 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 @@ -23,7 +23,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL, + MAX_PUBLIC_LOGS_PER_CALL, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, } from '../constants.gen.js'; import { isEmptyArray } from '../utils/index.js'; @@ -34,10 +34,10 @@ import { ContractStorageUpdateRequest } from './contract_storage_update_request. import { Gas } from './gas.js'; import { GlobalVariables } from './global_variables.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 { PublicInnerCallRequest } from './public_inner_call_request.js'; +import { PublicLog } from './public_log.js'; import { ReadRequest } from './read_request.js'; import { RevertCode } from './revert_code.js'; import { TreeLeafReadRequest } from './tree_leaf_read_request.js'; @@ -113,10 +113,9 @@ export class PublicCircuitPublicInputs { */ public endSideEffectCounter: Fr, /** - * Hash of the unencrypted logs emitted in this function call. - * Note: Truncated to 31 bytes to fit in Fr. + * The public logs emitted in this function call. */ - public unencryptedLogsHashes: Tuple, + public publicLogs: Tuple, /** * Header of a block whose state is used during public execution. Set by sequencer to be a header of a block * previous to the one in which the tx is included. @@ -174,7 +173,7 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, - makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash.empty), + makeTuple(MAX_PUBLIC_LOGS_PER_CALL, PublicLog.empty), BlockHeader.empty(), GlobalVariables.empty(), AztecAddress.ZERO, @@ -201,7 +200,7 @@ export class PublicCircuitPublicInputs { isEmptyArray(this.l2ToL1Msgs) && this.startSideEffectCounter.isZero() && this.endSideEffectCounter.isZero() && - isEmptyArray(this.unencryptedLogsHashes) && + isEmptyArray(this.publicLogs) && this.historicalHeader.isEmpty() && this.globalVariables.isEmpty() && this.proverAddress.isZero() && @@ -234,7 +233,7 @@ export class PublicCircuitPublicInputs { fields.l2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, - fields.unencryptedLogsHashes, + fields.publicLogs, fields.historicalHeader, fields.globalVariables, fields.proverAddress, @@ -286,7 +285,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), + reader.readArray(MAX_PUBLIC_LOGS_PER_CALL, PublicLog), reader.readObject(BlockHeader), reader.readObject(GlobalVariables), reader.readObject(AztecAddress), @@ -316,7 +315,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), + reader.readArray(MAX_PUBLIC_LOGS_PER_CALL, PublicLog), BlockHeader.fromFields(reader), GlobalVariables.fromFields(reader), AztecAddress.fromFields(reader), @@ -375,7 +374,7 @@ export class PublicCircuitPublicInputs { startSideEffectCounter: ${inspect(this.startSideEffectCounter)}, endSideEffectCounter: ${inspect(this.endSideEffectCounter)}, startSideEffectCounter: ${inspect(this.startSideEffectCounter)}, - unencryptedLogsHashes: [${this.unencryptedLogsHashes + publicLogs: [${this.publicLogs .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}]}, diff --git a/yarn-project/circuits.js/src/structs/public_log.test.ts b/yarn-project/circuits.js/src/structs/public_log.test.ts new file mode 100644 index 00000000000..19ec895a97a --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_log.test.ts @@ -0,0 +1,27 @@ +import { PUBLIC_LOG_SIZE_IN_FIELDS } from '../constants.gen.js'; +import { PublicLog } from './public_log.js'; + +describe('PublicLog', () => { + let log: PublicLog; + + beforeAll(() => { + log = PublicLog.random(); + }); + + it('serializes to buffer and deserializes it back', () => { + const buffer = log.toBuffer(); + const res = PublicLog.fromBuffer(buffer); + expect(res).toEqual(log); + }); + + it('serializes to field array and deserializes it back', () => { + const fieldArray = log.toFields(); + const res = PublicLog.fromFields(fieldArray); + expect(res).toEqual(log); + }); + + it('number of fields matches constant', () => { + const fields = log.toFields(); + expect(fields.length).toBe(PUBLIC_LOG_SIZE_IN_FIELDS); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/public_log.ts b/yarn-project/circuits.js/src/structs/public_log.ts new file mode 100644 index 00000000000..7eb63da7516 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_log.ts @@ -0,0 +1,83 @@ +import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { Fr } from '@aztec/foundation/fields'; +import { schemas } from '@aztec/foundation/schemas'; +import { + BufferReader, + FieldReader, + type Tuple, + serializeToBuffer, + serializeToFields, +} from '@aztec/foundation/serialize'; + +import { inspect } from 'util'; +import { z } from 'zod'; + +import { PUBLIC_LOG_DATA_SIZE_IN_FIELDS, PUBLIC_LOG_SIZE_IN_FIELDS } from '../constants.gen.js'; + +export class PublicLog { + static SIZE_IN_BYTES = Fr.SIZE_IN_BYTES * PUBLIC_LOG_SIZE_IN_FIELDS; + + constructor(public contractAddress: AztecAddress, public log: Tuple) {} + + toFields(): Fr[] { + return serializeToFields(...PublicLog.getFields(this)); + } + + static getFields(fields: FieldsOf) { + return [fields.contractAddress, fields.log] as const; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new PublicLog(reader.readObject(AztecAddress), reader.readFieldArray(PUBLIC_LOG_DATA_SIZE_IN_FIELDS)); + } + + isEmpty() { + return this.contractAddress.isZero() && this.log.every(f => f.isZero()); + } + + static empty() { + return new PublicLog(AztecAddress.ZERO, makeTuple(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr.zero)); + } + + toBuffer(): Buffer { + return serializeToBuffer(...PublicLog.getFields(this)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicLog(reader.readObject(AztecAddress), reader.readArray(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr)); + } + + static random() { + return new PublicLog(AztecAddress.random(), makeTuple(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr.random)); + } + + equals(other: this) { + return ( + this.contractAddress.equals(other.contractAddress) && + this.log.reduce((acc, field, i) => acc && field.equals(other.log[i]), true) + ); + } + + toHumanReadable(): string { + return `PublicLog: (contractAddress: ${this.contractAddress} log: ${this.log})`; + } + + static get schema() { + return z + .object({ + contractAddress: AztecAddress.schema, + log: z.array(schemas.Fr), + }) + .transform(({ contractAddress, log }) => PublicLog.fromFields([contractAddress.toField(), ...log])); + } + + [inspect.custom](): string { + return `PublicLog { + contractAddress: ${inspect(this.contractAddress)}, + log: [${this.log.map(x => inspect(x)).join(', ')}], + }`; + } +} diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 1d145255b2e..908778ea909 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -55,8 +55,8 @@ import { MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL, MAX_PRIVATE_LOGS_PER_TX, + MAX_PUBLIC_LOGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, MaxBlockNumber, MembershipWitness, NESTED_RECURSIVE_PROOF_LENGTH, @@ -71,6 +71,7 @@ import { NullifierLeafPreimage, PRIVATE_LOG_SIZE_IN_FIELDS, PUBLIC_DATA_TREE_HEIGHT, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, ParityPublicInputs, PartialPrivateTailPublicInputsForPublic, PartialPrivateTailPublicInputsForRollup, @@ -134,6 +135,7 @@ import { PrivateToPublicAccumulatedData, PrivateToPublicKernelCircuitPublicInputs, PublicDataWrite, + PublicLog, ScopedL2ToL1Message, TreeSnapshots, TxConstantData, @@ -197,6 +199,10 @@ function makePrivateLogData(seed: number) { return new PrivateLogData(makePrivateLog(seed + 0x100), seed, seed + 1); } +function makePublicLog(seed: number) { + return new PublicLog(makeAztecAddress(seed), makeTuple(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, fr, seed + 1)); +} + /** * Creates an arbitrary tx context with the given seed. * @param seed - The seed to use for generating the tx context. @@ -348,7 +354,7 @@ function makeAvmAccumulatedData(seed = 1) { makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed), makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100), makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x200), - makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x300), + makeTuple(MAX_PUBLIC_LOGS_PER_TX, makePublicLog, seed + 0x300), makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataWrite, seed + 0x400), ); } diff --git a/yarn-project/cli/src/cmds/pxe/get_logs.ts b/yarn-project/cli/src/cmds/pxe/get_logs.ts index b976956d7b7..18b68e4dae9 100644 --- a/yarn-project/cli/src/cmds/pxe/get_logs.ts +++ b/yarn-project/cli/src/cmds/pxe/get_logs.ts @@ -28,7 +28,7 @@ export async function getLogs( const filter: LogFilter = { txHash, fromBlock, toBlock, afterLog, contractAddress }; const fetchLogs = async () => { - const response = await pxe.getUnencryptedLogs(filter); + const response = await pxe.getPublicLogs(filter); const logs = response.logs; if (!logs.length) { @@ -43,7 +43,7 @@ export async function getLogs( if (!follow && !filter.afterLog) { log('Logs found: \n'); } - logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); + logs.forEach(publicLog => log(publicLog.toHumanReadable())); // Set the continuation parameter for the following requests filter.afterLog = logs[logs.length - 1].id; } diff --git a/yarn-project/cli/src/cmds/pxe/index.ts b/yarn-project/cli/src/cmds/pxe/index.ts index 56fe779ac17..14ebe624fb3 100644 --- a/yarn-project/cli/src/cmds/pxe/index.ts +++ b/yarn-project/cli/src/cmds/pxe/index.ts @@ -82,7 +82,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: Logger program .command('get-logs') - .description('Gets all the unencrypted logs from an intersection of all the filter params.') + .description('Gets all the public logs from an intersection of all the filter params.') .option('-tx, --tx-hash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) .option( '-fb, --from-block ', diff --git a/yarn-project/cli/src/utils/inspect.ts b/yarn-project/cli/src/utils/inspect.ts index a1a8148d559..7ed8e2b00b6 100644 --- a/yarn-project/cli/src/utils/inspect.ts +++ b/yarn-project/cli/src/utils/inspect.ts @@ -3,7 +3,6 @@ import { type ExtendedNote, NoteStatus, type PXE, type TxHash } from '@aztec/cir import { type AztecAddress, type Fr } from '@aztec/circuits.js'; import { siloNullifier } from '@aztec/circuits.js/hash'; import { type LogFn } from '@aztec/foundation/log'; -import { toHumanReadable } from '@aztec/foundation/serialize'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; export async function inspectBlock(pxe: PXE, blockNumber: number, log: LogFn, opts: { showTxs?: boolean } = {}) { @@ -65,13 +64,12 @@ export async function inspectTx( log(` Fee: ${receipt.transactionFee.toString()}`); } - // Unencrypted logs - const unencryptedLogs = effects.unencryptedLogs.unrollLogs(); - if (unencryptedLogs.length > 0) { + // Public logs + const publicLogs = effects.publicLogs; + if (publicLogs.length > 0) { log(' Logs:'); - for (const unencryptedLog of unencryptedLogs) { - const data = toHumanReadable(unencryptedLog.data, 1000); - log(` ${toFriendlyAddress(unencryptedLog.contractAddress, artifactMap)}: ${data}`); + for (const publicLog of publicLogs) { + log(` ${publicLog.toHumanReadable()}`); } } diff --git a/yarn-project/end-to-end/src/bench/utils.ts b/yarn-project/end-to-end/src/bench/utils.ts index 4fb6bb568b8..8003534c240 100644 --- a/yarn-project/end-to-end/src/bench/utils.ts +++ b/yarn-project/end-to-end/src/bench/utils.ts @@ -122,7 +122,7 @@ export function getFolderSize(path: string): number { /** * Returns a call to the benchmark contract. Each call has a private execution (account entrypoint), * a nested private call (create_note), a public call (increment_balance), and a nested public - * call (broadcast). These include emitting one private note and one unencrypted log, two storage + * call (broadcast). These include emitting one private note and one public log, two storage * reads and one write. * @param index - Index of the call within a block. * @param context - End to end context. diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts index 881a587c89c..6250c19b8e2 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts @@ -2,6 +2,7 @@ import { getDeployedTestAccountsWallets } from '@aztec/accounts/testing'; import { AztecAddress, BatchCall, + Fr, type Logger, type PXE, type Wallet, @@ -107,8 +108,8 @@ describe('e2e_deploy_contract deploy method', () => { const contract = await TestContract.deploy(wallet).send().deployed(); logger.debug(`Call a public function to check that it was publicly deployed`); const receipt = await contract.methods.emit_unencrypted(42).send().wait(); - const logs = await pxe.getUnencryptedLogs({ txHash: receipt.txHash }); - expect(logs.logs[0].log.data.toString('hex').replace(/^0+/, '')).toEqual('2a'); + const logs = await pxe.getPublicLogs({ txHash: receipt.txHash }); + expect(logs.logs[0].log.log[0]).toEqual(new Fr(42)); }); it('refuses to deploy a contract with no constructor and no public deployment', async () => { diff --git a/yarn-project/end-to-end/src/e2e_event_logs.test.ts b/yarn-project/end-to-end/src/e2e_event_logs.test.ts index 914b99ad8ac..fae4cab3509 100644 --- a/yarn-project/end-to-end/src/e2e_event_logs.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_logs.test.ts @@ -84,7 +84,7 @@ describe('Logs', () => { expect(badEvent1).toBe(undefined); }); - it('emits multiple events as encrypted logs and decodes them', async () => { + it('emits multiple events as private logs and decodes them', async () => { const preimages = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple, 5>; const txs = await Promise.all( @@ -98,13 +98,13 @@ describe('Logs', () => { // We get all the events we can decrypt with our incoming viewing keys - const collectedEvent0s = await wallets[0].getEncryptedEvents( + const collectedEvent0s = await wallets[0].getPrivateEvents( TestLogContract.events.ExampleEvent0, firstBlockNumber, numBlocks, ); - const collectedEvent0sWithIncoming = await wallets[0].getEncryptedEvents( + const collectedEvent0sWithIncoming = await wallets[0].getPrivateEvents( TestLogContract.events.ExampleEvent0, firstBlockNumber, numBlocks, @@ -112,7 +112,7 @@ describe('Logs', () => { [wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey], ); - const collectedEvent1s = await wallets[0].getEncryptedEvents( + const collectedEvent1s = await wallets[0].getPrivateEvents( TestLogContract.events.ExampleEvent1, firstBlockNumber, numBlocks, @@ -123,7 +123,7 @@ describe('Logs', () => { expect(collectedEvent0s.length).toBe(5); expect(collectedEvent1s.length).toBe(5); - const emptyEvent1s = await wallets[0].getEncryptedEvents( + const emptyEvent1s = await wallets[0].getPrivateEvents( TestLogContract.events.ExampleEvent1, firstBlockNumber, numBlocks, @@ -151,7 +151,7 @@ describe('Logs', () => { ); }); - it('emits multiple events as unencrypted logs and decodes them', async () => { + it('emits multiple unencrypted events as public logs and decodes them', async () => { const preimage = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple, 5>; let i = 0; @@ -161,13 +161,13 @@ describe('Logs', () => { ); const lastTx = await testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait(); - const collectedEvent0s = await wallets[0].getUnencryptedEvents( + const collectedEvent0s = await wallets[0].getPublicEvents( TestLogContract.events.ExampleEvent0, firstTx.blockNumber!, lastTx.blockNumber! - firstTx.blockNumber! + 1, ); - const collectedEvent1s = await wallets[0].getUnencryptedEvents( + const collectedEvent1s = await wallets[0].getPublicEvents( TestLogContract.events.ExampleEvent1, firstTx.blockNumber!, lastTx.blockNumber! - firstTx.blockNumber! + 1, diff --git a/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts index 0db8df6f558..69d71fb17fb 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract/manual_public.test.ts @@ -1,4 +1,5 @@ import { type AztecAddress, BatchCall, Fr, type Wallet, toBigIntBE } from '@aztec/aztec.js'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; import { NestedContractTest } from './nested_contract_test.js'; @@ -50,11 +51,13 @@ describe('e2e_nested_contract manual', () => { const tx = await new BatchCall(wallet, actions).send().wait(); const extendedLogs = ( - await wallet.getUnencryptedLogs({ + await wallet.getPublicLogs({ fromBlock: tx.blockNumber!, }) ).logs; - const processedLogs = extendedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); + const processedLogs = extendedLogs.map(extendedLog => + toBigIntBE(serializeToBuffer(extendedLog.log.log.filter(elt => !elt.isZero()))), + ); expect(processedLogs).toEqual([20n, 40n]); expect(await getChildStoredValue(childContract)).toEqual(new Fr(40n)); }); diff --git a/yarn-project/end-to-end/src/e2e_ordering.test.ts b/yarn-project/end-to-end/src/e2e_ordering.test.ts index f87a10f6e9a..da87ad57ddf 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -1,5 +1,6 @@ // Test suite for testing proper ordering of side effects import { Fr, type FunctionSelector, type PXE, type Wallet, toBigIntBE } from '@aztec/aztec.js'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; import { ChildContract } from '@aztec/noir-contracts.js/Child'; import { ParentContract } from '@aztec/noir-contracts.js/Parent'; @@ -18,13 +19,18 @@ describe('e2e_ordering', () => { let teardown: () => Promise; const expectLogsFromLastBlockToBe = async (logMessages: bigint[]) => { + // docs:start:get_logs const fromBlock = await pxe.getBlockNumber(); const logFilter = { fromBlock, toBlock: fromBlock + 1, }; - const unencryptedLogs = (await pxe.getUnencryptedLogs(logFilter)).logs; - const bigintLogs = unencryptedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); + const publicLogs = (await pxe.getPublicLogs(logFilter)).logs; + // docs:end:get_logs + + const bigintLogs = publicLogs.map(extendedLog => + toBigIntBE(serializeToBuffer(extendedLog.log.log.filter(elt => !elt.isZero()))), + ); expect(bigintLogs).toStrictEqual(logMessages); }; @@ -115,7 +121,7 @@ describe('e2e_ordering', () => { 'set_value_twice_with_nested_first', 'set_value_twice_with_nested_last', 'set_value_with_two_nested_calls', - ] as const)('orders unencrypted logs in %s', async method => { + ] as const)('orders public logs in %s', async method => { const expectedOrder = expectedOrders[method]; await child.methods[method]().send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_synching.test.ts b/yarn-project/end-to-end/src/e2e_synching.test.ts index f30ec157241..8b7d393faa9 100644 --- a/yarn-project/end-to-end/src/e2e_synching.test.ts +++ b/yarn-project/end-to-end/src/e2e_synching.test.ts @@ -533,7 +533,7 @@ describe('e2e_synching', () => { expect(await archiver.getTxEffect(txHash)).not.toBeUndefined; expect(await archiver.getPrivateLogs(blockTip.number, 1)).not.toEqual([]); expect( - await archiver.getUnencryptedLogs({ fromBlock: blockTip.number, toBlock: blockTip.number + 1 }), + await archiver.getPublicLogs({ fromBlock: blockTip.number, toBlock: blockTip.number + 1 }), ).not.toEqual([]); await rollup.write.prune(); @@ -557,9 +557,9 @@ describe('e2e_synching', () => { expect(await archiver.getTxEffect(txHash)).toBeUndefined; expect(await archiver.getPrivateLogs(blockTip.number, 1)).toEqual([]); - expect( - await archiver.getUnencryptedLogs({ fromBlock: blockTip.number, toBlock: blockTip.number + 1 }), - ).toEqual([]); + expect(await archiver.getPublicLogs({ fromBlock: blockTip.number, toBlock: blockTip.number + 1 })).toEqual( + [], + ); // Check world state reverted as well expect(await worldState.getLatestBlockNumber()).toEqual(Number(assumeProvenThrough)); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts index 43e789c6887..b23c219d915 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts @@ -45,7 +45,7 @@ describe('e2e_token_contract private transfer recursion', () => { // We should have created a single new note, for the recipient expect(tx.debugInfo?.noteHashes.length).toBe(1); - const events = await wallets[1].getEncryptedEvents(TokenContract.events.Transfer, tx.blockNumber!, 1); + const events = await wallets[1].getPrivateEvents(TokenContract.events.Transfer, tx.blockNumber!, 1); expect(events[0]).toEqual({ from: accounts[0].address, @@ -71,7 +71,7 @@ describe('e2e_token_contract private transfer recursion', () => { const senderBalance = await asset.methods.balance_of_private(accounts[0].address).simulate(); expect(senderBalance).toEqual(expectedChange); - const events = await wallets[1].getEncryptedEvents(TokenContract.events.Transfer, tx.blockNumber!, 1); + const events = await wallets[1].getPrivateEvents(TokenContract.events.Transfer, tx.blockNumber!, 1); expect(events[0]).toEqual({ from: accounts[0].address, diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts index f586644a680..a5eead3ae09 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts @@ -33,7 +33,7 @@ describe('e2e_token_contract transfer private', () => { const tx = await asset.methods.transfer(accounts[1].address, amount).send().wait(); tokenSim.transferPrivate(accounts[0].address, accounts[1].address, amount); - const events = await wallets[1].getEncryptedEvents(TokenContract.events.Transfer, tx.blockNumber!, 1); + const events = await wallets[1].getPrivateEvents(TokenContract.events.Transfer, tx.blockNumber!, 1); expect(events[0]).toEqual({ from: accounts[0].address, diff --git a/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json b/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json index 0bd70d4dde7..0aa2277b426 100644 --- a/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json +++ b/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json @@ -1 +1 @@ -{"proof":"0x0000b3640000059b000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000000010237797d6a2c04d20d4fa06b74482bd970ccd51a43d9b05b57e9b91fa1ae1cae00000000000000000000000000000000000000000000000000000000000000012925752f6e51bf2738d82bf0e4cb0805eb37e908a909db140c8ce9073d03bad900000000000000000000000000000000000000000000000000000000000000032da55666630fdf8594065c377958c827dc1c130dac91f17c6699b53dce60ef752c2cd74ae9c2b2a1ab717d69eb4753f65607db94e93a8c0a51f23b96e34f3038000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000241a65339d99ce6f973739bda9c459c80e677af4783b35941098d8cea5b54022dcbefa1ba7a12eb4f2ca5632698034aaab9a60c0428603cb64a7685760f203200000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e7f4db29a33c7bc000000000000000000000000000000000000000000000000ed49e97fd7fe5ac9500000000000000000000000000000000000000000000000090b4c341609973f90000000000000000000000000000000000000000000000000001ca25a0325af100000000000000000000000000000000000000000000000dad49a5e22948da6a00000000000000000000000000000000000000000000000d1c2474fcbc5840fb00000000000000000000000000000000000000000000000dcaa30af196fd23d90000000000000000000000000000000000000000000000000002308ba6a6655e000000000000000000000000000000000000000000000004d28cdf4637523a2a00000000000000000000000000000000000000000000000d7853cd15fee2d4e500000000000000000000000000000000000000000000000c3f4ac44973c66a3000000000000000000000000000000000000000000000000000018be2f90f4088000000000000000000000000000000000000000000000001e3a57aa949af543d000000000000000000000000000000000000000000000007e5ea0fe99a92469900000000000000000000000000000000000000000000000f214cc918d2a5f92400000000000000000000000000000000000000000000000000023c100eb331e000000000000000000000000000000091f3bfe5f9c9c3b173e3036d8a3307e9de0000000000000000000000000000000000066b3766100e6228dbad6bac16f4c50000000000000000000000000000008c449318af170ae6213db4d074d95dc935000000000000000000000000000000000007795f6456bf9f0fb91b4b85da625e000000000000000000000000000000cf9848382a0e66a280138616fc9c249adb00000000000000000000000000000000001bcf32cbd55b6b3a666937fc3f8edf0000000000000000000000000000002f09183910cb0aefb011597b98f243f844000000000000000000000000000000000000593f0f28aab706e410019dcadba30000000000000000000000000000000a6033f17b156db5ccceee834fa616cff6000000000000000000000000000000000013c138c24dff08179431b79b5068c00000000000000000000000000000001ecac88156d61863938f02c41216b8db360000000000000000000000000000000000252f6b8dc18cb5f6b545dc0c60eb1200000000000000000000000000000096650cbf350fd79e4e21a3a53f084e5359000000000000000000000000000000000025e86237c45eeb6939f852e4019e10000000000000000000000000000000870ec61adc23bc1294a793de7d329135e300000000000000000000000000000000000d59e4f667228b55d76d57b80cbb4a000000000000000000000000000000dfa123d263c27f5e0a447510bbbf014a24000000000000000000000000000000000014c0e9197abcac09fcca8aa3f56231000000000000000000000000000000693200aaa7a1cf111060bfd9649742812e00000000000000000000000000000000000a64ac6619042e406467e1ef5c7d80000000000000000000000000000000943eb949eb308771c1e869edbf1841ff9600000000000000000000000000000000001500279270c3f90d607b10a71ddd52000000000000000000000000000000abd4c7d987d9fda5eba112d0af91347d290000000000000000000000000000000000287af2e9da0883ea9b240a315b9ef60000000000000000000000000000002de60d201937100a2eb81f8cf35567c96e0000000000000000000000000000000000176dda3e54555b05161896f6ece72700000000000000000000000000000042f29116c4bda52cefccab14522ac6036300000000000000000000000000000000002ae355e6dec29fab03b5ad15bddee20000000000000000000000000000007aea39ceaf25e6701dd110975058d4860a00000000000000000000000000000000001748775b76f6e7eef4030ca57412c00000000000000000000000000000004be73afdbee9f7c834b3aba893345a96dc00000000000000000000000000000000000e9d72e07666bd21f05a55343eaa4a030a7e92cb52c0fcdbc1e5b66db397763920c5c4354d4aec7ed14fb3c69ac3fa2d59cfe015dedf2cdc8e600013cdc0e6ef132284446c25a4c510a5e029653c072b41a16d2ed27f730ab204592e3a660f1f7dd9252855c1c4b271b9416bc4f20606b4d830d14765142ff08104c499bb24b5433cfcf25b3e3767ffafe13bdc62ed16d7a3775d3eaf1af8bc2d37a3316c488a8bbd181bcd33ca48ff0ed0158d1d6429e6528ff77358d50e1fae17bcf4fd1c3884eb4a74154398b666cf79a3b8486f27d3c21d06fc0d8b884a6e026f3c6cc010bb189ed50e543100766f67e363ed8f242a6b1bd551132d0f2a4cba597b9122e936d2af7990135e1349d66dc4f019d82d3124ae130c2fd190f750380fc127a9af0bc9aef9500e3139f536f4cf7fed762c948b4695e4b46af2aa64aa399febffa2c93befdb21e20ed3b00ba64370c3ac2722225004fdbaeb3719ba760fcec0b6d1233068f085314a809f42bb600ba06f2724a4f5fc44a362c707ae9620b83a6ee75bebd33dd277460e207aa845856e9801a4cbb20e0c748e1dd813a0fe3a9b663afe049bc95f92f0c5185a7d639da62719d3a08c7b6fbe96149bc60f81207e716590672a627dbc8e0fe4cb1cff7e63f92badc4e087622bda8db6f3d909c83238a6192f351c28a45d14b1991c2bd6c7db11856d4920ae25700ac65d48b4945beda5f3e37e0c67da7f2f565ccbba9b888516a4e9eda070f6a1da4adef274972cc8a9e4c15c648e959b98a7fa5cc357456f12deb2382f48c2bded2032382e20a70dbb628804e27f339001c93c7d5b98a6452450aa98ba8dd10a6678ea0242e65098c227bc1dc928563282c82c53faf537292ec403cf29a1319a021d06db6552065c5c4a7d68aae7257c62edd568ceb6934c2f34d040a39af552c560b5321c997bbd7ce4cfb6d7acadd9c22b14426af478ef26fb564ffffb9629240232aef5e42fa3db2d7832f5e6786aa79743d57e958b6d15b6218822172e8389a3f32dd58c7507485c89e47f647b865ee0adf8bb188bd824230a945a832165dfc93887de320b5d4ac54352b8b1ee1b761acd1fcb42b4e42a82daf4909f16b239d651a8de66331dd97efa6a21c89e49810ee2c3d26e483614db28fb02ea5d0a69e901b5a6a1a0ef1aad9306ebd1b832d28d81f54840ce481fc6bdda822c08068c9dc85ee6374de4fbd9799b4fd0a065e3801435d181d6ff2e1a516fd74d4d1b4ce61811114ce728b0085caa000652b4248c1b1b52ee397b17c0314b6a0b901cc12bcc75640fc3648f8a09b4003deb42ab618e3869b69d2a195fc243b2bbb004c78dd9ec4989bbf342e28cd900901938668664afc08b4a0126035159df2d6129688cc300df36c2c6a143b431b8b415993a6002aa45ad3c861e81a078dcd59cb7841e851a35218da2becd86b9d0040c9e84fde6aa8983dff90ea1df312fcc07e0e78a08d8685173ceb6dfc339292137026de21b9d45fc161c17c9b490d4f4f12790e28cf43b75a70c3e7338548a551273f37ada27ef9a1002116328debd7b8f0e88c0460efa16a5c2bffd1d1ce06b60a34e659b4d79f9f5d605ce6cd28ab72472748b1e8b67b70fcaf9c604697bddeece0aef1903a9b4addb1a64f2bbe4e2ff8d4a5f1db8d1f3365f63dd8df7f5c363e16238bb30f0fc46f11c8f5c39a96b7c1eb3249d330c7a306b03f6589c2726fb5d191c2ad285fcac00046a61db58ce5403c7ca5c35c4c563c2ad1e2d3cacdbd230ab5e883dade80dec18d51a4d605835b2d9272fb80af2de9c118b18e04d1797516d389fc3466ca0d91a9521139825aab4af6f53477d1403d013de6f768cc167495017a4774a5af12e268487a5a53bed1999dd7495a3411433d63634c8ad6ac9c6428008b55fb674e210ffcd055fec443a3809b4174d03145472e45436ee6b5bcb50921089e4007c221bc2f15b6864dbf87bb90e51eec3ef8c2027f8c5a092d1c41356c127f2f7debf1b3bf1345aab5c6c34da371b8af768a26410264e394e1428e0e0ea89687c33722598ae03328533f4de38f79c5e148f093c31dd597d269513c76ba68e1ef3b5ec08a15150a5fc50feb6305092b086215b18377c9770369bac72239cbae72cd6c3013771029abe458eb35b12a768d990b97ca89b7bb6a029a220f3b5e34e510cc31576e011b2686118e1d36d173766bd6b082a9ccd80f7aba59e3e4f9dab782dad049146a25646471002b57358c722b31a53b4ed59c033eb45124eedd6bb8879c20130eb718c07145fb9347ee363ec3dee946c3550ae738c1922d4a935b459097310ac7bd937f463c5f261fd65e681b0db557f303e7161fe77e7b83d427575119000475b48eb910b185fcfe1377461952dd3bb8012d3b0d67cfaa2299f9c9458792c41e141acc7c1b2a21bfc841d3e4d01f9182f71573a0a9a27de7ed91ed0d2442bfb71915b1563be538598d914d4f31496e954aa198d39edd1c369deb86c22dc19923c24ce6d55a387ff88a573b65e39aa4b55621a3fe535a764c850b09bafc01cb1ada2cd69a2d5a6fc511482746bf9de45af87ef726d6f88d2819a9a4dfa100fd1772394594e4709a6dcea556f8cd33cf2c5da33a59729b3b39e90c504da55100d29d4a6162a351f8391fef5b3c793be2da3c57583513f84136b7bdfecbb4201049d428ddd71ddb9b7adb5bc33ee937a12fc09c9159319f96e671e65fc1c1e0eb12a061cb8749aa019752521edc1894049f0b2f7d885559bd518bf4a3f0e562edf5b01980b1c53d913695f3b15e77ea043e43487b8c70c3469d9ea891ac942298a91098f0a5a9de683c1b3e82a203433c6a8f15361e91766876d9787d9734a24b012b46dd55aa12b5358c3b28b707ccbacffc4a76c47c6f5b7bcd6532cfe0e2e46deed7bc771e16c3639836ce9c9d973e60d25384cfd727380c40d88a86c122e9249471681f56974515ae6d44f129d6dd325f817fd848cbbffa80d3b8546d225ac98e3373b80b2eb4e0775dd9b576e1e627ef7aa77c15a5e813cb90b7fc2062cd6a7fc287ebbfe316f911ffd4cbceae909ee8ec068d83235a69c3cd6f8c2fe1d34db9077b71367bd6dfc797f91fc44e4deb469016dd4bd04f405e809933bac12dd72d845ae0c2ab8ca0a5cd357401d99d70bd3f8283b7dcb2fec435b59933d03935ea714fe02f0e541db40a308f18945c7066075e0786b8907ee22a29ea7491756b296d3347d7ea5d62fdaf65884c321ddf9e98b2857a970156930689ae05717866e82b8fb1402987ea51baaa86f2af7d7612b5fbd2e2cc41a49541a0500c21682b641d4d6afd438ed950a2a068e96013b47316ce035c7bce9c9b37d3367db10fe6348c0ed6b4d5d61f95cea1d5c63a7b3ec41c8f19e8f3e4c0d1d215ae1351ee7a9497c7c2dd42d568f2448faef048b19b39352fb4934fd7b078323e198400ec8406e8937901d5edac991b252070e4919b3c5716a1229efbe0681d16168052226d55b0d835f512be4d36abe8e3f158b7ccae5d5ef343b7fd958b53e3a13591e5bd7c4c2e6fb21222b5bf52d341f79d3ed8899e2fdefd65163a6b43bbee5012a05cd792640b15189fd6aa599a0cdb8349b39b35f361e166a5e323013711d011d56415ec0a4ffd85741322709766767e75d47cc9683d0063d6f5484283833340b1f4c8386e8053f150f3953ae8c05c00deb270e1feeee68b82976c31d72e2c0087ff388e8840fa2b6ac03b93bc5b8c82bade4abebc74b5fb3f03ebfd65bad21101cd9c9c6f677ca994c6795ad69d1cc98a86920f2e0767c6963ada0ca651e2d2c455d233930940935e6c0670d8186f8046a8df7ca53fecaa8508e3abc1a41ed1269839bae75863894238219b09f612f84b5773f644b2ee1a1a14661c9075ef52aa82e5d0babbef91c3e05aec3ca51fe2f741c86ba1c5b08a331fa79d4e13c240811954e8ec510f62d0532a533deb0c1c99dc97d4aa784abd2ee6ca364c39f8e2863fa053e7f9fb577e9a6d01b9ec7d5537615d71d9aff1b848da01516bd96a604b50f397c34834e06250ab04c7e10aa692eac8be6b36c712150af4e9ac414d32c985886c544aba1d713fa51cff707e09ba97c7d90c4506c0888ac0aefb4dd1e02759db149b40826b5de2c61297ed99581114136953a0ecbcce1e90e96d859c817ce75e5b7b86822cf6ebaba04dbfbc913c0972943aeb0b42e19de8a132ff62d110bb67c2df9b2287dbd6b4603df6869b6d3536bb5501184fdd76fc30adde8ea17dc026b8fb91b6691fdba900f0bac657a21f6885bc3321453094447a0d456d72540c6bab1c24355327e6f319e2d2bae3dc336bac5563c3f2ce4cc9ac889419b269200b9952d9f0083c0a1038c71a63f309a9eeb8690eeadc5c34b452ff1b1262c2ee193825b1ceae70d9505897ab96e1e7156560ee7ac8a66f038cf26fceddb1e2cf34e8077c6f976f532dcd384731001e2651f8ff32af7cc7e4a2b279c567f016d0ab776952cbe052bd1895c9bbb1d9b93a0f6a36de95b3968259acda0a3d51b5c9d352d7275181a80c1c8fe1479b46b48b50e19e64b61a66d975d399931d52ebd39222b2787e21e15957038211856d37b62e11812c0ef9e75822c2781c340235f6c206bc1f4f25ece1fb3877f15736a07d09e4f5d4aa0c907a1c615ba38362de8a3f081b9bcb451b87dbafd8185de5ba37e07778613f9546756b67d8552d612289d83b4fe1d0541a8071f13318b0cc0c7350d3c6706e3c09d9e6403fbecd82ada85cc595965bd8c02f6a3d328d4f9785eb83fd98d5207c128c3f215e938ae17a16b12c80bfcd185f3a9cc7e3a2732fa255e58143600f2f16d91e98e7eb4f706d9e22bf7c049156fafa3803fafa5086b264022d0d54b2c670755aa77ba95cc0a72edd2ce16bd3f69bd220ea0cd28e8fd227876538b57355d058ca3e8f590362fce1157836b2dbdd5a7306eba9cdcdacdf412021c9b996a4eccbf93992c532701cd672d78acce91c98cb99a23fb7c5cf40dde269f0f2270301fe4ab67da56ca0ff7a75a5c5380a28410ef82bc337ee2d57eb077a94f56e6aa4a6238ed0924470dd09741a7c8523fda77861d7af0948d975155b612d7e7d8ae2605f748df6b4f23366ea7ee86d370604aeaf8119db82c26c08d7a793344ebd3688a0ff917dabc0c3168b53f5be5a273a923f36019ada90147252002123eb3feb05155b95aceda12a841448b50e8ac9bee11ea1adbda0f042bec8cb941cadda12b01b06d4a713f073e2bd076c547d68ec3b19eb4a2fd65dcd660111de6529847a369876ffea86a24a1dd0db68254a6a7c7db6497e18c415078e29843846556e2eb672954e0bf72248889d551119d89a7c7e36a0d12efa851c506db54c7e788b52c9ebab2fb0cae2db43c10f5cbd33294ad252ecfbc20ddf5e18c2d6b5e661a3f00e8700bf22f4d0837ca356d58a7d41da23e4373e54179d97e595f8a544cd33ad1e1ce8d293429169964da6111712c45e7e5bddd9dd9b276f07d381267817f476ce9087c7b436607e208d1ae86ada32fd79602f1b26eb5fc810c58e8f3fa2237103e8c021eb0e21d7c6bb688a418a2259097eff23a365fa30f605057bcc2f604c4564f02114d0c2a6501bc5d47c980c8c8555fad40eb19878ac43955b32f66a6df8d42f85b18c90584b3ce3de7ae61c37b72db485b0d8ca07daa48c73a66f3312c5512b2ad6bcd04956451e4ec5938744282fdd9142e4d3de2a0ab2903bd0dd2277922466766b01d5539b2b5ffaaeefd830ce8e075b9097bc5954cb4c7f486d355b294d885157219c60aab412c8105113bc498e9d68c490d2453ca7994ceb23e2e76ae8631b9be0fc18d4da4add967e2fb52fa71157bf60569cf435e2830542af4ea9ac2c255a40cdf5ddd450e75c3c6cbf3533bc06395e272ed2e18c1a6a132dc411f496d8bed13232cc939a9d46a217f4b98e9d6f2c61f656e6679891c6acddfd7bb9f76b5422f7aac6066f61fe3e8b4815872c7e0fbb4122e05d0c8428fd475b7a6d6e2d1a60e6d49dfe364253e7a74615155ed5c51ab53ec4bab46043c53bc5b4a334815050006ea15b793ce863e21b6fc74f39ae4d73a3c1ba04b4371fba56680107ec599283e765accaec717186927afee813c0c61345620e41582a4b6e1763d239348c00aed40e84f6afbaa2f132a345af772acce7d8a3429fc72f12390691322afd6b21378102f808029399b18eee20eefb74308e22aa54272662f5e53ad6bce704aac277fa2d04933c524165ef30372adb95e6fb3c09c4623df2fa50a8826515a1fd7171723c7d36eb5a62ffb0a1e42eac359818f2f0613fd672de920b3514c251dc714682cd869e429808c60dc07939bfebf6f0b4e17d468d4bd4ef7d5c50b3c80fd0c2250c1ed3f10f37c4a7aae14efdc99528b787a14f90a8d3c97d2957c9db2471fbeaf4d5e970caee4fda90ef87aa3aa1b3fb3cf7cd2a8eb87588d13f7005236231fa0ccd4f023116f269e95dc0157e43d50fda9282243c2d3e0b9ba52dea1210116777d42045cb667086434b700584ed21175a0a713c220a9fb25769fd9a768038d24f1cba3abfe51a788769f09a8fc2d6273171d09a065187ed15ec5c941061f50bc49f3fa3a6dac9488e0a17b95984d31f230105f31d5c41cf319661ee2d50ef16f48a13c7fcde2b96c4c1b5fa6b08a80aeff3c8dd5fcd889d7684f72b0a11a89a8171d0f180ddee0e44b836d0e6950d3cd601eb9c418d48a246b4977762e2d75ebe775d3abef64e043d86cc9cb0531670ade2e0d1d915741de824706fcdc179bcf7582a09b675d67768db9aa27499d7d4cf07500923f7f0e681e3a852f5c11c56fd7d11c34d02212e8447b46f2c628e744caa9a1079eedf1c10c880be41c085512abda963eb5bbbc09d311b3a8a4377fd6e8c9f9b20e72168c031973135914b7fac24dc0e57b32e86b931e8d793d65ac984733dccb31225f5c7cb7676ac929f6eaa2e9741ed87c198556b124aabe2e8946ddaef7365e2c48d3ce79bc06371a09f587d1b99a488262031011186674cd9173eaae9217b3a44bf54ae3ed4a5d0fb4c9e7f866d7c93b3eab57fce71ecced8cc0009318cccf04b2a7abd1271857036e6b65a8881c2b5d61088cac87b72cbdb3ac7873271ca8f60a19d975b567bc2907124f5e0e4e8461223b870f06297a10f24311bf56f47c2f4deb4cd6db0a230a338b8383431309470ba3a3843785e4ef43a1c746d8651e99665da831d0004e21a1271314880dd1d29bb95f3f14c0f8b86aed6be2c80218508e2b77526db213080936a1f869d17a38b30ab453bcebe9fa18b2ea2262f49667edb780359605301a7498f7c542f884f8418df02fad03b8e06dec65355ed7d4c85cfa075bde264c0ecd7f93cff65c4e004085b228c14ff7a13f34a578d11d19cd58c3a105e86d4f209f7c56ab7204938156fc5b095917e7caded57715d3904cfef2be2ca8b4df212ea3db8726ba2e16d2e0e137dd0bc37539980be8b70ee95233302262c75f51b61f4a2bd88135279b18040b03044b93969f9a4b34582dd307821a0053674367e70b2c4a54e6388f9fd98526b773af9b31ef3e0b78d5af4a06296367fc3570247c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000237f2fd32765627dbcf6b00421894d9cd731548970aa8b15819fe62e85f1419a1a09f8dc69dc3bfe59a55c9095dd23d95f8aeb4a107f2ee1b2c16fbb4b20b9d313e9c7268c955e406bb09770414b87305ff00fb25c0b6ec827bafa780bc3b35c1370122a399a92211f41fec156c4590f817594f4752705640a508a9b7247bd660284df1f95cb01913f09f2db9a4e43987cedb15e180d91a487225828c268147525685b075335fed820a131ce5e9f3d5c437611891adc050cd7b9e187c2d8bf7e08976aa27380eaf8d41469af0e8d53da08f2cae637af290f0244a5fe92b85846222424b978fe0c9b6b728b54dff94e435ba2bda4919247d69d8c1f10af7537550aa1661e310ef589f7ca4f8d6cf299571aaf79605c753dfafe9da797dde22144090461edeabe61992c7cd8dc57e8a0f77a1c5fb3c14d23eae7f9bfc8267ff54226edd2c0001ee33b6621e441098dd4e572843a40500365c1fd9cd70c08288431036ea04071dfa48832b6bbdd3901d31ff7b5fc59c0a2892d301c2fe858c13e6a10974a0ad4c8bac6c7b505431016e5097f510e4d0212d3a22fab8e9d9cc76cde2dc7e7dbf42112c1387324b3ba611377051d23cd3f57bd55802c6896c8eb4461152eeac6f1630716d98a1ab87733a78e0a08048d0e2f0e4c087dced7f88b7cd22ed6c29ab52c06a825735d9ac733fc7345641b274c0a534a5e7d948f07afb17d158ccfc87344c2f5ef7201a8c99e20cfb2a82d6979649c57831866e1e77ab5e51db2ab55cb7ef10d7d57c4f1e730d1c3a8d3ef6e01b0dfc003b244c010b0a9740cf6f4e591e8bff4718a9a179200a4a6419eb0a3aa8f973829c34880879860a11d52e23031dad5ee05c173a00fe4cfe3254d9d7099706a4b69ac109817255b4406a3c48a334042c4446dc263bf5aa8b5eb7b80484ec5de3c95acc7b74ff0f2e20b5f3325ecf32f4019abeb0c8bf590065323951a5f8652786ac68bb960cb584702c6f37ee34622b5323576acce05eb63fe8e239f5660b1cbb880ca3f9ad8cf5f16ab08f5b502f9862ab2287632d219358f1a0cf333e6f842d0b8b5d47842c7b306042180f0166693e25651998e5612ee37761f5da0088e13837d060fa2cbcb1f2e9d30ddf1d9e01eb787ecf8aa565561928a33bdea5c92df61fab70a78a06a1b1edff7e1135a50c6dac0fd82585fd636a2452514a209365889f569faeb49882200f90584d66a4d1202045027bef9cd575bf692f4c925430a6fad49816936b29201d6ac7e814388642cf2bfe155a61703fe247056a46f19d5d904eb279cc4465102a62d744918c35b61f7e6755aba173ffe5d0561c561519b9e0b18231a6041fb12486e4d72e90695ab094d743a9a3b54d820231bd1970ee77f0116c2c84b05481cadcca23f0d2021c6e562c71d3d123e9da655cffdeaddd0890420da7621001b1242b48f2f4c931964e26957b6d3f556c30d11a3fbdf560ee418cabb487211eb24ca3eddf67c8d1be2441f5e3c6ef1c13597d909d6adfeb04db99fe90381af760fdccbf6dcd6476312cb6f1a28c8f83d7de852f5fcb70531160cb6743839e00c16eb1f4a2555c77b1ce69ac9bbf3455c7d33ce579d03868ea1618665ecb66eb30b27f01d3b8a68ea76d85ec5f4337bcb9730327918d3d85dc10c80b4c694e769008eefdbbead0f41a57b81c6fceee8ee269201af632be10441c0ba538f7daa7f2f870060719f256cd9638de56f4b9dc7e74dc0e673d5e19d7e4be3317b2c7f2d1e6ee6563882348656e52d572ca4b0606d34b01bdca5702f9152c2e0a4bde43211399c95d35176ee8a1b0289cd5a130217b037c310ad96f5cb9dc480cfe40f351500b70645a23ec61acdaa475c647f988f3f8744ac936809bb06e39ddeef67c72e28bc3bb2afe1e88c9495f7723ab75525dc1997bbfc4b9a7a06703043f2eb1609753dc35fb18ddeae42cde9646cef12495441ec20b29e480c64486bef6451ee00000000000000000000000000000021832da38a76f2cf570a85021b10d9b73200000000000000000000000000000000002bc1a1edeedb96ec58c2f796b244fc0000000000000000000000000000009d7f0285fb7f125457d05a7bf09ce62a0d00000000000000000000000000000000000034fd1e534c5d5fc47cadb62f7f70000000000000000000000000000000718a738370c68121898444c2f31fedc59a000000000000000000000000000000000007efa8939e0e7d2e0c3cf2e947a7bf00000000000000000000000000000081ca5e851ed9daf9f7f3e6f910d2ba3422000000000000000000000000000000000014740e632ad58f25b03cfd5d2f4af80000000000000000000000000000005a4af29b7861763ae072226dfad708158100000000000000000000000000000000000354c32b56722b40a1da12a948461600000000000000000000000000000034ae9b69e09f6fa305372d8d59897905df0000000000000000000000000000000000200b5bdac916509ef32fb70b19c6b700000000000000000000000000000040eafd7ba8e659703f8789a16655118394000000000000000000000000000000000015081872eb808acd83faa2195fae5c0000000000000000000000000000009863fd8cd6b56862c33bd03e422edb052900000000000000000000000000000000001ad2508b60a69c9dfc169484612aa60000000000000000000000000000002172add10f95b245472e56c1b5b771f6760000000000000000000000000000000000289438e0af460c55da1fb46bf04bb30000000000000000000000000000000e39d6ac65048a28d4c3e2f1a29957cdc90000000000000000000000000000000000184eb6259750b76db37dd6355550b000000000000000000000000000000037866489a22ebf296b6961a9cd34096b5b00000000000000000000000000000000002aeecefa9adf3761ed80cb30dbe07e00000000000000000000000000000087108f92ff7cac44040bb334249438727300000000000000000000000000000000000896ff02172853ed6903c5749d5ba0000000000000000000000000000000cd31ec7c968bb5fe7b5a4bad0f0eee550e00000000000000000000000000000000002dbda89b46e67c0e62ec2713869f32000000000000000000000000000000b3691c7d6165ef8ee7a03f8d5c2b23cd6500000000000000000000000000000000001f15e7996abcaf8c4df98ec8f7a98800000000000000000000000000000007da78e3c63a4ce2e06d7010071ec43ced00000000000000000000000000000000002e570068ca407364693025bd459f71000000000000000000000000000000139fdee42e16c73c68b47bf2c3a1d485f80000000000000000000000000000000000016684c552b8434f7d72effa112de10000000000000000000000000000009e93e240a5fda7767f876ca79bf705e8090000000000000000000000000000000000154c63195c44c538318cb912e4e9910000000000000000000000000000007d266afec0c3b1f516c70e1db41be2994d000000000000000000000000000000000008d773f6aa4d40e92b19627ab08d21000000000000000000000000000000a23106d0b9c127c2207bbd4ca55ac4c920000000000000000000000000000000000012d6f6e2ecfd810edc98e49d8a4456000000000000000000000000000000304934c2405c0fe101a5a4d2ce2593c28c000000000000000000000000000000000023220e4cc9443e0807c0c3b84747a8000000000000000000000000000000df5531781404739805e0a3521a1c36b15600000000000000000000000000000000001cdfe0a6a22614fd450da3c1fde51f000000000000000000000000000000b6545383732c969c0354ea7c6b2572c8cd00000000000000000000000000000000002d6166371a5a3ca6699c9a82454327000000000000000000000000000000a6b378e0affcaff899f951f7572016ca8c00000000000000000000000000000000002a2fe2a4b68944515d2ea065e863ca00000000000000000000000000000093605b491f1f433e8ba151074b8f7221ac00000000000000000000000000000000002f520182f125987ae0e990d1e2e55a00000000000000000000000000000038a682e98018da9f5872f89caf85a7842a000000000000000000000000000000000024aa2c8b84e50042933bc37a902fce00000000000000000000000000000076209f64e6436ecd39ca466f90bab9b0f4000000000000000000000000000000000007d634b9ead7c8e635fdd4a3ce264c000000000000000000000000000000ac6ddca15d8d72fd3c7c04dd677e4682d300000000000000000000000000000000000bff121dde91bd0842a7035af4333b0000000000000000000000000000001da55c8f6953530eea5f8b44c1d0d30fdb000000000000000000000000000000000022813be77edfd6fcd496e0762cfc6a000000000000000000000000000000cbc78b35a6385972a7d1893b2d6c89c3a900000000000000000000000000000000002e6aae447640071a78df475ef2937d000000000000000000000000000000ff020f82b567b7ad490338e9c5bc7ae7b40000000000000000000000000000000000294215b29e9953b9a29b6e7843fdbc000000000000000000000000000000dfab109744c0ebc6cbe431ab259e8b6ecb000000000000000000000000000000000029bc5b0e12d2a15245f45651206d36000000000000000000000000000000419a93b230a13698f1104ecbfe90b34aad00000000000000000000000000000000000e5426a396f8064d929fa383128a92000000000000000000000000000000ff2fc34f7823e392fd8eceda7336afdc5300000000000000000000000000000000001613ad953672393754e40a3ffd8d0300000000000000000000000000000017e2eb2c42b4997cfd046d27e127af79f300000000000000000000000000000000001eacdaf645dc631308c187a36dc24f000000000000000000000000000000eea9e38990eb71048d9742b7eb81ce5bd700000000000000000000000000000000002b622c508810fd1a751c49ab9524b9000000000000000000000000000000340323a65eb3c803bdf4d5fd70d10c5b340000000000000000000000000000000000029f8e5f38168ed7e401bff18421ac000000000000000000000000000000634b01df56c54b7e94fa30354df1a9c22c0000000000000000000000000000000000186cbbdcea11d10d22ecefd1eab80f000000000000000000000000000000227b9dcca51271edd73f05778d5d9cb8e100000000000000000000000000000000002f3546b6e65b130cbfa72fdc37824300000000000000000000000000000080c5281d0645614f9f39d8550c6001150200000000000000000000000000000000001c61ff8a26c657d6dd47a8ed2000d4000000000000000000000000000000dabdbc5c6b1311faeba2af94c2dab34ed0000000000000000000000000000000000003eee2291bbb77f7161dac074ab6c600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001217d5f9c62467c591956d4144b2d43a6cef051c29d4f4f5d46a6172c969b58d011468bdd6772fa6c0c44301411023d0c9c1d8a78312ebe267f666040f2687a92a1bc24f0488967f2d9a4a91f986641bcea7bc7dff4f21055c034262daeeaff3165125dd34228974a10a94207311d2d9907b5248fb2cd2aec3c511cef82a0db309eb9d9b32369d573b9d3f56dc6d29d55464fc62fc59f01c6526fe667827f2910064efc84a63839ba24296afce1ec0040a4648e52bc44ec8a01de9359a18e64729cca82acd4c4babff771ec5ea289c3743bf100c62309cdd54030f682ad37b102044e74074daa6a66a17d10eb36230dcb5e1acfdcd434cbe5e2e7c30d00160ae0d244931bd1808f837b89bdf0703e8ab09042350b73852a617ad033b6ac1b8cb10222fabcee4203d3a7fa21732f8dcb201e2f4176ac348dcb8e5fcbb442c8cfe2cef85f1c5bc63a50375505bdf06470bfea035edf59934489bff2d283a643f0c1e5facdbf0c7dd02c8991f33631aa12630bdc8862defedd441c9bc2a8960395f22860bcacedc5f989a6d814003a45b7b7f4d1cb35597c3f0426f348d8211588429b47624e027a3c169a72579bc0331485459f41520db6a3dcfb53a2e044f31761d76e84a99dd931f5a5970f6c3f15e127af855e89ce46453e936b74288a414432f01b6b538c510cc85641ede3ab2583d95ff25c59a856b9a92840e1a4f68e1400a8d8378c420b7aa8fb87bf3287fe73dfc405b2ed531aa35b3044bb1bf653b6909be0901c6ebf3c377bdbf3bf397e60069fb0278687998e667866b7ed43cef5b0b2e3d9bec91e167a63d13abd4091d24cc92d6102b33bc832e3c200b3f8f8e0715bff4ba5b6021fc4cd93cba6650acaabfe73457b3988036311879620a65c4c326096c677f92607e5f0cb1bf0948b065af3a032c5ac8f3690773c32fe29f552f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0609bbcee71e708093ece326ba89b8e6400000000000000000000000000000000000e2e4134b9d3e322d13f42bcf0f33e000000000000000000000000000000d05b774fe48d74f4207abf4fae1e2bbc3600000000000000000000000000000000000008eb62e7d152a6d9ab001e7c40b600000000000000000000000000000084d6718112c54eb0d13ee24a3c24332109000000000000000000000000000000000017f84b0afb48259e15b5eb4d7907cc0000000000000000000000000000004edfbdf184c6e4f277fd3b19eb0bb2199b00000000000000000000000000000000001493897df01651f2c7937511130c36000003dc","publicInputs":"0x0237797d6a2c04d20d4fa06b74482bd970ccd51a43d9b05b57e9b91fa1ae1cae000000012925752f6e51bf2738d82bf0e4cb0805eb37e908a909db140c8ce9073d03bad9000000032da55666630fdf8594065c377958c827dc1c130dac91f17c6699b53dce60ef752c2cd74ae9c2b2a1ab717d69eb4753f65607db94e93a8c0a51f23b96e34f3038000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000241a65339d99ce6f973739bda9c459c80e677af4783b35941098d8cea5b54022dcbefa1ba7a12eb4f2ca5632698034aaab9a60c0428603cb64a7685760f203200000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} \ No newline at end of file +{"proof":"0x0000b2e400000597000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000000010237797d6a2c04d20d4fa06b74482bd970ccd51a43d9b05b57e9b91fa1ae1cae00000000000000000000000000000000000000000000000000000000000000010d479a9973afca679d8246d894b92f79675c4ebe01db6d6f1b20e98368a4129500000000000000000000000000000000000000000000000000000000000000032da55666630fdf8594065c377958c827dc1c130dac91f17c6699b53dce60ef7506d1612daf507b160ff518e5f0df28014966c7a498e474e1e88ab9813389fe0e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000183a8619af9f5968db6aef510e527aae5927e5df6092d9498f183f4bc2afc5b115c4ba754a1c246494577702f41a1f2f87b62dd22356c3e52e041870e8b1ebfc00000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103d54df615ab5d910000000000000000000000000000000000000000000000010c09879420f63ed50000000000000000000000000000000000000000000000067b948ec6de78969a00000000000000000000000000000000000000000000000000002fb9983cc784000000000000000000000000000000000000000000000004d25138948fa1019900000000000000000000000000000000000000000000000cc0c2e95f2338bd20000000000000000000000000000000000000000000000001bd2764d36be817ac0000000000000000000000000000000000000000000000000002896033c7c1ea00000000000000000000000000000000000000000000000e1327bcb74ac3c5380000000000000000000000000000000000000000000000091fbbaa38ae5f649f00000000000000000000000000000000000000000000000df26374cda4a95f5f00000000000000000000000000000000000000000000000000017b91fe4fa5cd00000000000000000000000000000000000000000000000298d35be6962d2c0300000000000000000000000000000000000000000000000f04c15652d7c8d78700000000000000000000000000000000000000000000000d7139f74133c70f060000000000000000000000000000000000000000000000000001f80f2550fd16000000000000000000000000000000f3a0d88e7ec5bdbd558467d44c604fa1c70000000000000000000000000000000000027234bba8ff5b1fbc7a7259ecae1e0000000000000000000000000000006f121e44201caef92676331ccbe126fd3a00000000000000000000000000000000001ff94ff7f6a76697a3fe6c88f8df23000000000000000000000000000000cc0a86849036d3bfdf173a1977895e6868000000000000000000000000000000000024b4df4038efbbfa3561acb4b0f7cf0000000000000000000000000000008653353a8bf37fcfa8ef191f95ebe1be1200000000000000000000000000000000000369029059e2ec172985d5a4344cf3000000000000000000000000000000e76f96061889807a8885b9d3fcce7917a100000000000000000000000000000000001b50ec5afeffc2323eaa9e58e23fe80000000000000000000000000000005aaee50c39a4e5ac4e59384c9b0e061ba50000000000000000000000000000000000133f81c5f7fb90777f564135f1beee000000000000000000000000000000d3af96f7ffa8abbae7efea472c417513f800000000000000000000000000000000001a64a2596a31f148377ad9b94a644100000000000000000000000000000081ab6d2572f482b5efc4f9754903dfb14f0000000000000000000000000000000000153e2f313789115c69c2aeadcfa3c300000000000000000000000000000097657e195a4e3494202383635b31df178e00000000000000000000000000000000001b753e0748a93a4d9dee8c5dc8152a000000000000000000000000000000f379dca46ae12dc4496557888113a926cc000000000000000000000000000000000019e91e77e1d76d2936dd5def9ca9f50000000000000000000000000000009087a51f512664a95a453c948e7b8f875900000000000000000000000000000000002e84370013eccb907961c07fe8071e000000000000000000000000000000df1bc58c1ad4630ab2a840e3a1780fa45200000000000000000000000000000000001e81a7b42a827bc15c994701e38e020000000000000000000000000000001bf9cbfc47f90da995d226e46c81ad669700000000000000000000000000000000000bc5e01203ec6d731651f3eb0c589c000000000000000000000000000000b2ff23c9d981a6c25c68ac2e5f0cc6bd900000000000000000000000000000000000016c16d05be5e24bcb536bc3aa4bc1000000000000000000000000000000e6c44f35b0f63707ec12ec52527ae824c200000000000000000000000000000000001ed76bdf2366bb5a33019a08015848000000000000000000000000000000a4f9c8448ad94ef0937bf334d9024c3c700000000000000000000000000000000000051b0c9f6302338a8d63e201c529600299c879db9ec2ba9cb1928d3eb03d92357367559812d5c4f7e396716bdf59f22dca85f90592dd6f1b9eb32942d11acaf2c080f2e1a69acc4bfe5f228420a60f2745f44c1814c1f1454b275b6f1493d0e109dd4bdd7dd386a7f9b59838f940a61d74997beee67b90f66e6a31381f906bff582b7feb4d6cdd65ccdbbc8d40f3860aeda2fd86c39d1f48e6e889f8ffbb7cd795c41cc464cccba9c0d959eab24bf42a1c0807c3a8b910e5a48b926228224ed66ff2bbe970d6489517f71f8a0f7dd623b45bbae596c958958b35ae60548a5fba085836d69701129f6935f4d6781ce61ab55ac57392e2d98f2d9073a9be81b0c7cf2ec19020aab1706944f6b4d80a2e1d65e474b556cfbac652280976d920c22901559d9a790711cdda7cc31b2c01c3252e809b26d3b53728ce6d05ce2c198bb676362ff266244cfc1e13d4f8abb227051e4fab89494f2826a0bbf4b653194f3f29bd73f8306f89aa319476ff0178fd08306955bca7ccecca7c9b0c2341c22bb80c69910797f54b8392f000587f55f818ac5405744a3731264379df2bc6e085de863c5afdc225373badf91b676e7faf19ca8bf73629f445091b09bbd2e1b3a37ce35876b72c52dc7c54e1708804acca1f9ccf3cf5a9f65742474c3c02d87f177335fd0b814ce4001c4a9dae9d652c08215de4bbfb2c5e26f1f237a72aa4388b3abe4bfe1c4c1a0a97b218cb8d176bb220d40a1981b0d7683d2d2ad63c1a25062db5d0ec78cb26b858788a202496e05e0cf7e41ebc37e520be3ae7afd48eeaf75c9e27f1374b4fee8d8f1718521354ab1c57e481b8cd5105c3c96ddb2021e4f356726ad9da1804271a262f14eeb5e28e0db9353c3ddb4b8e7990c7a99fff8b67c97b9c1b6fe9ce5a42ed04f866aba27c01a7bc21e8846ec1f70caa8ddff6f3a794c0a08cd449b3796fd30ec3a8861db015e6b9c4e79ed2da189f9df2a66e716ce6a8127311e43836eea2802efea6eefa1ab083b9eeef8720a6c5f3477c710261418513666e8d8508c9c6608b6b1600b804ca146d540353a5b9541c75761321ac62e3208d6e18e76d7fe512feb0ca34fb2d1446e8fdf919173cfc1fc7ca76e4592bb9db5e25a899ab45c71625a68152d10887febad3615ebb4c17a14c595ee2e180fc01474aa2f3b36c959951776c64672050a13b5eaefe8373a57751523f18a15192bdafab61b98f318bc19aa9fcbfd3097e843f2bf44fb5f1c51348590f022b26f109b22962eba48e85cac3f6aa091f0b12f9d193924765059e2ab3edda9d56aefabd245b73b4fa1cabd9fdfcc921421ee04202d1bc52273bc2d890acad650101b5cbd56d56cce5d19f57494d2a274501fe3e9e123de9560b4c6414847f6ee50acb969e5424875bae8c25fee31369d7074e6cb608a69f65390fbc9b51256777f1c53cea8008f1455204108f90c21bc20f6c5567d36ed014fe3891fabed1ef3d0b2c1b6b0f0d5b2df74889348268189522ddc933cd5d88ae258df1705f887f1b616899721ebbe1f048c75d133cdfc17411784c82ac62fa8d31064f317e0780fbfb5dd9850129acb60dfee095d7eb7e1f0f7a5b95c242593f264deaf26aaa4e6177adb5187ac869e95a60a5f03f8df00f00f04cfa660723d649204409ca6ef4e8809caafa4305d0c43110237edc4f30e90dd3cd0805a1139d2c8fb7c4fefc46dcff43e5f3aa9595b76fae6e155f1e816f1038c2493e22ce030f2c0a2fc3942429d2a34bccaf63a7197b160546dd579bf21bfd3cc2896e372a38b2d6c6e3886a53b6c2ad1de53a7afe90411f370f0d27c717551ad492d348276ebf621d59f1e86e8b100ef74e536fa6711ba2887d1dddae047dc117979906809a82e8992e0d309753174975693d2ba0ea6bbbd245fef33d2b61cf146223cf02310e9cfe9a383b709f6885d291aa67168d5b69e3aaac6ff205e9a395fcf21e31cf4e4deb878a40449e8b6d1a8d7b98517ef96e33b17ad2c402292880c98a44963fcba3d38e401a087182f3632ab971d4b38d032876857e4808d4581bcd2061e73b4fc9a0d8222612981d94c05cc50e0ce3fab3d586cfa4492c9c1a259046d197e63702bf280d953d607acb17a2f5eac438d008c57f312eff2c9b063ba79751a18d4ecb3d31d592e426219f28f8757662eb0afc8650c3fed41c2c7a64fdc08163b7e6fd63a21d6e86260a876cfb638356a37e07ec158264b40729189e109e2278a94340f1cf3c658e72fb636f14d9ed2dc5360fd9ac0af73d13b76b101f6e0e6af4bce452e5b1b432c6cf24894957a1225bc9046e5dcfef820a422e67741056e0f73cf54b74f8ebba229fc589dfdc72bbea5ff9655b7a693a15e4c10a9c062f550bf37715bbaaf2bcdd39644cc9b1ae9d504c558766ee270a076ece08cf9af15097445fd703f50d4db7e49920c4dd8db907aeb22b8e094a061eb9e6a7dc3fe24d953684d4ef5efd23877e2d7573bff2e17a4561c5fc865aa215d9905c46abaf5dd7ad8a5c7ff3346e64adaf75b2ee6a0d3877df9facf080761f98298b968ac81aed1fb0281f4325f98cc9f2f80fee39068b4191f82234ceab0c52ef9eeaf0ec9f130cdea2415df5a4db8e8ca6729f2962e82fb2762a391029153cf4d928364c69699557ac4d10868509f6e91d96c3193d595be31b3db812422972de89582881bb0b775cec2adb14a9d87be40aa13d445ae2768b34b110e1ea05dc9661028af33976bda4c5812db12d88b16a0f5a060302078af6c721e2c01e2efd4df3b9e681bb2d5457e1bc69151e17d783fd194ea1212367a4ae6dddaa1900b5e6a52f653e9fa60ffac084839514d0bb409e9482ac3f23fff55e1fde9bda035d4ed446a6abba751a270a28e776a81cf6e1bcbde92cf7e55a99bf01defa6d264be2422675914dc70228fabd19b3e71b083b773899051ddf7eaeaba00b1d3d0d04d63751b4784591bb5dbfc33554ef156f0abb6b03048b416a4f63166ac5a118bcef044b7cfd12270a467029f8a8457e3e0cb86523f2dba11fadc5f4b2d0b5004e2c8bd8ed741e4c46e01269287c1b44ac20f1d55854fe7e4f88c35ae3ac3410637a17200d51f70132bf22199f3c89344edadef31e0a45c4385cdb8fafd11000c040945970e3a00fd119c68adbc6e9b5317b9bd62a3aaaeacaaa1b9cbf51611f509c77d094c62878ba8c7e7f872ba5d51206aef7cc90eca1f4e33038a01f840af3f0d4707fc2221433646d1918f597401704bd443cc1bcb6c05a2b92c9623f0bcd52a6d63fe77ded2ff85d4a992322cdba11f8556b3dc970ffca988ed82f2a201ab4b3bfb9391c57b4ec2342990853fcdc7264a307723af3e0938d793a5c21133b0084fdf9966cddf81e18365cbf5eb0a28f4e6887f27c432535f370fa862c213046b4fcdc11a9f7568d643d398d019bfd0a7fd6584566e67a5638c28f379728e89dc45eaac68bfe44a344f43438bb6981ecbf4474d5eb6629b6ca7745d74b2898685067780347ea9ba1ba2449c07a985bcb20398eb3e99805e6fd256607270952922a2732a3ceb602c53fc91db24ec25fcdfc1f5ec05b8b2102ec9b36b8be2cf4108bb4e1912ba789c4d896359d0c3c55053014926576f8c7bf72df48c4351ad15875a71fc2f418352a69a81ed4467ea65aa72561e76939f7a70ac82fe3a810615a74716353179317244796d2e4bd82ff042dc68167eb74ae59fdac153fa82e7edcba4785e6e0594e24c48031413c3fc7fd74e8ebb501ee06e71ac2b4e0c61d78ba82758ed5a47e223994496af8a1a9761e2905714cd9020deb2d47a0a12a1aa42667a8aeeba9f58601c422802400cee240046f1c3300853b83907f600d452170c56e2eb04c1e5ca9538751e4cc2095c56357b6efde0807128f339a8ddb002b547a831f72918bd7e0105c895d07ad67a61012a22837e5790f37ecb84d0824130af0e2b030e81c4cca3160a11a90f1eaa273a7da480b1ae853557cdbab08b71bcd2a8d8821eaec376264679714c81687024717628a00d4de5e96d065af301418eeafac9f1197dafca3548f94a8d3fecfa2042607969c980ba1d15150efb5301a579389f23c3ef5516f3bdfd0ffa79adc72c8fdb5dabd5584435a87633c995e12817217bbb9883a35162a130a0bf9baed871cf94b950c6096a5df05f4b3d0cd0202bb79c069c14d7f4cf226801f3499f7cb2cce99cb60868cb627c4fee22ec410718e6c273f1b2536cd3dd36ca270f7ce1884f1f1c8f7987877aaaa4f82023c15b01f300b3fc357110db12413718abb27cae5e923b00c4c1ed7d2650d29c3ff0a80c91c580160701de5490b8e71378e5bc8f743d5d0db13dbeb1a18dc78d4a215747b0a69e603cc0ef06c6bc20f79779774fea435eb83af49ded3b413e4cba51ace881e3c00e953182c436af0b4582e7d1550f5366cf6f7f911d3e21901114b1aea1887cf20c1d343dec00fbed08f641bec0db9ce64e7b3e6ebf482baaf7edb1d96791ba51f9a160c268fed8dd3034796954566639dcf311cacac3d27aa4e372fb0fd900b212b8569bb99ae815a17a78c0ca0c5991e9ea17243c673460ec35a1f09fdd396a3790f792492acb6a96ec5219ca128a3fd45a083e122861bb2a07f19ec73050d3f02e65df6472cd4bc93ab2be89fb689c70bee939237027d843bb51db7b1231f9e873dc038b86d0a346172d9ea9aeecd81e0f548f13e63b03ec6e22ef97d00f6bffec7c1c1724ca18f6358157e7c24b3c630f0b17ca104e7e789a325ecd79251e1760cca1798a50e3f3750b9be59906369396bed1b61a7cc56cd161691c34fb4006a0b1959861a41db3c67cffd4daa61d0c6240e43880a5f0ecf2714fe3e854f7f1c4f229206284a2a503b9672efd27e0c56145b920cf83c7671e62f3087233dd48644a18c3c07ebb8463fd8ff1c59dbcef9a3c5e54935bfdd9f9e105a737ba5250f4fc1b4a4c661bc48f371f15fbb27955dcaa7c80bc9d2eabb490318dd831c8023d15612c73bcdbe0c7f2db70b15bf2b881877c403d1b191722326d96f93b7aefabca028bfe27270ce00a2c9b9636f2ef5287932d3e2e96330b3030e0fe71624bf79ec2953c8e9df8c0e8a7451b3ca197393399ccc98d8e3367a2b7cfaa2cb7e2e60d1f5c3df941ff37466dc3bef116158565d17ebb56df48d6a015088ef17d0500e39c49262cf7e27cd276beedf3d71a1c69159271a196e590b162d5cf704ba3c96b42b6afaed9f51c6d08f0747799db81f080067b744f55320014cca7f94ba25589f829e9c99fa9f867f12095c65ded85a119eaaf1bf41deec2a5e6d5afb2c7ba77452e5137c6167e91c0204cd6a927118874bf7115d0d118c245d552ed8088bc7ec231142580eb354c893da6f3fda136e9657f439bde9bcd612ff07816a9cafc8924de0c82c67ad7bed598a9a7412f322468ef92907407654086440dbe1c58404ce4f5baea0be4b45bd1449269466ba85b8093e153e6e40950c1243f39744f4b84c31be6f6633d87e44d55ce8896ec264589b569dc754ea2b2ba4f7abf2ffa5d67a7d6b667c88db5ffa8658cecbc77ba8f36d2c6b900cfe81076784263be3237e2a4859585876955208744a155b99d318bd52cd08a058ea9a1de48ccef2475868cee8f79fa4a733267fe2ff2993d875ca3bd1c1ad8b96cacc28398347aa78bc154636b9979622c9631e072f8ef34e7f50325702ce2098d1951138ac09a826fcb73c80d6be13ef6c1be749cec155f535a2c35e497ab3046fe514e91cf90fe22b6cb50b374bb85a7b792e8698884aefd1bf62b4188e543b43a622ab3050c3db9282b8e412a5d51aa91e008e624c44cdae0e603ba04ac574549f075f78bd156c9cf93d7cf0e519ca3b3655b507ad4525de78c10c3abfd403fab62a955e29e7c985a641a00dea541ac49435f418276abd510f24ebcdc81fc3513c1fdb77173a32f66561525ca3367e5a4e140ffe19f6250204736a5d8e91e69806106f27fe6fb0ec3d214112dc66c0b2352b7051a92d8444668c087eb9a04299c011715c683f17b8a04064dafd5cd15ce77e3af576be8437f76df94053128a967f2b2c8be3aeef482b78af22298b7c7bfe73e475ea6e4e37c90e2080058a0737ee0b3258e7820630b9d421ec8902a79749eaac0a0a8bd7e818e5717e549ef62f8e033a2ae78e13309a176f4f00dea74e3c5f5311f1ada44bed1e716bafc13a904f09a50684604db24fa643a895ba51aef5d5d482ebaf8baf0248d07ea058a881f6011ed3270d7235b8b88a605cfb1c766ba18bc68186862bed5711c4c4cfca74cf11d356cb15e22217c4ad3f1ddaff93257f2490a0ee4d730e37a38dada7dd969e296bfaa0b4938fef11784b578c4e791102ddde57bf777ae47cb592702b8945150c98be0bc52571a272ab82ed03338f3af48f9514c17fec916dac1eaf3c06949420f587f3c385d4880fca802d69b59970f8c83543eb9cd1c34844faaa1d306ef606996526f2bc007b028093cd4c3439f0eb49951a3c8503f519fab76ab39e493e079564d61db64d48db49b554d12568f27dc165c22431fa5436cebe6123cf5f281e7ebfaf723db9210f87a72023bda9038be386ae6d3bb6c77d9c17ca8fdc8bc52fb3cf0aa51093606246ef27d8a0145ab2973cbd6d618b90cea988c24692945328bb5b8a78bb5baeb18291d8ebd4ceb8a33fcd1ff15ca17ef8b4d3b4dc2516850d76a840392f7fe4babb905b7117dd4bb97c6ab67d0be93a3135dc4b52ace1540da742ab6d03796949d082678bb5719e1035c6dc68284690c6816599650322f91e6f276c1e9cd8f6222a7bdb9d715c9b006fc664dc55b74bb9b06fb3feb2c53906dd58850c209ff3a50972bc04dac4a766e66eb5356e35a16338ef7c2de97cb618df0f1bbd10f9a777d6bc924a229be77bb22ae03618b4e9486d4b999272611e05168e828b0130118c7cec7b5edb9b2c3289854911380a09e7a147a6c17c05570a49f32ed8b35b4fc578c6d3105d809d199134617a865ed5282cb03e3f74b286097a9312daeeeb30a338de3f491d351877c5f29c8c9fbd0ba4398f77d278ab7d00b32747e45034390c34677ce1f9a62d059748c583c8cf46e843e6c293de6d340c5522b6067f6b13f03cd8af586c429e5d9b43e0a6bd2e75f9a43468d8075ac528e6054f318bf63e2dabb7152b45390615a24b1cf43be957084dd7ff0b5f78841bb9ed3b7524ec5394871b656a89b6326b4380f2a623759d00f2fdf0666e335405b557dd780e33c163b7dd6a2d2213b898bbdf06694612d007ab978598d2de501ceee4c7f0e22f6639b032feefefdea63da01198dedf226db7709e2bf70948fe0a6a6dbcde55519d07d7b8fa940de560d2447f3622009630789c7c2c0a65369f1ede770636f3bfd2c7e91a257c3d864f662f27f574ca69afa9ea466406697f3400c1b9eca76176d201c04fc3525e4ff9eb66e19ffa574e05ee1d53d025b80b65016ffdf253493075d3a3c5ac0adc75e609bab166bc4cfa32f4f48defa657d41e2972bf4da3f4ac8d355ac1f6c74c870425b1c0a72897c0b2dce92ef8728dcf621212836cd12e02c87e2b482204a282cc2326bd320a235fcf2cc6305c04cff58e285dc0dc77888f20bab7afb1ac435bcdea0dd02b47222c422d85ed8f1ae25d922c22bac11a84143610f3b961d980edd9a039b58092d17a5c7f1a479033c8317d022ea9a80f5f3a9de355fde6e97b747a5aea3012ec53f230cc9ac182cdca924709d704b4578b0c0d179279df667e84eb9be4b79498a5abcd0a0416d030cea04827d5c669485512da16d3419c1051b2391d02c944a09dd7760c7e6bf78bcda2a5064a469399199e1ad88a8ea378dc15c99e0bfa9a5ee83251fcbcf8f604f46f7a077039074ef3e6e9e57867fe20a3dffa4d123d5f71539c124b24f396bc6afd32066641db5aaff0cf6119ea6c4764badca9e5125e484be9cc4eb4e4a61840e772149dfec9eef43b3cd53194d1b21e018f97a553b25583fa8ca3c15912aa0079a9108fa124c923fee2fdef0cb6afd51d1a6975c3aa82bdf5b1ebb2bdc3e74b22002394a8bfaaf0d471a836691a7b3d31a80e2e672ee89f20a97be25fb3f09b9bf815f2c579b0486d6a6716374aceef869dba050f24b5a99027c8153c53ac72c5171a14cb383e5dea8edebe8d91f7887821cb285804592dc8a7d000047cf276496f2ca62b1bdc1237c667bdd419f7d9aac2d45ee6835bbb78e1f70d2e07fe18f7801e98022a4a1e6066d7faffd2e7e8a3b2a2b49e86d784b7fdaf642bcbea89cea711f10096e17e6d54b77c19a678bf28c0bc17612a87924b38c1fae0bb8cb15e872273285c7d9249ee0305e299d71e21bc5e94c0d7c184ca89995b81f2263442a52da4dc3b5a3bb45ab7004d0850a3dc66cbe64150f05ffdc3a1a67e94f357f6f6170d37b97cc457708123feaf3c28b211d2a6ea2f3b95e50f9ac89f74a5afe7c9071400acb078f6e3c924a3e63b57394ea803f52a14e837e329d31858aed0e6960c7326bc6108c5d5fc9751d7bd43ca5a949709efbb6a17f78b925f9d0ea4439c25040a1f40c4c9664ea6a592a0f8db63ceca0f97b1cf982a98853991c3bec137086c5edcb9b267101bcb290af3957ff3896214734a6fcf98807fafd4f9a5534307d7f7485c7bc369e76886b3766222ed0464f9abb28dc4418d88aa151ebc8769000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ddbc11522fdb37cd54d66ff0d031224c534fa1d99035f3a76e1c851eb98abf11683a6e8603dc51d00fa6ab5460727b4164079075cefcb9b73be96c560d96d8d0bfab78d21f72b9b9ba69ec56a4e3984d0a4f0adbdc1b631d8cec4e45fac6f7a2b68f4f799bd6dd8e98a75e7bb5359120cd031659754cd7a43e14c69b7b7a4ca02f607c7e95907fb1a303c11ff8d559462243b5a32e5c69d74675687d927c4010543237165fb042e777b14b7c8b7b8d0dc9dd68684401bf0f192c6bb076a9a912fce5c2a4cf11181087641da559972c4b35b31a1993718bfca40c9a8693ea372001f08c21298463a9e00d48291b81d296a37902e3476b531a9e41b611d627b4523be885842b6a96910d0fdd0f3bf3939e1a9a5217e332455392112139b1f55420d768328c6bbe2d917c39a94e76423a02df8f0a8593b35d9b29679adc519b51c0a3fed47b7d6bb0072bde12e48a412f8a98c3ca43a385095337c055b6800680d01018f80508e71f91230a165e3d6c96af799b4b1a8b384ce34eb2413346df1d0258d88c0e73cfc4f0933b2eaa8d5ae54ef83c5e99539e4dd5976e5c935bad92a163ba68768fe12f7eca3f21916dd679633457cf392bd07d1f9785599b9285f2409296c76caa4014273e98d36e8c5fe622cf294031d04600d67d54f3e33953ffb119cdcc5a1543f792caead9cbb4689973e43ee745db52a4c6532e108ee3c32dd243a2728e468044612ac3b88b6d2abee33bccc89664928c2b626e108f1df458a090e891bcd6ccca7af5dac51c8884d91ec4c7a28b96c66924bfad57fe53f91bc27aad909837eae75448b9b006decc64b880beb9a5acfbd7db42c95a4f81c188a0cde069d2ca358498603edf1a393a5370003978a74568aa7245e4ac08e66af9507e0c7752b5c4349c734afff0ab4e15dac077453a448249b5d4c4d707f74e54410fa5fbd682c4c067a845bfdb234805f2960e72c4141371dd78b2ac9e78206dc21f7b8beee045d462dcce3e861bd832822290ca1d44fd3210ac2d823b18300970acd8f5af1fc6288526609e3e7158fc3e862910f33b49c30d5bd7c0061ab0a2606a4d894bd6bba7db8a91460442e656f130e0920c6b8dfee2af159b08debb0ce2bff3feb549bf676c2c23b1d303c7c787fec3af98868e7107bc339f2a0421f0529d1a64e7f51301082ed283722bec32fc4058a7b6d89836618c5a861a3de1e95250df0ac0d913887e33eb5b4d6c028cec45804f2e735e7927ef56e85557f03a60b863ea6d1123a4167f0fe78403d246cc3ae226d209eabded6c94dc8ae27b14e0467892da92ff4333e3dab741135cd7a3d322962594b1a5babb279a14d7c994307a53022df0fd582387b05f51be1417c9eebbd258c1996d5ae7cec960914c6c70fda04a512d10d1cef63c589416e38c3959545e317bfd131e6af034f4e722899244a4395fdc1142f327eeafb131869f590fb6ae3c6d5163cec626944ea346936263479b13287b25f41c366d557921da4f311979033f8b949f01028e7984b000302ef578d87bd0f1279bb67c0338e8401d0c3dcb03850183c82eb91293ee4313d018b3c7b802c5fec69ce923fc17c7de8e188edbcb3656229a20b958a5b417f5513244866b7e29af836249e5e621116c00c48f688e3b70866b47d338f0ae1da48031c0f1c3a33155686f7691aab538e8cd7d80a45f492f792e5e21d751a06bf880c5612ac1da3c2cf3783d8b81c3ae4045ef6dcfd4ef34a74659f3029a3e1d212261a1b47e19f579c1ce48c3707d5ec61436bb435c6d1ccf129d88f3153f4aa4a00000000000000000000000000000063d9d8d71404157eb9145a961a7f7859160000000000000000000000000000000000143ce09bdfc295fa61945d0e28c5f1000000000000000000000000000000264b9ab8900bc11d63ead0c03f7e903d400000000000000000000000000000000000297e7593e99062c7b0df616d482e930000000000000000000000000000002e93628d47b15a68952fcb4057be835db20000000000000000000000000000000000006b39f99b64b03c67b4db8fce3da6000000000000000000000000000000ac62d6f017b91f88f52e75b90c74862a9400000000000000000000000000000000001643b7bc26a819053b1333ed82cb7800000000000000000000000000000091bd70369e88869e490bdafb5cb26bdc9000000000000000000000000000000000000dd9123ca345150cff84b58034fd2400000000000000000000000000000037dd34ffc38a8368227472182605c9d8040000000000000000000000000000000000027a9a93a8911854d836f4b2e02dc10000000000000000000000000000000e1cda90bc884b5895a4399c2b4f97608b00000000000000000000000000000000001c0edb8bb62c8d5fc150c1da4a5cf60000000000000000000000000000001f0cc784165acfbf64e74c8d60d52cdb850000000000000000000000000000000000054116be84b9259d5af02a7a708fe30000000000000000000000000000005ef69f1d29233660bcdbe7632b8952b3d8000000000000000000000000000000000030058df00b1633a6dbea05c433384500000000000000000000000000000073a789e69e9035b40f5f5bfc9649e46ce800000000000000000000000000000000001d7d2d9774ee5799bf12fa0df396c9000000000000000000000000000000b54830c5de8e14fd8e325a99dc4c46b32b0000000000000000000000000000000000192d72e1c3df08f68c61748d838dcc00000000000000000000000000000014c077826c347323b56ec87d3765a40501000000000000000000000000000000000000918e90c42e1b4241c6deffd4a375000000000000000000000000000000f0b2edfa65e0315734c9eb0b2fc624de790000000000000000000000000000000000296ae7f79f9bc2b560a363c223e8a0000000000000000000000000000000eb4cb0bcdc7a5a3385ed80a3af61c4ae8b00000000000000000000000000000000002b6ee3130739a352a20e891e512bd3000000000000000000000000000000350cedd0e109c80a7077e852e8e0e1c71b0000000000000000000000000000000000212fca72dcd4b411fee680b9a7f56300000000000000000000000000000094e3b7945e503766aa63a39bc82124def80000000000000000000000000000000000155b4e636cbc620ba1aefbf88764c7000000000000000000000000000000aae845f1261b00814adb5d08243e7b9d75000000000000000000000000000000000012f0f42d54a5195c0da148bce2ff4b0000000000000000000000000000006100b564556553256275a80b73f791559f000000000000000000000000000000000018a90133159d272596287bc01348ef000000000000000000000000000000fb680cac0c832d4d327daf11220e2c507e00000000000000000000000000000000001ef2676b31e934d25616343c8aa9740000000000000000000000000000008a23167c62e6e2015b83e77cc711b1bbf90000000000000000000000000000000000192f767a29cbcb17e080f0d71a417e0000000000000000000000000000003f6f84c1a27f75bfbbe336c99f6e2ec7e100000000000000000000000000000000000b68a0f1287299b94a59150d2362bd000000000000000000000000000000dc80e22cc0525b96d070992d75101dfa9500000000000000000000000000000000000d47dc1ad7ba36c3ae6f4c4c6cf7b0000000000000000000000000000000225a7fb811e266f22189b5247f4e521119000000000000000000000000000000000025203813115395e05262fa62dd3dee0000000000000000000000000000006610313efe88407bad338e07a33b0b4ecf000000000000000000000000000000000007d64baa3c9e9d19af7d978fb9218d00000000000000000000000000000094f54aadd2c3f51f446b8a2e28d93ad20300000000000000000000000000000000002153b035beb4ef431f68e93dfbc81a0000000000000000000000000000009f6da8fb227b9b0287e50d1f46bfb9d7f20000000000000000000000000000000000271fb22a92fe7a00136d2734dc5e6b000000000000000000000000000000638e64589bd2b7fe9baf56b2662d2986b600000000000000000000000000000000001bdfd01817faf3fa096e04782685ea000000000000000000000000000000a88b2944a3a0a1e3e22b97c51f202afecb00000000000000000000000000000000001bed22f73c9b520966edcfa9c60d7b0000000000000000000000000000008fa49b75512dc93e0073b2144105d68201000000000000000000000000000000000004bbd2fd6dbd1bf0679c6d5cd2df450000000000000000000000000000008eaa9861f96071db670cafe2358625da310000000000000000000000000000000000125605f8f3bf8e21c117bb5352f1940000000000000000000000000000008bc5264cc4d3838d7f5cc1d9574d4ce70700000000000000000000000000000000002e3a86246ff868491c0970d330cdae0000000000000000000000000000005f8b8885efc5e108f1aa47ec365bd1d47f000000000000000000000000000000000010d5dc1de8641f633d54c8cfc5a6620000000000000000000000000000009adfd18ab035ac2279aace684cb18f9e3400000000000000000000000000000000001c260c7bf92861c3bba0907e3e08ce0000000000000000000000000000007b4fd3e0780107c48f90d2b5e4f25479bf00000000000000000000000000000000002f4da73ff082a27f7b11e49f55b6b40000000000000000000000000000000719161d5d9945e36b02dd8b82921764590000000000000000000000000000000000207a360fb08fb7a07079c25581c7890000000000000000000000000000006e0a3066ef6eb7c3937a8dc08afaf7afdb000000000000000000000000000000000029f16a68711855d03610851717b9690000000000000000000000000000009b3ea8848e6946845a36584f01fa51c12a00000000000000000000000000000000001752bf5bd5738574672d65f9e63e4b000000000000000000000000000000ab13b9df79c94a0ba64782867f564365b80000000000000000000000000000000000151658ee2dbae3cd6896c2a1c371e10000000000000000000000000000003df28e172f8a09cbd2c32b0b90ab9773bd000000000000000000000000000000000025407a46eb0ce63b0997710d341b56000000000000000000000000000000030499d339f2b44828c2119a7faf3af29a00000000000000000000000000000000002c89ca055d19cb31d25d682322a582000000000000000000000000000000d006f8c62844d76cd0ff4031a630e9756900000000000000000000000000000000001c93ee64fe493f10a1bca911c3a8f00000000000000000000000000000004e429bb69f358a436f088cdc4c5fb590a00000000000000000000000000000000000175effb7e02a137d4a6c93624854a7000000000000000000000000000000eb66098683f97503a5633f638e8f58cbff00000000000000000000000000000000000b97da3690b016024cec5d4d6757a2000000000000000000000000000000aafa700deb31dfcca7586bb94c81f5410c0000000000000000000000000000000000137b0d6a57667d7e00fced77f5fb99000000000000000000000000000000b6568c6d6ab2f999a87eafd44ab9c1571b000000000000000000000000000000000004baef934661960e6412fd1fe7e8dd0000000000000000000000000000003991d0f8f06f12b42a3c179bdd51a81d75000000000000000000000000000000000030306b57f8fb480a16f5bc379a7a6800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001d9c325d0ee6e2871c065558150baf04ead6494bada4611783f9c8e3ed835cb31734beaed64130c9a7792dcf8ac95baab35c43ed3fca3a625ac9ac64049cf3571c296b7d7856db80c8eaeb95990b033406fdd76d860af32e194e0d818fcffc95112b154f783d955fa15376b8a3396b2090dd6d765a83439b421f7206596f592c282415fffab3c36a04016a5e8f1b4393f722fba5212cbefe0706b5fad0e2d8442da92db3ba11940fc1357d77ff8862b2c14d41e57e1dda083076af1bd4b8cf1f06302abce23c2ea7f1a6e1f54e2ceddf944626f52e9dc512f8e4ef15c26df46d1724cbcc9da2848b9f190fa3115510c27492ef53536377d544cd345e29fe476d219a8a92dab1e0d9287c6a531bb35001512ffea3d322f5235496dd0ed512ba752b133b0a39866586a0e6480c71786edbcdbd2f8a603eae732aa1734ce71935f9019a3f7466556ecc363edb3e8764050cbf16e5d9434dc94c346eaea473cb605409720f05c0939a0299afcb87747120fe1b1583bbafc86b6dc7433cf98d499f5118b2b2571cfee1a2cc661e5b460cbc5064c33605a1802af9735efd195b6cd1931b18a257e9028b58b349ba4935ee4ad903a2d665d872d9e56ccdaa2d3330a1d40a99c40dd893e083e38506ab13a952750ae7fe37975673850ffc9f2c912374b613e83a461ffecc9bcb2ce4d2aa8d246913be050f9ab114b15967a305a3f4486123c2d060781f7bbde5139f76e161ea4306bd1d495451d724324e15ac8e29eb772e042ce8cfbd59d137bd0f7e42c46595f8c0ec7763b88d215dee681456d1e17722df43a1c2a29aba785493351a14e8ea167e50f6e4fbed3a70c8386407a5222e198ba1e4658cde8e823be818aa2c01d1cb12a2e1aa8cab906d71ca642dc93ac72c4caf79b03d04276bf63c5fd87a35ee834f1930f348c55bc764f224d960031a1b200cdda403cb070a0bc2da551594477a5a54a0f337e39dc89e58fac5d302621de40a99fe4c01ecf1d04b1eac102e340b3e5243db938ca247bc087d9bc234452dc1842c5c1c7857c5e920dd1ef5a5f79309bf440017c098e8587b7052a43b220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f361e5a37efd4aa4075bf015903c3487d00000000000000000000000000000000000032b2054a1ff4c126ad4ec5e29b9d3000000000000000000000000000000876adbd07f9f901d08177ac6324681d1450000000000000000000000000000000000255574deb2c3d5304e587fcce71573000000000000000000000000000000d7b73474106c95250ec9c74d11adf96bd50000000000000000000000000000000000181995a8e81d6a488a3ae7a0eb9c0a00000000000000000000000000000017402103869df1f8aef9325bd12154318f00000000000000000000000000000000000304f0967ee8e5284d63977b14d66e000003dc","publicInputs":"0x0237797d6a2c04d20d4fa06b74482bd970ccd51a43d9b05b57e9b91fa1ae1cae000000010d479a9973afca679d8246d894b92f79675c4ebe01db6d6f1b20e98368a41295000000032da55666630fdf8594065c377958c827dc1c130dac91f17c6699b53dce60ef7506d1612daf507b160ff518e5f0df28014966c7a498e474e1e88ab9813389fe0e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000183a8619af9f5968db6aef510e527aae5927e5df6092d9498f183f4bc2afc5b115c4ba754a1c246494577702f41a1f2f87b62dd22356c3e52e041870e8b1ebfc00000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} \ No newline at end of file diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index aa85ef06c52..f0f8523b3e6 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -14,7 +14,6 @@ import { type Logger, NoFeePaymentMethod, type PXE, - type SentTx, SignerlessWallet, type Wallet, createAztecNodeClient, @@ -628,38 +627,6 @@ export function getLogger() { return createLogger('e2e:' + describeBlockName); } -/** - * Checks that the last block contains the given expected unencrypted log messages. - * @param tx - An instance of SentTx for which to retrieve the logs. - * @param logMessages - The set of expected log messages. - */ -export const expectUnencryptedLogsInTxToBe = async (tx: SentTx, logMessages: string[]) => { - const unencryptedLogs = (await tx.getUnencryptedLogs()).logs; - const asciiLogs = unencryptedLogs.map(extendedLog => extendedLog.log.data.toString('ascii')); - - expect(asciiLogs).toStrictEqual(logMessages); -}; - -/** - * Checks that the last block contains the given expected unencrypted log messages. - * @param pxe - An instance of PXE for retrieving the logs. - * @param logMessages - The set of expected log messages. - */ -export const expectUnencryptedLogsFromLastBlockToBe = async (pxe: PXE, logMessages: string[]) => { - // docs:start:get_logs - // Get the unencrypted logs from the last block - const fromBlock = await pxe.getBlockNumber(); - const logFilter = { - fromBlock, - toBlock: fromBlock + 1, - }; - const unencryptedLogs = (await pxe.getUnencryptedLogs(logFilter)).logs; - // docs:end:get_logs - const asciiLogs = unencryptedLogs.map(extendedLog => extendedLog.log.data.toString('ascii')); - - expect(asciiLogs).toStrictEqual(logMessages); -}; - export type BalancesFn = ReturnType; export function getBalancesFn( symbol: string, diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index d9cbf1f3553..e786cb2551f 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -131,7 +131,7 @@ describe('guides/dapp/testing', () => { // docs:end:public-storage }); - it('checks unencrypted logs, [Kinda broken with current implementation]', async () => { + it('checks public logs, [Kinda broken with current implementation]', async () => { // docs:start:unencrypted-logs const value = Fr.fromHexString('ef'); // Only 1 bytes will make its way in there :( so no larger stuff const tx = await testContract.methods.emit_unencrypted(value).send().wait(); @@ -139,8 +139,8 @@ describe('guides/dapp/testing', () => { fromBlock: tx.blockNumber!, limit: 1, // 1 log expected }; - const logs = (await pxe.getUnencryptedLogs(filter)).logs; - expect(Fr.fromBuffer(logs[0].log.data)).toEqual(value); + const logs = (await pxe.getPublicLogs(filter)).logs; + expect(logs[0].log.log[0]).toEqual(value); // docs:end:unencrypted-logs }); diff --git a/yarn-project/end-to-end/src/sample-dapp/index.mjs b/yarn-project/end-to-end/src/sample-dapp/index.mjs index fff9f14e117..bc19f9cd613 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.mjs @@ -91,7 +91,7 @@ async function mintPublicFunds(pxe) { // docs:start:showLogs const blockNumber = await pxe.getBlockNumber(); - const logs = (await pxe.getUnencryptedLogs({ fromBlock: blockNumber - 1 })).logs; + const logs = (await pxe.getPublicLogs({ fromBlock: blockNumber - 1 })).logs; const textLogs = logs.map(extendedLog => extendedLog.toHumanReadable().slice(0, 200)); for (const log of textLogs) console.log(`Log emitted: ${log}`); // docs:end:showLogs diff --git a/yarn-project/noir-protocol-circuits-types/src/conversion/common.ts b/yarn-project/noir-protocol-circuits-types/src/conversion/common.ts index e4fb401537e..8081f183aa8 100644 --- a/yarn-project/noir-protocol-circuits-types/src/conversion/common.ts +++ b/yarn-project/noir-protocol-circuits-types/src/conversion/common.ts @@ -23,6 +23,7 @@ import { NUM_BYTES_PER_SHA256, type NullifierLeafPreimage, OptionalNumber, + type PRIVATE_LOG_SIZE_IN_FIELDS, PartialStateReference, Point, PrivateLog, @@ -30,6 +31,7 @@ import { PublicCallRequest, type PublicDataTreeLeafPreimage, type PublicDataWrite, + PublicLog, ScopedL2ToL1Message, ScopedLogHash, StateReference, @@ -53,6 +55,7 @@ import type { EmbeddedCurveScalar as GrumpkinScalarNoir, L2ToL1Message as L2ToL1MessageNoir, LogHash as LogHashNoir, + Log as LogNoir, MaxBlockNumber as MaxBlockNumberNoir, MembershipWitness as MembershipWitnessNoir, AztecAddress as NoirAztecAddress, @@ -62,11 +65,11 @@ import type { NullifierLeafPreimage as NullifierLeafPreimageNoir, Option as OptionalNumberNoir, PartialStateReference as PartialStateReferenceNoir, - Log as PrivateLogNoir, PrivateToRollupAccumulatedData as PrivateToRollupAccumulatedDataNoir, PublicCallRequest as PublicCallRequestNoir, PublicDataTreeLeafPreimage as PublicDataTreeLeafPreimageNoir, PublicDataWrite as PublicDataWriteNoir, + PublicLog as PublicLogNoir, ScopedL2ToL1Message as ScopedL2ToL1MessageNoir, ScopedLogHash as ScopedLogHashNoir, StateReference as StateReferenceNoir, @@ -243,16 +246,30 @@ export function mapGasFeesFromNoir(gasFees: GasFeesNoir): GasFees { return new GasFees(mapFieldFromNoir(gasFees.fee_per_da_gas), mapFieldFromNoir(gasFees.fee_per_l2_gas)); } -export function mapPrivateLogToNoir(log: PrivateLog): PrivateLogNoir { +export function mapPrivateLogToNoir(log: PrivateLog): LogNoir { return { fields: mapTuple(log.fields, mapFieldToNoir), }; } -export function mapPrivateLogFromNoir(log: PrivateLogNoir) { +export function mapPrivateLogFromNoir(log: LogNoir) { return new PrivateLog(mapTupleFromNoir(log.fields, log.fields.length, mapFieldFromNoir)); } +export function mapPublicLogToNoir(log: PublicLog): PublicLogNoir { + return { + contract_address: mapAztecAddressToNoir(log.contractAddress), + log: { fields: mapTuple(log.log, mapFieldToNoir) }, + }; +} + +export function mapPublicLogFromNoir(log: PublicLogNoir) { + return new PublicLog( + mapAztecAddressFromNoir(log.contract_address), + mapTupleFromNoir(log.log.fields, log.log.fields.length, mapFieldFromNoir), + ); +} + /** * Maps an array from noir types to a tuple of parsed types. * @param noirArray - The noir array. @@ -666,9 +683,30 @@ export function mapPublicDataWriteToNoir(write: PublicDataWrite): PublicDataWrit } /** - * Maps combined accumulated data from noir to the parsed type. - * @param PrivateToRollupAccumulatedData - The noir combined accumulated data. - * @returns The parsed combined accumulated data. + * Maps private to rollup accumulated data to noir to the parsed type. + * @param privateToRollupAccumulatedData - The ts private to rollup accumulated data. + * @returns The noir private to rollup accumulated data. + */ +export function mapPrivateToRollupAccumulatedDataToNoir( + privateToRollupAccumulatedData: PrivateToRollupAccumulatedData, +): PrivateToRollupAccumulatedDataNoir { + return { + note_hashes: mapTuple(privateToRollupAccumulatedData.noteHashes, mapFieldToNoir), + nullifiers: mapTuple(privateToRollupAccumulatedData.nullifiers, mapFieldToNoir), + l2_to_l1_msgs: mapTuple(privateToRollupAccumulatedData.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), + private_logs: mapTuple(privateToRollupAccumulatedData.privateLogs, mapPrivateLogToNoir), + contract_class_logs_hashes: mapTuple( + privateToRollupAccumulatedData.contractClassLogsHashes, + mapScopedLogHashToNoir, + ), + contract_class_log_preimages_length: mapFieldToNoir(privateToRollupAccumulatedData.contractClassLogPreimagesLength), + }; +} + +/** + * Maps private to rollup accumulated data from noir to the parsed type. + * @param PrivateToRollupAccumulatedData - The noir private to rollup accumulated data. + * @returns The parsed private to rollup accumulated data. */ export function mapPrivateToRollupAccumulatedDataFromNoir( privateToRollupAccumulatedData: PrivateToRollupAccumulatedDataNoir, diff --git a/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts b/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts index d6782809e19..c6ba0c6f315 100644 --- a/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts +++ b/yarn-project/noir-protocol-circuits-types/src/conversion/server.ts @@ -17,7 +17,6 @@ import { type PrivateToAvmAccumulatedDataArrayLengths, type PrivateToPublicAccumulatedData, type PrivateToPublicKernelCircuitPublicInputs, - type PrivateToRollupAccumulatedData, PrivateToRollupKernelCircuitPublicInputs, type PublicDataHint, type RECURSIVE_PROOF_LENGTH, @@ -92,7 +91,6 @@ import type { PrivateToAvmAccumulatedData as PrivateToAvmAccumulatedDataNoir, PrivateToPublicAccumulatedData as PrivateToPublicAccumulatedDataNoir, PrivateToPublicKernelCircuitPublicInputs as PrivateToPublicKernelCircuitPublicInputsNoir, - PrivateToRollupAccumulatedData as PrivateToRollupAccumulatedDataNoir, PrivateToRollupKernelCircuitPublicInputs as PrivateToRollupKernelCircuitPublicInputsNoir, PrivateTubeData as PrivateTubeDataNoir, PublicBaseRollupInputs as PublicBaseRollupInputsNoir, @@ -136,9 +134,11 @@ import { mapPartialStateReferenceToNoir, mapPrivateLogToNoir, mapPrivateToRollupAccumulatedDataFromNoir, + mapPrivateToRollupAccumulatedDataToNoir, mapPublicCallRequestToNoir, mapPublicDataTreePreimageToNoir, mapPublicDataWriteToNoir, + mapPublicLogToNoir, mapScopedL2ToL1MessageToNoir, mapScopedLogHashToNoir, mapTupleFromNoir, @@ -471,22 +471,6 @@ export function mapPrivateToPublicAccumulatedDataToNoir( }; } -export function mapPrivateToRollupAccumulatedDataToNoir( - privateToRollupAccumulatedData: PrivateToRollupAccumulatedData, -): PrivateToRollupAccumulatedDataNoir { - return { - note_hashes: mapTuple(privateToRollupAccumulatedData.noteHashes, mapFieldToNoir), - nullifiers: mapTuple(privateToRollupAccumulatedData.nullifiers, mapFieldToNoir), - l2_to_l1_msgs: mapTuple(privateToRollupAccumulatedData.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), - private_logs: mapTuple(privateToRollupAccumulatedData.privateLogs, mapPrivateLogToNoir), - contract_class_logs_hashes: mapTuple( - privateToRollupAccumulatedData.contractClassLogsHashes, - mapScopedLogHashToNoir, - ), - contract_class_log_preimages_length: mapFieldToNoir(privateToRollupAccumulatedData.contractClassLogPreimagesLength), - }; -} - function mapTxConstantDataFromNoir(combinedConstantData: TxConstantDataNoir): TxConstantData { return new TxConstantData( mapHeaderFromNoir(combinedConstantData.historical_header), @@ -554,7 +538,7 @@ function mapAvmAccumulatedDataToNoir(data: AvmAccumulatedData): AvmAccumulatedDa note_hashes: mapTuple(data.noteHashes, mapFieldToNoir), nullifiers: mapTuple(data.nullifiers, mapFieldToNoir), l2_to_l1_msgs: mapTuple(data.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), - unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapScopedLogHashToNoir), + public_logs: mapTuple(data.publicLogs, mapPublicLogToNoir), public_data_writes: mapTuple(data.publicDataWrites, mapPublicDataWriteToNoir), }; } diff --git a/yarn-project/p2p/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts b/yarn-project/p2p/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts index ad7e4981fcb..cc26247a930 100644 --- a/yarn-project/p2p/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +++ b/yarn-project/p2p/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts @@ -283,7 +283,6 @@ export class AztecKVTxPool implements TxPool { const archivedTx: Tx = new Tx( tx.data, ClientIvcProof.empty(), - tx.unencryptedLogs, tx.contractClassLogs, tx.enqueuedPublicFunctionCalls, tx.publicTeardownFunctionCall, diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 4388a7a99f3..132d0387819 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -5,7 +5,8 @@ import { type EventMetadataDefinition, type ExtendedNote, type FunctionCall, - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, L1EventPayload, type L2Block, @@ -608,12 +609,12 @@ export class PXEService implements PXE { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - public getUnencryptedLogs(filter: LogFilter): Promise { - return this.node.getUnencryptedLogs(filter); + public getPublicLogs(filter: LogFilter): Promise { + return this.node.getPublicLogs(filter); } /** @@ -621,7 +622,7 @@ export class PXEService implements PXE { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - public getContractClassLogs(filter: LogFilter): Promise { + public getContractClassLogs(filter: LogFilter): Promise { return this.node.getContractClassLogs(filter); } @@ -833,7 +834,7 @@ export class PXEService implements PXE { return !!(await this.node.getNullifierMembershipWitness('latest', initNullifier)); } - public async getEncryptedEvents( + public async getPrivateEvents( eventMetadataDef: EventMetadataDefinition, from: number, limit: number, @@ -905,34 +906,32 @@ export class PXEService implements PXE { return decodedEvents; } - async getUnencryptedEvents(eventMetadataDef: EventMetadataDefinition, from: number, limit: number): Promise { + async getPublicEvents(eventMetadataDef: EventMetadataDefinition, from: number, limit: number): Promise { const eventMetadata = new EventMetadata(eventMetadataDef); - const { logs: unencryptedLogs } = await this.node.getUnencryptedLogs({ + const { logs } = await this.node.getPublicLogs({ fromBlock: from, toBlock: from + limit, }); - const decodedEvents = unencryptedLogs - .map(unencryptedLog => { - const unencryptedLogBuf = unencryptedLog.log.data; + const decodedEvents = logs + .map(log => { + // +1 for the event selector + const expectedLength = eventMetadata.fieldNames.length + 1; + const logFields = log.log.log.slice(0, expectedLength); // We are assuming here that event logs are the last 4 bytes of the event. This is not enshrined but is a function of aztec.nr raw log emission. - if ( - !EventSelector.fromBuffer(unencryptedLogBuf.subarray(unencryptedLogBuf.byteLength - 4)).equals( - eventMetadata.eventSelector, - ) - ) { + if (!EventSelector.fromField(logFields[logFields.length - 1]).equals(eventMetadata.eventSelector)) { return undefined; } - - if (unencryptedLogBuf.byteLength !== eventMetadata.fieldNames.length * 32 + 32) { + // If any of the remaining fields, are non-zero, the payload does match expected: + if (log.log.log.slice(expectedLength + 1).find(f => !f.isZero())) { throw new Error( 'Something is weird here, we have matching EventSelectors, but the actual payload has mismatched length', ); } - return eventMetadata.decode(unencryptedLog.log); + return eventMetadata.decode(log.log); }) - .filter(unencryptedLog => unencryptedLog !== undefined) as T[]; + .filter(log => log !== undefined) as T[]; return decodedEvents; } diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index 5bb9916eb5f..9a60012bf44 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -97,7 +97,7 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => ); }); - // Note: Not testing `getContractData` and `getUnencryptedLogs` here as these + // Note: Not testing `getContractData` and `getPublicLogs` here as these // functions only call AztecNode and these methods are frequently used by the e2e tests. it('successfully gets a block number', async () => { diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index ba80dc2940d..736c137d5da 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -27,6 +27,7 @@ import { MAX_NOTE_HASHES_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS, PrivateLog, + PublicLog, computeAddressSecret, computeTaggingSecretPoint, } from '@aztec/circuits.js'; @@ -499,15 +500,31 @@ export class SimulatorOracle implements DBOracle { logsByTags.forEach((logsByTag, logIndex) => { if (logsByTag.length > 0) { + // Check that public logs have the correct contract address + const checkedLogsbyTag = logsByTag.filter( + l => !l.isFromPublic || PublicLog.fromBuffer(l.logData).contractAddress.equals(contractAddress), + ); + if (checkedLogsbyTag.length < logsByTag.length) { + const discarded = logsByTag.filter( + log => checkedLogsbyTag.find(filteredLog => filteredLog.equals(log)) === undefined, + ); + this.log.warn( + `Discarded ${ + logsByTag.length - checkedLogsbyTag.length + } public logs with mismatched contract address ${contractAddress}:`, + discarded.map(l => PublicLog.fromBuffer(l.logData)), + ); + } + // The logs for the given tag exist so we store them for later processing - logsForRecipient.push(...logsByTag); + logsForRecipient.push(...checkedLogsbyTag); // We retrieve the indexed tagging secret corresponding to the log as I need that to evaluate whether // a new largest index have been found. const secretCorrespondingToLog = secretsForTheWholeWindow[logIndex]; const initialIndex = initialIndexesMap[secretCorrespondingToLog.appTaggingSecret.toString()]; - this.log.debug(`Found ${logsByTag.length} logs as recipient ${recipient}`, { + this.log.debug(`Found ${checkedLogsbyTag.length} logs as recipient ${recipient}`, { recipient, secret: secretCorrespondingToLog.appTaggingSecret, contractName, @@ -597,7 +614,7 @@ export class SimulatorOracle implements DBOracle { for (const scopedLog of scopedLogs) { const payload = scopedLog.isFromPublic - ? L1NotePayload.decryptAsIncomingFromPublic(scopedLog.logData, addressSecret) + ? L1NotePayload.decryptAsIncomingFromPublic(PublicLog.fromBuffer(scopedLog.logData), addressSecret) : L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret); if (!payload) { diff --git a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts index 3f7d3d19eab..cea8f8dc319 100644 --- a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts +++ b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts @@ -21,6 +21,8 @@ import { INITIAL_L2_BLOCK_NUM, IndexedTaggingSecret, MAX_NOTE_HASHES_PER_TX, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, + PublicLog, computeAddress, computeTaggingSecretPoint, deriveKeys, @@ -461,6 +463,27 @@ describe('Simulator oracle', () => { // Only NUM_SENDERS + 1 logs should be synched, since the rest have blockNumber > 1 expect(syncedLogs.get(recipient.address.toString())).toHaveLength(NUM_SENDERS + 1); }); + + it('should not sync public tagged logs with incorrect contract address', async () => { + const logs: { [k: string]: TxScopedL2Log[] } = {}; + const tag = computeSiloedTagForIndex(senders[0], recipient.address, contractAddress, 0); + // Create a public log with an address which doesn't match the tag + const logData = PublicLog.fromFields([ + AztecAddress.fromNumber(2).toField(), + Fr.ONE, + tag, + ...Array(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 2).fill(Fr.random()), + ]).toBuffer(); + const log = new TxScopedL2Log(TxHash.random(), 1, 0, true, logData); + logs[tag.toString()] = [log]; + aztecNode.getLogsByTags.mockImplementation(tags => { + return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); + }); + const syncedLogs = await simulatorOracle.syncTaggedLogs(contractAddress, 1); + + // We expect the above log to be discarded, and so none to be synced + expect(syncedLogs.get(recipient.address.toString())).toHaveLength(0); + }); }); describe('Process notes', () => { diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 447b5bcce13..69e53f5e9bc 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -693,8 +693,8 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); }); - describe('Unencrypted Logs', () => { - it(`Emit unencrypted logs (should be traced)`, async () => { + describe('Public Logs', () => { + it(`Emit public logs (should be traced)`, async () => { const context = createContext(); const bytecode = getAvmTestContractBytecode('emit_unencrypted_log'); @@ -708,10 +708,10 @@ describe('AVM simulator: transpiled Noir contracts', () => { '\0r far away...\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', ].map(s => new Fr(Buffer.from(s))); - expect(trace.traceUnencryptedLog).toHaveBeenCalledTimes(3); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, expectedFields); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, expectedString); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, expectedCompressedString); + expect(trace.tracePublicLog).toHaveBeenCalledTimes(3); + expect(trace.tracePublicLog).toHaveBeenCalledWith(address, expectedFields); + expect(trace.tracePublicLog).toHaveBeenCalledWith(address, expectedString); + expect(trace.tracePublicLog).toHaveBeenCalledWith(address, expectedCompressedString); }); }); diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 1c0182ad74d..a635424049f 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -524,14 +524,13 @@ export class AvmPersistableStateManager { } /** - * Write an unencrypted log + * Write a public log * @param contractAddress - address of the contract that emitted the log - * @param event - log event selector * @param log - log contents */ - public writeUnencryptedLog(contractAddress: AztecAddress, log: Fr[]) { - this.log.debug(`UnencryptedL2Log(${contractAddress}) += event with ${log.length} fields.`); - this.trace.traceUnencryptedLog(contractAddress, log); + public writePublicLog(contractAddress: AztecAddress, log: Fr[]) { + this.log.debug(`PublicLog(${contractAddress}) += event with ${log.length} fields.`); + this.trace.tracePublicLog(contractAddress, log); } /** diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts index 2fd3d84edba..dd0c97eb724 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts @@ -305,7 +305,7 @@ describe('Accrued Substate', () => { expect(inst.serialize()).toEqual(buf); }); - it('Should append unencrypted logs correctly', async () => { + it('Should append public logs correctly', async () => { const startOffset = 0; const logSizeOffset = 20; @@ -318,8 +318,8 @@ describe('Accrued Substate', () => { await new EmitUnencryptedLog(/*indirect=*/ 0, /*offset=*/ startOffset, logSizeOffset).execute(context); - expect(trace.traceUnencryptedLog).toHaveBeenCalledTimes(1); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, values); + expect(trace.tracePublicLog).toHaveBeenCalledTimes(1); + expect(trace.tracePublicLog).toHaveBeenCalledWith(address, values); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts index 0a8bd01f140..a3361f69d3f 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts @@ -201,6 +201,7 @@ export class L1ToL2MessageExists extends Instruction { } export class EmitUnencryptedLog extends Instruction { + // TODO(MW): rename unencrypted -> public static type: string = 'EMITUNENCRYPTEDLOG'; static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG; // Informs (de)serialization. See Instruction.deserialize. @@ -228,7 +229,7 @@ export class EmitUnencryptedLog extends Instruction { context.machineState.consumeGas(this.gasCost(logSize)); const log = memory.getSlice(logOffset, logSize).map(f => f.toFr()); - context.persistableState.writeUnencryptedLog(contractAddress, log); + context.persistableState.writePublicLog(contractAddress, log); memory.assert({ reads: 1 + logSize, addressing }); } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 342fe8fdc65..3b816ed4bd9 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -327,6 +327,7 @@ export class ClientExecutionContext extends ViewDataOracle { * This fn exists because sha hashing the preimage * is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it. * See private_context.nr + * TODO(#8945): Contract class logs are currently sha hashes. When these are fields, delete this. * @param log - The unencrypted log to be emitted. */ public override emitContractClassLog(log: UnencryptedL2Log, counter: number) { diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index 9faa6cbd0ec..d7399f2b885 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -1,4 +1,3 @@ -import { UnencryptedL2Log } from '@aztec/circuit-types'; import { AvmAppendTreeHint, AvmNullifierReadTreeHint, @@ -9,22 +8,24 @@ import { type ContractClassIdPreimage, EthAddress, L2ToL1Message, - LogHash, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_PUBLIC_LOGS_PER_TX, NoteHash, Nullifier, NullifierLeafPreimage, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, + PublicLog, SerializableContractInstance, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; +import { padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; import { randomInt } from 'crypto'; @@ -148,17 +149,14 @@ describe('Enqueued-call Side Effect Trace', () => { expect(trace.getSideEffects().l2ToL1Msgs).toEqual(expected); }); - it('Should trace new unencrypted logs', () => { - trace.traceUnencryptedLog(address, log); + it('Should trace new public logs', () => { + trace.tracePublicLog(address, log); expect(trace.getCounter()).toBe(startCounterPlus1); - const expectedLog = new UnencryptedL2Log(address, Buffer.concat(log.map(f => f.toBuffer()))); - const expectedHashes = [ - new LogHash(Fr.fromBuffer(expectedLog.hash()), startCounter, new Fr(expectedLog.length + 4)).scope(address), - ]; + const expectedLog = new PublicLog(address, padArrayEnd(log, Fr.ZERO, PUBLIC_LOG_DATA_SIZE_IN_FIELDS)); - expect(trace.getUnencryptedLogs()).toEqual([expectedLog]); - expect(trace.getSideEffects().unencryptedLogsHashes).toEqual(expectedHashes); + expect(trace.getPublicLogs()).toEqual([expectedLog]); + expect(trace.getSideEffects().publicLogs).toEqual([expectedLog]); }); it('Should trace get contract instance', () => { @@ -311,11 +309,11 @@ describe('Enqueued-call Side Effect Trace', () => { ); }); - it('Should enforce maximum number of new logs hashes', () => { - for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX; i++) { - trace.traceUnencryptedLog(AztecAddress.fromNumber(i), [new Fr(i), new Fr(i)]); + it('Should enforce maximum number of new logs', () => { + for (let i = 0; i < MAX_PUBLIC_LOGS_PER_TX; i++) { + trace.tracePublicLog(AztecAddress.fromNumber(i), [new Fr(i), new Fr(i)]); } - expect(() => trace.traceUnencryptedLog(AztecAddress.fromNumber(42), [new Fr(42), new Fr(42)])).toThrow( + expect(() => trace.tracePublicLog(AztecAddress.fromNumber(42), [new Fr(42), new Fr(42)])).toThrow( SideEffectLimitReachedError, ); }); @@ -360,7 +358,7 @@ describe('Enqueued-call Side Effect Trace', () => { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_PUBLIC_LOGS_PER_TX, ), ); expect(() => trace.tracePublicStorageWrite(AztecAddress.fromNumber(42), new Fr(42), new Fr(42), false)).toThrow( @@ -374,7 +372,7 @@ describe('Enqueued-call Side Effect Trace', () => { expect(() => trace.traceNewL2ToL1Message(AztecAddress.fromNumber(42), new Fr(42), new Fr(42))).toThrow( SideEffectLimitReachedError, ); - expect(() => trace.traceUnencryptedLog(AztecAddress.fromNumber(42), [new Fr(42), new Fr(42)])).toThrow( + expect(() => trace.tracePublicLog(AztecAddress.fromNumber(42), [new Fr(42), new Fr(42)])).toThrow( SideEffectLimitReachedError, ); }); @@ -406,7 +404,7 @@ describe('Enqueued-call Side Effect Trace', () => { // counter does not increment for l1tol2 message checks nestedTrace.traceNewL2ToL1Message(address, recipient, content); testCounter++; - nestedTrace.traceUnencryptedLog(address, log); + nestedTrace.tracePublicLog(address, log); testCounter++; nestedTrace.traceGetContractInstance(address, /*exists=*/ true, contractInstance, lowLeafPreimage, Fr.ZERO, []); testCounter++; @@ -427,8 +425,7 @@ describe('Enqueued-call Side Effect Trace', () => { expect(parentSideEffects.noteHashes).toEqual([]); expect(parentSideEffects.nullifiers).toEqual([]); expect(parentSideEffects.l2ToL1Msgs).toEqual([]); - expect(parentSideEffects.unencryptedLogs).toEqual([]); - expect(parentSideEffects.unencryptedLogsHashes).toEqual([]); + expect(parentSideEffects.publicLogs).toEqual([]); } else { expect(parentSideEffects).toEqual(childSideEffects); } diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index cfd3f76c11c..179ff3465b0 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -1,4 +1,3 @@ -import { UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types'; import { AvmAccumulatedData, AvmAppendTreeHint, @@ -19,15 +18,14 @@ import { type GlobalVariables, L1_TO_L2_MSG_TREE_HEIGHT, L2ToL1Message, - LogHash, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_PUBLIC_LOGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, NoteHash, @@ -35,14 +33,15 @@ import { NullifierLeafPreimage, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, PrivateToAvmAccumulatedData, PrivateToAvmAccumulatedDataArrayLengths, PublicCallRequest, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, PublicDataWrite, + PublicLog, ScopedL2ToL1Message, - ScopedLogHash, SerializableContractInstance, type TreeSnapshots, } from '@aztec/circuits.js'; @@ -79,8 +78,7 @@ export type SideEffects = { nullifiers: Nullifier[]; l2ToL1Msgs: ScopedL2ToL1Message[]; - unencryptedLogs: UnencryptedL2Log[]; - unencryptedLogsHashes: ScopedLogHash[]; + publicLogs: PublicLog[]; }; export class SideEffectArrayLengths { @@ -90,7 +88,7 @@ export class SideEffectArrayLengths { public readonly noteHashes: number, public readonly nullifiers: number, public readonly l2ToL1Msgs: number, - public readonly unencryptedLogs: number, + public readonly publicLogs: number, ) {} static empty() { @@ -115,8 +113,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI private noteHashes: NoteHash[] = []; private nullifiers: Nullifier[] = []; private l2ToL1Messages: ScopedL2ToL1Message[] = []; - private unencryptedLogs: UnencryptedL2Log[] = []; - private unencryptedLogsHashes: ScopedLogHash[] = []; + private publicLogs: PublicLog[] = []; private avmCircuitHints: AvmExecutionHints; @@ -147,7 +144,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length, this.previousSideEffectArrayLengths.nullifiers + this.nullifiers.length, this.previousSideEffectArrayLengths.l2ToL1Msgs + this.l2ToL1Messages.length, - this.previousSideEffectArrayLengths.unencryptedLogs + this.unencryptedLogs.length, + this.previousSideEffectArrayLengths.publicLogs + this.publicLogs.length, ), this.gotBytecodeFromClassIds.fork(), ); @@ -169,8 +166,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.noteHashes.push(...forkedTrace.noteHashes); this.nullifiers.push(...forkedTrace.nullifiers); this.l2ToL1Messages.push(...forkedTrace.l2ToL1Messages); - this.unencryptedLogs.push(...forkedTrace.unencryptedLogs); - this.unencryptedLogsHashes.push(...forkedTrace.unencryptedLogsHashes); + this.publicLogs.push(...forkedTrace.publicLogs); } this.mergeHints(forkedTrace); } @@ -359,23 +355,17 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.incrementSideEffectCounter(); } - public traceUnencryptedLog(contractAddress: AztecAddress, log: Fr[]) { - if ( - this.unencryptedLogs.length + this.previousSideEffectArrayLengths.unencryptedLogs >= - MAX_UNENCRYPTED_LOGS_PER_TX - ) { - throw new SideEffectLimitReachedError('unencrypted log', MAX_UNENCRYPTED_LOGS_PER_TX); + public tracePublicLog(contractAddress: AztecAddress, log: Fr[]) { + if (this.publicLogs.length + this.previousSideEffectArrayLengths.publicLogs >= MAX_PUBLIC_LOGS_PER_TX) { + throw new SideEffectLimitReachedError('public log', MAX_PUBLIC_LOGS_PER_TX); } - const ulog = new UnencryptedL2Log(contractAddress, Buffer.concat(log.map(f => f.toBuffer()))); - const basicLogHash = Fr.fromBuffer(ulog.hash()); - this.unencryptedLogs.push(ulog); - // This length is for charging DA and is checked on-chain - has to be length of log preimage + 4 bytes. - // The .length call also has a +4 but that is unrelated - this.unencryptedLogsHashes.push( - new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4)).scope(contractAddress), - ); - this.log.debug(`NEW_UNENCRYPTED_LOG cnt: ${this.sideEffectCounter}`); + if (log.length > PUBLIC_LOG_DATA_SIZE_IN_FIELDS) { + throw new Error(`Emitted public log is too large, max: ${PUBLIC_LOG_DATA_SIZE_IN_FIELDS}, passed: ${log.length}`); + } + const publicLog = new PublicLog(contractAddress, padArrayEnd(log, Fr.ZERO, PUBLIC_LOG_DATA_SIZE_IN_FIELDS)); + this.publicLogs.push(publicLog); + this.log.debug(`NEW_PUBLIC_LOG cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -518,8 +508,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI noteHashes: this.noteHashes, nullifiers: this.nullifiers, l2ToL1Msgs: this.l2ToL1Messages, - unencryptedLogs: this.unencryptedLogs, - unencryptedLogsHashes: this.unencryptedLogsHashes, + publicLogs: this.publicLogs, }; } @@ -541,8 +530,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI noteHashes: this.noteHashes, nullifiers: this.nullifiers, l2ToL1Messages: this.l2ToL1Messages, - unencryptedLogsHashes: this.unencryptedLogsHashes, // Scoped? - unencryptedLogs: new UnencryptedFunctionL2Logs(this.unencryptedLogs), + publicLogs: this.publicLogs, }, }; } @@ -612,8 +600,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI throw new Error('Not implemented'); } - public getUnencryptedLogs() { - return this.unencryptedLogs; + public getPublicLogs() { + return this.publicLogs; } public getAvmCircuitHints() { @@ -633,7 +621,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI MAX_NULLIFIERS_PER_TX, ), padArrayEnd(this.l2ToL1Messages, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX), - padArrayEnd(this.unencryptedLogsHashes, ScopedLogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX), + padArrayEnd(this.publicLogs, PublicLog.empty(), MAX_PUBLIC_LOGS_PER_TX), padArrayEnd( this.publicDataWrites.map(w => new PublicDataWrite(w.leafSlot, w.newValue)), PublicDataWrite.empty(), diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index cf9832201a2..c130619f047 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -1,8 +1,4 @@ -import { - type PublicExecutionRequest, - type SimulationError, - type UnencryptedFunctionL2Logs, -} from '@aztec/circuit-types'; +import { type PublicExecutionRequest, type SimulationError } from '@aztec/circuit-types'; import { type AvmExecutionHints, type ContractStorageRead, @@ -10,16 +6,15 @@ import { type Fr, Gas, type L2ToL1Message, - type LogHash, type NoteHash, type Nullifier, PublicCallStackItemCompressed, type PublicDataUpdateRequest, PublicInnerCallRequest, + type PublicLog, type ReadRequest, RevertCode, type ScopedL2ToL1Message, - type ScopedLogHash, type TreeLeafReadRequest, } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; @@ -33,16 +28,8 @@ export interface PublicSideEffects { nullifiers: Nullifier[]; /** The new l2 to l1 messages generated to be inserted into the messages tree. */ l2ToL1Messages: ScopedL2ToL1Message[]; - /** - * The hashed logs with side effect counter. - * Note: required as we don't track the counter anywhere else. - */ - unencryptedLogsHashes: ScopedLogHash[]; - /** - * Unencrypted logs emitted during execution. - * Note: These are preimages to `unencryptedLogsHashes`. - */ - unencryptedLogs: UnencryptedFunctionL2Logs; + /** Public logs emitted during execution. */ + publicLogs: PublicLog[]; } export interface EnqueuedPublicCallExecutionResult { @@ -124,21 +111,10 @@ export interface PublicFunctionCallResult { /** L1 to L2 message read requests emitted in this call. */ l1ToL2MsgReadRequests: TreeLeafReadRequest[]; /** - * The hashed logs with side effect counter. - * Note: required as we don't track the counter anywhere else. + * The public logs emitted in this call. + * Note: PublicLog has no counter - unsure if this is needed bc this struct is unused */ - unencryptedLogsHashes: LogHash[]; - /** - * Unencrypted logs emitted during execution of this function call. - * Note: These are preimages to `unencryptedLogsHashes`. - */ - unencryptedLogs: UnencryptedFunctionL2Logs; - /** - * Unencrypted logs emitted during this call AND any nested calls. - * Useful for maintaining correct ordering in ts. - */ - allUnencryptedLogs: UnencryptedFunctionL2Logs; - + publicLogs: PublicLog[]; /** The requests to call public functions made by this call. */ publicCallRequests: PublicInnerCallRequest[]; /** The results of nested calls. */ diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 5118d1f4a1d..add18bca89d 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -309,7 +309,7 @@ export class PublicProcessor implements Traceable { nullifierCount: processedTx.txEffect.nullifiers.length, noteHashCount: processedTx.txEffect.noteHashes.length, contractClassLogCount: processedTx.txEffect.contractClassLogs.getTotalLogCount(), - unencryptedLogCount: processedTx.txEffect.unencryptedLogs.getTotalLogCount(), + publicLogCount: processedTx.txEffect.publicLogs.length, privateLogCount: processedTx.txEffect.privateLogs.length, l2ToL1MessageCount: processedTx.txEffect.l2ToL1Msgs.length, durationMs: time, diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index 194838dd018..f840955a0f7 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -97,7 +97,7 @@ export class PublicTxContext { /*noteHashes*/ 0, /*nullifiers=*/ 0, countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.l2ToL1Msgs), - /*unencryptedLogsHashes*/ 0, + /*publicLogs*/ 0, ); const enqueuedCallTrace = new PublicEnqueuedCallSideEffectTrace( /*startSideEffectCounter=*/ 0, diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index b5886d93347..349311b88f7 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -7,7 +7,6 @@ import { type SimulationError, type Tx, TxExecutionPhase, - UnencryptedFunctionL2Logs, } from '@aztec/circuit-types'; import { type AvmSimulationStats } from '@aztec/circuit-types/stats'; import { type Fr, type Gas, type GlobalVariables, type PublicCallRequest, type RevertCode } from '@aztec/circuits.js'; @@ -121,7 +120,6 @@ export class PublicTxSimulator { const endStateReference = await this.db.getStateReference(); const avmProvingRequest = context.generateProvingRequest(endStateReference); - const avmCircuitPublicInputs = avmProvingRequest.inputs.output!; const revertCode = context.getFinalRevertCode(); if (!revertCode.isOK()) { @@ -131,13 +129,8 @@ export class PublicTxSimulator { // FIXME: we shouldn't need to directly modify worldStateDb here! await this.worldStateDB.removeNewContracts(tx); // FIXME(dbanks12): should not be changing immutable tx - tx.filterRevertedLogs( - tx.data.forPublic!.nonRevertibleAccumulatedData, - avmCircuitPublicInputs.accumulatedData.unencryptedLogsHashes, - ); + tx.filterRevertedLogs(tx.data.forPublic!.nonRevertibleAccumulatedData); } - // FIXME(dbanks12): should not be changing immutable tx - tx.unencryptedLogs.addFunctionLogs([new UnencryptedFunctionL2Logs(context.trace.getUnencryptedLogs())]); return { avmProvingRequest, diff --git a/yarn-project/simulator/src/public/side_effect_trace_interface.ts b/yarn-project/simulator/src/public/side_effect_trace_interface.ts index a08aa391d13..b4230efe0d0 100644 --- a/yarn-project/simulator/src/public/side_effect_trace_interface.ts +++ b/yarn-project/simulator/src/public/side_effect_trace_interface.ts @@ -1,10 +1,10 @@ -import { type UnencryptedL2Log } from '@aztec/circuit-types'; import { type ContractClassIdPreimage, type Gas, type NullifierLeafPreimage, type PublicCallRequest, type PublicDataTreeLeafPreimage, + type PublicLog, type SerializableContractInstance, } from '@aztec/circuits.js'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; @@ -63,7 +63,7 @@ export interface PublicSideEffectTraceInterface { path?: Fr[], ): void; traceNewL2ToL1Message(contractAddress: AztecAddress, recipient: Fr, content: Fr): void; - traceUnencryptedLog(contractAddress: AztecAddress, log: Fr[]): void; + tracePublicLog(contractAddress: AztecAddress, log: Fr[]): void; traceGetContractInstance( contractAddress: AztecAddress, exists: boolean, @@ -106,5 +106,5 @@ export interface PublicSideEffectTraceInterface { /** Function name for logging */ functionName: string, ): PublicFunctionCallResult; - getUnencryptedLogs(): UnencryptedL2Log[]; + getPublicLogs(): PublicLog[]; } diff --git a/yarn-project/txe/src/node/txe_node.ts b/yarn-project/txe/src/node/txe_node.ts index 458a42db182..03fdbb1c715 100644 --- a/yarn-project/txe/src/node/txe_node.ts +++ b/yarn-project/txe/src/node/txe_node.ts @@ -2,7 +2,8 @@ import { createLogger } from '@aztec/aztec.js'; import { type AztecNode, type EpochProofQuote, - type GetUnencryptedLogsResponse, + type GetContractClassLogsResponse, + type GetPublicLogsResponse, type InBlock, type L2Block, L2BlockHash, @@ -22,7 +23,6 @@ import { TxReceipt, TxScopedL2Log, type TxValidationResult, - type UnencryptedL2Log, } from '@aztec/circuit-types'; import { type ARCHIVE_HEIGHT, @@ -36,8 +36,10 @@ import { type NULLIFIER_TREE_HEIGHT, type NodeInfo, type PUBLIC_DATA_TREE_HEIGHT, + PUBLIC_LOG_DATA_SIZE_IN_FIELDS, type PrivateLog, type ProtocolContractAddresses, + type PublicLog, } from '@aztec/circuits.js'; import { type L1ContractAddresses } from '@aztec/ethereum'; import { poseidon2Hash } from '@aztec/foundation/crypto'; @@ -192,45 +194,48 @@ export class TXENode implements AztecNode { /** * Adds public logs to the txe node, given a block * @param blockNumber - The block number at which to add the public logs. - * @param privateLogs - The unencrypted logs to be added. - */ - addPublicLogsByTags(blockNumber: number, unencryptedLogs: UnencryptedL2Log[]) { - unencryptedLogs.forEach(log => { - if (log.data.length < 32 * 33) { - // TODO remove when #9835 and #9836 are fixed - this.#logger.warn(`Skipping unencrypted log with insufficient data length: ${log.data.length}`); + * @param publicLogs - The public logs to be added. + */ + addPublicLogsByTags(blockNumber: number, publicLogs: PublicLog[]) { + publicLogs.forEach(log => { + // Check that each log stores 3 lengths in its first field. If not, it's not a tagged log: + const firstFieldBuf = log.log[0].toBuffer(); + if ( + !firstFieldBuf.subarray(0, 24).equals(Buffer.alloc(24)) || + firstFieldBuf[26] !== 0 || + firstFieldBuf[29] !== 0 + ) { + // See parseLogFromPublic - the first field of a tagged log is 8 bytes structured: + // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]] + this.#logger.warn(`Skipping public log with invalid first field: ${log.log[0]}`); return; } - try { - // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields. - // This means that for every 32 bytes of payload, we only have 1 byte of data. - // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32. - const correctedBuffer = Buffer.alloc(32); - const initialOffset = 32; - for (let i = 0; i < 32; i++) { - const byte = Fr.fromBuffer(log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset)).toNumber(); - correctedBuffer.writeUInt8(byte, i); - } - const tag = new Fr(correctedBuffer); - - this.#logger.verbose( - `Found tagged unencrypted log with tag ${tag.toString()} in block ${this.getBlockNumber()}`, - ); - - const currentLogs = this.#logsByTags.get(tag.toString()) ?? []; - const scopedLog = new TxScopedL2Log( - new TxHash(new Fr(blockNumber)), - this.#noteIndex, - blockNumber, - true, - log.toBuffer(), - ); - - currentLogs.push(scopedLog); - this.#logsByTags.set(tag.toString(), currentLogs); - } catch (err) { - this.#logger.warn(`Failed to add tagged log to store: ${err}`); + // Check that the length values line up with the log contents + const publicValuesLength = firstFieldBuf.subarray(-8).readUint16BE(); + const privateValuesLength = firstFieldBuf.subarray(-8).readUint16BE(3); + // Add 1 for the first field holding lengths + const totalLogLength = 1 + publicValuesLength + privateValuesLength; + // Note that zeroes can be valid log values, so we can only assert that we do not go over the given length + if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find(f => !f.isZero())) { + this.#logger.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`); + return; } + // The first elt stores lengths => tag is in fields[1] + const tag = log.log[1]; + + this.#logger.verbose(`Found tagged public log with tag ${tag.toString()} in block ${this.getBlockNumber()}`); + + const currentLogs = this.#logsByTags.get(tag.toString()) ?? []; + const scopedLog = new TxScopedL2Log( + new TxHash(new Fr(blockNumber)), + this.#noteIndex, + blockNumber, + true, + log.toBuffer(), + ); + + currentLogs.push(scopedLog); + this.#logsByTags.set(tag.toString(), currentLogs); }); } /** @@ -497,12 +502,12 @@ export class TXENode implements AztecNode { } /** - * Gets unencrypted logs based on the provided filter. + * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(_filter: LogFilter): Promise { - throw new Error('TXE Node method getUnencryptedLogs not implemented'); + getPublicLogs(_filter: LogFilter): Promise { + throw new Error('TXE Node method getPublicLogs not implemented'); } /** @@ -510,7 +515,7 @@ export class TXENode implements AztecNode { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getContractClassLogs(_filter: LogFilter): Promise { + getContractClassLogs(_filter: LogFilter): Promise { throw new Error('TXE Node method getContractClassLogs not implemented'); } diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index b338e756b65..99293a325c2 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -35,6 +35,7 @@ import { PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, type PublicDataWrite, + type PublicLog, computeContractClassId, computeTaggingSecretPoint, deriveKeys, @@ -107,7 +108,7 @@ export class TXE implements TypedOracle { private uniqueNoteHashesFromPublic: Fr[] = []; private siloedNullifiersFromPublic: Fr[] = []; private privateLogs: PrivateLog[] = []; - private publicLogs: UnencryptedL2Log[] = []; + private publicLogs: PublicLog[] = []; private committedBlocks = new Set(); @@ -324,26 +325,13 @@ export class TXE implements TypedOracle { this.privateLogs.push(...privateLogs); } - addPublicLogs(logs: UnencryptedL2Log[]) { + addPublicLogs(logs: PublicLog[]) { logs.forEach(log => { - if (log.data.length < 32 * 33) { - // TODO remove when #9835 and #9836 are fixed - this.logger.warn(`Skipping unencrypted log with insufficient data length: ${log.data.length}`); - return; - } try { - // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields. - // This means that for every 32 bytes of payload, we only have 1 byte of data. - // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32. - const correctedBuffer = Buffer.alloc(32); - const initialOffset = 32; - for (let i = 0; i < 32; i++) { - const byte = Fr.fromBuffer(log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset)).toNumber(); - correctedBuffer.writeUInt8(byte, i); - } - const tag = new Fr(correctedBuffer); - - this.logger.verbose(`Found tagged unencrypted log with tag ${tag.toString()} in block ${this.blockNumber}`); + // The first elt stores lengths => tag is in fields[1] + const tag = log.log[1]; + + this.logger.verbose(`Found tagged public log with tag ${tag.toString()} in block ${this.blockNumber}`); this.publicLogs.push(log); } catch (err) { this.logger.warn(`Failed to add tagged log to store: ${err}`); @@ -847,7 +835,7 @@ export class TXE implements TypedOracle { const result = await simulator.simulate(tx); - this.addPublicLogs(tx.unencryptedLogs.unrollLogs()); + this.addPublicLogs(result.avmProvingRequest.inputs.publicInputs.publicLogs); return Promise.resolve(result); }