From 0d4c707079ff1ff4212fc3345066b0deded98449 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:39:25 +0200 Subject: [PATCH] chore(circuits): Base rollup cbind msgpack (#2263) Resolves #2096 # Checklist: Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge. - [x] If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag. - [x] I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code. - [x] Every change is related to the PR description. - [x] I have [linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this pull request to relevant issues (if any exist). --------- Co-authored-by: ludamad --- circuits/cpp/bootstrap.sh | 9 +- .../cpp/src/aztec3/circuits/abis/packers.hpp | 3 + .../base_or_merge_rollup_public_inputs.hpp | 6 +- .../abis/rollup/base/base_rollup_inputs.hpp | 20 +- .../src/aztec3/circuits/rollup/base/.test.cpp | 160 ++++++------- .../aztec3/circuits/rollup/base/c_bind.cpp | 57 +---- .../src/aztec3/circuits/rollup/base/c_bind.h | 11 +- circuits/cpp/src/aztec3/constants.hpp | 12 +- .../src/core/libraries/ConstantsGen.sol | 3 + .../aztec-nr/aztec/src/constants_gen.nr | 3 + .../circuits.js/src/cbind/circuits.gen.ts | 210 ++++++++++++++++++ .../circuits.js/src/cbind/constants.gen.ts | 3 + yarn-project/circuits.js/src/cbind/types.ts | 2 + yarn-project/circuits.js/src/rollup/index.ts | 2 +- .../src/rollup/rollup_wasm_wrapper.test.ts | 21 +- .../src/rollup/rollup_wasm_wrapper.ts | 22 -- .../src/structs/rollup/base_rollup.ts | 90 +++----- .../circuits.js/src/tests/factories.ts | 58 ++--- .../block_builder/solo_block_builder.test.ts | 6 +- .../src/block_builder/solo_block_builder.ts | 104 +++++++-- .../sequencer-client/src/simulator/rollup.ts | 11 +- yarn-project/types/src/sibling_path.ts | 10 + .../src/world-state-db/merkle_trees.ts | 4 +- 23 files changed, 518 insertions(+), 309 deletions(-) delete mode 100644 yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts diff --git a/circuits/cpp/bootstrap.sh b/circuits/cpp/bootstrap.sh index f90114e82a4..4c829a9570e 100755 --- a/circuits/cpp/bootstrap.sh +++ b/circuits/cpp/bootstrap.sh @@ -62,5 +62,10 @@ cmake --preset $PRESET -DCMAKE_BUILD_TYPE=RelWithAssert cmake --build --preset $PRESET ${@/#/--target } # Build WASM. -cmake --preset wasm -cmake --build --preset wasm +if [ -n "${WASM_DEBUG:-}" ] ; then + cmake --preset wasm-dbg + cmake --build --preset wasm-dbg +else + cmake --preset wasm + cmake --build --preset wasm +fi diff --git a/circuits/cpp/src/aztec3/circuits/abis/packers.hpp b/circuits/cpp/src/aztec3/circuits/abis/packers.hpp index 8c125d860c4..fb001b0f049 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/packers.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/packers.hpp @@ -41,6 +41,9 @@ struct ConstantsPacker { NUM_UNENCRYPTED_LOGS_HASHES_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, KERNELS_PER_BASE_ROLLUP, + MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, VK_TREE_HEIGHT, FUNCTION_TREE_HEIGHT, CONTRACT_TREE_HEIGHT, diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp index a72c64f055d..8b234ac8dc4 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp @@ -14,6 +14,7 @@ const uint32_t MERGE_ROLLUP_TYPE = 1; template struct BaseOrMergeRollupPublicInputs { using fr = typename NCT::fr; using AggregationObject = typename NCT::AggregationObject; + using boolean = typename NCT::boolean; uint32_t rollup_type; // subtree height is always 0 for base. @@ -52,7 +53,10 @@ template struct BaseOrMergeRollupPublicInputs { start_public_data_tree_root, end_public_data_tree_root, calldata_hash); - bool operator==(BaseOrMergeRollupPublicInputs const&) const = default; + boolean operator==(BaseOrMergeRollupPublicInputs const& other) const + { + return msgpack_derived_equals(*this, other); + }; }; } // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp index 7e78e21c250..b2b28ea726d 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp @@ -13,8 +13,9 @@ namespace aztec3::circuits::abis { template struct BaseRollupInputs { using fr = typename NCT::fr; + using boolean = typename NCT::boolean; - std::array, 2> kernel_data{}; + std::array, KERNELS_PER_BASE_ROLLUP> kernel_data{}; AppendOnlyTreeSnapshot start_private_data_tree_snapshot{}; AppendOnlyTreeSnapshot start_nullifier_tree_snapshot{}; @@ -22,8 +23,8 @@ template struct BaseRollupInputs { fr start_public_data_tree_root{}; AppendOnlyTreeSnapshot start_historic_blocks_tree_snapshot{}; - std::array, 2 * MAX_NEW_NULLIFIERS_PER_TX> low_nullifier_leaf_preimages{}; - std::array, 2 * MAX_NEW_NULLIFIERS_PER_TX> + std::array, MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP> low_nullifier_leaf_preimages{}; + std::array, MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP> low_nullifier_membership_witness{}; // For inserting the new subtrees into their respective trees: @@ -31,12 +32,13 @@ template struct BaseRollupInputs { std::array new_commitments_subtree_sibling_path{}; std::array new_nullifiers_subtree_sibling_path{}; std::array new_contracts_subtree_sibling_path{}; - std::array, 2 * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX> + std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP> new_public_data_update_requests_sibling_paths{}; - std::array, 2 * MAX_PUBLIC_DATA_READS_PER_TX> + std::array, MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP> new_public_data_reads_sibling_paths{}; - std::array, 2> historic_blocks_tree_root_membership_witnesses{}; + std::array, KERNELS_PER_BASE_ROLLUP> + historic_blocks_tree_root_membership_witnesses{}; ConstantRollupData constants{}; @@ -56,7 +58,11 @@ template struct BaseRollupInputs { new_public_data_reads_sibling_paths, historic_blocks_tree_root_membership_witnesses, constants); - bool operator==(BaseRollupInputs const&) const = default; + + boolean operator==(BaseRollupInputs const& other) const + { + return msgpack_derived_equals(*this, other); + }; }; } // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp index abd6dba76b8..9e14512f24c 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp @@ -64,67 +64,57 @@ class base_rollup_tests : public ::testing::Test { protected: static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } - static void run_cbind(BaseRollupInputs& base_rollup_inputs, - BaseOrMergeRollupPublicInputs& expected_public_inputs, - bool compare_pubins = true, - bool assert_no_circuit_failure = true) - { - info("Retesting via cbinds...."); - // TODO(banks12) might be able to get rid of proving key buffer - uint8_t const* pk_buf = nullptr; - size_t const pk_size = base_rollup__init_proving_key(&pk_buf); - (void)pk_size; - // info("Proving key size: ", pk_size); - - // TODO(banks12) might be able to get rid of verification key buffer - uint8_t const* vk_buf = nullptr; - size_t const vk_size = base_rollup__init_verification_key(pk_buf, &vk_buf); - (void)vk_size; - // info("Verification key size: ", vk_size); - - std::vector base_rollup_inputs_vec; - serialize::write(base_rollup_inputs_vec, base_rollup_inputs); - - // uint8_t const* proof_data; - // size_t proof_data_size; - uint8_t const* public_inputs_buf = nullptr; - size_t public_inputs_size = 0; - // info("simulating circuit via cbind"); - uint8_t* const circuit_failure_ptr = - base_rollup__sim(base_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); - - ASSERT_TRUE(assert_no_circuit_failure ? circuit_failure_ptr == nullptr : circuit_failure_ptr != nullptr); - // info("Proof size: ", proof_data_size); - // info("PublicInputs size: ", public_inputs_size); - - if (compare_pubins) { - BaseOrMergeRollupPublicInputs public_inputs; - uint8_t const* public_inputs_buf_tmp = public_inputs_buf; - serialize::read(public_inputs_buf_tmp, public_inputs); - ASSERT_EQ(public_inputs.calldata_hash.size(), expected_public_inputs.calldata_hash.size()); - for (size_t i = 0; i < public_inputs.calldata_hash.size(); i++) { - ASSERT_EQ(public_inputs.calldata_hash[i], expected_public_inputs.calldata_hash[i]); - } - - std::vector expected_public_inputs_vec; - serialize::write(expected_public_inputs_vec, expected_public_inputs); - - ASSERT_EQ(public_inputs_size, expected_public_inputs_vec.size()); - // Just compare the first 10 bytes of the serialized public outputs - if (public_inputs_size > 10) { - // for (size_t 0; i < public_inputs_size; i++) { - for (size_t i = 0; i < 10; i++) { - ASSERT_EQ(public_inputs_buf[i], expected_public_inputs_vec[i]); - } - } - } - - free((void*)pk_buf); - free((void*)vk_buf); - // free((void*)proof_data); - free((void*)public_inputs_buf); - // info("finished retesting via cbinds..."); - } + // TODO(1998): uncomment once https://github.com/AztecProtocol/aztec-packages/issues/1998 is solved and + // use new pattern such as call_func_and_wrapper from test_helper.hpp + + // static void run_cbind(BaseRollupInputs& base_rollup_inputs, + // BaseOrMergeRollupPublicInputs& expected_public_inputs, + // bool compare_pubins = true, + // bool assert_no_circuit_failure = true) + // { + // info("Retesting via cbinds...."); + + // std::vector base_rollup_inputs_vec; + // serialize::write(base_rollup_inputs_vec, base_rollup_inputs); + + // // uint8_t const* proof_data; + // // size_t proof_data_size; + // uint8_t const* public_inputs_buf = nullptr; + // size_t public_inputs_size = 0; + // // info("simulating circuit via cbind"); + // uint8_t* const circuit_failure_ptr = + // base_rollup__sim(base_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); + + // ASSERT_TRUE(assert_no_circuit_failure ? circuit_failure_ptr == nullptr : circuit_failure_ptr != nullptr); + // // info("Proof size: ", proof_data_size); + // // info("PublicInputs size: ", public_inputs_size); + + // if (compare_pubins) { + // BaseOrMergeRollupPublicInputs public_inputs; + // uint8_t const* public_inputs_buf_tmp = public_inputs_buf; + // serialize::read(public_inputs_buf_tmp, public_inputs); + // ASSERT_EQ(public_inputs.calldata_hash.size(), expected_public_inputs.calldata_hash.size()); + // for (size_t i = 0; i < public_inputs.calldata_hash.size(); i++) { + // ASSERT_EQ(public_inputs.calldata_hash[i], expected_public_inputs.calldata_hash[i]); + // } + + // std::vector expected_public_inputs_vec; + // serialize::write(expected_public_inputs_vec, expected_public_inputs); + + // ASSERT_EQ(public_inputs_size, expected_public_inputs_vec.size()); + // // Just compare the first 10 bytes of the serialized public outputs + // if (public_inputs_size > 10) { + // // for (size_t 0; i < public_inputs_size; i++) { + // for (size_t i = 0; i < 10; i++) { + // ASSERT_EQ(public_inputs_buf[i], expected_public_inputs_vec[i]); + // } + // } + // } + + // // free((void*)proof_data); + // free((void*)public_inputs_buf); + // // info("finished retesting via cbinds..."); + // } }; TEST_F(base_rollup_tests, native_no_new_contract_leafs) @@ -154,7 +144,8 @@ TEST_F(base_rollup_tests, native_no_new_contract_leafs) ASSERT_EQ(outputs.end_contract_tree_snapshot, expectedEndContractTreeSnapshot); ASSERT_EQ(outputs.start_contract_tree_snapshot, emptyInputs.start_contract_tree_snapshot); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(emptyInputs, outputs); + // TODO(1998): see above + // run_cbind(emptyInputs, outputs); } TEST_F(base_rollup_tests, native_contract_leaf_inserted) @@ -199,7 +190,8 @@ TEST_F(base_rollup_tests, native_contract_leaf_inserted) ASSERT_EQ(outputs.start_contract_tree_snapshot, inputs.start_contract_tree_snapshot); ASSERT_EQ(outputs.end_contract_tree_snapshot, expected_end_contracts_snapshot); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_contract_leaf_inserted_in_non_empty_snapshot_tree) @@ -255,7 +247,8 @@ TEST_F(base_rollup_tests, native_contract_leaf_inserted_in_non_empty_snapshot_tr ASSERT_EQ(outputs.start_contract_tree_snapshot, inputs.start_contract_tree_snapshot); ASSERT_EQ(outputs.end_contract_tree_snapshot, expected_end_contracts_snapshot); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_new_commitments_tree) @@ -297,7 +290,8 @@ TEST_F(base_rollup_tests, native_new_commitments_tree) ASSERT_EQ(outputs.start_private_data_tree_snapshot, inputs.start_private_data_tree_snapshot); ASSERT_EQ(outputs.end_private_data_tree_snapshot, expected_end_commitments_snapshot); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } template NT::fr calc_root(NT::fr leaf, NT::uint32 leafIndex, std::array siblingPath) @@ -477,8 +471,8 @@ TEST_F(base_rollup_tests, native_nullifier_tree_regression) // This test runs after some data has already been inserted into the tree // This test will pre-populate the tree with 6 * KERNEL_NEW_NULLIFIERS_LENGTH values (0 item + 6 * // KERNEL_NEW_NULLIFIERS_LENGTH -1 more) simulating that a rollup inserting two random values has already - // succeeded. Note that this corresponds to 3 (1 already initialized and 2 new ones) base rollups. This rollup then - // adds two further random values that will end up having their low nullifiers point at each other + // succeeded. Note that this corresponds to 3 (1 already initialized and 2 new ones) base rollups. This rollup + // then adds two further random values that will end up having their low nullifiers point at each other std::vector initial_values(6 * MAX_NEW_NULLIFIERS_PER_TX - 1, 0); for (size_t i = 0; i < 2 * MAX_NEW_NULLIFIERS_PER_TX - 1; i++) { initial_values[i] = i + 1; @@ -585,14 +579,14 @@ TEST_F(base_rollup_tests, native_empty_block_calldata_hash) ASSERT_TRUE(compare_field_hash_to_expected(output_calldata_hash, expected_calldata_hash) == true); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_calldata_hash) { - // Execute the base rollup circuit with nullifiers, commitments and a contract deployment. Then check the calldata - // hash against the expected value. + // Execute the base rollup circuit with nullifiers, commitments and a contract deployment. Then check the + // calldata hash against the expected value. std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; // Commitments inserted are [1,2,3,4,5,6,7,8 ...]. Nullifiers inserted are [8,9,10,11,12,13,14,15 ...] @@ -630,7 +624,8 @@ TEST_F(base_rollup_tests, native_calldata_hash) ASSERT_EQ(expected_calldata_hash, output_calldata_hash); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_compute_membership_historic_blocks_tree_negative) @@ -676,7 +671,8 @@ TEST_F(base_rollup_tests, native_constants_dont_change) aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); ASSERT_EQ(inputs.constants, outputs.constants); EXPECT_FALSE(builder.failed()); - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_constants_dont_match_kernels_chain_id) @@ -730,7 +726,8 @@ TEST_F(base_rollup_tests, native_cbind_0) // @todo Error handling? BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); BaseOrMergeRollupPublicInputs ignored_public_inputs; - run_cbind(inputs, ignored_public_inputs, false); + // TODO(1998): see above + // run_cbind(inputs, ignored_public_inputs, false); } TEST_F(base_rollup_tests, native_single_public_state_read) @@ -765,7 +762,8 @@ TEST_F(base_rollup_tests, native_single_public_state_read) ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); ASSERT_EQ(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_single_public_state_write) @@ -803,7 +801,8 @@ TEST_F(base_rollup_tests, native_single_public_state_write) ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); ASSERT_NE(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_multiple_public_state_read_writes) @@ -823,7 +822,8 @@ TEST_F(base_rollup_tests, native_multiple_public_state_read_writes) std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - // We set up reads and writes such that the right tx will read or write to indices already modified by the left tx + // We set up reads and writes such that the right tx will read or write to indices already modified by the left + // tx kernel_data[0].public_inputs.end.public_data_reads[0] = make_public_read(fr(1), fr(101)); kernel_data[0].public_inputs.end.public_data_reads[1] = make_public_read(fr(2), fr(102)); kernel_data[0].public_inputs.end.public_data_update_requests[0] = @@ -850,7 +850,8 @@ TEST_F(base_rollup_tests, native_multiple_public_state_read_writes) ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); ASSERT_NE(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - run_cbind(inputs, outputs); + // TODO(1998): see above + // run_cbind(inputs, outputs); } TEST_F(base_rollup_tests, native_invalid_public_state_read) @@ -889,7 +890,8 @@ TEST_F(base_rollup_tests, native_invalid_public_state_read) ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); ASSERT_EQ(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); ASSERT_TRUE(builder.failed()); - run_cbind(inputs, outputs, true, false); + // TODO(1998): see above + // run_cbind(inputs, outputs, true, false); } } // namespace aztec3::circuits::rollup::base::native_base_rollup_circuit diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp index 2a2cbbe1945..0be1cd67ae3 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp @@ -14,62 +14,13 @@ namespace { using Builder = UltraCircuitBuilder; using NT = aztec3::utils::types::NativeTypes; using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::BaseOrMergeRollupPublicInputs; using aztec3::circuits::abis::BaseRollupInputs; using aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit; - } // namespace // WASM Cbinds -extern "C" { - -WASM_EXPORT size_t base_rollup__init_proving_key(uint8_t const** pk_buf) -{ - std::vector pk_vec(42, 0); - - auto* raw_buf = (uint8_t*)malloc(pk_vec.size()); - memcpy(raw_buf, (void*)pk_vec.data(), pk_vec.size()); - *pk_buf = raw_buf; - - return pk_vec.size(); -} - -WASM_EXPORT size_t base_rollup__init_verification_key(uint8_t const* pk_buf, uint8_t const** vk_buf) -{ - std::vector vk_vec(42, 0); - // TODO remove when proving key is used - (void)pk_buf; // unused - - auto* raw_buf = (uint8_t*)malloc(vk_vec.size()); - memcpy(raw_buf, (void*)vk_vec.data(), vk_vec.size()); - *vk_buf = raw_buf; - - return vk_vec.size(); -} - -WASM_EXPORT uint8_t* base_rollup__sim(uint8_t const* base_rollup_inputs_buf, - size_t* base_rollup_public_inputs_size_out, - uint8_t const** base_or_merge_rollup_public_inputs_buf) -{ +CBIND(base_rollup__sim, [](BaseRollupInputs const& base_rollup_inputs) { DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup__sim"); - // TODO accept proving key and use that to initialize builders - // this info is just to prevent error for unused pk_buf - // TODO do we want to accept it or just get it from our factory? - // auto crs_factory = std::make_shared(); - - BaseRollupInputs base_rollup_inputs; - serialize::read(base_rollup_inputs_buf, base_rollup_inputs); - - BaseOrMergeRollupPublicInputs const public_inputs = base_rollup_circuit(builder, base_rollup_inputs); - - // serialize public inputs to bytes vec - std::vector public_inputs_vec; - serialize::write(public_inputs_vec, public_inputs); - // copy public inputs to output buffer - auto* raw_public_inputs_buf = (uint8_t*)malloc(public_inputs_vec.size()); - memcpy(raw_public_inputs_buf, (void*)public_inputs_vec.data(), public_inputs_vec.size()); - *base_or_merge_rollup_public_inputs_buf = raw_public_inputs_buf; - *base_rollup_public_inputs_size_out = public_inputs_vec.size(); - return builder.alloc_and_serialize_first_failure(); -} -} // extern "C" + auto const& public_inputs = base_rollup_circuit(builder, base_rollup_inputs); + return builder.result_or_error(public_inputs); +}); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h index 5f5095f9fa8..dc833dbda13 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h @@ -5,13 +5,4 @@ #include #include -extern "C" { - -WASM_EXPORT size_t base_rollup__init_proving_key(uint8_t const** pk_buf); -WASM_EXPORT size_t base_rollup__init_verification_key(uint8_t const* pk_buf, uint8_t const** vk_buf); -WASM_EXPORT size_t base_rollup__dummy_previous_rollup(uint8_t const** previous_rollup_buf); -WASM_EXPORT uint8_t* base_rollup__sim(uint8_t const* base_rollup_inputs_buf, - size_t* base_rollup_public_inputs_size_out, - uint8_t const** base_or_merge_rollup_public_inputs_buf); -WASM_EXPORT size_t base_rollup__verify_proof(uint8_t const* vk_buf, uint8_t const* proof, uint32_t length); -} \ No newline at end of file +CBIND_DECL(base_rollup__sim); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp index 5437250e474..4f90a329345 100644 --- a/circuits/cpp/src/aztec3/constants.hpp +++ b/circuits/cpp/src/aztec3/constants.hpp @@ -73,9 +73,13 @@ constexpr size_t NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; // TODO(961): Use this constant everywhere instead of hard-coded "2". constexpr size_t KERNELS_PER_BASE_ROLLUP = 2; constexpr size_t COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_COMMITMENTS_PER_TX * 32; -constexpr size_t NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_NULLIFIERS_PER_TX * 32; +constexpr size_t MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_NULLIFIERS_PER_TX; +constexpr size_t NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP * 32; +constexpr size_t MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP = + KERNELS_PER_BASE_ROLLUP * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; constexpr size_t PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP = - KERNELS_PER_BASE_ROLLUP * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 64; // old value, new value + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP * 64; // old value, new value +constexpr size_t MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_PUBLIC_DATA_READS_PER_TX; constexpr size_t CONTRACTS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_CONTRACTS_PER_TX * 32; constexpr size_t CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_CONTRACTS_PER_TX * 64; // aztec address + eth address (padded to 0x20) @@ -86,7 +90,6 @@ constexpr size_t L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLL constexpr size_t LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * 2 * 32; // 1 for encrypted + 1 for unencrypted - // TREES RELATED CONSTANTS constexpr size_t VK_TREE_HEIGHT = 3; constexpr size_t FUNCTION_TREE_HEIGHT = 4; @@ -100,7 +103,8 @@ constexpr size_t ROLLUP_VK_TREE_HEIGHT = 8; // TODO: update // SUB-TREES RELATED CONSTANTS -constexpr size_t CONTRACT_SUBTREE_HEIGHT = 1; +constexpr size_t CONTRACT_SUBTREE_HEIGHT = + static_cast(log2(MAX_NEW_CONTRACTS_PER_TX * KERNELS_PER_BASE_ROLLUP)); constexpr size_t CONTRACT_SUBTREE_SIBLING_PATH_LENGTH = CONTRACT_TREE_HEIGHT - CONTRACT_SUBTREE_HEIGHT; constexpr size_t PRIVATE_DATA_SUBTREE_HEIGHT = static_cast(log2(KERNELS_PER_BASE_ROLLUP * MAX_NEW_COMMITMENTS_PER_TX)); diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index d1c76b84f6c..f314fbf484c 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -38,6 +38,9 @@ library Constants { uint256 internal constant NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; uint256 internal constant NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; uint256 internal constant KERNELS_PER_BASE_ROLLUP = 2; + uint256 internal constant MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP = 128; + uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP = 32; + uint256 internal constant MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP = 32; uint256 internal constant VK_TREE_HEIGHT = 3; uint256 internal constant FUNCTION_TREE_HEIGHT = 4; uint256 internal constant CONTRACT_TREE_HEIGHT = 16; diff --git a/yarn-project/aztec-nr/aztec/src/constants_gen.nr b/yarn-project/aztec-nr/aztec/src/constants_gen.nr index 8f680055a4f..6764ee657c3 100644 --- a/yarn-project/aztec-nr/aztec/src/constants_gen.nr +++ b/yarn-project/aztec-nr/aztec/src/constants_gen.nr @@ -23,6 +23,9 @@ global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: Field = 1; global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: Field = 1; global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: Field = 16; global KERNELS_PER_BASE_ROLLUP: Field = 2; +global MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP: Field = 128; +global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP: Field = 32; +global MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP: Field = 32; global VK_TREE_HEIGHT: Field = 3; global FUNCTION_TREE_HEIGHT: Field = 4; global CONTRACT_TREE_HEIGHT: Field = 16; diff --git a/yarn-project/circuits.js/src/cbind/circuits.gen.ts b/yarn-project/circuits.js/src/cbind/circuits.gen.ts index 3a257d984b1..5dabbdef88f 100644 --- a/yarn-project/circuits.js/src/cbind/circuits.gen.ts +++ b/yarn-project/circuits.js/src/cbind/circuits.gen.ts @@ -11,6 +11,7 @@ import { Address, AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, + BaseRollupInputs, CallContext, CircuitError, CombinedAccumulatedData, @@ -35,6 +36,7 @@ import { MergeRollupInputs, NativeAggregationState, NewContractData, + NullifierLeafPreimage, OptionallyRevealedData, Point, PreviousKernelData, @@ -2264,6 +2266,42 @@ export function fromAppendOnlyTreeSnapshot(o: AppendOnlyTreeSnapshot): MsgpackAp }; } +interface MsgpackNullifierLeafPreimage { + leaf_value: Buffer; + next_value: Buffer; + next_index: number; +} + +export function toNullifierLeafPreimage(o: MsgpackNullifierLeafPreimage): NullifierLeafPreimage { + if (o.leaf_value === undefined) { + throw new Error('Expected leaf_value in NullifierLeafPreimage deserialization'); + } + if (o.next_value === undefined) { + throw new Error('Expected next_value in NullifierLeafPreimage deserialization'); + } + if (o.next_index === undefined) { + throw new Error('Expected next_index in NullifierLeafPreimage deserialization'); + } + return new NullifierLeafPreimage(Fr.fromBuffer(o.leaf_value), Fr.fromBuffer(o.next_value), o.next_index); +} + +export function fromNullifierLeafPreimage(o: NullifierLeafPreimage): MsgpackNullifierLeafPreimage { + if (o.leafValue === undefined) { + throw new Error('Expected leafValue in NullifierLeafPreimage serialization'); + } + if (o.nextValue === undefined) { + throw new Error('Expected nextValue in NullifierLeafPreimage serialization'); + } + if (o.nextIndex === undefined) { + throw new Error('Expected nextIndex in NullifierLeafPreimage serialization'); + } + return { + leaf_value: toBuffer(o.leafValue), + next_value: toBuffer(o.nextValue), + next_index: o.nextIndex, + }; +} + interface MsgpackConstantRollupData { start_historic_blocks_tree_roots_snapshot: MsgpackAppendOnlyTreeSnapshot; private_kernel_vk_tree_root: Buffer; @@ -2331,6 +2369,172 @@ export function fromConstantRollupData(o: ConstantRollupData): MsgpackConstantRo }; } +interface MsgpackBaseRollupInputs { + kernel_data: Tuple; + start_private_data_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + start_nullifier_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + start_contract_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + start_public_data_tree_root: Buffer; + start_historic_blocks_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + low_nullifier_leaf_preimages: Tuple; + low_nullifier_membership_witness: Tuple; + new_commitments_subtree_sibling_path: Tuple; + new_nullifiers_subtree_sibling_path: Tuple; + new_contracts_subtree_sibling_path: Tuple; + new_public_data_update_requests_sibling_paths: Tuple, 32>; + new_public_data_reads_sibling_paths: Tuple, 32>; + historic_blocks_tree_root_membership_witnesses: Tuple; + constants: MsgpackConstantRollupData; +} + +export function toBaseRollupInputs(o: MsgpackBaseRollupInputs): BaseRollupInputs { + if (o.kernel_data === undefined) { + throw new Error('Expected kernel_data in BaseRollupInputs deserialization'); + } + if (o.start_private_data_tree_snapshot === undefined) { + throw new Error('Expected start_private_data_tree_snapshot in BaseRollupInputs deserialization'); + } + if (o.start_nullifier_tree_snapshot === undefined) { + throw new Error('Expected start_nullifier_tree_snapshot in BaseRollupInputs deserialization'); + } + if (o.start_contract_tree_snapshot === undefined) { + throw new Error('Expected start_contract_tree_snapshot in BaseRollupInputs deserialization'); + } + if (o.start_public_data_tree_root === undefined) { + throw new Error('Expected start_public_data_tree_root in BaseRollupInputs deserialization'); + } + if (o.start_historic_blocks_tree_snapshot === undefined) { + throw new Error('Expected start_historic_blocks_tree_snapshot in BaseRollupInputs deserialization'); + } + if (o.low_nullifier_leaf_preimages === undefined) { + throw new Error('Expected low_nullifier_leaf_preimages in BaseRollupInputs deserialization'); + } + if (o.low_nullifier_membership_witness === undefined) { + throw new Error('Expected low_nullifier_membership_witness in BaseRollupInputs deserialization'); + } + if (o.new_commitments_subtree_sibling_path === undefined) { + throw new Error('Expected new_commitments_subtree_sibling_path in BaseRollupInputs deserialization'); + } + if (o.new_nullifiers_subtree_sibling_path === undefined) { + throw new Error('Expected new_nullifiers_subtree_sibling_path in BaseRollupInputs deserialization'); + } + if (o.new_contracts_subtree_sibling_path === undefined) { + throw new Error('Expected new_contracts_subtree_sibling_path in BaseRollupInputs deserialization'); + } + if (o.new_public_data_update_requests_sibling_paths === undefined) { + throw new Error('Expected new_public_data_update_requests_sibling_paths in BaseRollupInputs deserialization'); + } + if (o.new_public_data_reads_sibling_paths === undefined) { + throw new Error('Expected new_public_data_reads_sibling_paths in BaseRollupInputs deserialization'); + } + if (o.historic_blocks_tree_root_membership_witnesses === undefined) { + throw new Error('Expected historic_blocks_tree_root_membership_witnesses in BaseRollupInputs deserialization'); + } + if (o.constants === undefined) { + throw new Error('Expected constants in BaseRollupInputs deserialization'); + } + return new BaseRollupInputs( + mapTuple(o.kernel_data, (v: MsgpackPreviousKernelData) => toPreviousKernelData(v)), + toAppendOnlyTreeSnapshot(o.start_private_data_tree_snapshot), + toAppendOnlyTreeSnapshot(o.start_nullifier_tree_snapshot), + toAppendOnlyTreeSnapshot(o.start_contract_tree_snapshot), + Fr.fromBuffer(o.start_public_data_tree_root), + toAppendOnlyTreeSnapshot(o.start_historic_blocks_tree_snapshot), + mapTuple(o.low_nullifier_leaf_preimages, (v: MsgpackNullifierLeafPreimage) => toNullifierLeafPreimage(v)), + mapTuple(o.low_nullifier_membership_witness, (v: MsgpackMembershipWitness16) => toMembershipWitness16(v)), + mapTuple(o.new_commitments_subtree_sibling_path, (v: Buffer) => Fr.fromBuffer(v)), + mapTuple(o.new_nullifiers_subtree_sibling_path, (v: Buffer) => Fr.fromBuffer(v)), + mapTuple(o.new_contracts_subtree_sibling_path, (v: Buffer) => Fr.fromBuffer(v)), + mapTuple(o.new_public_data_update_requests_sibling_paths, (v: Tuple) => + mapTuple(v, (v: Buffer) => Fr.fromBuffer(v)), + ), + mapTuple(o.new_public_data_reads_sibling_paths, (v: Tuple) => + mapTuple(v, (v: Buffer) => Fr.fromBuffer(v)), + ), + mapTuple(o.historic_blocks_tree_root_membership_witnesses, (v: MsgpackMembershipWitness16) => + toMembershipWitness16(v), + ), + toConstantRollupData(o.constants), + ); +} + +export function fromBaseRollupInputs(o: BaseRollupInputs): MsgpackBaseRollupInputs { + if (o.kernelData === undefined) { + throw new Error('Expected kernelData in BaseRollupInputs serialization'); + } + if (o.startPrivateDataTreeSnapshot === undefined) { + throw new Error('Expected startPrivateDataTreeSnapshot in BaseRollupInputs serialization'); + } + if (o.startNullifierTreeSnapshot === undefined) { + throw new Error('Expected startNullifierTreeSnapshot in BaseRollupInputs serialization'); + } + if (o.startContractTreeSnapshot === undefined) { + throw new Error('Expected startContractTreeSnapshot in BaseRollupInputs serialization'); + } + if (o.startPublicDataTreeRoot === undefined) { + throw new Error('Expected startPublicDataTreeRoot in BaseRollupInputs serialization'); + } + if (o.startHistoricBlocksTreeSnapshot === undefined) { + throw new Error('Expected startHistoricBlocksTreeSnapshot in BaseRollupInputs serialization'); + } + if (o.lowNullifierLeafPreimages === undefined) { + throw new Error('Expected lowNullifierLeafPreimages in BaseRollupInputs serialization'); + } + if (o.lowNullifierMembershipWitness === undefined) { + throw new Error('Expected lowNullifierMembershipWitness in BaseRollupInputs serialization'); + } + if (o.newCommitmentsSubtreeSiblingPath === undefined) { + throw new Error('Expected newCommitmentsSubtreeSiblingPath in BaseRollupInputs serialization'); + } + if (o.newNullifiersSubtreeSiblingPath === undefined) { + throw new Error('Expected newNullifiersSubtreeSiblingPath in BaseRollupInputs serialization'); + } + if (o.newContractsSubtreeSiblingPath === undefined) { + throw new Error('Expected newContractsSubtreeSiblingPath in BaseRollupInputs serialization'); + } + if (o.newPublicDataUpdateRequestsSiblingPaths === undefined) { + throw new Error('Expected newPublicDataUpdateRequestsSiblingPaths in BaseRollupInputs serialization'); + } + if (o.newPublicDataReadsSiblingPaths === undefined) { + throw new Error('Expected newPublicDataReadsSiblingPaths in BaseRollupInputs serialization'); + } + if (o.historicBlocksTreeRootMembershipWitnesses === undefined) { + throw new Error('Expected historicBlocksTreeRootMembershipWitnesses in BaseRollupInputs serialization'); + } + if (o.constants === undefined) { + throw new Error('Expected constants in BaseRollupInputs serialization'); + } + return { + kernel_data: mapTuple(o.kernelData, (v: PreviousKernelData) => fromPreviousKernelData(v)), + start_private_data_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startPrivateDataTreeSnapshot), + start_nullifier_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startNullifierTreeSnapshot), + start_contract_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startContractTreeSnapshot), + start_public_data_tree_root: toBuffer(o.startPublicDataTreeRoot), + start_historic_blocks_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startHistoricBlocksTreeSnapshot), + low_nullifier_leaf_preimages: mapTuple(o.lowNullifierLeafPreimages, (v: NullifierLeafPreimage) => + fromNullifierLeafPreimage(v), + ), + low_nullifier_membership_witness: mapTuple(o.lowNullifierMembershipWitness, (v: MembershipWitness16) => + fromMembershipWitness16(v), + ), + new_commitments_subtree_sibling_path: mapTuple(o.newCommitmentsSubtreeSiblingPath, (v: Fr) => toBuffer(v)), + new_nullifiers_subtree_sibling_path: mapTuple(o.newNullifiersSubtreeSiblingPath, (v: Fr) => toBuffer(v)), + new_contracts_subtree_sibling_path: mapTuple(o.newContractsSubtreeSiblingPath, (v: Fr) => toBuffer(v)), + new_public_data_update_requests_sibling_paths: mapTuple( + o.newPublicDataUpdateRequestsSiblingPaths, + (v: Tuple) => mapTuple(v, (v: Fr) => toBuffer(v)), + ), + new_public_data_reads_sibling_paths: mapTuple(o.newPublicDataReadsSiblingPaths, (v: Tuple) => + mapTuple(v, (v: Fr) => toBuffer(v)), + ), + historic_blocks_tree_root_membership_witnesses: mapTuple( + o.historicBlocksTreeRootMembershipWitnesses, + (v: MembershipWitness16) => fromMembershipWitness16(v), + ), + constants: fromConstantRollupData(o.constants), + }; +} + interface MsgpackBaseOrMergeRollupPublicInputs { rollup_type: number; rollup_subtree_height: Buffer; @@ -2981,6 +3185,12 @@ export function publicKernelSim(wasm: IWasmModule, arg0: PublicKernelInputs): Ci callCbind(wasm, 'public_kernel__sim', [fromPublicKernelInputs(arg0)]), ); } +export function baseRollupSim(wasm: IWasmModule, arg0: BaseRollupInputs): CircuitError | BaseOrMergeRollupPublicInputs { + return ((v: MsgpackCircuitError | MsgpackBaseOrMergeRollupPublicInputs) => + isCircuitError(v) ? toCircuitError(v) : toBaseOrMergeRollupPublicInputs(v))( + callCbind(wasm, 'base_rollup__sim', [fromBaseRollupInputs(arg0)]), + ); +} export function mergeRollupSim( wasm: IWasmModule, arg0: MergeRollupInputs, diff --git a/yarn-project/circuits.js/src/cbind/constants.gen.ts b/yarn-project/circuits.js/src/cbind/constants.gen.ts index 03cfb374225..1631800e633 100644 --- a/yarn-project/circuits.js/src/cbind/constants.gen.ts +++ b/yarn-project/circuits.js/src/cbind/constants.gen.ts @@ -24,6 +24,9 @@ export const NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; export const NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; export const NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; export const KERNELS_PER_BASE_ROLLUP = 2; +export const MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP = 128; +export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP = 32; +export const MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP = 32; export const VK_TREE_HEIGHT = 3; export const FUNCTION_TREE_HEIGHT = 4; export const CONTRACT_TREE_HEIGHT = 16; diff --git a/yarn-project/circuits.js/src/cbind/types.ts b/yarn-project/circuits.js/src/cbind/types.ts index dfe90681ffc..5c2d7c9f8b5 100644 --- a/yarn-project/circuits.js/src/cbind/types.ts +++ b/yarn-project/circuits.js/src/cbind/types.ts @@ -119,6 +119,8 @@ export { TxRequest, PreviousRollupData, AppendOnlyTreeSnapshot, + BaseRollupInputs, + NullifierLeafPreimage, BaseOrMergeRollupPublicInputs, ConstantRollupData, MergeRollupInputs, diff --git a/yarn-project/circuits.js/src/rollup/index.ts b/yarn-project/circuits.js/src/rollup/index.ts index be38690e08a..acb407b5c0f 100644 --- a/yarn-project/circuits.js/src/rollup/index.ts +++ b/yarn-project/circuits.js/src/rollup/index.ts @@ -1 +1 @@ -export * from './rollup_wasm_wrapper.js'; +export { baseRollupSim, mergeRollupSim, rootRollupSim } from '../cbind/circuits.gen.js'; diff --git a/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.test.ts b/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.test.ts index c7c4d945fcf..4ec49ae2ac2 100644 --- a/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.test.ts +++ b/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.test.ts @@ -1,22 +1,23 @@ import { AggregationObject, + BaseOrMergeRollupPublicInputs, CircuitError, MergeRollupInputs, RootRollupInputs, RootRollupPublicInputs, VerificationKey, + baseRollupSim, + mergeRollupSim, + rootRollupSim, } from '../index.js'; import { makeBaseRollupInputs, makeMergeRollupInputs, makeRootRollupInputs } from '../tests/factories.js'; import { CircuitsWasm } from '../wasm/circuits_wasm.js'; -import { RollupWasmWrapper, mergeRollupSim, rootRollupSim } from './rollup_wasm_wrapper.js'; describe('rollup/rollup_wasm_wrapper', () => { let wasm: CircuitsWasm; - let rollupWasm: RollupWasmWrapper; beforeAll(async () => { wasm = await CircuitsWasm.get(); - rollupWasm = new RollupWasmWrapper(wasm); }); const makeBaseRollupInputsForCircuit = () => { @@ -54,11 +55,13 @@ describe('rollup/rollup_wasm_wrapper', () => { // Task to repair this test: https://github.com/AztecProtocol/aztec-packages/issues/1586 it.skip('calls base_rollup__sim', () => { const input = makeBaseRollupInputsForCircuit(); + const output = baseRollupSim(wasm, input); + expect(output instanceof BaseOrMergeRollupPublicInputs).toBeTruthy(); - const output = rollupWasm.simulateBaseRollup(input); - expect(output.startContractTreeSnapshot).toEqual(input.startContractTreeSnapshot); - expect(output.startNullifierTreeSnapshot).toEqual(input.startNullifierTreeSnapshot); - expect(output.startPrivateDataTreeSnapshot).toEqual(input.startPrivateDataTreeSnapshot); + const publicInputs = output as BaseOrMergeRollupPublicInputs; + expect(publicInputs.startContractTreeSnapshot).toEqual(input.startContractTreeSnapshot); + expect(publicInputs.startNullifierTreeSnapshot).toEqual(input.startNullifierTreeSnapshot); + expect(publicInputs.startPrivateDataTreeSnapshot).toEqual(input.startPrivateDataTreeSnapshot); }); it('calls merge_rollup__sim', () => { @@ -104,7 +107,9 @@ describe('rollup/rollup_wasm_wrapper', () => { for (const rd of input.previousRollupData) { rd.vk = VerificationKey.makeFake(); rd.baseOrMergeRollupPublicInputs.endAggregationObject = AggregationObject.makeFake(); - rd.baseOrMergeRollupPublicInputs = rollupWasm.simulateBaseRollup(makeBaseRollupInputsForCircuit()); + const output = baseRollupSim(wasm, makeBaseRollupInputsForCircuit()); + expect(output instanceof BaseOrMergeRollupPublicInputs).toBeTruthy(); + rd.baseOrMergeRollupPublicInputs = output as BaseOrMergeRollupPublicInputs; } fixPreviousRollupInputs(input); diff --git a/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts b/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts deleted file mode 100644 index 429d34bb666..00000000000 --- a/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { BaseOrMergeRollupPublicInputs, BaseRollupInputs } from '../index.js'; -import { callWasm } from '../utils/call_wasm.js'; -import { CircuitsWasm } from '../wasm/circuits_wasm.js'; - -export { mergeRollupSim, rootRollupSim } from '../cbind/circuits.gen.js'; - -/** - * A wrapper around `CircuitsWasm` used to expose only the functions relevant for rollup circuits. - */ -export class RollupWasmWrapper { - constructor(private wasm: CircuitsWasm) {} - - /** - * Simulates the base rollup circuit from its inputs. - * @param baseRollupInputs - Inputs to the circuit. - * @returns The result of the simulation. Since the circuits are recursive the result is in a form which can be used - * as an input of the next iteration. - */ - public simulateBaseRollup(baseRollupInputs: BaseRollupInputs): BaseOrMergeRollupPublicInputs { - return callWasm(this.wasm, 'base_rollup__sim', baseRollupInputs, BaseOrMergeRollupPublicInputs); - } -} diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts index 7f3fed8f22f..dce0afd133d 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts @@ -1,19 +1,19 @@ import { Fr } from '@aztec/foundation/fields'; -import { BufferReader } from '@aztec/foundation/serialize'; +import { BufferReader, Tuple } from '@aztec/foundation/serialize'; import { - CONTRACT_TREE_HEIGHT, + CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, HISTORIC_BLOCKS_TREE_HEIGHT, - MAX_NEW_COMMITMENTS_PER_TX, - MAX_NEW_CONTRACTS_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + KERNELS_PER_BASE_ROLLUP, + MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, - PRIVATE_DATA_TREE_HEIGHT, + PRIVATE_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, } from '../../cbind/constants.gen.js'; -import { FieldsOf, assertItemsLength, assertMemberLength } from '../../utils/jsUtils.js'; +import { FieldsOf } from '../../utils/jsUtils.js'; import { serializeToBuffer } from '../../utils/serialize.js'; import { GlobalVariables } from '../global_variables.js'; import { PreviousKernelData } from '../kernel/previous_kernel_data.js'; @@ -118,26 +118,11 @@ export class ConstantRollupData { * Inputs to the base rollup circuit. */ export class BaseRollupInputs { - /** - * Height of the private data subtree which is to be inserted into the private data tree. - * Note: There are notes from 2 kernels being processed here so kernel new commitments length is multiplied by 2. - */ - public static PRIVATE_DATA_SUBTREE_HEIGHT = Math.log2(MAX_NEW_COMMITMENTS_PER_TX * 2); - /** - * Height of the contract subtree which is to be inserted into the contract tree. - */ - public static CONTRACT_SUBTREE_HEIGHT = Math.log2(MAX_NEW_CONTRACTS_PER_TX * 2); - /** - * Height of the nullifier subtree which is to be inserted into the nullifier tree. - */ - public static NULLIFIER_SUBTREE_HEIGHT = Math.log2(MAX_NEW_NULLIFIERS_PER_TX * 2); - constructor( /** * Data of the 2 kernels that preceded this base rollup circuit. */ - public kernelData: [PreviousKernelData, PreviousKernelData], - + public kernelData: Tuple, /** * Snapshot of the private data tree at the start of the base rollup circuit. */ @@ -163,70 +148,55 @@ export class BaseRollupInputs { * The nullifiers which need to be updated to perform the batch insertion of the new nullifiers. * See `StandardIndexedTree.batchInsert` function for more details. */ - public lowNullifierLeafPreimages: NullifierLeafPreimage[], + public lowNullifierLeafPreimages: Tuple, /** * Membership witnesses for the nullifiers which need to be updated to perform the batch insertion of the new * nullifiers. */ - public lowNullifierMembershipWitness: MembershipWitness[], - + public lowNullifierMembershipWitness: Tuple< + MembershipWitness, + typeof MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP + >, /** * Sibling path "pointing to" where the new commitments subtree should be inserted into the private data tree. */ - public newCommitmentsSubtreeSiblingPath: Fr[], + public newCommitmentsSubtreeSiblingPath: Tuple, /** * Sibling path "pointing to" where the new nullifiers subtree should be inserted into the nullifier tree. */ - public newNullifiersSubtreeSiblingPath: Fr[], + public newNullifiersSubtreeSiblingPath: Tuple, /** * Sibling path "pointing to" where the new contracts subtree should be inserted into the contract tree. */ - public newContractsSubtreeSiblingPath: Fr[], + public newContractsSubtreeSiblingPath: Tuple, /** * Sibling paths of leaves which are to be affected by the public data update requests. * Each item in the array is the sibling path that corresponds to an update request. */ - public newPublicDataUpdateRequestsSiblingPaths: Fr[][], + public newPublicDataUpdateRequestsSiblingPaths: Tuple< + Tuple, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP + >, /** * Sibling paths of leaves which are to be read by the public data reads. * Each item in the array is the sibling path that corresponds to a read request. */ - public newPublicDataReadsSiblingPaths: Fr[][], + public newPublicDataReadsSiblingPaths: Tuple< + Tuple, + typeof MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP + >, /** * Membership witnesses of historic blocks referred by each of the 2 kernels. */ - public historicBlocksTreeRootMembershipWitnesses: [ + public historicBlocksTreeRootMembershipWitnesses: Tuple< MembershipWitness, - MembershipWitness, - ], - + typeof KERNELS_PER_BASE_ROLLUP + >, /** * Data which is not modified by the base rollup circuit. */ public constants: ConstantRollupData, - ) { - assertMemberLength(this, 'lowNullifierLeafPreimages', 2 * MAX_NEW_NULLIFIERS_PER_TX); - assertMemberLength(this, 'lowNullifierMembershipWitness', 2 * MAX_NEW_NULLIFIERS_PER_TX); - assertMemberLength( - this, - 'newCommitmentsSubtreeSiblingPath', - PRIVATE_DATA_TREE_HEIGHT - BaseRollupInputs.PRIVATE_DATA_SUBTREE_HEIGHT, - ); - assertMemberLength( - this, - 'newNullifiersSubtreeSiblingPath', - NULLIFIER_TREE_HEIGHT - BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, - ); - assertMemberLength( - this, - 'newContractsSubtreeSiblingPath', - CONTRACT_TREE_HEIGHT - BaseRollupInputs.CONTRACT_SUBTREE_HEIGHT, - ); - assertMemberLength(this, 'newPublicDataUpdateRequestsSiblingPaths', 2 * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX); - assertMemberLength(this, 'newPublicDataReadsSiblingPaths', 2 * MAX_PUBLIC_DATA_READS_PER_TX); - assertItemsLength(this, 'newPublicDataUpdateRequestsSiblingPaths', PUBLIC_DATA_TREE_HEIGHT); - assertItemsLength(this, 'newPublicDataReadsSiblingPaths', PUBLIC_DATA_TREE_HEIGHT); - } + ) {} static from(fields: FieldsOf): BaseRollupInputs { return new BaseRollupInputs(...BaseRollupInputs.getFields(fields)); diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 2bbd35a704e..8f6a1cbb601 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -10,6 +10,7 @@ import { AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, BaseRollupInputs, + CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, CONTRACT_TREE_HEIGHT, CallContext, CircuitType, @@ -29,6 +30,7 @@ import { G1AffineElement, HISTORIC_BLOCKS_TREE_HEIGHT, HistoricBlockData, + KERNELS_PER_BASE_ROLLUP, KernelCircuitPublicInputs, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, MAX_NEW_COMMITMENTS_PER_CALL, @@ -36,6 +38,7 @@ import { MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, + MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NULLIFIERS_PER_TX, MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX, @@ -43,20 +46,24 @@ import { MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_READ_REQUESTS_PER_CALL, MAX_READ_REQUESTS_PER_TX, MembershipWitness, MergeRollupInputs, + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_FIELDS_PER_SHA256, NewContractData, NullifierLeafPreimage, OptionallyRevealedData, + PRIVATE_DATA_SUBTREE_SIBLING_PATH_LENGTH, PRIVATE_DATA_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, Point, @@ -876,10 +883,7 @@ export function makeMergeRollupInputs(seed = 0): MergeRollupInputs { * @returns A base rollup inputs. */ export function makeBaseRollupInputs(seed = 0): BaseRollupInputs { - const kernelData: [PreviousKernelData, PreviousKernelData] = [ - makePreviousKernelData(seed + 0x100), - makePreviousKernelData(seed + 0x200), - ]; + const kernelData = makeTuple(KERNELS_PER_BASE_ROLLUP, x => makePreviousKernelData(seed + (x + 1) * 0x100)); const startPrivateDataTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x100); const startNullifierTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x200); @@ -887,41 +891,37 @@ export function makeBaseRollupInputs(seed = 0): BaseRollupInputs { const startPublicDataTreeRoot = fr(seed + 0x400); const startHistoricBlocksTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x500); - const lowNullifierLeafPreimages = range(2 * MAX_NEW_NULLIFIERS_PER_TX, seed + 0x1000).map( + const lowNullifierLeafPreimages = makeTuple( + MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, x => new NullifierLeafPreimage(fr(x), fr(x + 0x100), x + 0x200), + seed + 0x1000, ); - const lowNullifierMembershipWitness = range(2 * MAX_NEW_NULLIFIERS_PER_TX, seed + 0x2000).map(x => - makeMembershipWitness(NULLIFIER_TREE_HEIGHT, x), + const lowNullifierMembershipWitness = makeTuple( + MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, + x => makeMembershipWitness(NULLIFIER_TREE_HEIGHT, x), + seed + 0x2000, ); - const newCommitmentsSubtreeSiblingPath = range( - PRIVATE_DATA_TREE_HEIGHT - BaseRollupInputs.PRIVATE_DATA_SUBTREE_HEIGHT, - seed + 0x3000, - ).map(x => fr(x)); + const newCommitmentsSubtreeSiblingPath = makeTuple(PRIVATE_DATA_SUBTREE_SIBLING_PATH_LENGTH, fr, seed + 0x3000); + const newNullifiersSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, fr, seed + 0x4000); + const newContractsSubtreeSiblingPath = makeTuple(CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, fr, seed + 0x5000); - const newNullifiersSubtreeSiblingPath = range( - NULLIFIER_TREE_HEIGHT - BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, - seed + 0x4000, - ).map(x => fr(x)); - - const newContractsSubtreeSiblingPath = range( - CONTRACT_TREE_HEIGHT - BaseRollupInputs.CONTRACT_SUBTREE_HEIGHT, - seed + 0x5000, - ).map(x => fr(x)); - - const newPublicDataUpdateRequestsSiblingPaths = range(2 * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, seed + 0x6000).map( - x => range(PUBLIC_DATA_TREE_HEIGHT, x).map(fr), + const newPublicDataUpdateRequestsSiblingPaths = makeTuple( + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, + x => makeTuple(PUBLIC_DATA_TREE_HEIGHT, fr, x), + seed + 0x6000, ); - const newPublicDataReadsSiblingPaths = range(2 * MAX_PUBLIC_DATA_READS_PER_TX, seed + 0x6000).map(x => - range(PUBLIC_DATA_TREE_HEIGHT, x).map(fr), + const newPublicDataReadsSiblingPaths = makeTuple( + MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, + x => makeTuple(PUBLIC_DATA_TREE_HEIGHT, fr, x), + seed + 0x6000, ); - const historicBlocksTreeRootMembershipWitnesses: BaseRollupInputs['historicBlocksTreeRootMembershipWitnesses'] = [ - makeMembershipWitness(HISTORIC_BLOCKS_TREE_HEIGHT, seed + 0x7000), - makeMembershipWitness(HISTORIC_BLOCKS_TREE_HEIGHT, seed + 0x8000), - ]; + const historicBlocksTreeRootMembershipWitnesses = makeTuple(KERNELS_PER_BASE_ROLLUP, x => + makeMembershipWitness(HISTORIC_BLOCKS_TREE_HEIGHT, seed + x * 0x1000 + 0x7000), + ); const constants = makeConstantBaseRollupData(0x100); diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts index 8f715f94a51..6f1b23c9c93 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts @@ -1,7 +1,6 @@ import { AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, - BaseRollupInputs, CircuitsWasm, Fr, GlobalVariables, @@ -11,6 +10,7 @@ import { MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + NULLIFIER_SUBTREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, Proof, PublicDataUpdateRequest, @@ -138,7 +138,7 @@ describe('sequencer/solo_block_builder', () => { await expectsDb.batchInsert( MerkleTreeId.NULLIFIER_TREE, flatMap(txs, tx => tx.data.end.newNullifiers.map(x => x.toBuffer())), - BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, ); for (const write of txs.flatMap(tx => tx.data.end.publicDataUpdateRequests)) { await expectsDb.updateLeaf(MerkleTreeId.PUBLIC_DATA_TREE, write.newValue.toBuffer(), write.leafIndex.value); @@ -411,7 +411,7 @@ describe('sequencer/solo_block_builder', () => { await builderDb.batchInsert( MerkleTreeId.NULLIFIER_TREE, updateVals.map(v => toBufferBE(v, 32)), - BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, ); const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages); diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index 10285ee6256..0435ef2eea4 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -2,17 +2,29 @@ import { AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, BaseRollupInputs, + CONTRACT_SUBTREE_HEIGHT, + CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, CircuitsWasm, ConstantRollupData, GlobalVariables, HISTORIC_BLOCKS_TREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, + MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_READS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MergeRollupInputs, + NULLIFIER_SUBTREE_HEIGHT, + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NullifierLeafPreimage, + PRIVATE_DATA_SUBTREE_HEIGHT, + PRIVATE_DATA_SUBTREE_SIBLING_PATH_LENGTH, + PUBLIC_DATA_TREE_HEIGHT, PreviousKernelData, PreviousRollupData, Proof, @@ -593,22 +605,38 @@ export class SoloBlockBuilder implements BlockBuilder { } protected async processPublicDataUpdateRequests(tx: ProcessedTx) { - const newPublicDataUpdateRequestsSiblingPaths: Fr[][] = []; - for (const publicDataUpdateRequest of tx.data.end.publicDataUpdateRequests) { - const index = publicDataUpdateRequest.leafIndex.value; + const newPublicDataUpdateRequestsSiblingPaths: Tuple< + Tuple, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + > = makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, () => makeTuple(PUBLIC_DATA_TREE_HEIGHT, Fr.zero)); + for (const i in tx.data.end.publicDataUpdateRequests) { + const index = tx.data.end.publicDataUpdateRequests[i].leafIndex.value; + await this.db.updateLeaf( + MerkleTreeId.PUBLIC_DATA_TREE, + tx.data.end.publicDataUpdateRequests[i].newValue.toBuffer(), + index, + ); const path = await this.db.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, index); - await this.db.updateLeaf(MerkleTreeId.PUBLIC_DATA_TREE, publicDataUpdateRequest.newValue.toBuffer(), index); - newPublicDataUpdateRequestsSiblingPaths.push(path.toFieldArray()); + const array = path.toFieldArray(); + newPublicDataUpdateRequestsSiblingPaths[i] = makeTuple(PUBLIC_DATA_TREE_HEIGHT, j => + j < array.length ? array[j] : Fr.ZERO, + ); } return newPublicDataUpdateRequestsSiblingPaths; } protected async getPublicDataReadsSiblingPaths(tx: ProcessedTx) { - const newPublicDataReadsSiblingPaths: Fr[][] = []; - for (const publicDataRead of tx.data.end.publicDataReads) { - const index = publicDataRead.leafIndex.value; + const newPublicDataReadsSiblingPaths: Tuple< + Tuple, + typeof MAX_PUBLIC_DATA_READS_PER_TX + > = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => makeTuple(PUBLIC_DATA_TREE_HEIGHT, Fr.zero)); + for (const i in tx.data.end.publicDataReads) { + const index = tx.data.end.publicDataReads[i].leafIndex.value; const path = await this.db.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, index); - newPublicDataReadsSiblingPaths.push(path.toFieldArray()); + const array = path.toFieldArray(); + newPublicDataReadsSiblingPaths[i] = makeTuple(PUBLIC_DATA_TREE_HEIGHT, j => + j < array.length ? array[j] : Fr.ZERO, + ); } return newPublicDataReadsSiblingPaths; } @@ -626,13 +654,22 @@ export class SoloBlockBuilder implements BlockBuilder { const startHistoricBlocksTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.BLOCKS_TREE); // Get the subtree sibling paths for the circuit - const newCommitmentsSubtreeSiblingPath = await this.getSubtreeSiblingPath( + const newCommitmentsSubtreeSiblingPathArray = await this.getSubtreeSiblingPath( MerkleTreeId.PRIVATE_DATA_TREE, - BaseRollupInputs.PRIVATE_DATA_SUBTREE_HEIGHT, + PRIVATE_DATA_SUBTREE_HEIGHT, ); - const newContractsSubtreeSiblingPath = await this.getSubtreeSiblingPath( + + const newCommitmentsSubtreeSiblingPath = makeTuple(PRIVATE_DATA_SUBTREE_SIBLING_PATH_LENGTH, i => + i < newCommitmentsSubtreeSiblingPathArray.length ? newCommitmentsSubtreeSiblingPathArray[i] : Fr.ZERO, + ); + + const newContractsSubtreeSiblingPathArray = await this.getSubtreeSiblingPath( MerkleTreeId.CONTRACT_TREE, - BaseRollupInputs.CONTRACT_SUBTREE_HEIGHT, + CONTRACT_SUBTREE_HEIGHT, + ); + + const newContractsSubtreeSiblingPath = makeTuple(CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, i => + i < newContractsSubtreeSiblingPathArray.length ? newContractsSubtreeSiblingPathArray[i] : Fr.ZERO, ); // Update the contract and private data trees with the new items being inserted to get the new roots @@ -658,11 +695,17 @@ export class SoloBlockBuilder implements BlockBuilder { const rightPublicDataReadSiblingPaths = await this.getPublicDataReadsSiblingPaths(right); const rightPublicDataUpdateRequestsSiblingPaths = await this.processPublicDataUpdateRequests(right); - const newPublicDataReadsSiblingPaths = [...leftPublicDataReadSiblingPaths, ...rightPublicDataReadSiblingPaths]; - const newPublicDataUpdateRequestsSiblingPaths = [ - ...leftPublicDataUpdateRequestsSiblingPaths, - ...rightPublicDataUpdateRequestsSiblingPaths, - ]; + const newPublicDataReadsSiblingPaths = makeTuple(MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, i => + i < MAX_PUBLIC_DATA_READS_PER_TX + ? leftPublicDataReadSiblingPaths[i] + : rightPublicDataReadSiblingPaths[i - MAX_PUBLIC_DATA_READS_PER_TX], + ); + + const newPublicDataUpdateRequestsSiblingPaths = makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, i => + i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + ? leftPublicDataUpdateRequestsSiblingPaths[i] + : rightPublicDataUpdateRequestsSiblingPaths[i - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + ); // Update the nullifier tree, capturing the low nullifier info for each individual operation const newNullifiers = [...left.data.end.newNullifiers, ...right.data.end.newNullifiers]; @@ -670,7 +713,7 @@ export class SoloBlockBuilder implements BlockBuilder { const [nullifierWitnessLeaves, newNullifiersSubtreeSiblingPath] = await this.db.batchInsert( MerkleTreeId.NULLIFIER_TREE, newNullifiers.map(fr => fr.toBuffer()), - BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, ); if (nullifierWitnessLeaves === undefined) { throw new Error(`Could not craft nullifier batch insertion proofs`); @@ -682,6 +725,8 @@ export class SoloBlockBuilder implements BlockBuilder { MembershipWitness.fromBufferArray(l.index, assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT)), ); + const newNullifiersSubtreeSiblingPathArray = newNullifiersSubtreeSiblingPath.toFieldArray(); + return BaseRollupInputs.from({ constants, startNullifierTreeSnapshot, @@ -691,14 +736,25 @@ export class SoloBlockBuilder implements BlockBuilder { startHistoricBlocksTreeSnapshot, newCommitmentsSubtreeSiblingPath, newContractsSubtreeSiblingPath, - newNullifiersSubtreeSiblingPath: newNullifiersSubtreeSiblingPath.toFieldArray(), + newNullifiersSubtreeSiblingPath: makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, i => + i < newNullifiersSubtreeSiblingPathArray.length ? newNullifiersSubtreeSiblingPathArray[i] : Fr.ZERO, + ), newPublicDataUpdateRequestsSiblingPaths, newPublicDataReadsSiblingPaths, - lowNullifierLeafPreimages: nullifierWitnessLeaves.map( - ({ leafData }) => - new NullifierLeafPreimage(new Fr(leafData.value), new Fr(leafData.nextValue), Number(leafData.nextIndex)), + lowNullifierLeafPreimages: makeTuple(MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, i => + i < nullifierWitnessLeaves.length + ? new NullifierLeafPreimage( + new Fr(nullifierWitnessLeaves[i].leafData.value), + new Fr(nullifierWitnessLeaves[i].leafData.nextValue), + Number(nullifierWitnessLeaves[i].leafData.nextIndex), + ) + : new NullifierLeafPreimage(Fr.ZERO, Fr.ZERO, 0), + ), + lowNullifierMembershipWitness: makeTuple(MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, i => + i < lowNullifierMembershipWitnesses.length + ? lowNullifierMembershipWitnesses[i] + : this.makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT), ), - lowNullifierMembershipWitness: lowNullifierMembershipWitnesses, kernelData: [this.getKernelDataFor(left), this.getKernelDataFor(right)], historicBlocksTreeRootMembershipWitnesses: [ await this.getHistoricTreesMembershipWitnessFor(left), diff --git a/yarn-project/sequencer-client/src/simulator/rollup.ts b/yarn-project/sequencer-client/src/simulator/rollup.ts index 3c971f14794..99fe554bcc6 100644 --- a/yarn-project/sequencer-client/src/simulator/rollup.ts +++ b/yarn-project/sequencer-client/src/simulator/rollup.ts @@ -4,9 +4,9 @@ import { CircuitError, CircuitsWasm, MergeRollupInputs, - RollupWasmWrapper, RootRollupInputs, RootRollupPublicInputs, + baseRollupSim, mergeRollupSim, rootRollupSim, } from '@aztec/circuits.js'; @@ -17,11 +17,9 @@ import { RollupSimulator } from './index.js'; * Implements the rollup circuit simulator using the wasm circuits implementation. */ export class WasmRollupCircuitSimulator implements RollupSimulator { - private rollupWasmWrapper: RollupWasmWrapper; private wasm: CircuitsWasm; constructor(wasm: CircuitsWasm) { - this.rollupWasmWrapper = new RollupWasmWrapper(wasm); this.wasm = wasm; } @@ -39,7 +37,12 @@ export class WasmRollupCircuitSimulator implements RollupSimulator { * @returns The public inputs as outputs of the simulation. */ baseRollupCircuit(input: BaseRollupInputs): Promise { - return Promise.resolve(this.rollupWasmWrapper.simulateBaseRollup(input)); + const result = baseRollupSim(this.wasm, input); + if (result instanceof CircuitError) { + throw new CircuitError(result.code, result.message); + } + + return Promise.resolve(result); } /** * Simulates the merge rollup circuit from its inputs. diff --git a/yarn-project/types/src/sibling_path.ts b/yarn-project/types/src/sibling_path.ts index 4323ca30818..450546b898e 100644 --- a/yarn-project/types/src/sibling_path.ts +++ b/yarn-project/types/src/sibling_path.ts @@ -1,3 +1,4 @@ +import { makeTuple } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { Tuple, @@ -80,6 +81,15 @@ export class SiblingPath { return this.data.map(buf => Fr.fromBuffer(buf)); } + /** + * Convert Sibling Path object into a tuple of field elements. + * @returns A tuple representation of the sibling path. + */ + public toTuple(): Tuple { + const array = this.toFieldArray(); + return makeTuple(array.length as N, i => array[i], 0); + } + /** * Deserializes a SiblingPath from a buffer. * @param buf - A buffer containing the buffer representation of SiblingPath. 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 b4cd63846a7..5d01d107f4b 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 @@ -1,11 +1,11 @@ import { - BaseRollupInputs, CONTRACT_TREE_HEIGHT, CircuitsWasm, Fr, GlobalVariables, HISTORIC_BLOCKS_TREE_HEIGHT, L1_TO_L2_MSG_TREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PRIVATE_DATA_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, @@ -562,7 +562,7 @@ export class MerkleTrees implements MerkleTreeDb { // Sync the indexed trees await (this.trees[MerkleTreeId.NULLIFIER_TREE] as StandardIndexedTree).batchInsert( l2Block.newNullifiers.map(fr => fr.toBuffer()), - BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, ); // Sync the public data tree