diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp index 672c49fa7081..e16d8b738e12 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp @@ -27,6 +27,14 @@ template struct RootRollupInputs { std::array new_historic_private_data_tree_root_sibling_path; std::array new_historic_contract_tree_root_sibling_path; + // inputs required to process l1 to l2 messages + std::array l1_to_l2_messages; + std::array new_l1_to_l2_message_tree_root_sibling_path; + std::array new_historic_l1_to_l2_message_roots_tree_sibling_path; + + AppendOnlyTreeSnapshot start_l1_to_l2_message_tree_snapshot; + AppendOnlyTreeSnapshot start_historic_tree_l1_to_l2_message_tree_roots_snapshot; + bool operator==(RootRollupInputs const&) const = default; }; @@ -37,6 +45,11 @@ template void read(uint8_t const*& it, RootRollupInputs& obj read(it, obj.previous_rollup_data); read(it, obj.new_historic_private_data_tree_root_sibling_path); read(it, obj.new_historic_contract_tree_root_sibling_path); + read(it, obj.l1_to_l2_messages); + read(it, obj.new_l1_to_l2_message_tree_root_sibling_path); + read(it, obj.new_historic_l1_to_l2_message_roots_tree_sibling_path); + read(it, obj.start_l1_to_l2_message_tree_snapshot); + read(it, obj.start_historic_tree_l1_to_l2_message_tree_roots_snapshot); }; template void write(std::vector& buf, RootRollupInputs const& obj) @@ -46,6 +59,11 @@ template void write(std::vector& buf, RootRollupInputs std::ostream& operator<<(std::ostream& os, RootRollupInputs const& obj) @@ -53,7 +71,15 @@ template std::ostream& operator<<(std::ostream& os, RootRollupInp return os << "previous_rollup_data: " << obj.previous_rollup_data << "\n" << "new_historic_private_data_tree_roots: " << obj.new_historic_private_data_tree_root_sibling_path << "\n" - << "new_historic_contract_tree_roots: " << obj.new_historic_contract_tree_root_sibling_path << "\n"; + << "new_historic_contract_tree_roots: " << obj.new_historic_contract_tree_root_sibling_path << "\n" + << "new_l1_to_l2_messages: " << obj.l1_to_l2_messages << "\n" + << "new_l1_to_l2_message_tree_root_sibling_path: " << obj.new_l1_to_l2_message_tree_root_sibling_path + << "\n" + << "new_historic_l1_to_l2_message_roots_tree_sibling_path: " + << obj.new_historic_l1_to_l2_message_roots_tree_sibling_path << "\n" + << "start_l1_to_l2_message_tree_snapshot: " << obj.start_l1_to_l2_message_tree_snapshot << "\n" + << "start_historic_tree_l1_to_l2_message_tree_roots_snapshot: " + << obj.start_historic_tree_l1_to_l2_message_tree_roots_snapshot << "\n"; } } // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp index a2d1b560b1f4..5aca0ad21a14 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp @@ -15,6 +15,7 @@ namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; + template struct RootRollupPublicInputs { using fr = typename NCT::fr; using AggregationObject = typename NCT::AggregationObject; @@ -40,7 +41,14 @@ template struct RootRollupPublicInputs { AppendOnlyTreeSnapshot start_tree_of_historic_contract_tree_roots_snapshot; AppendOnlyTreeSnapshot end_tree_of_historic_contract_tree_roots_snapshot; + AppendOnlyTreeSnapshot start_l1_to_l2_messages_tree_snapshot; + AppendOnlyTreeSnapshot end_l1_to_l2_messages_tree_snapshot; + + AppendOnlyTreeSnapshot start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot; + AppendOnlyTreeSnapshot end_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot; + std::array calldata_hash; + std::array l1_to_l2_messages_hash; bool operator==(RootRollupPublicInputs const&) const = default; @@ -53,11 +61,15 @@ template struct RootRollupPublicInputs { write(buf, start_contract_tree_snapshot); write(buf, start_tree_of_historic_private_data_tree_roots_snapshot); write(buf, start_tree_of_historic_contract_tree_roots_snapshot); + write(buf, start_l1_to_l2_messages_tree_snapshot); + write(buf, start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot); write(buf, end_private_data_tree_snapshot); write(buf, end_nullifier_tree_snapshot); write(buf, end_contract_tree_snapshot); write(buf, end_tree_of_historic_private_data_tree_roots_snapshot); write(buf, end_tree_of_historic_contract_tree_roots_snapshot); + write(buf, end_l1_to_l2_messages_tree_snapshot); + write(buf, end_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot); // Stitching calldata hash together auto high_buffer = calldata_hash[0].to_buffer(); @@ -70,6 +82,17 @@ template struct RootRollupPublicInputs { buf.push_back(low_buffer[16 + i]); } + // Stitch l1_to_l2_messages_hash + auto high_buffer_m = l1_to_l2_messages_hash[0].to_buffer(); + auto low_buffer_m = l1_to_l2_messages_hash[1].to_buffer(); + + for (uint8_t i = 0; i < 16; i++) { + buf.push_back(high_buffer_m[16 + i]); + } + for (uint8_t i = 0; i < 16; i++) { + buf.push_back(low_buffer_m[16 + i]); + } + return sha256::sha256_to_field(buf); } }; @@ -91,7 +114,12 @@ template void read(uint8_t const*& it, RootRollupPublicInputs void write(std::vector& buf, RootRollupPublicInputs const& obj) @@ -111,7 +139,12 @@ template void write(std::vector& buf, RootRollupPublicIn write(buf, obj.end_tree_of_historic_private_data_tree_roots_snapshot); write(buf, obj.start_tree_of_historic_contract_tree_roots_snapshot); write(buf, obj.end_tree_of_historic_contract_tree_roots_snapshot); + write(buf, obj.start_l1_to_l2_messages_tree_snapshot); + write(buf, obj.end_l1_to_l2_messages_tree_snapshot); + write(buf, obj.start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot); + write(buf, obj.end_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot); write(buf, obj.calldata_hash); + write(buf, obj.l1_to_l2_messages_hash); }; template std::ostream& operator<<(std::ostream& os, RootRollupPublicInputs const& obj) @@ -133,7 +166,15 @@ template std::ostream& operator<<(std::ostream& os, RootRollupPub << obj.start_tree_of_historic_contract_tree_roots_snapshot << "\n" << "end_tree_of_historic_contract_tree_roots_snapshot: " << obj.end_tree_of_historic_contract_tree_roots_snapshot << "\n" - << "calldata_hash: " << obj.calldata_hash << "\n"; + << "start_l1_to_l2_messages_tree_snapshot: " << obj.start_l1_to_l2_messages_tree_snapshot << "\n" + << "end_l1_tol2_messages_tree_snapshot: " << obj.end_l1_to_l2_messages_tree_snapshot << "\n" + << "start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot: " + << obj.start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot << "\n" + << "end_tree_of_historic_l1_tol2_messages_tree_roots_snapshot: " + << obj.end_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot << "\n" + << "calldata_hash: " << obj.calldata_hash << "\n" + << "l1_to_l2_messages_hash: " << obj.l1_to_l2_messages_hash << "\n"; + ; }; } // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp index 6cf0e9612179..926f16779b84 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp @@ -400,7 +400,7 @@ AppendOnlySnapshot check_nullifier_tree_non_membership_and_insert_to_tree(DummyC } // Check that the new subtree is to be inserted at the next location, and is empty currently - const auto empty_nullifier_subtree_root = calculate_empty_tree_root(NULLIFIER_SUBTREE_DEPTH); + const auto empty_nullifier_subtree_root = components::calculate_empty_tree_root(NULLIFIER_SUBTREE_DEPTH); auto leafIndexNullifierSubtreeDepth = baseRollupInputs.start_nullifier_tree_snapshot.next_available_leaf_index >> NULLIFIER_SUBTREE_DEPTH; check_membership(composer, @@ -541,7 +541,7 @@ BaseOrMergeRollupPublicInputs base_rollup_circuit(DummyComposer& composer, BaseR NT::fr const commitments_tree_subroot = calculate_commitments_subtree(composer, baseRollupInputs); // Insert commitment subtrees: - const auto empty_commitments_subtree_root = calculate_empty_tree_root(PRIVATE_DATA_SUBTREE_DEPTH); + const auto empty_commitments_subtree_root = components::calculate_empty_tree_root(PRIVATE_DATA_SUBTREE_DEPTH); auto end_private_data_tree_snapshot = components::insert_subtree_to_snapshot_tree(composer, baseRollupInputs.start_private_data_tree_snapshot, @@ -552,7 +552,7 @@ BaseOrMergeRollupPublicInputs base_rollup_circuit(DummyComposer& composer, BaseR "empty commitment subtree membership check"); // Insert contract subtrees: - const auto empty_contracts_subtree_root = calculate_empty_tree_root(CONTRACT_SUBTREE_DEPTH); + const auto empty_contracts_subtree_root = components::calculate_empty_tree_root(CONTRACT_SUBTREE_DEPTH); auto end_contract_tree_snapshot = components::insert_subtree_to_snapshot_tree(composer, baseRollupInputs.start_contract_tree_snapshot, diff --git a/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp b/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp index 8f776438660d..48d2b3d84c40 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp @@ -8,6 +8,7 @@ #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/stdlib/hash/pedersen/pedersen.hpp" +#include "barretenberg/stdlib/merkle_tree/memory_tree.hpp" #include #include @@ -18,6 +19,18 @@ namespace aztec3::circuits::rollup::components { +/** + * @brief Get the root of an empty tree of a given depth + * + * @param depth + * @return NT::fr + */ +NT::fr calculate_empty_tree_root(const size_t depth) +{ + stdlib::merkle_tree::MemoryTree const empty_tree = stdlib::merkle_tree::MemoryTree(depth); + return empty_tree.root(); +} + /** * @brief Create an aggregation object for the proofs that are provided * - We add points P0 for each of our proofs diff --git a/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp b/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp index f6df9f8a8a7c..42074456b1e0 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp @@ -8,6 +8,7 @@ using aztec3::circuits::check_membership; using aztec3::circuits::root_from_sibling_path; namespace aztec3::circuits::rollup::components { +NT::fr calculate_empty_tree_root(size_t depth); std::array compute_calldata_hash(std::array, 2> previous_rollup_data); void assert_prev_rollups_follow_on_from_each_other(DummyComposer& composer, BaseOrMergeRollupPublicInputs const& left, diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp index ed2dfa6ce73a..ecef5951bea2 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp @@ -54,7 +54,9 @@ using aztec3::circuits::abis::PreviousKernelData; // using aztec3::circuits::mock::mock_circuit; +using aztec3::circuits::rollup::test_utils::utils::compare_field_hash_to_expected; using aztec3::circuits::rollup::test_utils::utils::get_empty_kernel; +using aztec3::circuits::rollup::test_utils::utils::get_empty_l1_to_l2_messages; using aztec3::circuits::rollup::test_utils::utils::get_root_rollup_inputs; using aztec3::circuits::rollup::test_utils::utils::set_kernel_commitments; // using aztec3::circuits::mock::mock_kernel_inputs; @@ -71,7 +73,7 @@ using aztec3::circuits::rollup::native_root_rollup::RootRollupPublicInputs; using aztec3::circuits::abis::NewContractData; -using MemoryTree = proof_system::plonk::stdlib::merkle_tree::MemoryTree; +using MemoryTree = stdlib::merkle_tree::MemoryTree; using KernelData = aztec3::circuits::abis::PreviousKernelData; } // namespace @@ -139,8 +141,11 @@ class root_rollup_tests : public ::testing::Test { } }; -TEST_F(root_rollup_tests, native_calldata_hash_empty_blocks) +TEST_F(root_rollup_tests, native_check_block_hashes_empty_blocks) { + MemoryTree const data_tree = MemoryTree(PRIVATE_DATA_TREE_HEIGHT); + + // calculate calldata hash std::vector const zero_bytes_vec(704, 0); auto call_data_hash_inner = sha256::sha256(zero_bytes_vec); @@ -152,31 +157,33 @@ TEST_F(root_rollup_tests, native_calldata_hash_empty_blocks) std::vector const calldata_hash_input_bytes_vec(hash_input.begin(), hash_input.end()); - auto hash = sha256::sha256(calldata_hash_input_bytes_vec); + auto calldata_hash = sha256::sha256(calldata_hash_input_bytes_vec); + + // get messages + std::array const l1_to_l2_messages = get_empty_l1_to_l2_messages(); + + // hash messages + std::vector const messages_hash_input_bytes_vec(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 32, 0); + auto messages_hash = sha256::sha256(messages_hash_input_bytes_vec); utils::DummyComposer composer = utils::DummyComposer(); std::array const kernels = { get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() }; - RootRollupInputs inputs = get_root_rollup_inputs(composer, kernels); + + RootRollupInputs inputs = get_root_rollup_inputs(composer, kernels, l1_to_l2_messages); RootRollupPublicInputs outputs = aztec3::circuits::rollup::native_root_rollup::root_rollup_circuit(composer, inputs); - std::array calldata_hash_fr = outputs.calldata_hash; - auto high_buffer = calldata_hash_fr[0].to_buffer(); - auto low_buffer = calldata_hash_fr[1].to_buffer(); + // check calldata hash + ASSERT_TRUE(compare_field_hash_to_expected(outputs.calldata_hash, calldata_hash)); + // Check messages hash + ASSERT_TRUE(compare_field_hash_to_expected(outputs.l1_to_l2_messages_hash, messages_hash)); - std::array calldata_hash; - for (uint8_t i = 0; i < 16; ++i) { - calldata_hash[i] = high_buffer[16 + i]; - calldata_hash[16 + i] = low_buffer[16 + i]; - } - - ASSERT_EQ(hash, calldata_hash); EXPECT_FALSE(composer.failed()); // Expected hash of public inputs for an empty L2 block. Also used in the contract tests. - fr const expected_hash = uint256_t("0013b2202a3e48b039cda7eef0976060d86e610d77fc9bb8cd5b0f1b561df48c"); + fr const expected_hash = uint256_t("11840efc30e9fcbdd0aae30da2a5b441132420b4f0cc4ffd6bdc41888845f775"); ASSERT_EQ(outputs.hash(), expected_hash); run_cbind(inputs, outputs, true); @@ -190,14 +197,18 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) MemoryTree contract_tree = MemoryTree(CONTRACT_TREE_HEIGHT); MemoryTree historic_data_tree = MemoryTree(PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT); MemoryTree historic_contract_tree = MemoryTree(CONTRACT_TREE_ROOTS_TREE_HEIGHT); + MemoryTree l1_to_l2_messages_tree = MemoryTree(L1_TO_L2_MSG_TREE_HEIGHT); + MemoryTree historic_l1_to_l2_tree = MemoryTree(L1_TO_L2_MSG_TREE_ROOTS_TREE_HEIGHT); // Historic trees are initialised with an empty root at position 0. historic_data_tree.update_element(0, data_tree.root()); historic_contract_tree.update_element(0, contract_tree.root()); + historic_l1_to_l2_tree.update_element(0, l1_to_l2_messages_tree.root()); std::array kernels = { get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() }; + std::array l1_to_l2_messages = get_empty_l1_to_l2_messages(); // Create commitments for (uint8_t kernel_j = 0; kernel_j < 4; kernel_j++) { @@ -230,24 +241,41 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) contract_tree.update_element(2, contract_leaf); kernels[2].public_inputs.end.new_contracts[0] = new_contract; - // The start historic data snapshot + // l1 to l2 messages snapshot + AppendOnlyTreeSnapshot const start_l1_to_l2_messages_tree_snapshot = { .root = l1_to_l2_messages_tree.root(), + .next_available_leaf_index = 0 }; + + // The start historic data snapshots AppendOnlyTreeSnapshot const start_historic_data_tree_snapshot = { .root = historic_data_tree.root(), .next_available_leaf_index = 1 }; AppendOnlyTreeSnapshot const start_historic_contract_tree_snapshot = { .root = historic_contract_tree.root(), .next_available_leaf_index = 1 }; + AppendOnlyTreeSnapshot const start_historic_l1_to_l2_tree_snapshot = { .root = historic_l1_to_l2_tree.root(), + .next_available_leaf_index = 1 }; + + // Create 16 empty l1 to l2 messages, and update the l1_to_l2 messages tree + for (size_t i = 0; i < l1_to_l2_messages.size(); i++) { + l1_to_l2_messages_tree.update_element(i, l1_to_l2_messages[i]); + } // Insert the newest data root into the historic tree historic_data_tree.update_element(1, data_tree.root()); historic_contract_tree.update_element(1, contract_tree.root()); + historic_l1_to_l2_tree.update_element(1, l1_to_l2_messages_tree.root()); // Compute the end snapshot AppendOnlyTreeSnapshot const end_historic_data_tree_snapshot = { .root = historic_data_tree.root(), .next_available_leaf_index = 2 }; AppendOnlyTreeSnapshot const end_historic_contract_tree_snapshot = { .root = historic_contract_tree.root(), .next_available_leaf_index = 2 }; + AppendOnlyTreeSnapshot const end_historic_l1_to_l2_tree_snapshot = { .root = historic_l1_to_l2_tree.root(), + .next_available_leaf_index = 2 }; + AppendOnlyTreeSnapshot const end_l1_to_l2_messages_tree_snapshot = { .root = l1_to_l2_messages_tree.root(), + .next_available_leaf_index = + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP }; - RootRollupInputs rootRollupInputs = get_root_rollup_inputs(composer, kernels); - RootRollupPublicInputs const outputs = + RootRollupInputs rootRollupInputs = get_root_rollup_inputs(composer, kernels, l1_to_l2_messages); + RootRollupPublicInputs outputs = aztec3::circuits::rollup::native_root_rollup::root_rollup_circuit(composer, rootRollupInputs); // Check private data trees @@ -286,7 +314,18 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) ASSERT_EQ(outputs.start_tree_of_historic_contract_tree_roots_snapshot, start_historic_contract_tree_snapshot); ASSERT_EQ(outputs.end_tree_of_historic_contract_tree_roots_snapshot, end_historic_contract_tree_snapshot); + // Check historic l1 to l2 messages trees + ASSERT_EQ(outputs.start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot, + start_historic_l1_to_l2_tree_snapshot); + ASSERT_EQ(outputs.end_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot, end_historic_l1_to_l2_tree_snapshot); + + // Check l1 to l2 messages trees + ASSERT_EQ(outputs.start_l1_to_l2_messages_tree_snapshot, start_l1_to_l2_messages_tree_snapshot); + ASSERT_EQ(outputs.end_l1_to_l2_messages_tree_snapshot, end_l1_to_l2_messages_tree_snapshot); + EXPECT_FALSE(composer.failed()); + + run_cbind(rootRollupInputs, outputs, true); } } // namespace aztec3::circuits::rollup::root::native_root_rollup_circuit \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp b/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp index 2a15f32de12e..efb914db4222 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp @@ -6,12 +6,12 @@ #include "aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp" #include "aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp" #include "aztec3/utils/dummy_composer.hpp" -#include #include #include #include #include +#include "barretenberg/stdlib/merkle_tree/memory_tree.hpp" #include namespace aztec3::circuits::rollup::native_root_rollup { @@ -26,4 +26,6 @@ using RootRollupPublicInputs = abis::RootRollupPublicInputs; using Aggregator = aztec3::circuits::recursion::Aggregator; -} // namespace aztec3::circuits::rollup::native_root_rollup \ No newline at end of file +using MerkleTree = stdlib::merkle_tree::MemoryTree; + +} // namespace aztec3::circuits::rollup::native_root_rollup diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp index 64e0bd981f37..536f805f70a9 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp @@ -28,6 +28,55 @@ namespace aztec3::circuits::rollup::native_root_rollup { // Access Native types through NT namespace +/** + * @brief Calculates the messages subtree from the leaves array + * @param leaves + * @return root + */ +NT::fr calculate_subtree(std::array leaves) +{ + MerkleTree merkle_tree = MerkleTree(L1_TO_L2_MSG_SUBTREE_DEPTH); + + for (size_t i = 0; i < NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP; i++) { + merkle_tree.update_element(i, leaves[i]); + } + return merkle_tree.root(); +} + +/** + * @brief Computes the messages hash from the leaves array + * @param leaves + * @param return - hash split into two field elements + */ +std::array compute_messages_hash(std::array leaves) +{ + // convert vector of field elements into uint_8 + std::array messages_hash_input_bytes; + for (size_t i = 0; i < NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP; i++) { + auto bytes = leaves[i].to_buffer(); + for (size_t j = 0; j < 32; j++) { + messages_hash_input_bytes[i * 32 + j] = bytes[j]; + } + } + + std::vector const messages_hash_input_bytes_vec(messages_hash_input_bytes.begin(), + messages_hash_input_bytes.end()); + auto h = sha256::sha256(messages_hash_input_bytes_vec); + + std::array buf_1; + std::array buf_2; + for (uint8_t i = 0; i < 16; i++) { + buf_1[i] = 0; + buf_1[16 + i] = h[i]; + buf_2[i] = 0; + buf_2[16 + i] = h[i + 16]; + } + auto high = fr::serialize_from_buffer(buf_1.data()); + auto low = fr::serialize_from_buffer(buf_2.data()); + + return { high, low }; +} + RootRollupPublicInputs root_rollup_circuit(DummyComposer& composer, RootRollupInputs const& rootRollupInputs) { // TODO: Verify the previous rollup proofs @@ -63,6 +112,31 @@ RootRollupPublicInputs root_rollup_circuit(DummyComposer& composer, RootRollupIn 0, "historic contract tree roots insertion"); + // Check correct l1 to l2 tree given + // Compute subtree inserting l1 to l2 messages + auto l1_to_l2_subtree_root = calculate_subtree(rootRollupInputs.l1_to_l2_messages); + + // // Insert subtree into the l1 to l2 data tree + const auto empty_l1_to_l2_subtree_root = components::calculate_empty_tree_root(L1_TO_L2_MSG_SUBTREE_DEPTH); + auto new_l1_to_l2_messages_tree_snapshot = + components::insert_subtree_to_snapshot_tree(composer, + rootRollupInputs.start_l1_to_l2_message_tree_snapshot, + rootRollupInputs.new_l1_to_l2_message_tree_root_sibling_path, + empty_l1_to_l2_subtree_root, + l1_to_l2_subtree_root, + L1_TO_L2_MSG_SUBTREE_INCLUSION_CHECK_DEPTH, + "l1 to l2 message tree insertion"); + + // Update the historic l1 to l2 data tree + auto end_l1_to_l2_data_roots_tree_snapshot = components::insert_subtree_to_snapshot_tree( + composer, + rootRollupInputs.start_historic_tree_l1_to_l2_message_tree_roots_snapshot, + rootRollupInputs.new_historic_l1_to_l2_message_roots_tree_sibling_path, + fr::zero(), + new_l1_to_l2_messages_tree_snapshot.root, + 0, + "historic l1 to l2 message tree roots insertion"); + RootRollupPublicInputs public_inputs = { .end_aggregation_object = aggregation_object, .start_private_data_tree_snapshot = left.start_private_data_tree_snapshot, @@ -79,7 +153,13 @@ RootRollupPublicInputs root_rollup_circuit(DummyComposer& composer, RootRollupIn .start_tree_of_historic_contract_tree_roots_snapshot = left.constants.start_tree_of_historic_contract_tree_roots_snapshot, .end_tree_of_historic_contract_tree_roots_snapshot = end_tree_of_historic_contract_tree_roots_snapshot, + .start_l1_to_l2_messages_tree_snapshot = rootRollupInputs.start_l1_to_l2_message_tree_snapshot, + .end_l1_to_l2_messages_tree_snapshot = new_l1_to_l2_messages_tree_snapshot, + .start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot = + rootRollupInputs.start_historic_tree_l1_to_l2_message_tree_roots_snapshot, + .end_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot = end_l1_to_l2_data_roots_tree_snapshot, .calldata_hash = components::compute_calldata_hash(rootRollupInputs.previous_rollup_data), + .l1_to_l2_messages_hash = compute_messages_hash(rootRollupInputs.l1_to_l2_messages) }; return public_inputs; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp index ac3aa2ece62b..714f8eca986e 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp @@ -56,6 +56,12 @@ KernelData get_empty_kernel() return dummy_previous_kernel(); } +std::array get_empty_l1_to_l2_messages() +{ + std::array l1_to_l2_messages = { 0 }; + return l1_to_l2_messages; +} + void set_kernel_nullifiers(KernelData& kernel_data, std::array new_nullifiers) { for (size_t i = 0; i < KERNEL_NEW_NULLIFIERS_LENGTH; i++) { @@ -298,7 +304,9 @@ MergeRollupInputs get_merge_rollup_inputs(utils::DummyComposer& composer, std::a return inputs; } -RootRollupInputs get_root_rollup_inputs(utils::DummyComposer& composer, std::array kernel_data) +RootRollupInputs get_root_rollup_inputs(utils::DummyComposer& composer, + std::array kernel_data, + std::array l1_to_l2_messages) { MerkleTree historic_private_data_tree = MerkleTree(PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT); MerkleTree historic_contract_tree = MerkleTree(CONTRACT_TREE_ROOTS_TREE_HEIGHT); @@ -306,21 +314,42 @@ RootRollupInputs get_root_rollup_inputs(utils::DummyComposer& composer, std::arr MerkleTree const private_data_tree = MerkleTree(PRIVATE_DATA_TREE_HEIGHT); MerkleTree const contract_tree = MerkleTree(CONTRACT_TREE_HEIGHT); + MerkleTree l1_to_l2_msg_tree = MerkleTree(L1_TO_L2_MSG_TREE_HEIGHT); // Historic trees are initialised with an empty root at position 0. historic_private_data_tree.update_element(0, private_data_tree.root()); historic_contract_tree.update_element(0, contract_tree.root()); - historic_l1_to_l2_msg_tree.update_element(0, MerkleTree(L1_TO_L2_MSG_TREE_HEIGHT).root()); + historic_l1_to_l2_msg_tree.update_element(0, l1_to_l2_msg_tree.root()); auto historic_data_sibling_path = get_sibling_path(historic_private_data_tree, 1, 0); auto historic_contract_sibling_path = get_sibling_path(historic_contract_tree, 1, 0); + auto historic_l1_to_l2_msg_sibling_path = + get_sibling_path(historic_l1_to_l2_msg_tree, 1, 0); + auto l1_to_l2_tree_sibling_path = get_sibling_path( + l1_to_l2_msg_tree, 0, L1_TO_L2_MSG_SUBTREE_INCLUSION_CHECK_DEPTH); + + // l1_to_l2_message tree snapshots + AppendOnlyTreeSnapshot const start_l1_to_l2_msg_tree_snapshot = { + .root = l1_to_l2_msg_tree.root(), + .next_available_leaf_index = 0, + }; + AppendOnlyTreeSnapshot const start_historic_tree_l1_to_l2_message_tree_roots_snapshot = { + .root = historic_l1_to_l2_msg_tree.root(), + .next_available_leaf_index = 1, + }; RootRollupInputs rootRollupInputs = { .previous_rollup_data = get_previous_rollup_data(composer, std::move(kernel_data)), .new_historic_private_data_tree_root_sibling_path = historic_data_sibling_path, .new_historic_contract_tree_root_sibling_path = historic_contract_sibling_path, + .l1_to_l2_messages = l1_to_l2_messages, + .new_l1_to_l2_message_tree_root_sibling_path = l1_to_l2_tree_sibling_path, + .new_historic_l1_to_l2_message_roots_tree_sibling_path = historic_l1_to_l2_msg_sibling_path, + .start_l1_to_l2_message_tree_snapshot = start_l1_to_l2_msg_tree_snapshot, + .start_historic_tree_l1_to_l2_message_tree_roots_snapshot = + start_historic_tree_l1_to_l2_message_tree_roots_snapshot, }; return rootRollupInputs; } @@ -472,4 +501,27 @@ nullifier_tree_testing_values generate_nullifier_tree_testing_values_explicit( return std::make_tuple(rollupInputs, nullifier_tree_start_snapshot, nullifier_tree_end_snapshot); } -} // namespace aztec3::circuits::rollup::test_utils::utils \ No newline at end of file +/** + * @brief Compares a hash calculated within a circuit (made up of two field elements) against + * one generated natively, (32 bytes) and checks if they match + * + * @param field_hash + * @param expected_hash + * @return true + * @return false + */ +bool compare_field_hash_to_expected(std::array field_hash, std::array expected_hash) +{ + auto high_buffer = field_hash[0].to_buffer(); + auto low_buffer = field_hash[1].to_buffer(); + + std::array field_expanded_hash; + for (uint8_t i = 0; i < 16; ++i) { + field_expanded_hash[i] = high_buffer[16 + i]; + field_expanded_hash[16 + i] = low_buffer[16 + i]; + } + + return expected_hash == field_expanded_hash; +} + +} // namespace aztec3::circuits::rollup::test_utils::utils diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp index 525bf17192e9..dd2a7b8c3f9d 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp @@ -3,6 +3,7 @@ #include "nullifier_tree_testing_harness.hpp" #include "aztec3/circuits/abis/public_data_transition.hpp" +#include "aztec3/constants.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" @@ -88,6 +89,8 @@ nullifier_tree_testing_values generate_nullifier_tree_testing_values(BaseRollupI size_t starting_insertion_value, size_t spacing); +std::array get_empty_l1_to_l2_messages(); + nullifier_tree_testing_values generate_nullifier_tree_testing_values( BaseRollupInputs inputs, std::array new_nullifiers, size_t spacing); @@ -95,7 +98,9 @@ NullifierMemoryTreeTestingHarness get_initial_nullifier_tree(const std::vector kernel_data); +RootRollupInputs get_root_rollup_inputs(utils::DummyComposer& composer, + std::array kernel_data, + std::array l1_to_l2_messages); void set_kernel_commitments(KernelData& kernel_data, std::array new_commitments); @@ -120,4 +125,6 @@ inline abis::PublicDataRead make_public_read(fr leaf_index, fr value) }; } -} // namespace aztec3::circuits::rollup::test_utils::utils \ No newline at end of file +bool compare_field_hash_to_expected(std::array field_hash, std::array expected_hash); + +} // namespace aztec3::circuits::rollup::test_utils::utils diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp index edcc1460dc1b..3bf6ed53269e 100644 --- a/circuits/cpp/src/aztec3/constants.hpp +++ b/circuits/cpp/src/aztec3/constants.hpp @@ -43,6 +43,11 @@ constexpr size_t PRIVATE_DATA_SUBTREE_INCLUSION_CHECK_DEPTH = PRIVATE_DATA_TREE_ constexpr size_t NULLIFIER_SUBTREE_DEPTH = 3; constexpr size_t NULLIFIER_SUBTREE_INCLUSION_CHECK_DEPTH = NULLIFIER_TREE_HEIGHT - NULLIFIER_SUBTREE_DEPTH; +// NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP must equal 2^L1_TO_L2_MSG_SUBTREE_DEPTH for subtree insertions. +constexpr size_t L1_TO_L2_MSG_SUBTREE_DEPTH = 4; +constexpr size_t NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; +constexpr size_t L1_TO_L2_MSG_SUBTREE_INCLUSION_CHECK_DEPTH = L1_TO_L2_MSG_TREE_HEIGHT - L1_TO_L2_MSG_SUBTREE_DEPTH; + constexpr size_t PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT = 8; constexpr size_t CONTRACT_TREE_ROOTS_TREE_HEIGHT = 8; constexpr size_t L1_TO_L2_MSG_TREE_ROOTS_TREE_HEIGHT = 8; @@ -50,6 +55,7 @@ constexpr size_t ROLLUP_VK_TREE_HEIGHT = 8; // TODO: update constexpr size_t FUNCTION_SELECTOR_NUM_BYTES = 4; // must be <= 31 + // Enumerate the hash_indices which are used for pedersen hashing // Start from 1 to avoid the default generators. enum GeneratorIndex { diff --git a/l1-contracts/Dockerfile b/l1-contracts/Dockerfile index adbe93a91929..7a963e49c28c 100644 --- a/l1-contracts/Dockerfile +++ b/l1-contracts/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /usr/src/contracts # Install foundry RUN git init -COPY . . +COPY ./scripts/install_foundry.sh ./scripts/install_foundry.sh RUN ./scripts/install_foundry.sh ENV PATH="/usr/src/contracts/.foundry/bin:${PATH}" @@ -17,7 +17,9 @@ RUN forge install --no-commit \ https://github.com/openzeppelin/openzeppelin-contracts ENV MAINNET_RPC_URL='https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c' +COPY . . + # Run build and tests -RUN forge clean && forge build && forge test +RUN forge clean && forge fmt --check && forge build && forge test WORKDIR /usr/src/contracts \ No newline at end of file diff --git a/l1-contracts/README.md b/l1-contracts/README.md index b2e2d07cf75d..1e2e48ee7dfa 100644 --- a/l1-contracts/README.md +++ b/l1-contracts/README.md @@ -1 +1,51 @@ -# Aztec 3 contracts \ No newline at end of file +# L1 Contracts + +This directory contains the Ethereum smart contract that we will be using for progressing the state of the Rollup. + +## Installation +You can install foundry as https://book.getfoundry.sh/ or by running the `./bootstrap.sh` script. + +Alternatively you can use docker instead, it will handle installations and run tests. Simply run `docker build .` from the `l1-contracts` folder. + +## Structure +The `src` folder contain contracts that is to be used by the local developer testnet. It is grouped into 3 catagories: +- `core` contains the required contracts, the bare minimum +- `mock` contains stubs, for now an always true verifier. +- `periphery` stuff that is nice to have, convenience contracts and functions belong in here. + +## Running tests +The tests are located in the `test` folder, and execute two consecutive L2Blocks. The blocks and the values they are checked against is generated using the block builder tests (there also is a typescript test in `l2-block-publisher.test.ts` that tests E2E). The tests are currently limited in functionality as it is mainly decoding happening, but will expand over time to include L1 <-> L2 communication and cross chain applications. + +As mentioned earlier, you can also use docker. If you rerun `docker build .` after changing the contracts, it will use a cache for most values, and rerun your tests in a few seconds. + +## Formatting +We use `forge fmt` to format. But follow a few general guidelines beyond the standard: +- use `_` prefix for function arguments, e.g., + - Don't `function transfer(address to, uint256 amount);` + - Do `function transfer(address _to, uint256 _amount);` +- use `_` prefix for `internal` and `private` functions. + +## Contracts: + +The contracts are in a very early stage, and don't worry about gas costs right now. Instead they prioritise development velocity. + +### Decoder +Job: Extract values from `L2Block` + +The decoder is a core rollup contract which takes the `L2Block` bytes and computes/extracts values required to: +1. keep track of the state +1. perform proof verification + +If the structure of the `L2Block` changes, so should the decoder! + +### Rollup +Job: Keep track of state and perform state transitions. + +It is the job of the rollup contract to store the state of the rollup and progress it when receiving a new L2 block that is built on top of the current state. + +Currently not running any proofs *nor* access control so blocks can be submitted by anyone and can be complete garbage. + +### UnverifiedDataEmitter +Job: Share unverified data on chain. + +For now, this include bytecode for contract deployment, but over time this will be verified for public functions. diff --git a/l1-contracts/src/core/Decoder.sol b/l1-contracts/src/core/Decoder.sol index 950cab912da3..99947884153c 100644 --- a/l1-contracts/src/core/Decoder.sol +++ b/l1-contracts/src/core/Decoder.sol @@ -27,34 +27,45 @@ pragma solidity >=0.8.18; * | 0x94 | 0x20 | startTreeOfHistoricContractTreeRootsSnapshot.root * | 0xb4 | 0x04 | startTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex * | 0xb8 | 0x20 | startPublicDataTreeRoot - * | 0xd8 | 0x20 | endPrivateDataTreeSnapshot.root - * | 0xf8 | 0x04 | endPrivateDataTreeSnapshot.nextAvailableLeafIndex - * | 0xfc | 0x20 | endNullifierTreeSnapshot.root - * | 0x11c | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex - * | 0x120 | 0x20 | endContractTreeSnapshot.root - * | 0x140 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex - * | 0x144 | 0x20 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.root - * | 0x164 | 0x04 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x168 | 0x20 | endTreeOfHistoricContractTreeRootsSnapshot.root - * | 0x188 | 0x04 | endTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x18c | 0x20 | endPublicDataTreeRoot - * | 0x1ac | 0x04 | len(newCommitments) denoted a - * | 0x1b0 | a | newCommitments (each element 32 bytes) - * | 0x1b0 + a | 0x04 | len(newNullifiers) denoted b - * | 0x1b4 + a | b | newNullifiers (each element 32 bytes) - * | 0x1b4 + a + b | 0x04 | len(newPublicDataWrites) denoted c - * | 0x1b8 + a + b | c | newPublicDataWrites (each element 64 bytes) - * | 0x1b8 + a + b + c | 0x04 | len(newContracts) denoted d - * | 0x1bc + a + b + c | v | newContracts (each element 32 bytes) - * | 0x1bc + a + b + c + d | v | newContractData (each element 52 bytes) + * | 0xd8 | 0x20 | startL1ToL2MessagesTreeSnapshot.root + * | 0xf8 | 0x04 | startL1ToL2MessagesTreeSnapshot.nextAvailableLeafIndex + * | 0xfc | 0x20 | startTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.root + * | 0x11c | 0x04 | startTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x120 | 0x20 | endPrivateDataTreeSnapshot.root + * | 0x140 | 0x04 | endPrivateDataTreeSnapshot.nextAvailableLeafIndex + * | 0x144 | 0x20 | endNullifierTreeSnapshot.root + * | 0x164 | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex + * | 0x168 | 0x20 | endContractTreeSnapshot.root + * | 0x188 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex + * | 0x18c | 0x20 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.root + * | 0x1ac | 0x04 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x1b0 | 0x20 | endTreeOfHistoricContractTreeRootsSnapshot.root + * | 0x1d0 | 0x04 | endTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x1d4 | 0x20 | endPublicDataTreeRoot + * | 0x1f4 | 0x20 | endL1ToL2MessagesTreeSnapshot.root + * | 0x214 | 0x04 | endL1ToL2MessagesTreeSnapshot.nextAvailableLeafIndex + * | 0x218 | 0x20 | endTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.root + * | 0x238 | 0x04 | endTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x23c | 0x04 | len(newCommitments) denoted x + * | 0x240 | x | newCommits + * | 0x240 + x | 0x04 | len(newNullifiers) denoted y + * | 0x244 + x | y | newNullifiers + * | 0x244 + a + b | 0x04 | len(newPublicDataWrites) denoted c + * | 0x248 + a + b | c | newPublicDataWrites (each element 64 bytes) + * | 0x248 + a + b + c | 0x04 | len(newContracts) denoted d + * | 0x24c + a + b + c | d | newContracts (each element 32 bytes) + * | 0x24c + a + b + c + d | d | newContractData (each element 52 bytes) + * | 0x24c + a + b + c + d | 0x04 | len(l1ToL2Messages) denoted e + * | 0x250 + a + b + c + d + e| e | l1ToL2Messages * |--- |--- | --- - * TODO: a,b,c,d are number of elements and not bytes, need to be multiplied by the length of the elements. + * TODO: a,b,c,d,e are number of elements and not bytes, need to be multiplied by the length of the elements. */ contract Decoder { uint256 internal constant COMMITMENTS_PER_KERNEL = 4; uint256 internal constant NULLIFIERS_PER_KERNEL = 4; uint256 internal constant PUBLIC_DATA_WRITES_PER_KERNEL = 4; uint256 internal constant CONTRACTS_PER_KERNEL = 1; + uint256 internal constant L1_TO_L2_MESSAGES_PER_ROLLUP = 16; // Prime field order uint256 internal constant P = @@ -82,26 +93,31 @@ contract Decoder { // Note, for startStateHash to match the storage, the l2 block number must be new - 1. // Only jumping 1 block at a time. startStateHash = _computeStateHash(l2BlockNumber - 1, 0x4, _l2Block); - endStateHash = _computeStateHash(l2BlockNumber, 0xd8, _l2Block); + endStateHash = _computeStateHash(l2BlockNumber, 0x120, _l2Block); publicInputHash = _computePublicInputsHash(_l2Block); } /** * Computes a hash of the public inputs from the calldata * @param _l2Block - The L2 block calldata. - * @return sha256(header[0x4: 0x1ac], diffRoot) + * @return sha256(header[0x4: 0x23c], diffRoot, l1Tol2MessagesHash) */ function _computePublicInputsHash(bytes calldata _l2Block) internal pure returns (bytes32) { - // header size - block number size + one value for the diffRoot - uint256 size = 0x1ac - 0x04 + 0x20; + // header size - block number size + one value for the diffRoot + one value for l1ToL2MessagesHash + uint256 size = 0x23c - 0x04 + 0x20 + 0x20; + + // Compute the public inputs hash bytes memory temp = new bytes(size); assembly { calldatacopy(add(temp, 0x20), add(_l2Block.offset, 0x04), size) } - bytes32 diffRoot = _computeDiffRoot(_l2Block); + // Diff root + (bytes32 diffRoot, bytes32 l1ToL2messagesHash) = _computeDiffRootAndMessagesHash(_l2Block); assembly { - mstore(add(temp, add(0x20, sub(0x1ac, 0x04))), diffRoot) + let endOfTreesData := sub(0x23c, 0x04) + mstore(add(temp, add(0x20, endOfTreesData)), diffRoot) + mstore(add(temp, add(0x40, endOfTreesData)), l1ToL2messagesHash) } return bytes32(uint256(sha256(temp)) % P); @@ -130,7 +146,7 @@ contract Decoder { pure returns (bytes32) { - bytes memory temp = new bytes(0xd8); + bytes memory temp = new bytes(0x120); assembly { mstore8(add(temp, 0x20), shr(24, _l2BlockNumber)) @@ -140,30 +156,45 @@ contract Decoder { } assembly { // Copy header elements (not including block number) for start or end (size 0xd4) - calldatacopy(add(temp, 0x24), add(_l2Block.offset, _offset), 0xd4) + calldatacopy(add(temp, 0x24), add(_l2Block.offset, _offset), 0x11c) } return sha256(temp); } - struct Vars { + struct ArrayLengths { uint256 commitmentCount; uint256 nullifierCount; uint256 dataWritesCount; uint256 contractCount; + uint256 l1Tol2MessagesCount; + } + + struct ArrayOffsets { + uint256 commitmentOffset; + uint256 nullifierOffset; + uint256 publicDataOffset; + uint256 contractOffset; + uint256 contractDataOffset; + uint256 l1ToL2MessagesOffset; } /** * @notice Creates a "diff" tree and compute its root * @param _l2Block - The L2 block calldata. - * @return The root of the "diff" tree */ - function _computeDiffRoot(bytes calldata _l2Block) internal pure returns (bytes32) { + function _computeDiffRootAndMessagesHash(bytes calldata _l2Block) + internal + pure + returns (bytes32, bytes32) + { // Find the lengths of the different inputs - Vars memory vars; + // TOOD: Naming / getting the messages root within this function is a bit weird + ArrayLengths memory lengths; + ArrayOffsets memory offsets; { assembly { - let offset := add(_l2Block.offset, 0x1ac) + let offset := add(_l2Block.offset, 0x23c) let commitmentCount := and(shr(224, calldataload(offset)), 0xffffffff) offset := add(add(offset, 0x4), mul(commitmentCount, 0x20)) let nullifierCount := and(shr(224, calldataload(offset)), 0xffffffff) @@ -171,110 +202,140 @@ contract Decoder { let dataWritesCount := and(shr(224, calldataload(offset)), 0xffffffff) offset := add(add(offset, 0x4), mul(nullifierCount, 0x40)) let contractCount := and(shr(224, calldataload(offset)), 0xffffffff) + offset := add(add(offset, 0x4), mul(contractCount, 0x54)) + let l1Tol2MessagesCount := and(shr(224, calldataload(offset)), 0xffffffff) - // Store it in vars - mstore(vars, commitmentCount) - mstore(add(vars, 0x20), nullifierCount) - mstore(add(vars, 0x40), dataWritesCount) - mstore(add(vars, 0x60), contractCount) + // Store it in lengths + mstore(lengths, commitmentCount) + mstore(add(lengths, 0x20), nullifierCount) + mstore(add(lengths, 0x40), dataWritesCount) + mstore(add(lengths, 0x60), contractCount) + mstore(add(lengths, 0x80), l1Tol2MessagesCount) // currently included to allow optimisation where empty messages are not included in calldata } } bytes32[] memory baseLeafs = new bytes32[]( - vars.commitmentCount / (COMMITMENTS_PER_KERNEL * 2) + lengths.commitmentCount / (COMMITMENTS_PER_KERNEL * 2) ); // Data starts after header. Look at L2 Block Data specification at the top of this file. - uint256 srcCommitmentOffset = 0x1b0; - uint256 srcNullifierOffset = srcCommitmentOffset + 0x4 + vars.commitmentCount * 0x20; - uint256 srcDataOffset = srcNullifierOffset + 0x4 + vars.nullifierCount * 0x20; - uint256 srcContractOffset = srcDataOffset + 0x4 + vars.dataWritesCount * 0x40; - uint256 srcContractDataOffset = srcContractOffset + vars.contractCount * 0x20; - - for (uint256 i = 0; i < baseLeafs.length; i++) { - /** - * Compute the leaf to insert. - * Leaf_i = ( - * newCommitmentsKernel1, - * newCommitmentsKernel2, - * newNullifiersKernel1, - * newNullifiersKernel2, - * newPublicDataWritesKernel1, - * newPublicDataWritesKernel2, - * newContractLeafKernel1, - * newContractLeafKernel2, - * newContractDataKernel1.aztecAddress, - * newContractDataKernel1.ethAddress (padded to 32 bytes) - * newContractDataKernel2.aztecAddress, - * newContractDataKernel2.ethAddress (padded to 32 bytes) - * ); - * Note that we always read data, the l2Block (atm) must therefore include dummy or zero-notes for - * Zero values. - */ - // Create the leaf to contain commitments (8 * 0x20) + nullifiers (8 * 0x20) - // + new public data writes (8 * 0x40) + contract deployments (2 * 0x60) - bytes memory baseLeaf = new bytes(0x4c0); + { + offsets.commitmentOffset = 0x240; + offsets.nullifierOffset = offsets.commitmentOffset + 0x4 + lengths.commitmentCount * 0x20; + offsets.publicDataOffset = offsets.nullifierOffset + 0x4 + lengths.nullifierCount * 0x20; + offsets.contractOffset = offsets.publicDataOffset + 0x4 + lengths.dataWritesCount * 0x40; + offsets.contractDataOffset = offsets.contractOffset + lengths.contractCount * 0x20; + offsets.l1ToL2MessagesOffset = offsets.contractDataOffset + lengths.contractCount * 0x54; - assembly { - let dstOffset := 0x20 - // Adding new commitments - calldatacopy( - add(baseLeaf, dstOffset), add(_l2Block.offset, srcCommitmentOffset), mul(0x08, 0x20) - ) - dstOffset := add(dstOffset, mul(0x08, 0x20)) + for (uint256 i = 0; i < baseLeafs.length; i++) { + /** + * Compute the leaf to insert. + * Leaf_i = ( + * newCommitmentsKernel1, + * newCommitmentsKernel2, + * newNullifiersKernel1, + * newNullifiersKernel2, + * newPublicDataWritesKernel1, + * newPublicDataWritesKernel2, + * newContractLeafKernel1, + * newContractLeafKernel2, + * newContractDataKernel1.aztecAddress, + * newContractDataKernel1.ethAddress (padded to 32 bytes) + * newContractDataKernel2.aztecAddress, + * newContractDataKernel2.ethAddress (padded to 32 bytes) + * ); + * Note that we always read data, the l2Block (atm) must therefore include dummy or zero-notes for + * Zero values. + */ + // Create the leaf to contain commitments (8 * 0x20) + nullifiers (8 * 0x20) + // + new public data writes (8 * 0x40) + contract deployments (2 * 0x60) + bytes memory baseLeaf = new bytes(0x4c0); - // Adding new nullifiers - calldatacopy( - add(baseLeaf, dstOffset), add(_l2Block.offset, srcNullifierOffset), mul(0x08, 0x20) - ) - dstOffset := add(dstOffset, mul(0x08, 0x20)) + assembly { + let dstOffset := 0x20 + // Adding new commitments + calldatacopy( + add(baseLeaf, dstOffset), add(_l2Block.offset, mload(offsets)), mul(0x08, 0x20) + ) + dstOffset := add(dstOffset, mul(0x08, 0x20)) - // Adding new public data writes - calldatacopy(add(baseLeaf, dstOffset), add(_l2Block.offset, srcDataOffset), mul(0x08, 0x40)) - dstOffset := add(dstOffset, mul(0x08, 0x40)) + // Adding new nullifiers + calldatacopy( + add(baseLeaf, dstOffset), + add(_l2Block.offset, mload(add(offsets, 0x20))), + mul(0x08, 0x20) + ) + dstOffset := add(dstOffset, mul(0x08, 0x20)) - // Adding Contract Leafs - calldatacopy( - add(baseLeaf, dstOffset), add(_l2Block.offset, srcContractOffset), mul(2, 0x20) - ) - dstOffset := add(dstOffset, mul(2, 0x20)) + // Adding new public data writes + calldatacopy( + add(baseLeaf, dstOffset), + add(_l2Block.offset, mload(add(offsets, 0x40))), + mul(0x08, 0x40) + ) + dstOffset := add(dstOffset, mul(0x08, 0x40)) - // Kernel1.contract.aztecAddress - calldatacopy(add(baseLeaf, dstOffset), add(_l2Block.offset, srcContractDataOffset), 0x20) - dstOffset := add(dstOffset, 0x20) + // Adding Contract Leafs + calldatacopy( + add(baseLeaf, dstOffset), add(_l2Block.offset, mload(add(offsets, 0x60))), mul(2, 0x20) + ) + dstOffset := add(dstOffset, mul(2, 0x20)) - // Kernel1.contract.ethAddress padded to 32 bytes - // Add 12 (0xc) bytes of padding to the ethAddress - dstOffset := add(dstOffset, 0xc) - calldatacopy( - add(baseLeaf, dstOffset), add(_l2Block.offset, add(srcContractDataOffset, 0x20)), 0x14 - ) - dstOffset := add(dstOffset, 0x20) + // Kernel1.contract.aztecAddress + let contractDataOffset := mload(add(offsets, 0x80)) + calldatacopy(add(baseLeaf, dstOffset), add(_l2Block.offset, contractDataOffset), 0x20) + dstOffset := add(dstOffset, 0x20) - // Kernel2.contract.aztecAddress - calldatacopy( - add(baseLeaf, dstOffset), add(_l2Block.offset, add(srcContractDataOffset, 0x34)), 0x20 - ) - dstOffset := add(dstOffset, 0x20) + // Kernel1.contract.ethAddress padded to 32 bytes + // Add 12 (0xc) bytes of padding to the ethAddress + dstOffset := add(dstOffset, 0xc) + calldatacopy( + add(baseLeaf, dstOffset), add(_l2Block.offset, add(contractDataOffset, 0x20)), 0x14 + ) + dstOffset := add(dstOffset, 0x20) + + // Kernel2.contract.aztecAddress + calldatacopy( + add(baseLeaf, dstOffset), add(_l2Block.offset, add(contractDataOffset, 0x34)), 0x20 + ) + dstOffset := add(dstOffset, 0x20) + + // Kernel2.contract.ethAddress padded to 32 bytes + // Add 12 (0xc) bytes of padding to the ethAddress + dstOffset := add(dstOffset, 0xc) + calldatacopy( + add(baseLeaf, dstOffset), add(_l2Block.offset, add(contractDataOffset, 0x54)), 0x14 + ) + } + + offsets.commitmentOffset += 2 * COMMITMENTS_PER_KERNEL * 0x20; + offsets.nullifierOffset += 2 * NULLIFIERS_PER_KERNEL * 0x20; + offsets.publicDataOffset += 2 * PUBLIC_DATA_WRITES_PER_KERNEL * 0x40; + offsets.contractOffset += 2 * 0x20; + offsets.contractDataOffset += 2 * 0x34; - // Kernel2.contract.ethAddress padded to 32 bytes - // Add 12 (0xc) bytes of padding to the ethAddress - dstOffset := add(dstOffset, 0xc) + baseLeafs[i] = sha256(baseLeaf); + } + } + + bytes32 diffRoot = _computeRoot(baseLeafs); + + bytes32 messagesHash; + { + uint256 messagesHashPreimageSize = 0x20 * L1_TO_L2_MESSAGES_PER_ROLLUP; + bytes memory messagesHashPreimage = new bytes(messagesHashPreimageSize); + assembly { calldatacopy( - add(baseLeaf, dstOffset), add(_l2Block.offset, add(srcContractDataOffset, 0x54)), 0x14 + add(messagesHashPreimage, 0x20), + add(mload(add(offsets, 0xa0)), 20), + messagesHashPreimageSize ) } - srcCommitmentOffset += 2 * COMMITMENTS_PER_KERNEL * 0x20; - srcNullifierOffset += 2 * NULLIFIERS_PER_KERNEL * 0x20; - srcDataOffset += 2 * PUBLIC_DATA_WRITES_PER_KERNEL * 0x40; - srcContractOffset += 2 * 0x20; - srcContractDataOffset += 2 * 0x34; - - baseLeafs[i] = sha256(baseLeaf); + messagesHash = sha256(messagesHashPreimage); } - return _computeRoot(baseLeafs); + return (diffRoot, messagesHash); } /** diff --git a/l1-contracts/test/Decoder.t.sol b/l1-contracts/test/Decoder.t.sol index 19f3d8994dc3..8e2c1f666d59 100644 --- a/l1-contracts/test/Decoder.t.sol +++ b/l1-contracts/test/Decoder.t.sol @@ -13,15 +13,15 @@ contract DecoderTest is Test { DecoderHelper internal helper; bytes block_1 = - hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000082f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd80000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b36b22912aa963f143c490227bd21e7a44338026b2f6a389cb98e82167c3718000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0283622796e1a2fa4718e254eb46d3f4287b05a5aaee35af02a54f2af8362f97000000101f99db4b9ffa5ab637607ad50c7d10ea3352a53478e14354355a02b6a87a7ab1000000181ba22861f1a04d910c399ce20125a7ef53c3a47e0f51fe1d2c179ea83b8da34e0000000415db3dd5c4e4589c0b7a5942f81c11548dda500600adefeb8c49d13481a88e24000000022309e4044d29f2906c728a7d19672aa7d80f3fbc289d4dd6fcab93f1e197b727000000020a20b604e286954cd8b1622dcbda5ef1c4ad6bfd80a81ad80dcff2f5080d5ba00000001000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002010000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020300000000000000000000000000000000000000000000000000000000000002040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008010000000000000000000000000000000000000000000000000000000000000803000000000000000000000000000000000000000000000000000000000000080200000000000000000000000000000000000000000000000000000000000008040000000000000000000000000000000000000000000000000000000000000803000000000000000000000000000000000000000000000000000000000000080500000000000000000000000000000000000000000000000000000000000008040000000000000000000000000000000000000000000000000000000000000806000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041b024f6e2e258ac4fa7b3a0d03f9fa242eee6d884ec85d0efd4beca26a88da2100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006010202020202020202020202020202020202020202000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000082f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd80000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b36b22912aa963f143c490227bd21e7a44338026b2f6a389cb98e82167c3718000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000010283622796e1a2fa4718e254eb46d3f4287b05a5aaee35af02a54f2af8362f97000000101f99db4b9ffa5ab637607ad50c7d10ea3352a53478e14354355a02b6a87a7ab1000000181ba22861f1a04d910c399ce20125a7ef53c3a47e0f51fe1d2c179ea83b8da34e0000000415db3dd5c4e4589c0b7a5942f81c11548dda500600adefeb8c49d13481a88e24000000022309e4044d29f2906c728a7d19672aa7d80f3fbc289d4dd6fcab93f1e197b727000000020a20b604e286954cd8b1622dcbda5ef1c4ad6bfd80a81ad80dcff2f5080d5ba00668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000010238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed000000020000001000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002010000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020300000000000000000000000000000000000000000000000000000000000002040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008010000000000000000000000000000000000000000000000000000000000000803000000000000000000000000000000000000000000000000000000000000080200000000000000000000000000000000000000000000000000000000000008040000000000000000000000000000000000000000000000000000000000000803000000000000000000000000000000000000000000000000000000000000080500000000000000000000000000000000000000000000000000000000000008040000000000000000000000000000000000000000000000000000000000000806000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041b024f6e2e258ac4fa7b3a0d03f9fa242eee6d884ec85d0efd4beca26a88da2100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006010202020202020202020202020202020202020202000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; bytes block_2 = - hex"000000020283622796e1a2fa4718e254eb46d3f4287b05a5aaee35af02a54f2af8362f97000000101f99db4b9ffa5ab637607ad50c7d10ea3352a53478e14354355a02b6a87a7ab1000000181ba22861f1a04d910c399ce20125a7ef53c3a47e0f51fe1d2c179ea83b8da34e0000000415db3dd5c4e4589c0b7a5942f81c11548dda500600adefeb8c49d13481a88e24000000022309e4044d29f2906c728a7d19672aa7d80f3fbc289d4dd6fcab93f1e197b727000000020a20b604e286954cd8b1622dcbda5ef1c4ad6bfd80a81ad80dcff2f5080d5ba0013ffea42e60a3be0af304384d83ad4411df13f66213997a7f0b7551e242f19d0000002001872181b5fe2c7ea15e1e72f5672bc777d61c807771ff7ae40c9b2aa816323500000028063d7b42d552599d3f3ff8fbc93e55484d49fc20dcc41940e3ebeaac4483a8ba0000000803b6339133ac1ca21463e1e3370ca136862bac1be49bdc6e1e69f73068a22ebe0000000316204b8532027613f551ad0530dc70c1c3be36fb7828a3a6539a100c57d25034000000030aa1281a92ab93a92ea1e45d49ce373a45fdb0b7a988416e63cd0728252a112a0000001000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008020000000000000000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000080300000000000000000000000000000000000000000000000000000000000008050000000000000000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000080600000000000000000000000000000000000000000000000000000000000008050000000000000000000000000000000000000000000000000000000000000807000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042ddfdac63df2e340ea582ed2b6c9d23bf04f6e98c281c25c6dd7e87251185b3500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006020303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000020283622796e1a2fa4718e254eb46d3f4287b05a5aaee35af02a54f2af8362f97000000101f99db4b9ffa5ab637607ad50c7d10ea3352a53478e14354355a02b6a87a7ab1000000181ba22861f1a04d910c399ce20125a7ef53c3a47e0f51fe1d2c179ea83b8da34e0000000415db3dd5c4e4589c0b7a5942f81c11548dda500600adefeb8c49d13481a88e24000000022309e4044d29f2906c728a7d19672aa7d80f3fbc289d4dd6fcab93f1e197b727000000020a20b604e286954cd8b1622dcbda5ef1c4ad6bfd80a81ad80dcff2f5080d5ba00668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000010238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed00000002013ffea42e60a3be0af304384d83ad4411df13f66213997a7f0b7551e242f19d0000002001872181b5fe2c7ea15e1e72f5672bc777d61c807771ff7ae40c9b2aa816323500000028063d7b42d552599d3f3ff8fbc93e55484d49fc20dcc41940e3ebeaac4483a8ba0000000803b6339133ac1ca21463e1e3370ca136862bac1be49bdc6e1e69f73068a22ebe0000000316204b8532027613f551ad0530dc70c1c3be36fb7828a3a6539a100c57d25034000000030aa1281a92ab93a92ea1e45d49ce373a45fdb0b7a988416e63cd0728252a112a0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000020236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c000000030000001000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008020000000000000000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000080300000000000000000000000000000000000000000000000000000000000008050000000000000000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000080600000000000000000000000000000000000000000000000000000000000008050000000000000000000000000000000000000000000000000000000000000807000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042ddfdac63df2e340ea582ed2b6c9d23bf04f6e98c281c25c6dd7e87251185b3500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006020303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; bytes block_empty_1 = - hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000082f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd80000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b36b22912aa963f143c490227bd21e7a44338026b2f6a389cb98e82167c3718000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000182f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed0000000225d4ca531bca7d097a93bc47d7aa2c4dbcc8d0d5ecf4138849104e363eb52c03000000022b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000082f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd80000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b36b22912aa963f143c490227bd21e7a44338026b2f6a389cb98e82167c3718000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000182f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed0000000225d4ca531bca7d097a93bc47d7aa2c4dbcc8d0d5ecf4138849104e363eb52c03000000022b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000010238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed00000002000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; bytes block_empty_2 = - hex"000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000182f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed0000000225d4ca531bca7d097a93bc47d7aa2c4dbcc8d0d5ecf4138849104e363eb52c03000000022b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000202d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000282f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000008236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c000000030aaa66ea64a4b9493d7237d092f8276e31eb3f8b14ae5c5e0a91fa5627745a83000000032b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000182f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed0000000225d4ca531bca7d097a93bc47d7aa2c4dbcc8d0d5ecf4138849104e363eb52c03000000022b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000010238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000202d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000282f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000008236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c000000030aaa66ea64a4b9493d7237d092f8276e31eb3f8b14ae5c5e0a91fa5627745a83000000032b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000020236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c00000003000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; function setUp() public { rollup = new Rollup(); @@ -30,13 +30,20 @@ contract DecoderTest is Test { function testEmptyBlocks() public { { - bytes32 diffRoot = helper.computeDiffRoot(block_empty_1); + (bytes32 diffRoot, bytes32 l1ToL2MessagesHash) = + helper.computeDiffRootAndMessagesHash(block_empty_2); assertEq( - 0x84036b397b37b2dab7c2d95581275797c8d06b432f3826ada23cca6d87d49b84, diffRoot, + 0x84036b397b37b2dab7c2d95581275797c8d06b432f3826ada23cca6d87d49b84, "Invalid diff root" ); + assertEq( + l1ToL2MessagesHash, + 0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560, + "Invalid messages hash" + ); + ( uint256 l2BlockNumber, bytes32 startStateHash, @@ -47,17 +54,17 @@ contract DecoderTest is Test { assertEq(l2BlockNumber, 1, "Invalid block number"); assertEq( startStateHash, - 0xc3c559a71e6e4e6120dc290ac2aefe6739be32216168d5c98899a86f1566d930, + 0x2d5d49acd86a4ce5d71f632bd8c39d61d12c7be4ad4ab1f17e134e55aa4e29c2, "Invalid start state hash" ); assertEq( endStateHash, - 0x448312391a3205ecaf22d804a780c19890d6425c621e9a731c342f9903a5e71f, + 0x3dff2c815f7e5f5b8b3a2397347cc928001c73e5442d6dad5af61c3329b4fc8c, "Invalid end state hash" ); assertEq( publicInputsHash, - 0x2e8af2457a0c7cef1b1d47efa0583f1e0840910ab1a802bff812bbc5e62b7321, + 0x23f698e487c4e1b7383889f8864bc19591773d136c364c01d980bd13d0786ba1, "Invalid public input hash" ); @@ -67,13 +74,20 @@ contract DecoderTest is Test { } { - bytes32 diffRoot = helper.computeDiffRoot(block_empty_2); + (bytes32 diffRoot, bytes32 l1ToL2MessagesHash) = + helper.computeDiffRootAndMessagesHash(block_empty_2); assertEq( - 0x84036b397b37b2dab7c2d95581275797c8d06b432f3826ada23cca6d87d49b84, diffRoot, + 0x84036b397b37b2dab7c2d95581275797c8d06b432f3826ada23cca6d87d49b84, "Invalid diff root" ); + assertEq( + l1ToL2MessagesHash, + 0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560, + "Invalid messages hash" + ); + ( uint256 l2BlockNumber, bytes32 startStateHash, @@ -84,17 +98,17 @@ contract DecoderTest is Test { assertEq(l2BlockNumber, 2, "Invalid block number"); assertEq( startStateHash, - 0x448312391a3205ecaf22d804a780c19890d6425c621e9a731c342f9903a5e71f, + 0x3dff2c815f7e5f5b8b3a2397347cc928001c73e5442d6dad5af61c3329b4fc8c, "Invalid start state hash" ); assertEq( endStateHash, - 0x2fb8f70b8011dfa8111055c18a0068294d795c2c82701f18b5bf93b3156fe83f, + 0x906b283a0f25f74711aa8e1cdaea18a6e80bebe9ce9118315a0f31433feaffe3, "Invalid end state hash" ); assertEq( publicInputsHash, - 0x0b0c644c9a7106d293ca833a1cb332a576de6971951c2167408545dd7e31a7bb, + 0x0f6cd26577a7c4edf15eb3785315d9f8dbcbc8a3ffc0dba7e04be4e37b09228f, "Invalid public input hash" ); @@ -106,13 +120,20 @@ contract DecoderTest is Test { function testNonEmptyBlocks() public { { - bytes32 diffRoot = helper.computeDiffRoot(block_1); + (bytes32 diffRoot, bytes32 l1ToL2MessagesHash) = + helper.computeDiffRootAndMessagesHash(block_1); assertEq( - 0x05ab40c0ddda5b1846c6283c0a99ea7da9ebb3ea46f33225e72e0d0333bf251f, diffRoot, + 0x05ab40c0ddda5b1846c6283c0a99ea7da9ebb3ea46f33225e72e0d0333bf251f, "Invalid diff root block 1" ); + assertEq( + l1ToL2MessagesHash, + 0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560, + "Invalid messages hash" + ); + ( uint256 l2BlockNumber, bytes32 startStateHash, @@ -123,17 +144,17 @@ contract DecoderTest is Test { assertEq(l2BlockNumber, 1, "Invalid block number"); assertEq( startStateHash, - 0xc3c559a71e6e4e6120dc290ac2aefe6739be32216168d5c98899a86f1566d930, + 0x2d5d49acd86a4ce5d71f632bd8c39d61d12c7be4ad4ab1f17e134e55aa4e29c2, "Invalid start state hash block 1" ); assertEq( endStateHash, - 0x45faded932e3a828a426370bd7275120c3f4ed27117a6c98c9c762e8b8cec9f6, + 0x8a6161ff9185b2354adadb2a6fbd0a8279d2b7558e617f46cfbd42af3073729c, "Invalid end state hash block 1" ); assertEq( publicInputsHash, - 0x28b90cb81b273c3ee583750e79bca15e9b01fe01a7eacacf462ee866cefb904a, + 0x04b30d90646ca894b0f04cafb6bd76cc7db900dc8cb0a8904b21ff2a6cd4f23e, "Invalid public input hash block 1" ); @@ -143,13 +164,20 @@ contract DecoderTest is Test { } { - bytes32 diffRoot = helper.computeDiffRoot(block_2); + (bytes32 diffRoot, bytes32 l1ToL2MessagesHash) = + helper.computeDiffRootAndMessagesHash(block_2); assertEq( - 0x04a10b2ce6eb66a3ae547efacc53760ec64fb86c901f9cadb36c104cc532cb99, diffRoot, + 0x04a10b2ce6eb66a3ae547efacc53760ec64fb86c901f9cadb36c104cc532cb99, "Invalid diff root block 2" ); + assertEq( + l1ToL2MessagesHash, + 0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560, + "Invalid l1 to l2 messages hash block 2" + ); + ( uint256 l2BlockNumber, bytes32 startStateHash, @@ -160,17 +188,17 @@ contract DecoderTest is Test { assertEq(l2BlockNumber, 2, "Invalid block number"); assertEq( startStateHash, - 0x45faded932e3a828a426370bd7275120c3f4ed27117a6c98c9c762e8b8cec9f6, + 0x8a6161ff9185b2354adadb2a6fbd0a8279d2b7558e617f46cfbd42af3073729c, "Invalid start state hash block 2" ); assertEq( endStateHash, - 0x0b04cfd8792e17a123c3c5c82bd2593e8da745d05296d4e1058708e11489909a, + 0xd2055c0813616d7073f6bcc905a755ed525e5541b3e5e1b286fd583729c74ea7, "Invalid end state hash block 2" ); assertEq( publicInputsHash, - 0x04f8878ba2e56773029c2b246d41f04963cc8b2654bc35a66b72ff79a7a756ec, + 0x22d088d033eac3347d80581f49057fe24d366cdfdaa644ad4a286d4f8280842b, "Invalid public input hash block 2" ); diff --git a/l1-contracts/test/DecoderHelper.sol b/l1-contracts/test/DecoderHelper.sol index 90a32fd24bb7..4bf7de3225cd 100644 --- a/l1-contracts/test/DecoderHelper.sol +++ b/l1-contracts/test/DecoderHelper.sol @@ -13,7 +13,12 @@ contract DecoderHelper is Decoder { return _decode(_l2Block); } - function computeDiffRoot(bytes calldata _l2Block) external pure returns (bytes32) { - return _computeDiffRoot(_l2Block); + function computeDiffRootAndMessagesHash(bytes calldata _l2Block) + external + pure + returns (bytes32, bytes32) + { + (bytes32 diffRoot, bytes32 l1ToL2MessagesHash) = _computeDiffRootAndMessagesHash(_l2Block); + return (diffRoot, l1ToL2MessagesHash); } } diff --git a/yarn-project/archiver/.eslintrc.cjs b/yarn-project/archiver/.eslintrc.cjs index 97d6f1878135..e659927475c0 100644 --- a/yarn-project/archiver/.eslintrc.cjs +++ b/yarn-project/archiver/.eslintrc.cjs @@ -1 +1 @@ -module.exports = require('@aztec/foundation/eslint-legacy'); +module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/archiver/README.md b/yarn-project/archiver/README.md index a6743c372bea..4f180b229cfc 100644 --- a/yarn-project/archiver/README.md +++ b/yarn-project/archiver/README.md @@ -1,6 +1,14 @@ # Archiver -To run: -1. Run `anvil`, -2. in the aztec3-l1-contracts repo check out my branch `janb/archiver-test-data`, -3. deploy the contracts and generate initial activity with: `forge script --fork-url "http://127.0.0.1:8545/" --ffi GenerateActivityTest --sig "testGenerateActivity()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --broadcast` -4. in this repository run `yarn start:dev` (Note: this repo is currently messy and eslint will not allow it to be built with `yarn start`) +Archiver is a service which is used to fetch data on-chain data and present them in a nice-to-consume form. +The on-chain data specifically are the following events: +1. `L2BlockProcessed` event emitted on Rollup contract, +2. `UnverifiedData` event emitted on UnverifiedDataEmitter contract and +3. `ContractDeployment` event emitted on UnverifiedDataEmitter contract as well. + +The interfaces defining how the data can be consumed from the archiver are `L2BlockSource`, `UnverifiedDataSource` and `ContractDataSource`. + +## Usage +To install dependencies and build the package run `yarn install` followed by `yarn build`. +To run test execute `yarn test`. + +To start the service export `ETHEREUM_HOST` (defaults to `http://127.0.0.1:8545/`), `ARCHIVER_POLLING_INTERVAL` (defaults to `1000 ms`), `ROLLUP_CONTRACT_ADDRESS`, `UNVERIFIED_DATA_EMITTER_ADDRESS` environmental variables and start the service with `yarn start`. diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index f68f25c2a267..91d47ffe461f 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -65,12 +65,12 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa private nextL2BlockFromBlock = 0n; /** - * Next L1 block number to fetch `UnverifiedData` logs from (i.e. `fromBlock` in eth_getLogs) + * Next L1 block number to fetch `UnverifiedData` logs from (i.e. `fromBlock` in eth_getLogs). */ private nextUnverifiedDataFromBlock = 0n; /** - * Next L1 block number to fetch `ContractPublicData` logs from (i.e. `fromBlock` in eth_getLogs) + * Next L1 block number to fetch `ContractPublicData` logs from (i.e. `fromBlock` in eth_getLogs). */ private nextContractDataFromBlock = 0n; @@ -79,7 +79,7 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa * @param publicClient - A client for interacting with the Ethereum node. * @param rollupAddress - Ethereum address of the rollup contract. * @param unverifiedDataEmitterAddress - Ethereum address of the unverifiedDataEmitter contract. - * @param pollingInterval - The interval for polling for rollup logs. + * @param pollingIntervalMs - The interval for polling for rollup logs (in milliseconds). * @param log - A logger. */ constructor( @@ -141,6 +141,11 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa await this.syncNewContractData(blockUntilSynced, currentBlockNumber); } + /** + * Fetches and processes new blocks. + * @param blockUntilSynced - If true, blocks until the archiver has fully synced. + * @param currentBlockNumber - Latest available block number in the ETH node. + */ private async syncBlocks(blockUntilSynced: boolean, currentBlockNumber: bigint) { do { if (this.nextL2BlockFromBlock > currentBlockNumber) { @@ -162,6 +167,11 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa } while (blockUntilSynced && this.nextL2BlockFromBlock <= currentBlockNumber); } + /** + * Fetches and processes new unverified data. + * @param blockUntilSynced - If true, blocks until the archiver has fully synced. + * @param currentBlockNumber - Latest available block number in the ETH node. + */ private async syncUnverifiedData(blockUntilSynced: boolean, currentBlockNumber: bigint) { do { if (this.nextUnverifiedDataFromBlock > currentBlockNumber) { @@ -181,6 +191,11 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa } while (blockUntilSynced && this.nextUnverifiedDataFromBlock <= currentBlockNumber); } + /** + * Fetches and processes new contract data. + * @param blockUntilSynced - If true, blocks until the archiver has fully synced. + * @param currentBlockNumber - Latest available block number in the ETH node. + */ private async syncNewContractData(blockUntilSynced: boolean, currentBlockNumber: bigint) { do { if (this.nextContractDataFromBlock > currentBlockNumber) { @@ -188,9 +203,9 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa } this.log(`Syncing ContractData logs from block ${this.nextContractDataFromBlock}`); - const contractDataLogs = await this.getContractDataLogs(this.nextContractDataFromBlock); + const contractDataLogs = await this.getContractDeploymentLogs(this.nextContractDataFromBlock); - this.processContractDataLogs(contractDataLogs); + this.processContractDeploymentLogs(contractDataLogs); this.nextContractDataFromBlock = (contractDataLogs.findLast(cd => !!cd)?.blockNumber || this.nextContractDataFromBlock) + 1n; } while (blockUntilSynced && this.nextContractDataFromBlock <= currentBlockNumber); @@ -234,7 +249,12 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa }); } - private async getContractDataLogs(fromBlock: bigint) { + /** + * Gets relevant `ContractDeployment` logs from chain. + * @param fromBlock - First block to get logs from (inclusive). + * @returns An array of `ContractDeployment` logs. + */ + private async getContractDeploymentLogs(fromBlock: bigint): Promise { const abiItem = getAbiItem({ abi: UnverifiedDataEmitterAbi, name: 'ContractDeployment', @@ -294,7 +314,11 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa this.log('Processed unverifiedData corresponding to ' + logs.length + ' blocks.'); } - private processContractDataLogs( + /** + * Processes newly received UnverifiedData logs. + * @param logs - ContractDeployment logs. + */ + private processContractDeploymentLogs( logs: Log[], ) { for (const log of logs) { @@ -389,8 +413,8 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa /** * Lookup all contract data in an L2 block. - * @param blockNumber - The block number to get all contract data from. - * @returns All new contract data in the block (if found) + * @param blockNum - The block number to get all contract data from. + * @returns All new contract data in the block (if found). */ public getL2ContractPublicDataInBlock(blockNum: number): Promise { if (blockNum > this.l2Blocks.length) { @@ -420,22 +444,28 @@ export class Archiver implements L2BlockSource, UnverifiedDataSource, ContractDa /** * Lookup the L2 contract info inside a block. * Contains contract address & the ethereum portal address. - * @param contractAddress - The contract data address. + * @param l2BlockNum - The L2 block number to get the contract data from. * @returns ContractData with the portal address (if we didn't throw an error). */ - public getL2ContractInfoInBlock(blockNum: number): Promise { - if (blockNum > this.l2Blocks.length) { + public getL2ContractInfoInBlock(l2BlockNum: number): Promise { + if (l2BlockNum > this.l2Blocks.length) { return Promise.resolve([]); } - const block = this.l2Blocks[blockNum]; + const block = this.l2Blocks[l2BlockNum]; return Promise.resolve(block.newContractData); } + /** + * Gets the public function data for a contract. + * @param contractAddress - The contract address containing the function to fetch. + * @param functionSelector - The function selector of the function to fetch. + * @returns The public function data (if found). + */ public async getPublicFunction( - address: AztecAddress, + contractAddress: AztecAddress, functionSelector: Buffer, ): Promise { - const contractData = await this.getL2ContractPublicData(address); + const contractData = await this.getL2ContractPublicData(contractAddress); const result = contractData?.publicFunctions?.find(fn => fn.functionSelector.equals(functionSelector)); return result; } diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index 405584b109f4..d84c94a73c4d 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -16,6 +16,11 @@ export interface ArchiverConfig extends L1Addresses { archiverPollingInterval?: number; } +/** + * Returns the archiver configuration from the environment variables. + * Note: If an environment variable is not set, the default value is used. + * @returns The archiver configuration. + */ export function getConfigEnvVars(): ArchiverConfig { const { ETHEREUM_HOST, ARCHIVER_POLLING_INTERVAL, ROLLUP_CONTRACT_ADDRESS, UNVERIFIED_DATA_EMITTER_ADDRESS } = process.env; diff --git a/yarn-project/circuits.js/src/structs/constants.ts b/yarn-project/circuits.js/src/structs/constants.ts index a4ba827ca060..8c06c37b2bb3 100644 --- a/yarn-project/circuits.js/src/structs/constants.ts +++ b/yarn-project/circuits.js/src/structs/constants.ts @@ -29,9 +29,14 @@ export const CONTRACT_TREE_HEIGHT = 4; export const PRIVATE_DATA_TREE_HEIGHT = 8; export const PUBLIC_DATA_TREE_HEIGHT = 254; export const NULLIFIER_TREE_HEIGHT = 8; +export const L1_TO_L2_MESSAGES_TREE_HEIGHT = 8; +export const L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT = 8; +export const L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT = 4; export const PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT = 8; export const CONTRACT_TREE_ROOTS_TREE_HEIGHT = 8; export const ROLLUP_VK_TREE_HEIGHT = 8; export const FUNCTION_SELECTOR_NUM_BYTES = 4; + +export const NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; diff --git a/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap index 72ef4bfa0d79..5eeab7ec5d22 100644 --- a/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap @@ -160,6 +160,15 @@ sibling_path: [ 0x1120 0x1121 0x1122 0x1123 0x1124 0x1125 0x1126 0x1127 ] ] new_historic_private_data_tree_roots: [ 0x2000 0x2001 0x2002 0x2003 0x2004 0x2005 0x2006 0x2007 ] new_historic_contract_tree_roots: [ 0x2100 0x2101 0x2102 0x2103 0x2104 0x2105 0x2106 0x2107 ] +new_l1_to_l2_messages: [ 0x2100 0x2101 0x2102 0x2103 0x2104 0x2105 0x2106 0x2107 0x2108 0x2109 0x210a 0x210b 0x210c 0x210d 0x210e 0x210f ] +new_l1_to_l2_message_tree_root_sibling_path: [ 0x2100 0x2101 0x2102 0x2103 ] +new_historic_l1_to_l2_message_roots_tree_sibling_path: [ 0x2100 0x2101 0x2102 0x2103 0x2104 0x2105 0x2106 0x2107 ] +start_l1_to_l2_message_tree_snapshot: root: 0x2200 +next_available_leaf_index: 8704 + +start_historic_tree_l1_to_l2_message_tree_roots_snapshot: root: 0x2300 +next_available_leaf_index: 8960 + " `; @@ -207,6 +216,19 @@ next_available_leaf_index: 2816 end_tree_of_historic_contract_tree_roots_snapshot: root: 0xc00 next_available_leaf_index: 3072 +start_l1_to_l2_messages_tree_snapshot: root: 0xd00 +next_available_leaf_index: 3328 + +end_l1_tol2_messages_tree_snapshot: root: 0xe00 +next_available_leaf_index: 3584 + +start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot: root: 0xf00 +next_available_leaf_index: 3840 + +end_tree_of_historic_l1_tol2_messages_tree_roots_snapshot: root: 0x1000 +next_available_leaf_index: 4096 + calldata_hash: [ 0x1 0x2 ] +l1_to_l2_messages_hash: [ 0x3 0x4 ] " `; diff --git a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index 41d719bed586..12da16b29fe9 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -1,7 +1,13 @@ import { assertLength, FieldsOf } from '../../utils/jsUtils.js'; import { serializeToBuffer } from '../../utils/serialize.js'; import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; -import { CONTRACT_TREE_ROOTS_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT } from '../constants.js'; +import { + CONTRACT_TREE_ROOTS_TREE_HEIGHT, + L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT, + L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, +} from '../constants.js'; import { PreviousRollupData } from './previous_rollup_data.js'; import { AggregationObject } from '../aggregation_object.js'; import { Fr } from '@aztec/foundation/fields'; @@ -13,17 +19,21 @@ export class RootRollupInputs { public newHistoricPrivateDataTreeRootSiblingPath: Fr[], public newHistoricContractDataTreeRootSiblingPath: Fr[], + public newL1ToL2Messages: Fr[], + public newL1ToL2MessageTreeRootSiblingPath: Fr[], + public newHistoricL1ToL2MessageTreeRootSiblingPath: Fr[], + public startL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot, + public startHistoricTreeL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot, ) { assertLength(this, 'newHistoricPrivateDataTreeRootSiblingPath', PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT); assertLength(this, 'newHistoricContractDataTreeRootSiblingPath', CONTRACT_TREE_ROOTS_TREE_HEIGHT); + assertLength(this, 'newL1ToL2MessageTreeRootSiblingPath', L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT); + assertLength(this, 'newHistoricL1ToL2MessageTreeRootSiblingPath', L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT); + assertLength(this, 'newL1ToL2Messages', NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP); } toBuffer() { - return serializeToBuffer( - this.previousRollupData, - this.newHistoricPrivateDataTreeRootSiblingPath, - this.newHistoricContractDataTreeRootSiblingPath, - ); + return serializeToBuffer(...RootRollupInputs.getFields(this)); } static from(fields: FieldsOf): RootRollupInputs { @@ -35,6 +45,11 @@ export class RootRollupInputs { fields.previousRollupData, fields.newHistoricPrivateDataTreeRootSiblingPath, fields.newHistoricContractDataTreeRootSiblingPath, + fields.newL1ToL2Messages, + fields.newL1ToL2MessageTreeRootSiblingPath, + fields.newHistoricL1ToL2MessageTreeRootSiblingPath, + fields.startL1ToL2MessageTreeSnapshot, + fields.startHistoricTreeL1ToL2MessageTreeRootsSnapshot, ] as const; } } @@ -64,7 +79,14 @@ export class RootRollupPublicInputs { public startTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot, public endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot, + public startL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot, + public endL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot, + + public startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot, + public endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot, + public calldataHash: [Fr, Fr], + public l1ToL2MessagesHash: [Fr, Fr], ) {} static getFields(fields: FieldsOf) { @@ -82,7 +104,12 @@ export class RootRollupPublicInputs { fields.endTreeOfHistoricPrivateDataTreeRootsSnapshot, fields.startTreeOfHistoricContractTreeRootsSnapshot, fields.endTreeOfHistoricContractTreeRootsSnapshot, + fields.startL1ToL2MessageTreeSnapshot, + fields.endL1ToL2MessageTreeSnapshot, + fields.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, + fields.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, fields.calldataHash, + fields.l1ToL2MessagesHash, ] as const; } @@ -110,6 +137,11 @@ export class RootRollupPublicInputs { reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + [reader.readFr(), reader.readFr()], [reader.readFr(), reader.readFr()], ); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 2d875a76de52..df8ae3e1bf07 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -49,10 +49,13 @@ import { KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, KERNEL_PRIVATE_CALL_STACK_LENGTH, KERNEL_PUBLIC_CALL_STACK_LENGTH, + L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT, + L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT, NEW_L2_TO_L1_MSGS_LENGTH, NEW_COMMITMENTS_LENGTH, NEW_NULLIFIERS_LENGTH, NULLIFIER_TREE_HEIGHT, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PRIVATE_CALL_STACK_LENGTH, PRIVATE_DATA_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, @@ -434,6 +437,11 @@ export function makeRootRollupInputs(seed = 0) { [makePreviousBaseRollupData(seed), makePreviousBaseRollupData(seed + 0x1000)], range(PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, 0x2000).map(fr), range(CONTRACT_TREE_ROOTS_TREE_HEIGHT, 0x2100).map(fr), + range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 0x2100).map(fr), + range(L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT, 0x2100).map(fr), + range(L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT, 0x2100).map(fr), + makeAppendOnlyTreeSnapshot(seed + 0x2200), + makeAppendOnlyTreeSnapshot(seed + 0x2300), ); } @@ -452,7 +460,12 @@ export function makeRootRollupPublicInputs(seed = 0) { endTreeOfHistoricPrivateDataTreeRootsSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), startTreeOfHistoricContractTreeRootsSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), endTreeOfHistoricContractTreeRootsSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), + startL1ToL2MessageTreeSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), + endL1ToL2MessageTreeSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), calldataHash: [new Fr(1n), new Fr(2n)], + l1ToL2MessagesHash: [new Fr(3n), new Fr(4n)], }); } diff --git a/yarn-project/ethereum.js/src/bigint_buffer/index.ts b/yarn-project/ethereum.js/src/bigint_buffer/index.ts deleted file mode 100644 index a75777a4f63c..000000000000 --- a/yarn-project/ethereum.js/src/bigint_buffer/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Convert a little-endian buffer into a BigInt. - * @param buf - The little-endian buffer to convert. - * @returns A BigInt with the little-endian representation of buf. - */ -export function toBigIntLE(buf: Buffer): bigint { - const reversed = Buffer.from(buf); - reversed.reverse(); - const hex = reversed.toString('hex'); - if (hex.length === 0) { - return BigInt(0); - } - return BigInt(`0x${hex}`); -} - -/** - * Convert a big-endian buffer into a BigInt. - * @param buf - The big-endian buffer to convert. - * @returns A BigInt with the big-endian representation of buf. - */ -export function toBigIntBE(buf: Buffer): bigint { - const hex = buf.toString('hex'); - if (hex.length === 0) { - return BigInt(0); - } - return BigInt(`0x${hex}`); -} - -/** - * Convert a BigInt to a little-endian buffer. - * @param num - The BigInt to convert. - * @param width - The number of bytes that the resulting buffer should be. - * @returns A little-endian buffer representation of num. - */ -export function toBufferLE(num: bigint, width: number): Buffer { - const hex = num.toString(16); - const buffer = Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex'); - buffer.reverse(); - return buffer; -} - -/** - * Convert a BigInt to a big-endian buffer. - * @param num - The BigInt to convert. - * @param width - The number of bytes that the resulting buffer should be. - * @returns A big-endian buffer representation of num. - */ -export function toBufferBE(num: bigint, width: number): Buffer { - const hex = num.toString(16); - return Buffer.from(hex.padStart(width * 2, '0').slice(0, width * 2), 'hex'); -} diff --git a/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts b/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts index 9e0051d40f79..ec50affeddbb 100644 --- a/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts +++ b/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts @@ -1,109 +1,106 @@ // THIS IS GENERATED CODE, DO NOT EDIT! /* eslint-disable */ -import { EthAddress } from "@aztec/foundation"; -import { EthereumRpc } from "../../eth_rpc/index.js"; -import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from "../../contract/index.js"; -import * as Bytes from "../../contract/bytes.js"; -import abi from "./TestContractAbi.js"; +import { EthAddress } from '@aztec/foundation/eth-address'; +import { EthereumRpc } from '../../eth_rpc/index.js'; +import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from '../../contract/index.js'; +import * as Bytes from '../../contract/bytes.js'; +import abi from './TestContractAbi.js'; /** * Type representing the 'ChangedEvent' that contains details about the change in balance, * such as the sender's address, the amount changed, and two timestamps for tracking. */ export type ChangedEvent = { - /** - * The Ethereum address initiating the event. - */ -from: EthAddress; - /** - * The amount involved in the transaction. - */ -amount: bigint; - /** - * Timestamp of the first event occurrence. - */ -t1: bigint; - /** - * Timestamp indicating the end time of an event. - */ -t2: bigint; + /** + * The Ethereum address initiating the event. + */ + from: EthAddress; + /** + * The amount involved in the transaction. + */ + amount: bigint; + /** + * Timestamp of the first event occurrence. + */ + t1: bigint; + /** + * Timestamp indicating the end time of an event. + */ + t2: bigint; }; /** * Type representing the 'UnchangedEvent', which is emitted when a specific condition in the contract remains unchanged. */ export type UnchangedEvent = { - /** - * The monetary amount associated with the transaction. - */ -value: bigint; - /** - * The originating Ethereum address. - */ -addressFrom: EthAddress; - /** - * The timestamp of the first event. - */ -t1: bigint; + /** + * The monetary amount associated with the transaction. + */ + value: bigint; + /** + * The originating Ethereum address. + */ + addressFrom: EthAddress; + /** + * The timestamp of the first event. + */ + t1: bigint; }; /** * Represents the ChangedEventLog interface for the TestContract. * Contains all the properties of a Changed event log, including event name and payload. */ -export interface ChangedEventLog extends EventLog { -} +export interface ChangedEventLog extends EventLog {} /** * Represents the log interface for UnchangedEvent in the TestContract. * Provides event details such as value, addressFrom, and t1 from the emitted Unchanged event. */ -export interface UnchangedEventLog extends EventLog { -} +export interface UnchangedEventLog extends EventLog {} /** * Represents the event types for the TestContract. * Provides a mapped definition of each event with its respective data structure. */ interface TestContractEvents { - /** - * Event emitted when a change occurs in the contract state. - */ -Changed: ChangedEvent; - /** - * An event indicating no change in the value. - */ -Unchanged: UnchangedEvent; + /** + * Event emitted when a change occurs in the contract state. + */ + Changed: ChangedEvent; + /** + * An event indicating no change in the value. + */ + Unchanged: UnchangedEvent; } /** * Represents the event logs for the TestContract interface. * Contains the mapping of event names to their corresponding event log interfaces for easy access and organization. */ interface TestContractEventLogs { - /** - * Represents an event triggered when a change occurs in the contract state. - */ -Changed: ChangedEventLog; - /** - * Event triggered when a value remains unchanged. - */ -Unchanged: UnchangedEventLog; + /** + * Represents an event triggered when a change occurs in the contract state. + */ + Changed: ChangedEventLog; + /** + * Event triggered when a value remains unchanged. + */ + Unchanged: UnchangedEventLog; } /** * Represents the event logs for all transactions involving the TestContract. * Contains an organized collection of event logs for each specific event in the contract, allowing easy access to relevant transaction information. */ interface TestContractTxEventLogs { - /** - * Triggered when a state change occurs in the contract. - */ -Changed: ChangedEventLog[]; - /** - * An event representing unaltered data. - */ -Unchanged: UnchangedEventLog[]; + /** + * Triggered when a state change occurs in the contract. + */ + Changed: ChangedEventLog[]; + /** + * An event representing unaltered data. + */ + Unchanged: UnchangedEventLog[]; } /** * Represents a TestContract transaction receipt. * Provides details about the transaction events, status, and other relevant information after executing a method call on the TestContract. */ -export interface TestContractTransactionReceipt extends ContractTxReceipt { -} +export interface TestContractTransactionReceipt extends ContractTxReceipt {} /** * Represents the methods available in the TestContract. * Provides functionality for interacting with and invoking smart contract functions, @@ -111,27 +108,31 @@ export interface TestContractTransactionReceipt extends ContractTxReceipt; - listOfNestedStructs(a0: EthAddress): TxCall<{ - /** - * Represents the active state of an entity. - */ -status: boolean; - }>; - balance(who: EthAddress): TxCall; - hasALotOfParams(_var1: number, _var2: string, _var3: Bytes.Bytes32[]): TxSend; - getStr(): TxCall; - owner(): TxCall; - mySend(to: EthAddress, value: bigint): TxSend; - myDisallowedSend(to: EthAddress, value: bigint): TxSend; - testArr(value: bigint[]): TxCall; - overloadedFunction(a: bigint): TxCall; - overloadedFunction(): TxCall; + addStruct(nestedStruct: { + /** + * Represents the active state of a specific object or process. + */ + status: boolean; + }): TxSend; + listOfNestedStructs(a0: EthAddress): TxCall<{ + /** + * Represents the active state of an entity. + */ + status: boolean; + }>; + balance(who: EthAddress): TxCall; + hasALotOfParams( + _var1: number, + _var2: string, + _var3: Bytes.Bytes32[], + ): TxSend; + getStr(): TxCall; + owner(): TxCall; + mySend(to: EthAddress, value: bigint): TxSend; + myDisallowedSend(to: EthAddress, value: bigint): TxSend; + testArr(value: bigint[]): TxCall; + overloadedFunction(a: bigint): TxCall; + overloadedFunction(): TxCall; } /** * Represents a TestContract definition interface. @@ -139,18 +140,18 @@ status: boolean; * Provides functionality for interacting with the TestContract on the Ethereum network. */ export interface TestContractDefinition { - /** - * Collection of smart contract methods. - */ -methods: TestContractMethods; - /** - * A collection of event definitions for the TestContract. - */ -events: TestContractEvents; - /** - * Collection of logs for emitted events. - */ -eventLogs: TestContractEventLogs; + /** + * Collection of smart contract methods. + */ + methods: TestContractMethods; + /** + * A collection of event definitions for the TestContract. + */ + events: TestContractEvents; + /** + * Collection of logs for emitted events. + */ + eventLogs: TestContractEventLogs; } /** * The TestContract class represents a smart contract deployed on the Ethereum blockchain. @@ -161,20 +162,20 @@ eventLogs: TestContractEventLogs; * to easily connect to existing contracts or deploy new ones. */ export class TestContract extends Contract { - constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { - super(eth, abi, address, options); - } - /** - * Deploy a new instance of the TestContract smart contract to the Ethereum network. - * The 'deploy' function takes the initial 'who' address and 'myValue' as arguments for the constructor of the TestContract. - * Returns a transaction receipt containing the contract address, gas used, and other details on successful deployment. - * - * @param who - The Ethereum address that will be set as the 'owner' of the newly deployed contract. - * @param myValue - The initial value (in bigint) to be set in the smart contract's internal state. - * @returns A promise that resolves to a TestContractTransactionReceipt with information about the deployed contract. - */ -deploy(who: EthAddress, myValue: bigint): TxSend { - return super.deployBytecode("0x01234567", who, myValue) as any; - } + constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { + super(eth, abi, address, options); + } + /** + * Deploy a new instance of the TestContract smart contract to the Ethereum network. + * The 'deploy' function takes the initial 'who' address and 'myValue' as arguments for the constructor of the TestContract. + * Returns a transaction receipt containing the contract address, gas used, and other details on successful deployment. + * + * @param who - The Ethereum address that will be set as the 'owner' of the newly deployed contract. + * @param myValue - The initial value (in bigint) to be set in the smart contract's internal state. + * @returns A promise that resolves to a TestContractTransactionReceipt with information about the deployed contract. + */ + deploy(who: EthAddress, myValue: bigint): TxSend { + return super.deployBytecode('0x01234567', who, myValue) as any; + } } export var TestContractAbi = abi; diff --git a/yarn-project/ethereum.js/src/contract/gen_def/index.ts b/yarn-project/ethereum.js/src/contract/gen_def/index.ts index f4c7c2084546..6f6abcae7cf7 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/index.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/index.ts @@ -36,7 +36,7 @@ function makeImports(name: string, importPath: string) { ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier('EthAddress')), ]), ), - ts.factory.createStringLiteral('@aztec/foundation'), + ts.factory.createStringLiteral('@aztec/foundation/eth-address'), ), ts.factory.createImportDeclaration( undefined, diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts index 30dcff20ae24..a71aca96946f 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts @@ -1,4 +1,4 @@ -import { EthAddress } from '@aztec/foundation'; +import { EthAddress } from '@aztec/foundation/eth-address'; import { bigIntToHex, bufferToHex, diff --git a/yarn-project/ethereum.js/src/serialize/free_funcs.ts b/yarn-project/ethereum.js/src/serialize/free_funcs.ts index eb3ce9b0a3ab..12a3298b5c9a 100644 --- a/yarn-project/ethereum.js/src/serialize/free_funcs.ts +++ b/yarn-project/ethereum.js/src/serialize/free_funcs.ts @@ -1,4 +1,4 @@ -import { toBigIntBE, toBufferBE } from '../bigint_buffer/index.js'; +import { toBigIntBE, toBufferBE } from '@aztec/foundation/bigint-buffer'; // For serializing bool. /** diff --git a/yarn-project/foundation/package.json b/yarn-project/foundation/package.json index 0242506d1230..1f03ee1aa069 100644 --- a/yarn-project/foundation/package.json +++ b/yarn-project/foundation/package.json @@ -25,7 +25,7 @@ "./timer": "./dest/timer/index.js", "./transport": "./dest/transport/index.js", "./wasm": "./dest/wasm/index.js", - "./bigint-buffer":"./dest/bigint-buffer/index.js" + "./bigint-buffer": "./dest/bigint-buffer/index.js" }, "scripts": { "prepare": "node ../yarn-project-base/scripts/update_build_manifest.mjs package.json", diff --git a/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelper.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelper.ts index c942acf16ad2..acc646ac7ec5 100644 --- a/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelper.ts +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelper.ts @@ -1,6 +1,6 @@ // THIS IS GENERATED CODE, DO NOT EDIT! /* eslint-disable */ -import { EthAddress } from '@aztec/foundation'; +import { EthAddress } from '@aztec/foundation/eth-address'; import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from '@aztec/ethereum.js/contract'; import * as Bytes from '@aztec/ethereum.js/contract/bytes.js'; @@ -10,7 +10,7 @@ interface DecoderHelperEventLogs {} interface DecoderHelperTxEventLogs {} export interface DecoderHelperTransactionReceipt extends ContractTxReceipt {} interface DecoderHelperMethods { - computeDiffRoot(_l2Block: Bytes.Bytes): TxCall; + computeDiffRootAndMessagesHash(_l2Block: Bytes.Bytes): TxCall<{ 0: Bytes.Bytes32; 1: Bytes.Bytes32 }>; decode(_l2Block: Bytes.Bytes): TxCall<{ 0: bigint; 1: Bytes.Bytes32; @@ -29,7 +29,7 @@ export class DecoderHelper extends Contract { } deploy(): TxSend { return super.deployBytecode( - '0x608060405234801561001057600080fd5b506109fb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634f93f40e1461003b578063e5c5e9a314610061575b600080fd5b61004e610049366004610745565b610094565b6040519081526020015b60405180910390f35b61007461006f366004610745565b6100a9565b604080519485526020850193909352918301526060820152608001610058565b60006100a083836100c9565b90505b92915050565b6000806000806100b98686610414565b9299919850965090945092505050565b60006100f66040518060800160405280600081526020016000815260200160008152602001600081525090565b6101ac84013560e090811c808352602090810286016101b0810135831c848301819052918202016101b4810135831c604085810191909152909102016101b80135901c6060820152600061014c600460026107cd565b825161015891906107fa565b67ffffffffffffffff8111156101705761017061080e565b604051908082528060200260200182016040528015610199578160200160208202803683370190505b5082519091506101b0906000906101b19060206107cd565b6101bc836004610824565b6101c69190610824565b90506000846020015160206101db91906107cd565b6101e6836004610824565b6101f09190610824565b905060008560400151604061020591906107cd565b610210836004610824565b61021a9190610824565b905060008660600151602061022f91906107cd565b6102399083610824565b905060005b86518110156103fc57604080516104c08082526104e0820190925260009160208201818036833701905050905060206101008d890182840137610100818101918e890190840182013761010081810191610200918f89019185010137610200818101916040918f880191850101376020600202810190506020848e0182840137602c808201916014918f870160200191850101376020810190506020603485018e0182840137602c808201916014918f8701605401918501013750610305600460026107cd565b6103109060206107cd565b61031a9088610824565b9650610328600460026107cd565b6103339060206107cd565b61033d9087610824565b955061034b600460026107cd565b6103569060406107cd565b6103609086610824565b945061036d604085610824565b935061037a606884610824565b925060028160405161038c9190610837565b602060405180830381855afa1580156103a9573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103cc9190610866565b8883815181106103de576103de61087f565b602090810291909101015250806103f481610895565b91505061023e565b506104068661045a565b9a9950505050505050505050565b813560e01c6000808061043461042b6001866108ae565b600488886105d2565b92506104438460d888886105d2565b915061044f868661067d565b905092959194509250565b6000805b825161046b8260026109a5565b1015610483578061047b81610895565b91505061045e565b60006104908260026109a5565b905080845260005b828110156105ad5760005b8281101561059a5760028682815181106104bf576104bf61087f565b6020026020010151878360016104d59190610824565b815181106104e5576104e561087f565b6020026020010151604051602001610507929190918252602082015260400190565b60408051601f198184030181529082905261052191610837565b602060405180830381855afa15801561053e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105619190610866565b8661056d6002846107fa565b8151811061057d5761057d61087f565b6020908102919091010152610593600282610824565b90506104a3565b50806105a581610895565b915050610498565b50836000815181106105c1576105c161087f565b602002602001015192505050919050565b6040805160d880825261010082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015360d485850160248301376002816040516106339190610837565b602060405180830381855afa158015610650573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106739190610866565b9695505050505050565b604080516101c88082526102008201909252600091908290826020820181803683370190505090508160048601602083013760006106bb86866100c9565b90508060046101ac036020018301527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516106fb9190610837565b602060405180830381855afa158015610718573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061073b9190610866565b61067391906109b1565b6000806020838503121561075857600080fd5b823567ffffffffffffffff8082111561077057600080fd5b818501915085601f83011261078457600080fd5b81358181111561079357600080fd5b8660208285010111156107a557600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176100a3576100a36107b7565b634e487b7160e01b600052601260045260246000fd5b600082610809576108096107e4565b500490565b634e487b7160e01b600052604160045260246000fd5b808201808211156100a3576100a36107b7565b6000825160005b81811015610858576020818601810151858301520161083e565b506000920191825250919050565b60006020828403121561087857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6000600182016108a7576108a76107b7565b5060010190565b818103818111156100a3576100a36107b7565b600181815b808511156108fc5781600019048211156108e2576108e26107b7565b808516156108ef57918102915b93841c93908002906108c6565b509250929050565b600082610913575060016100a3565b81610920575060006100a3565b816001811461093657600281146109405761095c565b60019150506100a3565b60ff841115610951576109516107b7565b50506001821b6100a3565b5060208310610133831016604e8410600b841016171561097f575081810a6100a3565b61098983836108c1565b806000190482111561099d5761099d6107b7565b029392505050565b60006100a08383610904565b6000826109c0576109c06107e4565b50069056fea26469706673582212202ef99c8a34102a8b892857ef4d2ff1773f31770e89ceca60a0bea54a127104f064736f6c63430008120033', + '0x608060405234801561001057600080fd5b50610bbd806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063bdfd97c01461003b578063e5c5e9a314610068575b600080fd5b61004e610049366004610900565b61009b565b604080519283526020830191909152015b60405180910390f35b61007b610076366004610900565b6100b8565b60408051948552602085019390935291830152606082015260800161005f565b6000806000806100ab86866100d8565b9097909650945050505050565b6000806000806100c886866105b6565b9299919850965090945092505050565b60008061010d6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6101466040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61023c86013560e090811c80845260209081028801610240810135831c85830181905291820201610244810135831c60408681019190915290910201610248810135821c606085018190526054020161024c0135901c608083015260006101af60046002610988565b83516101bb91906109b5565b67ffffffffffffffff8111156101d3576101d36109c9565b6040519080825280602002602001820160405280156101fc578160200160208202803683370190505b5061024083528351909150610212906020610988565b825161021f9060046109df565b61022991906109df565b6020808401919091528381015161023f91610988565b602083015161024f9060046109df565b61025991906109df565b6040808401919091528381015161026f91610988565b604083015161027f9060046109df565b61028991906109df565b6060808401919091528301516102a0906020610988565b82606001516102af91906109df565b608083015260608301516102c4906054610988565b82608001516102d391906109df565b60a083015260005b81518110156104df57604080516104c08082526104e0820190925260009160208201818036833701905050905060208060080285518b018284013760208501516101008281019290918c01908401820137604085015161010082810192610200928d019190850101376060850151610200828101926040928d0191908501013760206002028101905060808501516020818c0183850137602c808301926014918d840160200191860101376020820191506020603482018c0183850137602c808301926014918d84016054019186010137506103bb905060046002610988565b6103c6906020610988565b845185906103d59083906109df565b9052506103e460046002610988565b6103ef906020610988565b8460200181815161040091906109df565b90525061040f60046002610988565b61041a906040610988565b8460400181815161042b91906109df565b905250606084018051604091906104439083906109df565b9052506080840180516068919061045b9083906109df565b90525060405160029061046f9083906109f2565b602060405180830381855afa15801561048c573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104af9190610a21565b8383815181106104c1576104c1610a3a565b602090810291909101015250806104d781610a50565b9150506102db565b5060006104eb826105fd565b90506000806104fc60106020610988565b905060008167ffffffffffffffff811115610519576105196109c9565b6040519080825280601f01601f191660200182016040528015610543576020820181803683370190505b50905081601460a088015101602083013760028160405161056491906109f2565b602060405180830381855afa158015610581573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105a49190610a21565b939b939a509298505050505050505050565b813560e01c600080806105d66105cd600186610a69565b60048888610775565b92506105e6846101208888610775565b91506105f28686610822565b905092959194509250565b6000805b825161060e826002610b60565b1015610626578061061e81610a50565b915050610601565b6000610633826002610b60565b905080845260005b828110156107505760005b8281101561073d57600286828151811061066257610662610a3a565b60200260200101518783600161067891906109df565b8151811061068857610688610a3a565b60200260200101516040516020016106aa929190918252602082015260400190565b60408051601f19818403018152908290526106c4916109f2565b602060405180830381855afa1580156106e1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107049190610a21565b866107106002846109b5565b8151811061072057610720610a3a565b60209081029190910101526107366002826109df565b9050610646565b508061074881610a50565b91505061063b565b508360008151811061076457610764610a3a565b602002602001015192505050919050565b6040805161012080825261014082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015361011c85850160248301376002816040516107d891906109f2565b602060405180830381855afa1580156107f5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906108189190610a21565b9695505050505050565b604080516102788082526102a08201909252600091908290826020820181803683370190505090508160048601602083013760008061086187876100d8565b6102588501829052610278850181905260405191935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001906002906108a99086906109f2565b602060405180830381855afa1580156108c6573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906108e99190610a21565b6108f39190610b73565b9450505050505b92915050565b6000806020838503121561091357600080fd5b823567ffffffffffffffff8082111561092b57600080fd5b818501915085601f83011261093f57600080fd5b81358181111561094e57600080fd5b86602082850101111561096057600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176108fa576108fa610972565b634e487b7160e01b600052601260045260246000fd5b6000826109c4576109c461099f565b500490565b634e487b7160e01b600052604160045260246000fd5b808201808211156108fa576108fa610972565b6000825160005b81811015610a1357602081860181015185830152016109f9565b506000920191825250919050565b600060208284031215610a3357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060018201610a6257610a62610972565b5060010190565b818103818111156108fa576108fa610972565b600181815b80851115610ab7578160001904821115610a9d57610a9d610972565b80851615610aaa57918102915b93841c9390800290610a81565b509250929050565b600082610ace575060016108fa565b81610adb575060006108fa565b8160018114610af15760028114610afb57610b17565b60019150506108fa565b60ff841115610b0c57610b0c610972565b50506001821b6108fa565b5060208310610133831016604e8410600b8410161715610b3a575081810a6108fa565b610b448383610a7c565b8060001904821115610b5857610b58610972565b029392505050565b6000610b6c8383610abf565b9392505050565b600082610b8257610b8261099f565b50069056fea26469706673582212206f67550bf823fc5222b9bd273c244e63478d38338fa160a09802c12fd933f68964736f6c63430008120033', ) as any; } } diff --git a/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelperAbi.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelperAbi.ts index bc6ba0393e63..fb2cbe3e729d 100644 --- a/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelperAbi.ts +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/DecoderHelperAbi.ts @@ -8,15 +8,20 @@ export default new ContractAbi([ type: 'bytes', }, ], - name: 'computeDiffRoot', + name: 'computeDiffRootAndMessagesHash', outputs: [ { internalType: 'bytes32', name: '', type: 'bytes32', }, + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, ], - stateMutability: 'pure', + stateMutability: 'view', type: 'function', }, { @@ -50,7 +55,7 @@ export default new ContractAbi([ type: 'bytes32', }, ], - stateMutability: 'pure', + stateMutability: 'view', type: 'function', }, ]); diff --git a/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts index 6730db47af97..83f9a3971cce 100644 --- a/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts @@ -36,7 +36,7 @@ export class Rollup extends Contract { } deploy(): TxSend { return super.deployBytecode( - '0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610d5483390190565b608051610cdb61007960003960008181604b015261016b0152610cdb6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806308c84e70146100465780631ab9c6031461008a5780637c39d130146100a1575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61009360005481565b604051908152602001610081565b6100b46100af36600461091e565b6100b6565b005b6000806000806100c68686610237565b60005493975091955093509150158015906100e357508260005414155b1561011357600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b604080516001808252818301909252600091602080830190803683370190505090508181600081518110610149576101496109f9565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a2908b908590600401610a33565b602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610aad565b610200576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f655779015b9b95c7fd18f01ea4619ab4c31289bbe134ba85c5b20bcdeb1dabf391a25050505050505050565b813560e01c6000808061025761024e600186610aec565b6004888861027d565b92506102668460d8888861027d565b91506102728686610328565b905092959194509250565b6040805160d880825261010082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015360d485850160248301376002816040516102de9190610aff565b602060405180830381855afa1580156102fb573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061031e9190610b1b565b9695505050505050565b604080516101c880825261020082019092526000919082908260208201818036833701905050905081600486016020830137600061036686866103fc565b90508060046101ac036020018301527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516103a69190610aff565b602060405180830381855afa1580156103c3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103e69190610b1b565b6103f09190610b4a565b93505050505b92915050565b60006104296040518060800160405280600081526020016000815260200160008152602001600081525090565b6101ac84013560e090811c808352602090810286016101b0810135831c848301819052918202016101b4810135831c604085810191909152909102016101b80135901c6060820152600061047f60046002610b5e565b825161048b9190610b75565b67ffffffffffffffff8111156104a3576104a36108bf565b6040519080825280602002602001820160405280156104cc578160200160208202803683370190505b5082519091506101b0906000906104e4906020610b5e565b6104ef836004610b89565b6104f99190610b89565b905060008460200151602061050e9190610b5e565b610519836004610b89565b6105239190610b89565b90506000856040015160406105389190610b5e565b610543836004610b89565b61054d9190610b89565b90506000866060015160206105629190610b5e565b61056c9083610b89565b905060005b865181101561072f57604080516104c08082526104e0820190925260009160208201818036833701905050905060206101008d890182840137610100818101918e890190840182013761010081810191610200918f89019185010137610200818101916040918f880191850101376020600202810190506020848e0182840137602c808201916014918f870160200191850101376020810190506020603485018e0182840137602c808201916014918f870160540191850101375061063860046002610b5e565b610643906020610b5e565b61064d9088610b89565b965061065b60046002610b5e565b610666906020610b5e565b6106709087610b89565b955061067e60046002610b5e565b610689906040610b5e565b6106939086610b89565b94506106a0604085610b89565b93506106ad606884610b89565b92506002816040516106bf9190610aff565b602060405180830381855afa1580156106dc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106ff9190610b1b565b888381518110610711576107116109f9565b6020908102919091010152508061072781610b9c565b915050610571565b5061073986610747565b9a9950505050505050505050565b6000805b8251610758826002610c99565b1015610770578061076881610b9c565b91505061074b565b600061077d826002610c99565b905080845260005b8281101561089a5760005b828110156108875760028682815181106107ac576107ac6109f9565b6020026020010151878360016107c29190610b89565b815181106107d2576107d26109f9565b60200260200101516040516020016107f4929190918252602082015260400190565b60408051601f198184030181529082905261080e91610aff565b602060405180830381855afa15801561082b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061084e9190610b1b565b8661085a600284610b75565b8151811061086a5761086a6109f9565b6020908102919091010152610880600282610b89565b9050610790565b508061089281610b9c565b915050610785565b50836000815181106108ae576108ae6109f9565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b60008083601f8401126108e757600080fd5b50813567ffffffffffffffff8111156108ff57600080fd5b60208301915083602082850101111561091757600080fd5b9250929050565b60008060006040848603121561093357600080fd5b833567ffffffffffffffff8082111561094b57600080fd5b818601915086601f83011261095f57600080fd5b813581811115610971576109716108bf565b604051601f8201601f19908116603f01168101908382118183101715610999576109996108bf565b816040528281528960208487010111156109b257600080fd5b8260208601602083013760006020848301015280975050505060208601359150808211156109df57600080fd5b506109ec868287016108d5565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610a2a578181015183820152602001610a12565b50506000910152565b60408152600083518060408401526020610a538260608601838901610a0f565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610aa15784518252938301936001929092019190830190610a81565b50979650505050505050565b600060208284031215610abf57600080fd5b81518015158114610acf57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156103f6576103f6610ad6565b60008251610b11818460208701610a0f565b9190910192915050565b600060208284031215610b2d57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610b5957610b59610b34565b500690565b80820281158282048414176103f6576103f6610ad6565b600082610b8457610b84610b34565b500490565b808201808211156103f6576103f6610ad6565b600060018201610bae57610bae610ad6565b5060010190565b600181815b80851115610bf0578160001904821115610bd657610bd6610ad6565b80851615610be357918102915b93841c9390800290610bba565b509250929050565b600082610c07575060016103f6565b81610c14575060006103f6565b8160018114610c2a5760028114610c3457610c50565b60019150506103f6565b60ff841115610c4557610c45610ad6565b50506001821b6103f6565b5060208310610133831016604e8410600b8410161715610c73575081810a6103f6565b610c7d8383610bb5565b8060001904821115610c9157610c91610ad6565b029392505050565b6000610acf8383610bf856fea2646970667358221220ddf248ba6894d5466329c62aa3e8d071d039ec5f5594b21af88ea780d45fefb364736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea264697066735822122079065ece8684a52b261c9ab9f34e06d3a4e53f346b36185587fd3fe29e5c9cc764736f6c63430008120033', + '0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610eef83390190565b608051610e7661007960003960008181604b015261016b0152610e766000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806308c84e70146100465780631ab9c6031461008a5780637c39d130146100a1575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61009360005481565b604051908152602001610081565b6100b46100af366004610ab9565b6100b6565b005b6000806000806100c68686610237565b60005493975091955093509150158015906100e357508260005414155b1561011357600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061014957610149610b94565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a2908b908590600401610bce565b602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610c48565b610200576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f655779015b9b95c7fd18f01ea4619ab4c31289bbe134ba85c5b20bcdeb1dabf391a25050505050505050565b813560e01c6000808061025761024e600186610c87565b6004888861027e565b925061026784610120888861027e565b9150610273868661032b565b905092959194509250565b6040805161012080825261014082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015361011c85850160248301376002816040516102e19190610c9a565b602060405180830381855afa1580156102fe573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103219190610cb6565b9695505050505050565b604080516102788082526102a08201909252600091908290826020820181803683370190505090508160048601602083013760008061036a8787610409565b6102588501829052610278850181905260405191935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001906002906103b2908690610c9a565b602060405180830381855afa1580156103cf573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103f29190610cb6565b6103fc9190610ce5565b9450505050505b92915050565b60008061043e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6104776040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61023c86013560e090811c80845260209081028801610240810135831c85830181905291820201610244810135831c60408681019190915290910201610248810135821c606085018190526054020161024c0135901c608083015260006104e060046002610cf9565b83516104ec9190610d10565b67ffffffffffffffff81111561050457610504610a61565b60405190808252806020026020018201604052801561052d578160200160208202803683370190505b5061024083528351909150610543906020610cf9565b8251610550906004610d24565b61055a9190610d24565b6020808401919091528381015161057091610cf9565b6020830151610580906004610d24565b61058a9190610d24565b604080840191909152838101516105a091610cf9565b60408301516105b0906004610d24565b6105ba9190610d24565b6060808401919091528301516105d1906020610cf9565b82606001516105e09190610d24565b608083015260608301516105f5906054610cf9565b82608001516106049190610d24565b60a083015260005b815181101561081057604080516104c08082526104e0820190925260009160208201818036833701905050905060208060080285518b018284013760208501516101008281019290918c01908401820137604085015161010082810192610200928d019190850101376060850151610200828101926040928d0191908501013760206002028101905060808501516020818c0183850137602c808301926014918d840160200191860101376020820191506020603482018c0183850137602c808301926014918d84016054019186010137506106ec905060046002610cf9565b6106f7906020610cf9565b84518590610706908390610d24565b90525061071560046002610cf9565b610720906020610cf9565b846020018181516107319190610d24565b90525061074060046002610cf9565b61074b906040610cf9565b8460400181815161075c9190610d24565b90525060608401805160409190610774908390610d24565b9052506080840180516068919061078c908390610d24565b9052506040516002906107a0908390610c9a565b602060405180830381855afa1580156107bd573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107e09190610cb6565b8383815181106107f2576107f2610b94565b6020908102919091010152508061080881610d37565b91505061060c565b50600061081c826108e9565b905060008061082d60106020610cf9565b905060008167ffffffffffffffff81111561084a5761084a610a61565b6040519080825280601f01601f191660200182016040528015610874576020820181803683370190505b50905081601460a08801510160208301376002816040516108959190610c9a565b602060405180830381855afa1580156108b2573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906108d59190610cb6565b9398509296505050505050505b9250929050565b6000805b82516108fa826002610e34565b1015610912578061090a81610d37565b9150506108ed565b600061091f826002610e34565b905080845260005b82811015610a3c5760005b82811015610a2957600286828151811061094e5761094e610b94565b6020026020010151878360016109649190610d24565b8151811061097457610974610b94565b6020026020010151604051602001610996929190918252602082015260400190565b60408051601f19818403018152908290526109b091610c9a565b602060405180830381855afa1580156109cd573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109f09190610cb6565b866109fc600284610d10565b81518110610a0c57610a0c610b94565b6020908102919091010152610a22600282610d24565b9050610932565b5080610a3481610d37565b915050610927565b5083600081518110610a5057610a50610b94565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b60008083601f840112610a8957600080fd5b50813567ffffffffffffffff811115610aa157600080fd5b6020830191508360208285010111156108e257600080fd5b600080600060408486031215610ace57600080fd5b833567ffffffffffffffff80821115610ae657600080fd5b818601915086601f830112610afa57600080fd5b813581811115610b0c57610b0c610a61565b604051601f8201601f19908116603f01168101908382118183101715610b3457610b34610a61565b81604052828152896020848701011115610b4d57600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115610b7a57600080fd5b50610b8786828701610a77565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610bc5578181015183820152602001610bad565b50506000910152565b60408152600083518060408401526020610bee8260608601838901610baa565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610c3c5784518252938301936001929092019190830190610c1c565b50979650505050505050565b600060208284031215610c5a57600080fd5b81518015158114610c6a57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561040357610403610c71565b60008251610cac818460208701610baa565b9190910192915050565b600060208284031215610cc857600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610cf457610cf4610ccf565b500690565b808202811582820484141761040357610403610c71565b600082610d1f57610d1f610ccf565b500490565b8082018082111561040357610403610c71565b600060018201610d4957610d49610c71565b5060010190565b600181815b80851115610d8b578160001904821115610d7157610d71610c71565b80851615610d7e57918102915b93841c9390800290610d55565b509250929050565b600082610da257506001610403565b81610daf57506000610403565b8160018114610dc55760028114610dcf57610deb565b6001915050610403565b60ff841115610de057610de0610c71565b50506001821b610403565b5060208310610133831016604e8410600b8410161715610e0e575081810a610403565b610e188383610d50565b8060001904821115610e2c57610e2c610c71565b029392505050565b6000610c6a8383610d9356fea26469706673582212201c00b2c5d56e1c81c09d1676bc7d8d03a02f0908b4d016f19893cdd27242d27e64736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea264697066735822122079065ece8684a52b261c9ab9f34e06d3a4e53f346b36185587fd3fe29e5c9cc764736f6c63430008120033', ) as any; } } diff --git a/yarn-project/l1-contracts/src/viem-contracts/DecoderHelper.ts b/yarn-project/l1-contracts/src/viem-contracts/DecoderHelper.ts index fddfb2ee2717..7bd614dc0d66 100644 --- a/yarn-project/l1-contracts/src/viem-contracts/DecoderHelper.ts +++ b/yarn-project/l1-contracts/src/viem-contracts/DecoderHelper.ts @@ -10,15 +10,20 @@ export const DecoderHelperAbi = [ type: 'bytes', }, ], - name: 'computeDiffRoot', + name: 'computeDiffRootAndMessagesHash', outputs: [ { internalType: 'bytes32', name: '', type: 'bytes32', }, + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, ], - stateMutability: 'pure', + stateMutability: 'view', type: 'function', }, { @@ -52,7 +57,7 @@ export const DecoderHelperAbi = [ type: 'bytes32', }, ], - stateMutability: 'pure', + stateMutability: 'view', type: 'function', }, ] as const; @@ -60,4 +65,4 @@ export const DecoderHelperAbi = [ * DecoderHelper Bytecode for viem. */ export const DecoderHelperBytecode = - '0x608060405234801561001057600080fd5b506109fb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634f93f40e1461003b578063e5c5e9a314610061575b600080fd5b61004e610049366004610745565b610094565b6040519081526020015b60405180910390f35b61007461006f366004610745565b6100a9565b604080519485526020850193909352918301526060820152608001610058565b60006100a083836100c9565b90505b92915050565b6000806000806100b98686610414565b9299919850965090945092505050565b60006100f66040518060800160405280600081526020016000815260200160008152602001600081525090565b6101ac84013560e090811c808352602090810286016101b0810135831c848301819052918202016101b4810135831c604085810191909152909102016101b80135901c6060820152600061014c600460026107cd565b825161015891906107fa565b67ffffffffffffffff8111156101705761017061080e565b604051908082528060200260200182016040528015610199578160200160208202803683370190505b5082519091506101b0906000906101b19060206107cd565b6101bc836004610824565b6101c69190610824565b90506000846020015160206101db91906107cd565b6101e6836004610824565b6101f09190610824565b905060008560400151604061020591906107cd565b610210836004610824565b61021a9190610824565b905060008660600151602061022f91906107cd565b6102399083610824565b905060005b86518110156103fc57604080516104c08082526104e0820190925260009160208201818036833701905050905060206101008d890182840137610100818101918e890190840182013761010081810191610200918f89019185010137610200818101916040918f880191850101376020600202810190506020848e0182840137602c808201916014918f870160200191850101376020810190506020603485018e0182840137602c808201916014918f8701605401918501013750610305600460026107cd565b6103109060206107cd565b61031a9088610824565b9650610328600460026107cd565b6103339060206107cd565b61033d9087610824565b955061034b600460026107cd565b6103569060406107cd565b6103609086610824565b945061036d604085610824565b935061037a606884610824565b925060028160405161038c9190610837565b602060405180830381855afa1580156103a9573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103cc9190610866565b8883815181106103de576103de61087f565b602090810291909101015250806103f481610895565b91505061023e565b506104068661045a565b9a9950505050505050505050565b813560e01c6000808061043461042b6001866108ae565b600488886105d2565b92506104438460d888886105d2565b915061044f868661067d565b905092959194509250565b6000805b825161046b8260026109a5565b1015610483578061047b81610895565b91505061045e565b60006104908260026109a5565b905080845260005b828110156105ad5760005b8281101561059a5760028682815181106104bf576104bf61087f565b6020026020010151878360016104d59190610824565b815181106104e5576104e561087f565b6020026020010151604051602001610507929190918252602082015260400190565b60408051601f198184030181529082905261052191610837565b602060405180830381855afa15801561053e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105619190610866565b8661056d6002846107fa565b8151811061057d5761057d61087f565b6020908102919091010152610593600282610824565b90506104a3565b50806105a581610895565b915050610498565b50836000815181106105c1576105c161087f565b602002602001015192505050919050565b6040805160d880825261010082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015360d485850160248301376002816040516106339190610837565b602060405180830381855afa158015610650573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106739190610866565b9695505050505050565b604080516101c88082526102008201909252600091908290826020820181803683370190505090508160048601602083013760006106bb86866100c9565b90508060046101ac036020018301527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516106fb9190610837565b602060405180830381855afa158015610718573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061073b9190610866565b61067391906109b1565b6000806020838503121561075857600080fd5b823567ffffffffffffffff8082111561077057600080fd5b818501915085601f83011261078457600080fd5b81358181111561079357600080fd5b8660208285010111156107a557600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176100a3576100a36107b7565b634e487b7160e01b600052601260045260246000fd5b600082610809576108096107e4565b500490565b634e487b7160e01b600052604160045260246000fd5b808201808211156100a3576100a36107b7565b6000825160005b81811015610858576020818601810151858301520161083e565b506000920191825250919050565b60006020828403121561087857600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6000600182016108a7576108a76107b7565b5060010190565b818103818111156100a3576100a36107b7565b600181815b808511156108fc5781600019048211156108e2576108e26107b7565b808516156108ef57918102915b93841c93908002906108c6565b509250929050565b600082610913575060016100a3565b81610920575060006100a3565b816001811461093657600281146109405761095c565b60019150506100a3565b60ff841115610951576109516107b7565b50506001821b6100a3565b5060208310610133831016604e8410600b841016171561097f575081810a6100a3565b61098983836108c1565b806000190482111561099d5761099d6107b7565b029392505050565b60006100a08383610904565b6000826109c0576109c06107e4565b50069056fea26469706673582212202ef99c8a34102a8b892857ef4d2ff1773f31770e89ceca60a0bea54a127104f064736f6c63430008120033'; + '0x608060405234801561001057600080fd5b50610bbd806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063bdfd97c01461003b578063e5c5e9a314610068575b600080fd5b61004e610049366004610900565b61009b565b604080519283526020830191909152015b60405180910390f35b61007b610076366004610900565b6100b8565b60408051948552602085019390935291830152606082015260800161005f565b6000806000806100ab86866100d8565b9097909650945050505050565b6000806000806100c886866105b6565b9299919850965090945092505050565b60008061010d6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6101466040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61023c86013560e090811c80845260209081028801610240810135831c85830181905291820201610244810135831c60408681019190915290910201610248810135821c606085018190526054020161024c0135901c608083015260006101af60046002610988565b83516101bb91906109b5565b67ffffffffffffffff8111156101d3576101d36109c9565b6040519080825280602002602001820160405280156101fc578160200160208202803683370190505b5061024083528351909150610212906020610988565b825161021f9060046109df565b61022991906109df565b6020808401919091528381015161023f91610988565b602083015161024f9060046109df565b61025991906109df565b6040808401919091528381015161026f91610988565b604083015161027f9060046109df565b61028991906109df565b6060808401919091528301516102a0906020610988565b82606001516102af91906109df565b608083015260608301516102c4906054610988565b82608001516102d391906109df565b60a083015260005b81518110156104df57604080516104c08082526104e0820190925260009160208201818036833701905050905060208060080285518b018284013760208501516101008281019290918c01908401820137604085015161010082810192610200928d019190850101376060850151610200828101926040928d0191908501013760206002028101905060808501516020818c0183850137602c808301926014918d840160200191860101376020820191506020603482018c0183850137602c808301926014918d84016054019186010137506103bb905060046002610988565b6103c6906020610988565b845185906103d59083906109df565b9052506103e460046002610988565b6103ef906020610988565b8460200181815161040091906109df565b90525061040f60046002610988565b61041a906040610988565b8460400181815161042b91906109df565b905250606084018051604091906104439083906109df565b9052506080840180516068919061045b9083906109df565b90525060405160029061046f9083906109f2565b602060405180830381855afa15801561048c573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906104af9190610a21565b8383815181106104c1576104c1610a3a565b602090810291909101015250806104d781610a50565b9150506102db565b5060006104eb826105fd565b90506000806104fc60106020610988565b905060008167ffffffffffffffff811115610519576105196109c9565b6040519080825280601f01601f191660200182016040528015610543576020820181803683370190505b50905081601460a088015101602083013760028160405161056491906109f2565b602060405180830381855afa158015610581573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105a49190610a21565b939b939a509298505050505050505050565b813560e01c600080806105d66105cd600186610a69565b60048888610775565b92506105e6846101208888610775565b91506105f28686610822565b905092959194509250565b6000805b825161060e826002610b60565b1015610626578061061e81610a50565b915050610601565b6000610633826002610b60565b905080845260005b828110156107505760005b8281101561073d57600286828151811061066257610662610a3a565b60200260200101518783600161067891906109df565b8151811061068857610688610a3a565b60200260200101516040516020016106aa929190918252602082015260400190565b60408051601f19818403018152908290526106c4916109f2565b602060405180830381855afa1580156106e1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107049190610a21565b866107106002846109b5565b8151811061072057610720610a3a565b60209081029190910101526107366002826109df565b9050610646565b508061074881610a50565b91505061063b565b508360008151811061076457610764610a3a565b602002602001015192505050919050565b6040805161012080825261014082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015361011c85850160248301376002816040516107d891906109f2565b602060405180830381855afa1580156107f5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906108189190610a21565b9695505050505050565b604080516102788082526102a08201909252600091908290826020820181803683370190505090508160048601602083013760008061086187876100d8565b6102588501829052610278850181905260405191935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001906002906108a99086906109f2565b602060405180830381855afa1580156108c6573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906108e99190610a21565b6108f39190610b73565b9450505050505b92915050565b6000806020838503121561091357600080fd5b823567ffffffffffffffff8082111561092b57600080fd5b818501915085601f83011261093f57600080fd5b81358181111561094e57600080fd5b86602082850101111561096057600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176108fa576108fa610972565b634e487b7160e01b600052601260045260246000fd5b6000826109c4576109c461099f565b500490565b634e487b7160e01b600052604160045260246000fd5b808201808211156108fa576108fa610972565b6000825160005b81811015610a1357602081860181015185830152016109f9565b506000920191825250919050565b600060208284031215610a3357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060018201610a6257610a62610972565b5060010190565b818103818111156108fa576108fa610972565b600181815b80851115610ab7578160001904821115610a9d57610a9d610972565b80851615610aaa57918102915b93841c9390800290610a81565b509250929050565b600082610ace575060016108fa565b81610adb575060006108fa565b8160018114610af15760028114610afb57610b17565b60019150506108fa565b60ff841115610b0c57610b0c610972565b50506001821b6108fa565b5060208310610133831016604e8410600b8410161715610b3a575081810a6108fa565b610b448383610a7c565b8060001904821115610b5857610b58610972565b029392505050565b6000610b6c8383610abf565b9392505050565b600082610b8257610b8261099f565b50069056fea26469706673582212206f67550bf823fc5222b9bd273c244e63478d38338fa160a09802c12fd933f68964736f6c63430008120033'; diff --git a/yarn-project/l1-contracts/src/viem-contracts/Rollup.ts b/yarn-project/l1-contracts/src/viem-contracts/Rollup.ts index 843bfd9b2a7a..04e882b4f8cc 100644 --- a/yarn-project/l1-contracts/src/viem-contracts/Rollup.ts +++ b/yarn-project/l1-contracts/src/viem-contracts/Rollup.ts @@ -90,4 +90,4 @@ export const RollupAbi = [ * Rollup Bytecode for viem. */ export const RollupBytecode = - '0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610d5483390190565b608051610cdb61007960003960008181604b015261016b0152610cdb6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806308c84e70146100465780631ab9c6031461008a5780637c39d130146100a1575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61009360005481565b604051908152602001610081565b6100b46100af36600461091e565b6100b6565b005b6000806000806100c68686610237565b60005493975091955093509150158015906100e357508260005414155b1561011357600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b604080516001808252818301909252600091602080830190803683370190505090508181600081518110610149576101496109f9565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a2908b908590600401610a33565b602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610aad565b610200576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f655779015b9b95c7fd18f01ea4619ab4c31289bbe134ba85c5b20bcdeb1dabf391a25050505050505050565b813560e01c6000808061025761024e600186610aec565b6004888861027d565b92506102668460d8888861027d565b91506102728686610328565b905092959194509250565b6040805160d880825261010082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015360d485850160248301376002816040516102de9190610aff565b602060405180830381855afa1580156102fb573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061031e9190610b1b565b9695505050505050565b604080516101c880825261020082019092526000919082908260208201818036833701905050905081600486016020830137600061036686866103fc565b90508060046101ac036020018301527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516103a69190610aff565b602060405180830381855afa1580156103c3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103e69190610b1b565b6103f09190610b4a565b93505050505b92915050565b60006104296040518060800160405280600081526020016000815260200160008152602001600081525090565b6101ac84013560e090811c808352602090810286016101b0810135831c848301819052918202016101b4810135831c604085810191909152909102016101b80135901c6060820152600061047f60046002610b5e565b825161048b9190610b75565b67ffffffffffffffff8111156104a3576104a36108bf565b6040519080825280602002602001820160405280156104cc578160200160208202803683370190505b5082519091506101b0906000906104e4906020610b5e565b6104ef836004610b89565b6104f99190610b89565b905060008460200151602061050e9190610b5e565b610519836004610b89565b6105239190610b89565b90506000856040015160406105389190610b5e565b610543836004610b89565b61054d9190610b89565b90506000866060015160206105629190610b5e565b61056c9083610b89565b905060005b865181101561072f57604080516104c08082526104e0820190925260009160208201818036833701905050905060206101008d890182840137610100818101918e890190840182013761010081810191610200918f89019185010137610200818101916040918f880191850101376020600202810190506020848e0182840137602c808201916014918f870160200191850101376020810190506020603485018e0182840137602c808201916014918f870160540191850101375061063860046002610b5e565b610643906020610b5e565b61064d9088610b89565b965061065b60046002610b5e565b610666906020610b5e565b6106709087610b89565b955061067e60046002610b5e565b610689906040610b5e565b6106939086610b89565b94506106a0604085610b89565b93506106ad606884610b89565b92506002816040516106bf9190610aff565b602060405180830381855afa1580156106dc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906106ff9190610b1b565b888381518110610711576107116109f9565b6020908102919091010152508061072781610b9c565b915050610571565b5061073986610747565b9a9950505050505050505050565b6000805b8251610758826002610c99565b1015610770578061076881610b9c565b91505061074b565b600061077d826002610c99565b905080845260005b8281101561089a5760005b828110156108875760028682815181106107ac576107ac6109f9565b6020026020010151878360016107c29190610b89565b815181106107d2576107d26109f9565b60200260200101516040516020016107f4929190918252602082015260400190565b60408051601f198184030181529082905261080e91610aff565b602060405180830381855afa15801561082b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061084e9190610b1b565b8661085a600284610b75565b8151811061086a5761086a6109f9565b6020908102919091010152610880600282610b89565b9050610790565b508061089281610b9c565b915050610785565b50836000815181106108ae576108ae6109f9565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b60008083601f8401126108e757600080fd5b50813567ffffffffffffffff8111156108ff57600080fd5b60208301915083602082850101111561091757600080fd5b9250929050565b60008060006040848603121561093357600080fd5b833567ffffffffffffffff8082111561094b57600080fd5b818601915086601f83011261095f57600080fd5b813581811115610971576109716108bf565b604051601f8201601f19908116603f01168101908382118183101715610999576109996108bf565b816040528281528960208487010111156109b257600080fd5b8260208601602083013760006020848301015280975050505060208601359150808211156109df57600080fd5b506109ec868287016108d5565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610a2a578181015183820152602001610a12565b50506000910152565b60408152600083518060408401526020610a538260608601838901610a0f565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610aa15784518252938301936001929092019190830190610a81565b50979650505050505050565b600060208284031215610abf57600080fd5b81518015158114610acf57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156103f6576103f6610ad6565b60008251610b11818460208701610a0f565b9190910192915050565b600060208284031215610b2d57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610b5957610b59610b34565b500690565b80820281158282048414176103f6576103f6610ad6565b600082610b8457610b84610b34565b500490565b808201808211156103f6576103f6610ad6565b600060018201610bae57610bae610ad6565b5060010190565b600181815b80851115610bf0578160001904821115610bd657610bd6610ad6565b80851615610be357918102915b93841c9390800290610bba565b509250929050565b600082610c07575060016103f6565b81610c14575060006103f6565b8160018114610c2a5760028114610c3457610c50565b60019150506103f6565b60ff841115610c4557610c45610ad6565b50506001821b6103f6565b5060208310610133831016604e8410600b8410161715610c73575081810a6103f6565b610c7d8383610bb5565b8060001904821115610c9157610c91610ad6565b029392505050565b6000610acf8383610bf856fea2646970667358221220ddf248ba6894d5466329c62aa3e8d071d039ec5f5594b21af88ea780d45fefb364736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea264697066735822122079065ece8684a52b261c9ab9f34e06d3a4e53f346b36185587fd3fe29e5c9cc764736f6c63430008120033'; + '0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610eef83390190565b608051610e7661007960003960008181604b015261016b0152610e766000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806308c84e70146100465780631ab9c6031461008a5780637c39d130146100a1575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61009360005481565b604051908152602001610081565b6100b46100af366004610ab9565b6100b6565b005b6000806000806100c68686610237565b60005493975091955093509150158015906100e357508260005414155b1561011357600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061014957610149610b94565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a2908b908590600401610bce565b602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610c48565b610200576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f655779015b9b95c7fd18f01ea4619ab4c31289bbe134ba85c5b20bcdeb1dabf391a25050505050505050565b813560e01c6000808061025761024e600186610c87565b6004888861027e565b925061026784610120888861027e565b9150610273868661032b565b905092959194509250565b6040805161012080825261014082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015361011c85850160248301376002816040516102e19190610c9a565b602060405180830381855afa1580156102fe573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103219190610cb6565b9695505050505050565b604080516102788082526102a08201909252600091908290826020820181803683370190505090508160048601602083013760008061036a8787610409565b6102588501829052610278850181905260405191935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001906002906103b2908690610c9a565b602060405180830381855afa1580156103cf573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103f29190610cb6565b6103fc9190610ce5565b9450505050505b92915050565b60008061043e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6104776040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61023c86013560e090811c80845260209081028801610240810135831c85830181905291820201610244810135831c60408681019190915290910201610248810135821c606085018190526054020161024c0135901c608083015260006104e060046002610cf9565b83516104ec9190610d10565b67ffffffffffffffff81111561050457610504610a61565b60405190808252806020026020018201604052801561052d578160200160208202803683370190505b5061024083528351909150610543906020610cf9565b8251610550906004610d24565b61055a9190610d24565b6020808401919091528381015161057091610cf9565b6020830151610580906004610d24565b61058a9190610d24565b604080840191909152838101516105a091610cf9565b60408301516105b0906004610d24565b6105ba9190610d24565b6060808401919091528301516105d1906020610cf9565b82606001516105e09190610d24565b608083015260608301516105f5906054610cf9565b82608001516106049190610d24565b60a083015260005b815181101561081057604080516104c08082526104e0820190925260009160208201818036833701905050905060208060080285518b018284013760208501516101008281019290918c01908401820137604085015161010082810192610200928d019190850101376060850151610200828101926040928d0191908501013760206002028101905060808501516020818c0183850137602c808301926014918d840160200191860101376020820191506020603482018c0183850137602c808301926014918d84016054019186010137506106ec905060046002610cf9565b6106f7906020610cf9565b84518590610706908390610d24565b90525061071560046002610cf9565b610720906020610cf9565b846020018181516107319190610d24565b90525061074060046002610cf9565b61074b906040610cf9565b8460400181815161075c9190610d24565b90525060608401805160409190610774908390610d24565b9052506080840180516068919061078c908390610d24565b9052506040516002906107a0908390610c9a565b602060405180830381855afa1580156107bd573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107e09190610cb6565b8383815181106107f2576107f2610b94565b6020908102919091010152508061080881610d37565b91505061060c565b50600061081c826108e9565b905060008061082d60106020610cf9565b905060008167ffffffffffffffff81111561084a5761084a610a61565b6040519080825280601f01601f191660200182016040528015610874576020820181803683370190505b50905081601460a08801510160208301376002816040516108959190610c9a565b602060405180830381855afa1580156108b2573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906108d59190610cb6565b9398509296505050505050505b9250929050565b6000805b82516108fa826002610e34565b1015610912578061090a81610d37565b9150506108ed565b600061091f826002610e34565b905080845260005b82811015610a3c5760005b82811015610a2957600286828151811061094e5761094e610b94565b6020026020010151878360016109649190610d24565b8151811061097457610974610b94565b6020026020010151604051602001610996929190918252602082015260400190565b60408051601f19818403018152908290526109b091610c9a565b602060405180830381855afa1580156109cd573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109f09190610cb6565b866109fc600284610d10565b81518110610a0c57610a0c610b94565b6020908102919091010152610a22600282610d24565b9050610932565b5080610a3481610d37565b915050610927565b5083600081518110610a5057610a50610b94565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b60008083601f840112610a8957600080fd5b50813567ffffffffffffffff811115610aa157600080fd5b6020830191508360208285010111156108e257600080fd5b600080600060408486031215610ace57600080fd5b833567ffffffffffffffff80821115610ae657600080fd5b818601915086601f830112610afa57600080fd5b813581811115610b0c57610b0c610a61565b604051601f8201601f19908116603f01168101908382118183101715610b3457610b34610a61565b81604052828152896020848701011115610b4d57600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115610b7a57600080fd5b50610b8786828701610a77565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610bc5578181015183820152602001610bad565b50506000910152565b60408152600083518060408401526020610bee8260608601838901610baa565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610c3c5784518252938301936001929092019190830190610c1c565b50979650505050505050565b600060208284031215610c5a57600080fd5b81518015158114610c6a57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561040357610403610c71565b60008251610cac818460208701610baa565b9190910192915050565b600060208284031215610cc857600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082610cf457610cf4610ccf565b500690565b808202811582820484141761040357610403610c71565b600082610d1f57610d1f610ccf565b500490565b8082018082111561040357610403610c71565b600060018201610d4957610d49610c71565b5060010190565b600181815b80851115610d8b578160001904821115610d7157610d71610c71565b80851615610d7e57918102915b93841c9390800290610d55565b509250929050565b600082610da257506001610403565b81610daf57506000610403565b8160018114610dc55760028114610dcf57610deb565b6001915050610403565b60ff841115610de057610de0610c71565b50506001821b610403565b5060208310610133831016604e8410600b8410161715610e0e575081810a610403565b610e188383610d50565b8060001904821115610e2c57610e2c610c71565b029392505050565b6000610c6a8383610d9356fea26469706673582212201c00b2c5d56e1c81c09d1676bc7d8d03a02f0908b4d016f19893cdd27242d27e64736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea264697066735822122079065ece8684a52b261c9ab9f34e06d3a4e53f346b36185587fd3fe29e5c9cc764736f6c63430008120033'; diff --git a/yarn-project/merkle-tree/README.md b/yarn-project/merkle-tree/README.md index a59fc047a5fb..68d7716d4b2d 100644 --- a/yarn-project/merkle-tree/README.md +++ b/yarn-project/merkle-tree/README.md @@ -1 +1,41 @@ # Merkle Tree + +## Overview + +The Merkle Trees package contains typescript implementations of the various Merkle Trees required by the system. + +- Append only 'Standard' merkle trees. New values are inserted into the next available leaf index. Values are never updated. +- Indexed trees are also append only in nature but retain the ability to update leaves. The reason for this is that the Indexed Tree leaves not only store the value but the index of the next highest leaf. New insertions can require prior leaves to be updated. +- Sparse trees that can be updated at any index. The 'size' of the tree is defined by the number of non-empty leaves, not by the highest populated leaf index as is the case with a Standard Tree. + +## Implementations + +All implementations require the following arguments: + +- An instance of level db for storing information at a tree node level as well as some tree level metadata. +- An instance of a Hasher object. Used for hashing the nodes of the Merkle Tree. +- A name, for namespacing the tree's nodes within the db. +- The depth of the tree, this is exclusive of the root. + +Implementations have commit/rollback semantics with modifications stored only in memory until being committed. Rolling back returns the tree discards the cached modifications and returns the tree to it's previous committed state. + +## Tree Operations + +The primary operations available on the various implementations are: + +- Create a new, empty tree +- Restore a tree from the provided DB +- Append new leaves (Standard and Indexed trees only) +- Update a leaf (Sparse tree and Indexed trees only) +- Retrieve the number of leaves. This is the number of non empty leaves for a Sparse tree and the highest populated index for Standard and Indexed trees. +- Commit modifications +- Rollback modifications +- Retrieve a Sibling Path for a given index. For performing Merkle proofs it is necessary to derive the set of nodes from a leaf index to the root of the tree, known as the 'hash path'. Given a leaf, it is therefore required to have the 'sibling' node at each tree level in order for the hash path to be computed. + +Note: Tree operations are not 'thread' safe. Operations should be queued or otherwise executed serially to ensure consistency of the data structures and any data retrieved from them. + +## Building/Testing + +To build the package, execute `yarn build` in the root. + +To run the tests, execute `yarn test`. diff --git a/yarn-project/merkle-tree/src/tree_base.ts b/yarn-project/merkle-tree/src/tree_base.ts index 3ff1b9686acd..92b71037ad17 100644 --- a/yarn-project/merkle-tree/src/tree_base.ts +++ b/yarn-project/merkle-tree/src/tree_base.ts @@ -45,7 +45,7 @@ export abstract class TreeBase implements MerkleTree { root?: Buffer, ) { if (!(depth >= 1 && depth <= MAX_DEPTH)) { - throw Error('Bad depth'); + throw Error('Invalid depth'); } // Compute the zero values at each layer. diff --git a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts index b04b0ccc586b..6fde586eb08e 100644 --- a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts @@ -6,6 +6,7 @@ import { KernelCircuitPublicInputs, PublicDataRead, PublicDataTransition, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, RootRollupPublicInputs, UInt8Vector, } from '@aztec/circuits.js'; @@ -55,6 +56,7 @@ describe('sequencer/circuit_block_builder', () => { let baseRollupOutputLeft: BaseOrMergeRollupPublicInputs; let baseRollupOutputRight: BaseOrMergeRollupPublicInputs; let rootRollupOutput: RootRollupPublicInputs; + let mockL1ToL2Messages: Fr[]; let wasm: CircuitsWasm; @@ -73,6 +75,9 @@ describe('sequencer/circuit_block_builder', () => { prover = mock(); builder = new CircuitBlockBuilder(builderDb, vks, simulator, prover); + // Create mock l1 to L2 messages + mockL1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)); + // Create mock outputs for simualator baseRollupOutputLeft = makeBaseRollupPublicInputs(); baseRollupOutputRight = makeBaseRollupPublicInputs(); @@ -107,54 +112,71 @@ describe('sequencer/circuit_block_builder', () => { } }; + const updateL1ToL2MessagesTree = async (l1ToL2Messages: Fr[]) => { + const asBuffer = l1ToL2Messages.map(m => m.toBuffer()); + await expectsDb.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, asBuffer); + }; + const getTreeSnapshot = async (tree: MerkleTreeId) => { const treeInfo = await expectsDb.getTreeInfo(tree); return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size)); }; + const buildMockSimulatorInputs = async () => { + const kernelOutput = makeKernelPublicInputs(); + kernelOutput.constants.historicTreeRoots = await getCombinedHistoricTreeRoots(expectsDb); + const tx = await makeProcessedTx(Tx.createPrivate(kernelOutput, emptyProof, makeEmptyUnverifiedData())); + + const txsLeft = [tx, await makeEmptyProcessedTx()]; + const txsRight = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; + + // Calculate what would be the tree roots after the txs from the first base rollup land and update mock circuit output + await updateExpectedTreesFromTxs(txsLeft); + baseRollupOutputLeft.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + baseRollupOutputLeft.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + baseRollupOutputLeft.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + baseRollupOutputLeft.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root; + + // Same for the two txs on the right + await updateExpectedTreesFromTxs(txsRight); + baseRollupOutputRight.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + baseRollupOutputRight.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + baseRollupOutputRight.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + baseRollupOutputRight.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root; + + // Update l1 to l2 data tree + // And update the root trees now to create proper output to the root rollup circuit + await updateL1ToL2MessagesTree(mockL1ToL2Messages); + await expectsDb.updateHistoricRootsTrees(); + rootRollupOutput.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + rootRollupOutput.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + rootRollupOutput.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + rootRollupOutput.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root; + rootRollupOutput.endTreeOfHistoricContractTreeRootsSnapshot = await getTreeSnapshot( + MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, + ); + rootRollupOutput.endTreeOfHistoricPrivateDataTreeRootsSnapshot = await getTreeSnapshot( + MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, + ); + rootRollupOutput.endL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE); + rootRollupOutput.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot = await getTreeSnapshot( + MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, + ); + + return [...txsLeft, ...txsRight]; + }; + describe('mock simulator', () => { - it('builds an L2 block using mock simulator', async () => { + beforeEach(() => { // Create instance to test builder = new CircuitBlockBuilder(builderDb, vks, simulator, prover); - + }); + it('builds an L2 block using mock simulator', async () => { // Assemble a fake transaction - const kernelOutput = makeKernelPublicInputs(); - kernelOutput.constants.historicTreeRoots = await getCombinedHistoricTreeRoots(expectsDb); - const tx = await makeProcessedTx(Tx.createPrivate(kernelOutput, emptyProof, makeEmptyUnverifiedData())); - - const txsLeft = [tx, await makeEmptyProcessedTx()]; - const txsRight = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; - - // Calculate what would be the tree roots after the txs from the first base rollup land and update mock circuit output - await updateExpectedTreesFromTxs(txsLeft); - baseRollupOutputLeft.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); - baseRollupOutputLeft.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); - baseRollupOutputLeft.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); - baseRollupOutputLeft.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root; - - // Same for the two txs on the right - await updateExpectedTreesFromTxs(txsRight); - baseRollupOutputRight.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); - baseRollupOutputRight.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); - baseRollupOutputRight.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); - baseRollupOutputRight.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root; - - // And update the root trees now to create proper output to the root rollup circuit - await expectsDb.updateRootsTrees(); - rootRollupOutput.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); - rootRollupOutput.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); - rootRollupOutput.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); - rootRollupOutput.endPublicDataTreeRoot = (await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE)).root; - rootRollupOutput.endTreeOfHistoricContractTreeRootsSnapshot = await getTreeSnapshot( - MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, - ); - rootRollupOutput.endTreeOfHistoricPrivateDataTreeRootsSnapshot = await getTreeSnapshot( - MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, - ); + const txs = await buildMockSimulatorInputs(); // Actually build a block! - const txs = [tx, await makeEmptyProcessedTx(), await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; - const [l2Block, proof] = await builder.buildL2Block(blockNumber, txs); + const [l2Block, proof] = await builder.buildL2Block(blockNumber, txs, mockL1ToL2Messages); expect(l2Block.number).toEqual(blockNumber); expect(proof).toEqual(emptyProof); @@ -170,14 +192,20 @@ describe('sequencer/circuit_block_builder', () => { const leaves = nullifiers.map(i => toBufferBE(BigInt(i), 32)); await expectsDb.appendLeaves(MerkleTreeId.NULLIFIER_TREE, leaves); - builder = new CircuitBlockBuilder(builderDb, vks, simulator, prover); - await builder.performBaseRollupBatchInsertionProofs(leaves); const expected = await expectsDb.getTreeInfo(MerkleTreeId.NULLIFIER_TREE); const actual = await builderDb.getTreeInfo(MerkleTreeId.NULLIFIER_TREE); expect(actual).toEqual(expected); }); + + it('Rejects if too many l1 to l2 messages are provided', async () => { + // Assemble a fake transaction + const txs = await buildMockSimulatorInputs(); + const l1ToL2Messages = new Array(100).fill(new Fr(0n)); + + await expect(builder.buildL2Block(blockNumber, txs, l1ToL2Messages)).rejects.toThrow(); + }); }); describe('circuits simulator', () => { @@ -218,7 +246,7 @@ describe('sequencer/circuit_block_builder', () => { ...(await Promise.all(times(totalCount - deployCount, makeEmptyProcessedTx))), ]; - const [l2Block] = await builder.buildL2Block(blockNumber, txs); + const [l2Block] = await builder.buildL2Block(blockNumber, txs, mockL1ToL2Messages); expect(l2Block.number).toEqual(blockNumber); await updateExpectedTreesFromTxs(txs); @@ -243,7 +271,7 @@ describe('sequencer/circuit_block_builder', () => { makeEmptyProcessedTx(), ]); - const [l2Block] = await builder.buildL2Block(blockNumber, txs); + const [l2Block] = await builder.buildL2Block(blockNumber, txs, mockL1ToL2Messages); expect(l2Block.number).toEqual(blockNumber); expect(l2Block.newPublicDataWrites[0]).toEqual(new PublicDataWrite(fr(2), fr(12))); await updateExpectedTreesFromTxs(txs); @@ -274,8 +302,11 @@ describe('sequencer/circuit_block_builder', () => { ); const txs = [tx, await makeEmptyProcessedTx(), await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; - const [l2Block] = await builder.buildL2Block(blockNumber, txs); + const [l2Block] = await builder.buildL2Block(blockNumber, txs, mockL1ToL2Messages); expect(l2Block.number).toEqual(blockNumber); }, 10000); }); + + // describe("Input guard tests", () => { + // }) }); diff --git a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts index 2b51523f1d63..95f089d9d510 100644 --- a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts @@ -5,9 +5,11 @@ import { CONTRACT_TREE_ROOTS_TREE_HEIGHT, CircuitsWasm, ConstantBaseRollupData, + L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT, MembershipWitness, MergeRollupInputs, NULLIFIER_TREE_HEIGHT, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NullifierLeafPreimage, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, @@ -39,6 +41,7 @@ import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { toBigIntBE, toBufferBE } from '@aztec/foundation/bigint-buffer'; import { toFriendlyJSON } from '@aztec/circuits.js/utils'; +import { AllowedTreeNames, OutputWithTreeSnapshot } from './types.js'; const frToBigInt = (fr: Fr) => toBigIntBE(fr.toBuffer()); const bigintToFr = (num: bigint) => new Fr(num); @@ -86,7 +89,11 @@ export class CircuitBlockBuilder implements BlockBuilder { protected debug = createDebugLogger('aztec:sequencer'), ) {} - public async buildL2Block(blockNumber: number, txs: ProcessedTx[]): Promise<[L2Block, UInt8Vector]> { + public async buildL2Block( + blockNumber: number, + txs: ProcessedTx[], + newL1ToL2Messages: Fr[], + ): Promise<[L2Block, UInt8Vector]> { const [ startPrivateDataTreeSnapshot, startNullifierTreeSnapshot, @@ -94,6 +101,8 @@ export class CircuitBlockBuilder implements BlockBuilder { startPublicDataTreeSnapshot, startTreeOfHistoricPrivateDataTreeRootsSnapshot, startTreeOfHistoricContractTreeRootsSnapshot, + startL1ToL2MessageTreeSnapshot, + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, ] = await Promise.all( [ MerkleTreeId.PRIVATE_DATA_TREE, @@ -102,6 +111,8 @@ export class CircuitBlockBuilder implements BlockBuilder { MerkleTreeId.PUBLIC_DATA_TREE, MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, + MerkleTreeId.L1_TO_L2_MESSAGES_TREE, + MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, ].map(tree => this.getTreeSnapshot(tree)), ); @@ -109,7 +120,7 @@ export class CircuitBlockBuilder implements BlockBuilder { this.validateTxs(txs); // We fill the tx batch with empty txs, we process only one tx at a time for now - const [circuitsOutput, proof] = await this.runCircuits(txs); + const [circuitsOutput, proof] = await this.runCircuits(txs, newL1ToL2Messages); const { endPrivateDataTreeSnapshot, @@ -118,6 +129,8 @@ export class CircuitBlockBuilder implements BlockBuilder { endPublicDataTreeRoot, endTreeOfHistoricPrivateDataTreeRootsSnapshot, endTreeOfHistoricContractTreeRootsSnapshot, + endL1ToL2MessageTreeSnapshot, + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, } = circuitsOutput; // Collect all new nullifiers, commitments, and contracts from all txs in this block @@ -146,11 +159,16 @@ export class CircuitBlockBuilder implements BlockBuilder { endTreeOfHistoricPrivateDataTreeRootsSnapshot, startTreeOfHistoricContractTreeRootsSnapshot, endTreeOfHistoricContractTreeRootsSnapshot, + startL1ToL2MessageTreeSnapshot, + endL1ToL2MessageTreeSnapshot, + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, newCommitments, newNullifiers, newContracts, newContractData, newPublicDataWrites, + newL1ToL2Messages, }); return [l2Block, proof]; @@ -171,13 +189,20 @@ export class CircuitBlockBuilder implements BlockBuilder { return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size)); } - protected async runCircuits(txs: ProcessedTx[]): Promise<[RootRollupPublicInputs, Proof]> { + protected async runCircuits(txs: ProcessedTx[], newL1ToL2Messages: Fr[]): Promise<[RootRollupPublicInputs, Proof]> { // Check that the length of the array of txs is a power of two // See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 if (txs.length < 4 || (txs.length & (txs.length - 1)) !== 0) { throw new Error(`Length of txs for the block should be a power of two and at least four (got ${txs.length})`); } + // Check that the number of new L1 to L2 messages is the same as the max + if (newL1ToL2Messages.length !== NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP) { + throw new Error( + `Length of the l1 to l2 messages per block should be a constant ${NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP} (got ${newL1ToL2Messages.length})`, + ); + } + // Run the base rollup circuits for the txs const baseRollupOutputs: [BaseOrMergeRollupPublicInputs, Proof][] = []; for (const pair of chunk(txs, 2)) { @@ -199,7 +224,7 @@ export class CircuitBlockBuilder implements BlockBuilder { // Run the root rollup with the last two merge rollups (or base, if no merge layers) const [mergeOutputLeft, mergeOutputRight] = mergeRollupInputs; - return this.rootRollupCircuit(mergeOutputLeft, mergeOutputRight); + return this.rootRollupCircuit(mergeOutputLeft, mergeOutputRight, newL1ToL2Messages); } protected async baseRollupCircuit( @@ -244,18 +269,26 @@ export class CircuitBlockBuilder implements BlockBuilder { protected async rootRollupCircuit( left: [BaseOrMergeRollupPublicInputs, Proof], right: [BaseOrMergeRollupPublicInputs, Proof], + newL1ToL2Messages: Fr[], ): Promise<[RootRollupPublicInputs, Proof]> { this.debug(`Running root rollup circuit`); - const rootInput = await this.getRootRollupInput(...left, ...right); + const rootInput = await this.getRootRollupInput(...left, ...right, newL1ToL2Messages); + + // Update the local trees to include the new l1 to l2 messages + await this.db.appendLeaves( + MerkleTreeId.L1_TO_L2_MESSAGES_TREE, + newL1ToL2Messages.map(m => m.toBuffer()), + ); // Simulate and get proof for the root circuit const rootOutput = await this.simulator.rootRollupCircuit(rootInput); + const rootProof = await this.prover.getRootRollupProof(rootInput, rootOutput); // Update the root trees with the latest data and contract tree roots, // and validate them against the output of the root circuit simulation this.debug(`Updating and validating root trees`); - await this.db.updateRootsTrees(); + await this.db.updateHistoricRootsTrees(); await this.validateRootOutput(rootOutput); return [rootOutput, rootProof]; @@ -264,9 +297,9 @@ export class CircuitBlockBuilder implements BlockBuilder { // Validate that the new roots we calculated from manual insertions match the outputs of the simulation protected async validateTrees(rollupOutput: BaseOrMergeRollupPublicInputs | RootRollupPublicInputs) { await Promise.all([ - this.validateTreeSnapshot(rollupOutput, MerkleTreeId.CONTRACT_TREE, 'Contract'), - this.validateTreeSnapshot(rollupOutput, MerkleTreeId.PRIVATE_DATA_TREE, 'PrivateData'), - this.validateTreeSnapshot(rollupOutput, MerkleTreeId.NULLIFIER_TREE, 'Nullifier'), + this.validateTree(rollupOutput, MerkleTreeId.CONTRACT_TREE, 'Contract'), + this.validateTree(rollupOutput, MerkleTreeId.PRIVATE_DATA_TREE, 'PrivateData'), + this.validateTree(rollupOutput, MerkleTreeId.NULLIFIER_TREE, 'Nullifier'), this.validatePublicDataTreeRoot(rollupOutput), ]); } @@ -277,6 +310,8 @@ export class CircuitBlockBuilder implements BlockBuilder { this.validateTrees(rootOutput), this.validateRootTree(rootOutput, MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, 'Contract'), this.validateRootTree(rootOutput, MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, 'PrivateData'), + this.validateRootTree(rootOutput, MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, 'L1ToL2Message'), + this.validateTree(rootOutput, MerkleTreeId.L1_TO_L2_MESSAGES_TREE, 'L1ToL2Message'), ]); } @@ -284,7 +319,7 @@ export class CircuitBlockBuilder implements BlockBuilder { protected async validateRootTree( rootOutput: RootRollupPublicInputs, treeId: MerkleTreeId, - name: 'Contract' | 'PrivateData', + name: 'Contract' | 'PrivateData' | 'L1ToL2Message', ) { const localTree = await this.getTreeSnapshot(treeId); const simulatedTree = rootOutput[`endTreeOfHistoric${name}TreeRootsSnapshot`]; @@ -307,13 +342,17 @@ export class CircuitBlockBuilder implements BlockBuilder { } // Helper for validating a non-roots tree against a circuit simulation output - protected async validateTreeSnapshot( - output: BaseOrMergeRollupPublicInputs | RootRollupPublicInputs, + protected async validateTree( + output: T, treeId: MerkleTreeId, - name: 'PrivateData' | 'Contract' | 'Nullifier', + name: AllowedTreeNames, ) { + if ('endL1ToL2MessageTreeSnapshot' in output && !(output instanceof RootRollupPublicInputs)) { + throw new Error(`The name 'L1ToL2Message' can only be used when output is of type RootRollupPublicInputs`); + } + const localTree = await this.getTreeSnapshot(treeId); - const simulatedTree = output[`end${name}TreeSnapshot`]; + const simulatedTree = (output as OutputWithTreeSnapshot)[`end${name}TreeSnapshot`]; this.validateSimulatedTree(localTree, simulatedTree, name); } @@ -321,7 +360,7 @@ export class CircuitBlockBuilder implements BlockBuilder { protected validateSimulatedTree( localTree: AppendOnlyTreeSnapshot, simulatedTree: AppendOnlyTreeSnapshot, - name: 'PrivateData' | 'Contract' | 'Nullifier', + name: 'PrivateData' | 'Contract' | 'Nullifier' | 'L1ToL2Message', label?: string, ) { if (!simulatedTree.root.toBuffer().equals(localTree.root.toBuffer())) { @@ -342,6 +381,7 @@ export class CircuitBlockBuilder implements BlockBuilder { rollupProofLeft: Proof, rollupOutputRight: BaseOrMergeRollupPublicInputs, rollupProofRight: Proof, + newL1ToL2Messages: Fr[], ) { const vk = this.getVerificationKey(rollupOutputLeft.rollupType); const previousRollupData: RootRollupInputs['previousRollupData'] = [ @@ -363,11 +403,29 @@ export class CircuitBlockBuilder implements BlockBuilder { const newHistoricPrivateDataTreeRootSiblingPath = await getRootTreeSiblingPath( MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, ); + const newHistoricL1ToL2MessageTreeRootSiblingPath = await getRootTreeSiblingPath( + MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, + ); + const newL1ToL2MessageTreeRootSiblingPath = await this.getSubtreeSiblingPath( + MerkleTreeId.L1_TO_L2_MESSAGES_TREE, + L1_TO_L2_MESSAGES_SUBTREE_INSERTION_HEIGHT, + ); + + // Get tree snapshots + const startL1ToL2MessageTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE); + const startHistoricTreeL1ToL2MessageTreeRootsSnapshot = await this.getTreeSnapshot( + MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, + ); return RootRollupInputs.from({ previousRollupData, newHistoricContractDataTreeRootSiblingPath, newHistoricPrivateDataTreeRootSiblingPath, + newL1ToL2Messages, + newHistoricL1ToL2MessageTreeRootSiblingPath, + newL1ToL2MessageTreeRootSiblingPath, + startL1ToL2MessageTreeSnapshot, + startHistoricTreeL1ToL2MessageTreeRootsSnapshot, }); } diff --git a/yarn-project/sequencer-client/src/block_builder/index.ts b/yarn-project/sequencer-client/src/block_builder/index.ts index 8859a405a7a2..72a930476e63 100644 --- a/yarn-project/sequencer-client/src/block_builder/index.ts +++ b/yarn-project/sequencer-client/src/block_builder/index.ts @@ -1,7 +1,8 @@ import { L2Block } from '@aztec/types'; import { Proof } from '../prover/index.js'; import { ProcessedTx } from '../sequencer/processed_tx.js'; +import { Fr } from '@aztec/foundation'; export interface BlockBuilder { - buildL2Block(blockNumber: number, txs: ProcessedTx[]): Promise<[L2Block, Proof]>; + buildL2Block(blockNumber: number, txs: ProcessedTx[], newL1ToL2Messages: Fr[]): Promise<[L2Block, Proof]>; } diff --git a/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts index 633753534eb4..67882e5af8ab 100644 --- a/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts @@ -34,7 +34,7 @@ export class StandaloneBlockBuilder implements BlockBuilder { constructor(private db: MerkleTreeOperations, private log = createDebugLogger('aztec:block_builder')) {} - async buildL2Block(blockNumber: number, txs: ProcessedTx[]): Promise<[L2Block, Proof]> { + async buildL2Block(blockNumber: number, txs: ProcessedTx[], newL1ToL2Messages: Fr[]): Promise<[L2Block, Proof]> { const startPrivateDataTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); const startNullifierTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); const startContractTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); @@ -45,10 +45,15 @@ export class StandaloneBlockBuilder implements BlockBuilder { const startTreeOfHistoricContractTreeRootsSnapshot = await this.getTreeSnapshot( MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, ); + const startL1ToL2MessageTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE); + const startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot = await this.getTreeSnapshot( + MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, + ); for (const tx of txs) { await this.updateTrees(tx); } + await this.updateL1ToL2MessagesTree(newL1ToL2Messages); await this.updateRootTrees(); @@ -62,6 +67,10 @@ export class StandaloneBlockBuilder implements BlockBuilder { const endTreeOfHistoricContractTreeRootsSnapshot = await this.getTreeSnapshot( MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, ); + const endL1ToL2MessageTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE); + const endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot = await this.getTreeSnapshot( + MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, + ); const l2Block = L2Block.fromFields({ number: blockNumber, @@ -77,6 +86,10 @@ export class StandaloneBlockBuilder implements BlockBuilder { endTreeOfHistoricPrivateDataTreeRootsSnapshot, startTreeOfHistoricContractTreeRootsSnapshot, endTreeOfHistoricContractTreeRootsSnapshot, + startL1ToL2MessageTreeSnapshot, + endL1ToL2MessageTreeSnapshot, + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, newCommitments: this.dataTreeLeaves.map(b => Fr.fromBuffer(b)), newNullifiers: this.nullifierTreeLeaves.map(b => Fr.fromBuffer(b)), newContracts: this.contractTreeLeaves.map(b => Fr.fromBuffer(b)), @@ -84,6 +97,7 @@ export class StandaloneBlockBuilder implements BlockBuilder { newPublicDataWrites: txs.flatMap(tx => tx.data.end.stateTransitions.map(t => new PublicDataWrite(t.leafIndex, t.newValue)), ), + newL1ToL2Messages, }); return [l2Block, makeEmptyProof()]; } @@ -101,21 +115,22 @@ export class StandaloneBlockBuilder implements BlockBuilder { computeContractLeaf(wasm, x).toBuffer(), ); - for (let i = 0; i < KERNEL_NEW_COMMITMENTS_LENGTH; i++) { - await this.db.appendLeaves(MerkleTreeId.PRIVATE_DATA_TREE, [dataTreeLeaves[i]]); - } - for (let i = 0; i < KERNEL_NEW_NULLIFIERS_LENGTH; i++) { - await this.db.appendLeaves(MerkleTreeId.NULLIFIER_TREE, [nullifierTreeLeaves[i]]); - } - for (let i = 0; i < KERNEL_NEW_CONTRACTS_LENGTH; i++) { - await this.db.appendLeaves(MerkleTreeId.CONTRACT_TREE, [contractTreeLeaves[i]]); - } + await this.db.appendLeaves(MerkleTreeId.PRIVATE_DATA_TREE, dataTreeLeaves); + await this.db.appendLeaves(MerkleTreeId.NULLIFIER_TREE, nullifierTreeLeaves); + await this.db.appendLeaves(MerkleTreeId.CONTRACT_TREE, contractTreeLeaves); + } + + private async updateL1ToL2MessagesTree(l1ToL2Messages: Fr[]) { + const leaves = l1ToL2Messages.map((x: Fr) => x.toBuffer()); + await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, leaves); } private async updateRootTrees() { const newDataTreeInfo = await this.getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); const newContractsTreeInfo = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + const newL1ToL2MessagesTreeInfo = await this.getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGES_TREE); await this.db.appendLeaves(MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, [newContractsTreeInfo.root.toBuffer()]); await this.db.appendLeaves(MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, [newDataTreeInfo.root.toBuffer()]); + await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, [newL1ToL2MessagesTreeInfo.root.toBuffer()]); } } diff --git a/yarn-project/sequencer-client/src/block_builder/types.ts b/yarn-project/sequencer-client/src/block_builder/types.ts new file mode 100644 index 000000000000..d3fc4845051b --- /dev/null +++ b/yarn-project/sequencer-client/src/block_builder/types.ts @@ -0,0 +1,16 @@ +import { AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, RootRollupPublicInputs } from '@aztec/circuits.js'; + +/** + * Type to assert that only the correct trees are checked when validating rollup tree outputs + */ +export type AllowedTreeNames = + T extends RootRollupPublicInputs + ? 'PrivateData' | 'Contract' | 'Nullifier' | 'L1ToL2Message' + : 'PrivateData' | 'Contract' | 'Nullifier'; + +/** + * Type to assert the correct object field is indexed when validating rollup tree outputs + */ +export type OutputWithTreeSnapshot = { + [K in `end${AllowedTreeNames}TreeSnapshot`]: AppendOnlyTreeSnapshot; +}; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index f55205937c95..e39d672b7443 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -1,4 +1,4 @@ -import { CombinedHistoricTreeRoots, makeEmptyProof } from '@aztec/circuits.js'; +import { CombinedHistoricTreeRoots, Fr, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, makeEmptyProof } from '@aztec/circuits.js'; import { P2P, P2PClientState } from '@aztec/p2p'; import { L2Block, PrivateTx, Tx, UnverifiedData } from '@aztec/types'; import { MerkleTreeId, MerkleTreeOperations, WorldStateRunningState, WorldStateSynchroniser } from '@aztec/world-state'; @@ -65,6 +65,7 @@ describe('sequencer', () => { expect(blockBuilder.buildL2Block).toHaveBeenCalledWith( lastBlockNumber + 1, expectedTxHashes.map(hash => expect.objectContaining({ hash })), + Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(publisher.processUnverifiedData).toHaveBeenCalledWith(lastBlockNumber + 1, expectedUnverifiedData); @@ -101,6 +102,7 @@ describe('sequencer', () => { expect(blockBuilder.buildL2Block).toHaveBeenCalledWith( lastBlockNumber + 1, expectedTxHashes.map(hash => expect.objectContaining({ hash })), + Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(publisher.processUnverifiedData).toHaveBeenCalledWith(lastBlockNumber + 1, expectedUnverifiedData); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 9fd4dce8c1ae..67fa38d551b9 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -10,6 +10,8 @@ import { ProcessedTx } from './processed_tx.js'; import { PublicProcessor } from './public_processor.js'; import { RunningPromise } from '@aztec/foundation/running-promise'; import { createDebugLogger } from '@aztec/foundation/log'; +import { Fr } from '@aztec/foundation/fields'; +import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; /** * Sequencer client @@ -112,9 +114,14 @@ export class Sequencer { await this.p2pClient.deleteTxs(await Tx.getHashes(failedTxs)); } + // Get l1 to l2 messages from the contract + this.log('Requesting L1 to L2 messages from contract'); + const l1ToL2Messages = this.takeL1ToL2MessagesFromContract(); + this.log('Successfully retrieved L1 to L2 messages from contract'); + // Build the new block by running the rollup circuits this.log(`Assembling block with txs ${processedTxs.map(tx => tx.hash).join(', ')}`); - const block = await this.buildBlock(processedTxs); + const block = await this.buildBlock(processedTxs, l1ToL2Messages); this.log(`Assembled block ${block.number}`); // Publishes new block to the network and awaits the tx to be mined @@ -210,7 +217,7 @@ export class Sequencer { ); } - protected async buildBlock(txs: ProcessedTx[]) { + protected async buildBlock(txs: ProcessedTx[], newL1ToL2Messages: Fr[]) { // Pad the txs array with empty txs to be a power of two, at least 4 const txsTargetSize = Math.max(ceilPowerOfTwo(txs.length), 4); const emptyTxCount = txsTargetSize - txs.length; @@ -219,10 +226,19 @@ export class Sequencer { ...txs, ...(await Promise.all(times(emptyTxCount, () => this.publicProcessor.makeEmptyProcessedTx()))), ]; - const [block] = await this.blockBuilder.buildL2Block(this.lastBlockNumber + 1, allTxs); + const [block] = await this.blockBuilder.buildL2Block(this.lastBlockNumber + 1, allTxs, newL1ToL2Messages); return block; } + // TODO: this is a stubbed method + /** + * Checks on chain messages inbox and selects messages to inlcude within the + * next rollup block + */ + protected takeL1ToL2MessagesFromContract(): Fr[] { + return new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)); + } + /** * Returns true if one of the transaction nullifiers exist. * Nullifiers prevent double spends in a private context. diff --git a/yarn-project/sequencer-client/src/test/l2-block-publisher.test.ts b/yarn-project/sequencer-client/src/test/l2-block-publisher.test.ts index d5d56d818168..774b2650ce6f 100644 --- a/yarn-project/sequencer-client/src/test/l2-block-publisher.test.ts +++ b/yarn-project/sequencer-client/src/test/l2-block-publisher.test.ts @@ -3,6 +3,7 @@ import { BaseOrMergeRollupPublicInputs, CircuitsWasm, Fr, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, RootRollupPublicInputs, UInt8Vector, } from '@aztec/circuits.js'; @@ -68,8 +69,8 @@ describe.skip('L1Publisher integration', () => { const simulator = await WasmRollupCircuitSimulator.new(); const prover = new EmptyRollupProver(); builder = new CircuitBlockBuilder(builderDb, vks, simulator, prover); - await expectsDb.updateRootsTrees(); - await builderDb.updateRootsTrees(); + await expectsDb.updateHistoricRootsTrees(); + await builderDb.updateHistoricRootsTrees(); baseRollupOutputLeft = makeBaseRollupPublicInputs(); baseRollupOutputRight = makeBaseRollupPublicInputs(); @@ -97,6 +98,8 @@ describe.skip('L1Publisher integration', () => { }; it('Build 2 blocks of 4 txs building on each other', async () => { + const newL1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)); + const stateInRollup_ = await rollup.methods.rollupStateHash().call(); expect(hexStringToBuffer(stateInRollup_.toString())).toEqual(Buffer.alloc(32, 0)); @@ -105,7 +108,7 @@ describe.skip('L1Publisher integration', () => { Tx.createPrivate(makeKernelPublicInputs(1 + i), emptyProof, makeEmptyUnverifiedData()), ); - const txsLeft = [tx, await makeEmptyProcessedTx()]; + const txsLeft = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; const txsRight = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; // Set tree roots to proper values in the tx @@ -124,7 +127,7 @@ describe.skip('L1Publisher integration', () => { baseRollupOutputRight.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); // And update the root trees now to create proper output to the root rollup circuit - await expectsDb.updateRootsTrees(); + await expectsDb.updateHistoricRootsTrees(); rootRollupOutput.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); rootRollupOutput.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); rootRollupOutput.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); @@ -137,8 +140,7 @@ describe.skip('L1Publisher integration', () => { // Actually build a block! const txs = [tx, await makeEmptyProcessedTx(), await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; - // Here we die. - const [block] = await builder.buildL2Block(1 + i, txs); + const [block] = await builder.buildL2Block(1 + i, txs, newL1ToL2Messages); // Now we can use the block we built! const blockNumber = await ethRpc.blockNumber(); @@ -151,7 +153,7 @@ describe.skip('L1Publisher integration', () => { const expectedData = rollup.methods.process(l2Proof, block.encode()).encodeABI(); expect(ethTx.input).toEqual(expectedData); - const decodedCalldataHash = await decoderHelper.methods.computeDiffRoot(block.encode()).call(); + const decodedHashes = await decoderHelper.methods.computeDiffRootAndMessagesHash(block.encode()).call(); const decodedRes = await decoderHelper.methods.decode(block.encode()).call(); const stateInRollup = await rollup.methods.rollupStateHash().call(); @@ -161,7 +163,8 @@ describe.skip('L1Publisher integration', () => { expect(block.getEndStateHash()).toEqual(hexStringToBuffer(decodedRes[2].toString())); expect(block.getEndStateHash()).toEqual(hexStringToBuffer(stateInRollup.toString())); expect(block.getPublicInputsHash().toBuffer()).toEqual(hexStringToBuffer(decodedRes[3].toString())); - expect(block.getCalldataHash()).toEqual(hexStringToBuffer(decodedCalldataHash.toString())); + expect(block.getCalldataHash()).toEqual(hexStringToBuffer(decodedHashes[0].toString())); + expect(block.getL1ToL2MessagesHash()).toEqual(hexStringToBuffer(decodedHashes[1].toString())); } }, 60_000); diff --git a/yarn-project/types/.eslintrc.cjs b/yarn-project/types/.eslintrc.cjs index 97d6f1878135..e659927475c0 100644 --- a/yarn-project/types/.eslintrc.cjs +++ b/yarn-project/types/.eslintrc.cjs @@ -1 +1 @@ -module.exports = require('@aztec/foundation/eslint-legacy'); +module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/types/README.md b/yarn-project/types/README.md index e4c7ca7d18bb..4c489f776ef3 100644 --- a/yarn-project/types/README.md +++ b/yarn-project/types/README.md @@ -1 +1,2 @@ -# Unverified Data +# Types +A package containing types which are relevant through all the Aztec Typescript codebase (L2Block, Tx etc.). \ No newline at end of file diff --git a/yarn-project/types/src/contract_data.ts b/yarn-project/types/src/contract_data.ts index ee9aa37899c0..4bd1c3468e3e 100644 --- a/yarn-project/types/src/contract_data.ts +++ b/yarn-project/types/src/contract_data.ts @@ -9,7 +9,7 @@ import { FUNCTION_SELECTOR_NUM_BYTES } from '@aztec/circuits.js'; export { BufferReader } from '@aztec/circuits.js/utils'; /** - * Used for retrieval of contract data (A3 address, portal contract address, bytecode) + * Used for retrieval of contract data (A3 address, portal contract address, bytecode). */ export interface ContractDataSource { /** @@ -31,14 +31,14 @@ export interface ContractDataSource { /** * Lookup all contract public data in an L2 block. - * @param blockNumber - The block number + * @param blockNumber - The block number. * @returns Public data of contracts deployed in L2 block, including public function bytecode. */ getL2ContractPublicDataInBlock(blockNumber: number): Promise; /** * Lookup contract info in an L2 block. - * @param blockNumber - The block number + * @param blockNumber - The block number. * @returns Portal contract address info of contracts deployed in L2 block. */ getL2ContractInfoInBlock(blockNumber: number): Promise; @@ -46,27 +46,52 @@ export interface ContractDataSource { /** * Returns a contract's encoded public function, given its function selector. * @param address - The contract aztec address. - * @param functionSelector - The function's selector + * @param functionSelector - The function's selector. * @returns The function's data. */ getPublicFunction(address: AztecAddress, functionSelector: Buffer): Promise; } +/** + * Represents encoded contract function. + */ export class EncodedContractFunction { - constructor(public functionSelector: Buffer, public bytecode: Buffer) {} + constructor( + /** + * The function selector. + */ + public functionSelector: Buffer, + /** + * The function bytecode. + */ + public bytecode: Buffer, + ) {} - toBuffer() { + /** + * Serializes this instance into a buffer. + * @returns Encoded buffer. + */ + toBuffer(): Buffer { const bytecodeBuf = Buffer.concat([numToInt32BE(this.bytecode.length), this.bytecode]); return serializeToBuffer(this.functionSelector, bytecodeBuf); } - static fromBuffer(buffer: Buffer | BufferReader) { + /** + * Deserializes a contract function object from an encoded buffer. + * @param buffer - The encoded buffer. + * @returns The deserialized contract function. + */ + static fromBuffer(buffer: Buffer | BufferReader): EncodedContractFunction { const reader = BufferReader.asReader(buffer); const fnSelector = reader.readBytes(FUNCTION_SELECTOR_NUM_BYTES); return new EncodedContractFunction(fnSelector, reader.readBuffer()); } - static random() { + /** + * Creates a random contract function. + * @returns A random contract function. + */ + static random(): EncodedContractFunction { return new EncodedContractFunction(randomBytes(4), randomBytes(64)); } } @@ -86,7 +111,7 @@ export class ContractPublicData { public contractData: ContractData, /** - * ABIs of public functions + * ABIs of public functions. */ public publicFunctions: EncodedContractFunction[], ) { diff --git a/yarn-project/types/src/create_tx_hash.ts b/yarn-project/types/src/create_tx_hash.ts index f1619337907a..d77680e5b9c7 100644 --- a/yarn-project/types/src/create_tx_hash.ts +++ b/yarn-project/types/src/create_tx_hash.ts @@ -2,9 +2,21 @@ import { Fr } from '@aztec/foundation/fields'; import { TxHash } from './tx_hash.js'; import { keccak } from '@aztec/foundation/crypto'; +/** + * Defines transaction data. + */ interface TxData { + /** + * Commitments to be inserted into a private data tree that are created in the transaction. + */ newCommitments: Fr[]; + /** + * Nullifiers to be inserted into a nullifier tree that are created in the transaction. + */ newNullifiers: Fr[]; + /** + * Contractc leaves to be inserted into a contract tree that are created in the transaction. + */ newContracts: Fr[]; } diff --git a/yarn-project/types/src/l2_block.ts b/yarn-project/types/src/l2_block.ts index eeef5d7291e8..3a91e34c6a9d 100644 --- a/yarn-project/types/src/l2_block.ts +++ b/yarn-project/types/src/l2_block.ts @@ -4,6 +4,7 @@ import { KERNEL_NEW_CONTRACTS_LENGTH, KERNEL_NEW_NULLIFIERS_LENGTH, STATE_TRANSITIONS_LENGTH, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, } from '@aztec/circuits.js'; import { makeAppendOnlyTreeSnapshot } from '@aztec/circuits.js/factories'; import { BufferReader, serializeToBuffer } from '@aztec/circuits.js/utils'; @@ -19,55 +20,114 @@ import { sha256 } from '@aztec/foundation/crypto'; * TODO: Reuse data types and serialization functions from circuits package. */ export class L2Block { - /** - * Construct a new L2Block object. - * The data that goes into the rollup, BUT without the proof. - * @param number - The number of the L2 block. - * @param startPrivateDataTreeSnapshot - The tree snapshot of the private data tree at the start of the rollup. - * @param startNullifierTreeSnapshot - The tree snapshot of the nullifier tree at the start of the rollup. - * @param startContractTreeSnapshot - The tree snapshot of the contract tree at the start of the rollup. - * @param startTreeOfHistoricPrivateDataTreeRootsSnapshot - The tree snapshot of the historic private data tree roots at the start of the rollup. - * @param startTreeOfHistoricContractTreeRootsSnapshot - The tree snapshot of the historic contract tree roots at the start of the rollup. - * @param startPublicDataTreeRoot - The tree root of the public data tree at the start of the rollup. - * @param endPrivateDataTreeSnapshot - The tree snapshot of the private data tree at the end of the rollup. - * @param endNullifierTreeSnapshot - The tree snapshot of the nullifier tree at the end of the rollup. - * @param endContractTreeSnapshot - The tree snapshot of the contract tree at the end of the rollup. - * @param endTreeOfHistoricPrivateDataTreeRootsSnapshot - The tree snapshot of the historic private data tree roots at the end of the rollup. - * @param endTreeOfHistoricContractTreeRootsSnapshot - The tree snapshot of the historic contract tree roots at the end of the rollup. - * @param endPublicDataTreeRoot - The tree root of the public data tree at the end of the rollup. - * @param newCommitments - The commitments to be inserted into the private data tree. - * @param newNullifiers - The nullifiers to be inserted into the nullifier tree. - * @param newPublicDataWrites - The public data writes to be inserted into the public data tree. - * @param newContracts - The contracts leafs to be inserted into the contract tree. - * @param newContractData - The aztec_address and eth_address for the deployed contract and its portal contract. - */ constructor( + /** + * The number of the L2 block. + */ public number: number, + /** + * The tree snapshot of the private data tree at the start of the rollup. + */ public startPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the nullifier tree at the start of the rollup. + */ public startNullifierTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the contract tree at the start of the rollup. + */ public startContractTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the historic private data tree roots at the start of the rollup. + */ public startTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the historic contract tree roots at the start of the rollup. + */ public startTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree root of the public data tree at the start of the rollup. + */ public startPublicDataTreeRoot: Fr, + /** + * The tree snapshot of the L2 message tree at the start of the rollup. + */ + public startL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the historic L2 message tree roots at the start of the rollup. + */ + public startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the private data tree at the end of the rollup. + */ public endPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the nullifier tree at the end of the rollup. + */ public endNullifierTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the contract tree at the end of the rollup. + */ public endContractTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the historic private data tree roots at the end of the rollup. + */ public endTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the historic contract tree roots at the end of the rollup. + */ public endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree root of the public data tree at the end of the rollup. + */ public endPublicDataTreeRoot: Fr, + /** + * The tree snapshot of the L2 message tree at the end of the rollup. + */ + public endL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot, + /** + * The tree snapshot of the historic L2 message tree roots at the end of the rollup. + */ + public endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot, + /** + * The commitments to be inserted into the private data tree. + */ public newCommitments: Fr[], + /** + * The nullifiers to be inserted into the nullifier tree. + */ public newNullifiers: Fr[], + /** + * The public data writes to be inserted into the public data tree. + */ public newPublicDataWrites: PublicDataWrite[], + /** + * The contracts leafs to be inserted into the contract tree. + */ public newContracts: Fr[], + /** + * The aztec address and ethereum address for the deployed contract and its portal contract. + */ public newContractData: ContractData[], + /** + * The L1 to L2 messages to be inserted into the L2 toL2 message tree. + */ + public newL1ToL2Messages: Fr[] = [], ) {} - static random(l2BlockNum: number, txsPerBlock = 4) { + /** + * Creates an L2 block containing random data. + * @param l2BlockNum - The number of the L2 block. + * @param txsPerBlock - The number of transactions to include in the block. + * @returns The L2 block. + */ + static random(l2BlockNum: number, txsPerBlock = 4): L2Block { const newNullifiers = times(KERNEL_NEW_NULLIFIERS_LENGTH * txsPerBlock, Fr.random); const newCommitments = times(KERNEL_NEW_COMMITMENTS_LENGTH * txsPerBlock, Fr.random); const newContracts = times(KERNEL_NEW_CONTRACTS_LENGTH * txsPerBlock, Fr.random); const newContractData = times(KERNEL_NEW_CONTRACTS_LENGTH * txsPerBlock, ContractData.random); const newPublicDataWrites = times(STATE_TRANSITIONS_LENGTH * txsPerBlock, PublicDataWrite.random); + const newL1ToL2Messages = times(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, Fr.random); return L2Block.fromFields({ number: l2BlockNum, @@ -75,12 +135,16 @@ export class L2Block { startNullifierTreeSnapshot: makeAppendOnlyTreeSnapshot(0), startContractTreeSnapshot: makeAppendOnlyTreeSnapshot(0), startPublicDataTreeRoot: Fr.random(), + startL1ToL2MessageTreeSnapshot: makeAppendOnlyTreeSnapshot(0), + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(0), startTreeOfHistoricPrivateDataTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(0), startTreeOfHistoricContractTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(0), endPrivateDataTreeSnapshot: makeAppendOnlyTreeSnapshot(newCommitments.length), endNullifierTreeSnapshot: makeAppendOnlyTreeSnapshot(newNullifiers.length), endContractTreeSnapshot: makeAppendOnlyTreeSnapshot(newContracts.length), endPublicDataTreeRoot: Fr.random(), + endL1ToL2MessageTreeSnapshot: makeAppendOnlyTreeSnapshot(1), + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(1), endTreeOfHistoricPrivateDataTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(1), endTreeOfHistoricContractTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(1), newCommitments, @@ -88,6 +152,7 @@ export class L2Block { newContracts, newContractData, newPublicDataWrites, + newL1ToL2Messages, }); } @@ -97,24 +162,98 @@ export class L2Block { * @returns A new instance. */ static fromFields(fields: { + /** + * The number of the L2 block. + */ number: number; + /** + * The tree snapshot of the private data tree at the start of the rollup. + */ startPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the nullifier tree at the start of the rollup. + */ startNullifierTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the contract tree at the start of the rollup. + */ startContractTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the historic private data tree roots at the start of the rollup. + */ startTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the historic contract tree roots at the start of the rollup. + */ startTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree root of the public data tree at the start of the rollup. + */ startPublicDataTreeRoot: Fr; + /** + * The tree snapshot of the L2 message tree at the start of the rollup. + */ + startL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the historic L2 message tree roots at the start of the rollup. + */ + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the private data tree at the end of the rollup. + */ endPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the nullifier tree at the end of the rollup. + */ endNullifierTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the contract tree at the end of the rollup. + */ endContractTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the historic private data tree roots at the end of the rollup. + */ endTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the historic contract tree roots at the end of the rollup. + */ endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree root of the public data tree at the end of the rollup. + */ endPublicDataTreeRoot: Fr; + /** + * The tree snapshot of the L2 message tree at the end of the rollup. + */ + endL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot; + /** + * The tree snapshot of the historic L2 message tree roots at the end of the rollup. + */ + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: AppendOnlyTreeSnapshot; + /** + * The commitments to be inserted into the private data tree. + */ newCommitments: Fr[]; + /** + * The nullifiers to be inserted into the nullifier tree. + */ newNullifiers: Fr[]; + /** + * The public data writes to be inserted into the public data tree. + */ newPublicDataWrites: PublicDataWrite[]; + /** + * The contracts leafs to be inserted into the contract tree. + */ newContracts: Fr[]; + /** + * The aztec address and ethereum address for the deployed contract and its portal contract. + */ newContractData: ContractData[]; + /** + * The L1 to L2 messages to be inserted into the L2 toL2 message tree. + */ + newL1ToL2Messages: Fr[]; }) { return new this( fields.number, @@ -124,17 +263,22 @@ export class L2Block { fields.startTreeOfHistoricPrivateDataTreeRootsSnapshot, fields.startTreeOfHistoricContractTreeRootsSnapshot, fields.startPublicDataTreeRoot, + fields.startL1ToL2MessageTreeSnapshot, + fields.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, fields.endPrivateDataTreeSnapshot, fields.endNullifierTreeSnapshot, fields.endContractTreeSnapshot, fields.endTreeOfHistoricPrivateDataTreeRootsSnapshot, fields.endTreeOfHistoricContractTreeRootsSnapshot, fields.endPublicDataTreeRoot, + fields.endL1ToL2MessageTreeSnapshot, + fields.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, fields.newCommitments, fields.newNullifiers, fields.newPublicDataWrites, fields.newContracts, fields.newContractData, + fields.newL1ToL2Messages, ); } @@ -151,12 +295,16 @@ export class L2Block { this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, this.startTreeOfHistoricContractTreeRootsSnapshot, this.startPublicDataTreeRoot, + this.startL1ToL2MessageTreeSnapshot, + this.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, this.endPrivateDataTreeSnapshot, this.endNullifierTreeSnapshot, this.endContractTreeSnapshot, this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, this.endTreeOfHistoricContractTreeRootsSnapshot, this.endPublicDataTreeRoot, + this.endL1ToL2MessageTreeSnapshot, + this.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, this.newCommitments.length, this.newCommitments, this.newNullifiers.length, @@ -166,6 +314,8 @@ export class L2Block { this.newContracts.length, this.newContracts, this.newContractData, + this.newL1ToL2Messages.length, + this.newL1ToL2Messages, ); } @@ -191,17 +341,23 @@ export class L2Block { const startTreeOfHistoricPrivateDataTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const startTreeOfHistoricContractTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const startPublicDataTreeRoot = reader.readObject(Fr); + const startL1ToL2MessageTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const endPrivateDataTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const endNullifierTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const endContractTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const endTreeOfHistoricPrivateDataTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const endTreeOfHistoricContractTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const endPublicDataTreeRoot = reader.readObject(Fr); + const endL1ToL2MessageTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const newCommitments = reader.readVector(Fr); const newNullifiers = reader.readVector(Fr); const newPublicDataWrites = reader.readVector(PublicDataWrite); const newContracts = reader.readVector(Fr); const newContractData = reader.readArray(newContracts.length, ContractData); + // TODO(sean): could an optimisation of this be that it is encoded such that zeros are assumed + const newL1ToL2Messages = reader.readVector(Fr); return L2Block.fromFields({ number, @@ -211,26 +367,31 @@ export class L2Block { startTreeOfHistoricPrivateDataTreeRootsSnapshot, startTreeOfHistoricContractTreeRootsSnapshot, startPublicDataTreeRoot, + startL1ToL2MessageTreeSnapshot, + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, endPrivateDataTreeSnapshot, endNullifierTreeSnapshot, endContractTreeSnapshot, endTreeOfHistoricPrivateDataTreeRootsSnapshot, endTreeOfHistoricContractTreeRootsSnapshot, endPublicDataTreeRoot, + endL1ToL2MessageTreeSnapshot, + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, newCommitments, newNullifiers, newPublicDataWrites, newContracts, newContractData, + newL1ToL2Messages, }); } /** * Computes the public inputs hash for the L2 block. - * The same output as the hash of RootRollupPublicInputs - * @return The public input hash for the L2 block as a field element + * The same output as the hash of RootRollupPublicInputs. + * @returns The public input hash for the L2 block as a field element. */ - getPublicInputsHash() { + getPublicInputsHash(): Fr { const buf = serializeToBuffer( this.startPrivateDataTreeSnapshot, this.startNullifierTreeSnapshot, @@ -238,14 +399,20 @@ export class L2Block { this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, this.startTreeOfHistoricContractTreeRootsSnapshot, this.startPublicDataTreeRoot, + this.startL1ToL2MessageTreeSnapshot, + this.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, this.endPrivateDataTreeSnapshot, this.endNullifierTreeSnapshot, this.endContractTreeSnapshot, this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, this.endTreeOfHistoricContractTreeRootsSnapshot, this.endPublicDataTreeRoot, + this.endL1ToL2MessageTreeSnapshot, + this.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, this.getCalldataHash(), + this.getL1ToL2MessagesHash(), ); + const temp = toBigIntBE(sha256(buf)); // Prime order of BN254 curve const p = BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'); @@ -253,8 +420,8 @@ export class L2Block { } /** - * Computes the start state hash (should equal contract data before block) - * @returns The start state hash for the L2 block + * Computes the start state hash (should equal contract data before block). + * @returns The start state hash for the L2 block. */ getStartStateHash() { const inputValue = serializeToBuffer( @@ -265,13 +432,15 @@ export class L2Block { this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, this.startTreeOfHistoricContractTreeRootsSnapshot, this.startPublicDataTreeRoot, + this.startL1ToL2MessageTreeSnapshot, + this.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, ); return sha256(inputValue); } /** - * Computes the end state hash (should equal contract data after block) - * @returns The end state hash for the L2 block + * Computes the end state hash (should equal contract data after block). + * @returns The end state hash for the L2 block. */ getEndStateHash() { const inputValue = serializeToBuffer( @@ -282,6 +451,8 @@ export class L2Block { this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, this.endTreeOfHistoricContractTreeRootsSnapshot, this.endPublicDataTreeRoot, + this.endL1ToL2MessageTreeSnapshot, + this.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, ); return sha256(inputValue); } @@ -350,6 +521,17 @@ export class L2Block { return computeRoot(leafs); } + /** + * Compute the hash of all of this blocks l1 to l2 messages, + * The hash is also calculated within the contract when the block is submitted. + * @returns The hash of all of the l1 to l2 messages. + */ + getL1ToL2MessagesHash(): Buffer { + // Create a long buffer of all of the l1 to l2 messages + const l1ToL2Messages = Buffer.concat(this.newL1ToL2Messages.map(message => message.toBuffer())); + return sha256(l1ToL2Messages); + } + /** * Get the ith transaction in an L2 block. * @param txIndex - The index of the tx in the block. @@ -391,8 +573,12 @@ export class L2Block { * @returns A human-friendly string representation of the l2Block. */ inspect(maxBufferSize = 4): string { - const inspectHex = (fr: { toBuffer: () => Buffer }): string => - `0x${fr.toBuffer().subarray(0, maxBufferSize).toString('hex')}`; + const inspectHex = (fr: { + /** + * A function used to serialize the field element to a buffer. + */ + toBuffer: () => Buffer; + }): string => `0x${fr.toBuffer().subarray(0, maxBufferSize).toString('hex')}`; const inspectArray = (arr: T[], inspector: (t: T) => string) => '[' + arr.map(inspector).join(', ') + ']'; const inspectTreeSnapshot = (s: AppendOnlyTreeSnapshot): string => @@ -416,6 +602,10 @@ export class L2Block { this.startTreeOfHistoricContractTreeRootsSnapshot, )}`, `startPublicDataTreeRoot: ${this.startPublicDataTreeRoot.toString()}`, + `startL1ToL2MessageTreeSnapshot: ${inspectTreeSnapshot(this.startL1ToL2MessageTreeSnapshot)}`, + `startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: ${inspectTreeSnapshot( + this.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, + )}`, `endPrivateDataTreeSnapshot: ${inspectTreeSnapshot(this.endPrivateDataTreeSnapshot)}`, `endNullifierTreeSnapshot: ${inspectTreeSnapshot(this.endNullifierTreeSnapshot)}`, `endContractTreeSnapshot: ${inspectTreeSnapshot(this.endContractTreeSnapshot)}`, @@ -427,12 +617,17 @@ export class L2Block { this.endTreeOfHistoricContractTreeRootsSnapshot, )}`, `endPublicDataTreeRoot: ${this.endPublicDataTreeRoot.toString()}`, + `endL1ToL2MessageTreeSnapshot: ${inspectTreeSnapshot(this.endL1ToL2MessageTreeSnapshot)}`, + `endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: ${inspectTreeSnapshot( + this.endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, + )}`, `newCommitments: ${inspectFrArray(this.newCommitments)}`, `newNullifiers: ${inspectFrArray(this.newNullifiers)}`, `newPublicDataWrite: ${inspectPublicDataWriteArray(this.newPublicDataWrites)}`, `newContracts: ${inspectFrArray(this.newContracts)}`, `newContractData: ${inspectContractDataArray(this.newContractData)}`, `newPublicDataWrite: ${inspectPublicDataWriteArray(this.newPublicDataWrites)}`, + `newL1ToL2Messages: ${inspectFrArray(this.newL1ToL2Messages)}`, ].join('\n'); } } diff --git a/yarn-project/types/src/l2_block_context.ts b/yarn-project/types/src/l2_block_context.ts index f13ab5191a3e..2d88244aab82 100644 --- a/yarn-project/types/src/l2_block_context.ts +++ b/yarn-project/types/src/l2_block_context.ts @@ -4,14 +4,26 @@ import { L2Block } from './l2_block.js'; import { TxHash } from './tx_hash.js'; import { keccak } from '@aztec/foundation/crypto'; +/** + * A wrapper around L2 block used to cache results of expensive operations. + */ export class L2BlockContext { private txHashes: (TxHash | undefined)[]; private blockHash: Buffer | undefined; - constructor(public readonly block: L2Block) { + constructor( + /** + * The underlying L2 block. + */ + public readonly block: L2Block, + ) { this.txHashes = new Array(Math.floor(block.newCommitments.length / KERNEL_NEW_COMMITMENTS_LENGTH)); } + /** + * Returns the underlying block's hash. + * @returns The block's hash. + */ public getBlockHash(): Buffer { if (!this.blockHash) { this.blockHash = keccak(this.block.encode()); @@ -19,6 +31,11 @@ export class L2BlockContext { return this.blockHash; } + /** + * Returns the tx hash of the tx in the block at the given index. + * @param txIndex - The index of the tx. + * @returns The tx's hash. + */ public getTxHash(txIndex: number): TxHash { if (!this.txHashes[txIndex]) { const txHash = this.block.getTx(txIndex).txHash; @@ -30,6 +47,10 @@ export class L2BlockContext { return this.txHashes[txIndex]!; } + /** + * Returns the tx hashes of all txs in the block. + * @returns The tx hashes. + */ public getTxHashes(): TxHash[] { // First ensure that all tx hashes are calculated for (let txIndex = 0; txIndex < this.txHashes.length; txIndex++) { diff --git a/yarn-project/types/src/l2_tx.ts b/yarn-project/types/src/l2_tx.ts index 7d01dc7235b2..0389a0356d05 100644 --- a/yarn-project/types/src/l2_tx.ts +++ b/yarn-project/types/src/l2_tx.ts @@ -4,12 +4,30 @@ import { TxHash } from './tx_hash.js'; import { createTxHash } from './create_tx_hash.js'; import { PublicDataWrite } from './public_data_write.js'; +/** + * Represents an L2 transaction. + */ export class L2Tx { constructor( + /** + * New commitments created by the transaction. + */ public newCommitments: Fr[], + /** + * New nullifiers created by the transaction. + */ public newNullifiers: Fr[], + /** + * New public data writes created by the transaction. + */ public newPublicDataWrites: PublicDataWrite[], + /** + * New contracts leafs created by the transaction to be inserted into the contract tree. + */ public newContracts: Fr[], + /** + * New contract data created by the transaction. + */ public newContractData: ContractData[], private hash?: TxHash, ) {} diff --git a/yarn-project/types/src/public_data_write.ts b/yarn-project/types/src/public_data_write.ts index 0cad14d6f497..252fd725ba7e 100644 --- a/yarn-project/types/src/public_data_write.ts +++ b/yarn-project/types/src/public_data_write.ts @@ -5,30 +5,74 @@ import { BufferReader } from '@aztec/foundation/serialize'; * Write operations on the public state tree. */ export class PublicDataWrite { - constructor(public readonly leafIndex: Fr, public readonly newValue: Fr) {} + constructor( + /** + * Index of the updated leaf. + */ + public readonly leafIndex: Fr, + /** + * New value of the leaf. + */ + public readonly newValue: Fr, + ) {} - static from(args: { leafIndex: Fr; newValue: Fr }) { + /** + * Creates a new public data write operation from the given arguments. + * @param args - Arguments containing info used to create a new public data write operation. + * @returns A new public data write operation instance. + */ + static from(args: { + /** + * Index of the updated leaf. + */ + leafIndex: Fr; + /** + * New value of the leaf. + */ + newValue: Fr; + }) { return new PublicDataWrite(args.leafIndex, args.newValue); } - toBuffer() { + /** + * Serializes the public data write operation to a buffer. + * @returns A buffer containing the serialized public data write operation. + */ + toBuffer(): Buffer { return serializeToBuffer(this.leafIndex, this.newValue); } - isEmpty() { + /** + * Checks if the public data write operation is empty. + * @returns True if the public data write operation is empty, false otherwise. + */ + isEmpty(): boolean { return this.leafIndex.isZero() && this.newValue.isZero(); } - static fromBuffer(buffer: Buffer | BufferReader) { + /** + * Creates a new public data write operation from the given buffer. + * @param buffer - Buffer containing the serialized public data write operation. + * @returns A new public data write operation instance. + */ + static fromBuffer(buffer: Buffer | BufferReader): PublicDataWrite { const reader = BufferReader.asReader(buffer); return new PublicDataWrite(reader.readFr(), reader.readFr()); } - static empty() { + /** + * Creates an empty public data write operation. + * @returns A new public data write operation instance. + */ + static empty(): PublicDataWrite { return new PublicDataWrite(Fr.ZERO, Fr.ZERO); } - static random() { + /** + * Creates a random public data write operation. + * @returns A new public data write operation instance. + */ + static random(): PublicDataWrite { return new PublicDataWrite(Fr.random(), Fr.random()); } } diff --git a/yarn-project/types/src/tx.ts b/yarn-project/types/src/tx.ts index f13833f3e921..82cb8d60b2ba 100644 --- a/yarn-project/types/src/tx.ts +++ b/yarn-project/types/src/tx.ts @@ -7,16 +7,36 @@ import { UnverifiedData } from './unverified_data.js'; import { EncodedContractFunction } from './contract_data.js'; import { keccak } from '@aztec/foundation/crypto'; +/** + * Defines valid fields for a private transaction. + */ type PrivateTxFields = 'data' | 'proof' | 'unverifiedData'; + +/** + * Defines valid fields for a public transaction. + */ type PublicTxFields = 'txRequest'; +/** + * Defines private tx type. + */ export type PrivateTx = Required> & Tx; + +/** + * Defines public tx type. + */ export type PublicTx = Required> & Tx; +/** + * Checks if a tx is public. + */ export function isPublicTx(tx: Tx): tx is PublicTx { return !!tx.txRequest; } +/** + * Checks if a tx is private. + */ export function isPrivateTx(tx: Tx): tx is PrivateTx { return !!tx.data && !!tx.proof && !!tx.unverifiedData; } @@ -27,6 +47,14 @@ export function isPrivateTx(tx: Tx): tx is PrivateTx { export class Tx { private hashPromise?: Promise; + /** + * Creates a new private transaction. + * @param data - Public inputs of the private kernel circuit. + * @param proof - Proof from the private kernel circuit. + * @param unverifiedData - Unverified data created by this tx. + * @param newContractPublicFunctions - Public functions made available by this tx. + * @returns A new private tx instance. + */ public static createPrivate( data: KernelCircuitPublicInputs, proof: UInt8Vector, @@ -36,10 +64,23 @@ export class Tx { return new this(data, proof, unverifiedData, undefined, newContractPublicFunctions) as PrivateTx; } + /** + * Creates a new public transaction from the given tx request. + * @param txRequest - The tx request. + * @returns New public tx instance. + */ public static createPublic(txRequest: SignedTxRequest): PublicTx { return new this(undefined, undefined, undefined, txRequest) as PublicTx; } + /** + * Creates a new transaction containing both private and public calls. + * @param data - Public inputs of the private kernel circuit. + * @param proof - Proof from the private kernel circuit. + * @param unverifiedData - Unverified data created by this tx. + * @param txRequest - The tx request defining the public call. + * @returns A new tx instance. + */ public static createPrivatePublic( data: KernelCircuitPublicInputs, proof: UInt8Vector, @@ -49,6 +90,14 @@ export class Tx { return new this(data, proof, unverifiedData, txRequest) as PrivateTx & PublicTx; } + /** + * Creates a new transaction from the given tx request. + * @param data - Public inputs of the private kernel circuit. + * @param proof - Proof from the private kernel circuit. + * @param unverifiedData - Unverified data created by this tx. + * @param txRequest - The tx request defining the public call. + * @returns A new tx instance. + */ public static create( data?: KernelCircuitPublicInputs, proof?: UInt8Vector, @@ -58,27 +107,42 @@ export class Tx { return new this(data, proof, unverifiedData, txRequest); } + /** + * Checks if a tx is private. + * @returns True if the tx is private, false otherwise. + */ public isPrivate(): this is PrivateTx { return isPrivateTx(this); } + /** + * Checks if a tx is public. + * @returns True if the tx is public, false otherwise. + */ public isPublic(): this is PublicTx { return isPublicTx(this); } - /** - * Creates a new instance. - * @param data - Output of the private kernel circuit for this tx. - * @param proof - Proof from the private kernel circuit. - * @param unverifiedData - Information not needed to verify the tx (e.g. encrypted note pre-images etc.) - * @param txRequest - Signed public function call data. - * @param contractsBytecode - Selector + Bytecode of contract functions that were deployed in the tx. - */ protected constructor( + /** + * Output of the private kernel circuit for this tx. + */ public readonly data?: KernelCircuitPublicInputs, + /** + * Proof from the private kernel circuit. + */ public readonly proof?: UInt8Vector, + /** + * Information not needed to verify the tx (e.g. Encrypted note pre-images etc.). + */ public readonly unverifiedData?: UnverifiedData, + /** + * Signed public function call data. + */ public readonly txRequest?: SignedTxRequest, + /** + * New public functions made available by this tx. + */ public readonly newContractPublicFunctions?: EncodedContractFunction[], ) {} @@ -95,8 +159,8 @@ export class Tx { /** * Convenience function to get array of hashes for an array of txs. - * @param txs - the txs to get the hashes from - * @returns The corresponding array of hashes + * @param txs - The txs to get the hashes from. + * @returns The corresponding array of hashes. */ static async getHashes(txs: Tx[]): Promise { return await Promise.all(txs.map(tx => tx.getTxHash())); diff --git a/yarn-project/types/src/tx_hash.ts b/yarn-project/types/src/tx_hash.ts index 746e3cc4724b..dcd48fd39b82 100644 --- a/yarn-project/types/src/tx_hash.ts +++ b/yarn-project/types/src/tx_hash.ts @@ -1,12 +1,28 @@ -import { toBigInt } from '@aztec/foundation'; +import { toBigInt } from '@aztec/foundation/serialize'; +/** + * A class representing hash of Aztec transaction. + */ export class TxHash { + /** + * The size of the hash in bytes. + */ public static SIZE = 32; - constructor(public readonly buffer: Buffer) {} + constructor( + /** + * The buffer containing the hash. + */ + public readonly buffer: Buffer, + ) {} - public equals(rhs: TxHash) { - return this.buffer.equals(rhs.buffer); + /** + * Checks if this hash and another hash are equal. + * @param hash - A hash to compare with. + * @returns True if the hashes are equal, false otherwise. + */ + public equals(hash: TxHash): boolean { + return this.buffer.equals(hash.buffer); } /** diff --git a/yarn-project/types/src/unverified_data.ts b/yarn-project/types/src/unverified_data.ts index d2b0c832fe9b..01d4cf7cde4b 100644 --- a/yarn-project/types/src/unverified_data.ts +++ b/yarn-project/types/src/unverified_data.ts @@ -1,15 +1,21 @@ import { deserializeBufferFromVector, serializeBufferToVector } from '@aztec/foundation/serialize'; import { randomBytes } from 'crypto'; + /** * Data container of unverified data corresponding to one L2 block. */ export class UnverifiedData { + constructor( + /** + * Chunks of unverified data corresponding to individual pieces of information (e.g. Encrypted preimages). + */ + public readonly dataChunks: Buffer[], + ) {} + /** - * Constructs an object containing unverified data. - * @param dataChunks - Chunks of unverified data corresponding to individual pieces of information (e.g. encrypted preimages). + * Serializes unverified data into a buffer. + * @returns A buffer containing the serialized unverified data. */ - constructor(public readonly dataChunks: Buffer[]) {} - public toBuffer(): Buffer { // Serialize each buffer into the new buffer with prefix const serializedChunks = this.dataChunks.map(buffer => serializeBufferToVector(buffer)); @@ -28,6 +34,11 @@ export class UnverifiedData { return new UnverifiedData(datas.flatMap(chunk => chunk.dataChunks)); } + /** + * Deserializes unverified data from a buffer. + * @param buf - The buffer containing the serialized unverified data. + * @returns A new UnverifiedData object. + */ public static fromBuffer(buf: Buffer): UnverifiedData { let currIndex = 0; const chunks: Buffer[] = []; @@ -46,6 +57,11 @@ export class UnverifiedData { return new UnverifiedData(chunks); } + /** + * Creates a new UnverifiedData object with `numChunks` random data. + * @param numChunks - The number of chunks to create. + * @returns A new UnverifiedData object. + */ public static random(numChunks: number): UnverifiedData { const chunks: Buffer[] = []; for (let i = 0; i < numChunks; i++) { diff --git a/yarn-project/world-state/README.md b/yarn-project/world-state/README.md index 39212748a090..b55f68121234 100644 --- a/yarn-project/world-state/README.md +++ b/yarn-project/world-state/README.md @@ -1 +1,40 @@ # World State + +## Overview + +The primary functions of the world state package are to maintain the collection of Merkle Trees comprising the global state of the system and to offer an interface with which the trees can be queried. + +### The Merkle Tree DB, a collection of Merkle Trees of varying types. + +As of the time of writing the collection consisted of the following trees. + +#### Standard 'Append Only' trees + +- The Contract Tree. Every contract created within the system has a 'Function Tree', a tree of leaves generated from the functions on the contract. The root of the function tree is inserted as a leaf in the contracts tree. +- The Contract Tree Roots Tree. A tree whose leaves are the historic roots of the contract tree. +- The Private Data Tree. A tree whose leaves are the private data committments generated by the private txs within the system. +- The Private Data Tree Roots Tree. A tree whose leaves are the historic roots of the private data tree. + +#### Indexed trees + +- The Nullifier Tree. A tree whose leaves contain the consumed values (committments, tx hashes etc) of the system. + +#### Sparse trees + +- The Public Data Tree. A tree whose leaves are the current value of every item of public state in the system, addressed as `leaf_index = hash(contract_address, storage_slot_in_contract)` + +### The Synchroniser + +The synchroniser's role is to periodically poll for new block information and reconcile that information with the current state of the Merkle Trees. + +Once a new block is received, the synchroniser checks the uncommitted root values of all of the trees against the roots published as part of the block. If they are all equal, the tree state is committed. If they are not equal, the tree states are rolled back to the last committed state before the published data is inserted and committed. + +### The Merkle Tree Interface + +The interface to the Merkle Tree DB offers a unified asynchronous API to the set of trees available. Reads from the Merkle Trees need to be marked as to whether they should include uncommitted state. For this reason, the MerkleTreeOperationsFacade exists to abstract this detail away from the end consumer. + +# Building/Testing + +Building the package is as simple as calling `yarn build` from the package root. + +Running `yarn test` will execute the packages unit tests. diff --git a/yarn-project/world-state/src/merkle-tree/merkle_tree_operations_facade.ts b/yarn-project/world-state/src/merkle-tree/merkle_tree_operations_facade.ts index 918caefae71d..047743daa505 100644 --- a/yarn-project/world-state/src/merkle-tree/merkle_tree_operations_facade.ts +++ b/yarn-project/world-state/src/merkle-tree/merkle_tree_operations_facade.ts @@ -107,7 +107,7 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations { * the current roots of the corresponding trees (CONTRACT_TREE, PRIVATE_DATA_TREE). * @returns Empty promise. */ - public updateRootsTrees(): Promise { - return this.trees.updateRootsTrees(this.includeUncommitted); + public updateHistoricRootsTrees(): Promise { + return this.trees.updateHistoricRootsTrees(this.includeUncommitted); } } diff --git a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts index 42f0b91fef62..7586b04f0a72 100644 --- a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts +++ b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts @@ -1,5 +1,5 @@ import { BarretenbergWasm } from '@aztec/barretenberg.js/wasm'; -import { AppendOnlyTreeSnapshot } from '@aztec/circuits.js'; +import { AppendOnlyTreeSnapshot, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; import { fr } from '@aztec/circuits.js/factories'; import { INITIAL_LEAF, Pedersen, SiblingPath } from '@aztec/merkle-tree'; @@ -35,6 +35,10 @@ const getMockContractData = () => { return ContractData.random(); }; +const getMockL1ToL2MessagesData = () => { + return new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).map(() => Fr.random()); +}; + const getMockBlock = (blockNumber: number, newContractsCommitments?: Buffer[]) => { const block = L2Block.fromFields({ number: blockNumber, @@ -44,17 +48,22 @@ const getMockBlock = (blockNumber: number, newContractsCommitments?: Buffer[]) = startTreeOfHistoricPrivateDataTreeRootsSnapshot: getMockTreeSnapshot(), startTreeOfHistoricContractTreeRootsSnapshot: getMockTreeSnapshot(), startPublicDataTreeRoot: Fr.random(), + startL1ToL2MessageTreeSnapshot: getMockTreeSnapshot(), + startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: getMockTreeSnapshot(), endPrivateDataTreeSnapshot: getMockTreeSnapshot(), endNullifierTreeSnapshot: getMockTreeSnapshot(), endContractTreeSnapshot: getMockTreeSnapshot(), endTreeOfHistoricPrivateDataTreeRootsSnapshot: getMockTreeSnapshot(), endTreeOfHistoricContractTreeRootsSnapshot: getMockTreeSnapshot(), endPublicDataTreeRoot: Fr.random(), + endL1ToL2MessageTreeSnapshot: getMockTreeSnapshot(), + endTreeOfHistoricL1ToL2MessageTreeRootsSnapshot: getMockTreeSnapshot(), newCommitments: [Fr.random()], newNullifiers: [Fr.random()], newContracts: newContractsCommitments?.map(x => Fr.fromBuffer(x)) ?? [Fr.random()], newContractData: [getMockContractData()], newPublicDataWrites: [PublicDataWrite.random()], + newL1ToL2Messages: getMockL1ToL2MessagesData(), }); return block; }; @@ -83,7 +92,7 @@ describe('server_world_state_synchroniser', () => { SiblingPath.ZERO(32, INITIAL_LEAF, pedersen); }; //Promise.resolve(); }), - updateRootsTrees: jest.fn().mockImplementation(() => Promise.resolve()), + updateHistoricRootsTrees: jest.fn().mockImplementation(() => Promise.resolve()), commit: jest.fn().mockImplementation(() => Promise.resolve()), rollback: jest.fn().mockImplementation(() => Promise.resolve()), } as any; @@ -233,7 +242,7 @@ describe('server_world_state_synchroniser', () => { it('updates the contract tree', async () => { merkleTreeDb.appendLeaves.mockReset(); - merkleTreeDb.updateRootsTrees.mockReset(); + merkleTreeDb.updateHistoricRootsTrees.mockReset(); const server = createSynchroniser(merkleTreeDb, rollupSource); const totalBlocks = LATEST_BLOCK_NUMBER + 1; nextBlocks = Array(totalBlocks) @@ -244,7 +253,7 @@ describe('server_world_state_synchroniser', () => { // there are 3 data trees updated expect(merkleTreeDb.appendLeaves).toHaveBeenCalledTimes(totalBlocks * 3); // and 2 root trees - expect(merkleTreeDb.updateRootsTrees).toHaveBeenCalledTimes(totalBlocks); + expect(merkleTreeDb.updateHistoricRootsTrees).toHaveBeenCalledTimes(totalBlocks); // there should be a call to append to the contract tree for each block for (let i = 0; i < totalBlocks; i++) { expect( diff --git a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts index 5eb4b3d09adf..79c7cc15f845 100644 --- a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts +++ b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts @@ -168,7 +168,7 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { await this.merkleTreeDb.updateLeaf(MerkleTreeId.PUBLIC_DATA_TREE, newValue.toBuffer(), leafIndex.value); } - await this.merkleTreeDb.updateRootsTrees(true); + await this.merkleTreeDb.updateHistoricRootsTrees(true); await this.merkleTreeDb.commit(); } this.currentL2BlockNum = l2Block.number; diff --git a/yarn-project/world-state/src/world-state-db/index.ts b/yarn-project/world-state/src/world-state-db/index.ts index 469b6a219a39..36944827a887 100644 --- a/yarn-project/world-state/src/world-state-db/index.ts +++ b/yarn-project/world-state/src/world-state-db/index.ts @@ -13,6 +13,8 @@ export enum MerkleTreeId { PRIVATE_DATA_TREE = 3, PRIVATE_DATA_TREE_ROOTS_TREE = 4, PUBLIC_DATA_TREE = 5, + L1_TO_L2_MESSAGES_TREE = 6, + L1_TO_L2_MESSAGES_ROOTS_TREE = 7, } /** @@ -152,7 +154,7 @@ export interface MerkleTreeOperations { * Inserts into the roots trees (CONTRACT_TREE_ROOTS_TREE, PRIVATE_DATA_TREE_ROOTS_TREE) * the current roots of the corresponding trees (CONTRACT_TREE, PRIVATE_DATA_TREE). */ - updateRootsTrees(): Promise; + updateHistoricRootsTrees(): Promise; } /** diff --git a/yarn-project/world-state/src/world-state-db/merkle_trees.ts b/yarn-project/world-state/src/world-state-db/merkle_trees.ts index cce2a69b79ba..5fd25bcc2022 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_trees.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_trees.ts @@ -2,6 +2,8 @@ import { PrimitivesWasm } from '@aztec/barretenberg.js/wasm'; import { CONTRACT_TREE_HEIGHT, CONTRACT_TREE_ROOTS_TREE_HEIGHT, + L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT, + L1_TO_L2_MESSAGES_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PRIVATE_DATA_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, @@ -93,7 +95,20 @@ export class MerkleTrees implements MerkleTreeDb { `${MerkleTreeId[MerkleTreeId.PUBLIC_DATA_TREE]}`, PUBLIC_DATA_TREE_HEIGHT, ); - + const l1Tol2MessagesTree: AppendOnlyTree = await newTree( + StandardTree, + this.db, + hasher, + `${MerkleTreeId[MerkleTreeId.L1_TO_L2_MESSAGES_TREE]}`, + L1_TO_L2_MESSAGES_TREE_HEIGHT, + ); + const l1Tol2MessagesRootsTree: AppendOnlyTree = await newTree( + StandardTree, + this.db, + hasher, + `${MerkleTreeId[MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE]}`, + L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT, + ); this.trees = [ contractTree, contractTreeRootsTree, @@ -101,11 +116,13 @@ export class MerkleTrees implements MerkleTreeDb { privateDataTree, privateDataTreeRootsTree, publicDataTree, + l1Tol2MessagesTree, + l1Tol2MessagesRootsTree, ]; this.jobQueue.start(); - await this.updateRootsTrees(true); + await this.updateHistoricRootsTrees(true); } /** @@ -148,10 +165,11 @@ export class MerkleTrees implements MerkleTreeDb { * the current roots of the corresponding trees (CONTRACT_TREE, PRIVATE_DATA_TREE). * @param includeUncommitted - Indicates whether to include uncommitted data. */ - public async updateRootsTrees(includeUncommitted: boolean) { + public async updateHistoricRootsTrees(includeUncommitted: boolean) { for (const [newTree, rootTree] of [ [MerkleTreeId.PRIVATE_DATA_TREE, MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE], [MerkleTreeId.CONTRACT_TREE, MerkleTreeId.CONTRACT_TREE_ROOTS_TREE], + [MerkleTreeId.L1_TO_L2_MESSAGES_TREE, MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE], ] as const) { const newTreeInfo = await this.getTreeInfo(newTree, includeUncommitted); await this.appendLeaves(rootTree, [newTreeInfo.root]);