diff --git a/cpp/src/aztec3/circuits/rollup/merge/.test.cpp b/cpp/src/aztec3/circuits/rollup/merge/.test.cpp index e69de29b..b4ff1bad 100644 --- a/cpp/src/aztec3/circuits/rollup/merge/.test.cpp +++ b/cpp/src/aztec3/circuits/rollup/merge/.test.cpp @@ -0,0 +1,167 @@ +#include +#include +#include "aztec3/circuits/rollup/merge/init.hpp" +#include "aztec3/circuits/rollup/merge/utils.hpp" + +namespace { +using aztec3::circuits::rollup::merge::utils::dummy_merge_rollup_inputs_with_vk_proof; +using aztec3::circuits::rollup::native_merge_rollup::merge_rollup_circuit; +using aztec3::circuits::rollup::native_merge_rollup::MergeRollupInputs; +using aztec3::circuits::rollup::native_merge_rollup::MergeRollupPublicInputs; +using aztec3::circuits::rollup::native_merge_rollup::NT; + +} // namespace +namespace aztec3::circuits::rollup::merge::native_merge_rollup_circuit { + +class merge_rollup_tests : public ::testing::Test {}; + +TEST_F(merge_rollup_tests, test_different_rollup_type_fails) +{ + auto mergeInput = dummy_merge_rollup_inputs_with_vk_proof(); + mergeInput.previous_rollup_data[0].merge_rollup_public_inputs.rollup_type = 0; + mergeInput.previous_rollup_data[1].merge_rollup_public_inputs.rollup_type = 1; + EXPECT_DEATH(merge_rollup_circuit(mergeInput), ".*assert_both_input_proofs_of_same_rollup_type.*failed."); +} + +TEST_F(merge_rollup_tests, test_different_rollup_height_fails) +{ + auto mergeInput = dummy_merge_rollup_inputs_with_vk_proof(); + mergeInput.previous_rollup_data[0].merge_rollup_public_inputs.rollup_subtree_height = 0; + mergeInput.previous_rollup_data[1].merge_rollup_public_inputs.rollup_subtree_height = 1; + EXPECT_DEATH(merge_rollup_circuit(mergeInput), ".*assert_both_input_proofs_of_same_height_and_return.*failed."); +} + +TEST_F(merge_rollup_tests, test_constants_different_failure) +{ + MergeRollupInputs inputs = dummy_merge_rollup_inputs_with_vk_proof(); + inputs.previous_rollup_data[0].merge_rollup_public_inputs.constants.public_kernel_vk_tree_root = fr(1); + inputs.previous_rollup_data[1].merge_rollup_public_inputs.constants.public_kernel_vk_tree_root = fr(0); + + EXPECT_DEATH(merge_rollup_circuit(inputs), ".*assert_equal_constants.*failed."); +} + +TEST_F(merge_rollup_tests, test_fail_if_previous_rollups_dont_follow_on) +{ + MergeRollupInputs dummyInputs = dummy_merge_rollup_inputs_with_vk_proof(); + auto inputA = dummyInputs; + inputA.previous_rollup_data[0].merge_rollup_public_inputs.end_private_data_tree_snapshot = { + .root = fr(0), .next_available_leaf_index = 0 + }; + inputA.previous_rollup_data[1].merge_rollup_public_inputs.start_private_data_tree_snapshot = { + .root = fr(1), .next_available_leaf_index = 0 + }; + + EXPECT_DEATH(merge_rollup_circuit(inputA), ".*ensure_prev_rollups_follow_on_from_each_other.*failed."); + + // do the same for nullifier tree + auto inputB = dummyInputs; + inputB.previous_rollup_data[0].merge_rollup_public_inputs.end_nullifier_tree_snapshot = { + .root = fr(0), .next_available_leaf_index = 0 + }; + inputB.previous_rollup_data[1].merge_rollup_public_inputs.start_nullifier_tree_snapshot = { + .root = fr(1), .next_available_leaf_index = 0 + }; + EXPECT_DEATH(merge_rollup_circuit(inputB), ".*ensure_prev_rollups_follow_on_from_each_other.*failed."); + + // do the same for contract tree + auto inputC = dummyInputs; + inputC.previous_rollup_data[0].merge_rollup_public_inputs.end_contract_tree_snapshot = { + .root = fr(0), .next_available_leaf_index = 0 + }; + inputC.previous_rollup_data[1].merge_rollup_public_inputs.start_contract_tree_snapshot = { + .root = fr(1), .next_available_leaf_index = 0 + }; + EXPECT_DEATH(merge_rollup_circuit(inputC), ".*ensure_prev_rollups_follow_on_from_each_other.*failed."); +} + +TEST_F(merge_rollup_tests, test_rollup_fields_are_set_correctly) +{ + MergeRollupInputs inputs = dummy_merge_rollup_inputs_with_vk_proof(); + MergeRollupPublicInputs outputs = merge_rollup_circuit(inputs); + // check that rollup type is set to merge + ASSERT_EQ(outputs.rollup_type, 1); + // check that rollup height is incremented + ASSERT_EQ(outputs.rollup_subtree_height, + inputs.previous_rollup_data[0].merge_rollup_public_inputs.rollup_subtree_height + 1); + + // set inputs to have a merge rollup type and set the rollup height and test again. + inputs.previous_rollup_data[0].merge_rollup_public_inputs.rollup_type = 1; + inputs.previous_rollup_data[0].merge_rollup_public_inputs.rollup_subtree_height = 1; + + inputs.previous_rollup_data[1].merge_rollup_public_inputs.rollup_type = 1; + inputs.previous_rollup_data[1].merge_rollup_public_inputs.rollup_subtree_height = 1; + + outputs = merge_rollup_circuit(inputs); + ASSERT_EQ(outputs.rollup_type, 1); + ASSERT_EQ(outputs.rollup_subtree_height, 2); +} + +TEST_F(merge_rollup_tests, test_start_and_end_snapshots) +{ + MergeRollupInputs inputs = dummy_merge_rollup_inputs_with_vk_proof(); + MergeRollupPublicInputs outputs = merge_rollup_circuit(inputs); + // check that start and end snapshots are set correctly + ASSERT_EQ(outputs.start_private_data_tree_snapshot, + inputs.previous_rollup_data[0].merge_rollup_public_inputs.start_private_data_tree_snapshot); + ASSERT_EQ(outputs.end_private_data_tree_snapshot, + inputs.previous_rollup_data[1].merge_rollup_public_inputs.end_private_data_tree_snapshot); + + ASSERT_EQ(outputs.start_nullifier_tree_snapshot, + inputs.previous_rollup_data[0].merge_rollup_public_inputs.start_nullifier_tree_snapshot); + ASSERT_EQ(outputs.end_nullifier_tree_snapshot, + inputs.previous_rollup_data[1].merge_rollup_public_inputs.end_nullifier_tree_snapshot); + + ASSERT_EQ(outputs.start_contract_tree_snapshot, + inputs.previous_rollup_data[0].merge_rollup_public_inputs.start_contract_tree_snapshot); + ASSERT_EQ(outputs.end_contract_tree_snapshot, + inputs.previous_rollup_data[1].merge_rollup_public_inputs.end_contract_tree_snapshot); +} + +TEST_F(merge_rollup_tests, test_calldata_hash) +{ + std::vector zero_bytes_vec(704, 0); + auto call_data_hash_inner = sha256::sha256(zero_bytes_vec); + + std::array hash_input; + for (uint8_t i = 0; i < 32; ++i) { + hash_input[i] = call_data_hash_inner[i]; + hash_input[32 + i] = call_data_hash_inner[i]; + } + + std::vector calldata_hash_input_bytes_vec(hash_input.begin(), hash_input.end()); + + auto expected_calldata_hash = sha256::sha256(calldata_hash_input_bytes_vec); + + MergeRollupInputs inputs = dummy_merge_rollup_inputs_with_vk_proof(); + MergeRollupPublicInputs outputs = merge_rollup_circuit(inputs); + + std::array actual_calldata_hash_fr = outputs.calldata_hash; + auto high_buffer = actual_calldata_hash_fr[0].to_buffer(); + auto low_buffer = actual_calldata_hash_fr[1].to_buffer(); + + std::array actual_calldata_hash; + for (uint8_t i = 0; i < 16; ++i) { + actual_calldata_hash[i] = high_buffer[16 + i]; + actual_calldata_hash[16 + i] = low_buffer[16 + i]; + } + + ASSERT_EQ(expected_calldata_hash, actual_calldata_hash); +} + +TEST_F(merge_rollup_tests, test_constants_dont_change) +{ + MergeRollupInputs inputs = dummy_merge_rollup_inputs_with_vk_proof(); + MergeRollupPublicInputs outputs = merge_rollup_circuit(inputs); + ASSERT_EQ(inputs.previous_rollup_data[0].merge_rollup_public_inputs.constants, outputs.constants); + ASSERT_EQ(inputs.previous_rollup_data[1].merge_rollup_public_inputs.constants, outputs.constants); +} + +TEST_F(merge_rollup_tests, test_aggregate) +{ + // TODO: Fix this when aggregation works + MergeRollupInputs inputs = dummy_merge_rollup_inputs_with_vk_proof(); + MergeRollupPublicInputs outputs = merge_rollup_circuit(inputs); + ASSERT_EQ(inputs.previous_rollup_data[0].merge_rollup_public_inputs.end_aggregation_object.public_inputs, + outputs.end_aggregation_object.public_inputs); +} +} // namespace aztec3::circuits::rollup::merge::native_merge_rollup_circuit diff --git a/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp b/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp index 02af280e..5436d1ee 100644 --- a/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp +++ b/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp @@ -133,20 +133,20 @@ MergeRollupPublicInputs merge_rollup_circuit(MergeRollupInputs mergeRollupInputs // TODO: Check both previous rollup vks (in previous_rollup_data) against the permitted set of kernel vks. // we don't have a set of permitted kernel vks yet. - // compute calldata hash: - auto new_calldata_hash = compute_calldata_hash(mergeRollupInputs); + // Check that the constants are the same in both proofs + auto left = mergeRollupInputs.previous_rollup_data[0].merge_rollup_public_inputs; + auto right = mergeRollupInputs.previous_rollup_data[1].merge_rollup_public_inputs; + assert_equal_constants(left.constants, right.constants); // Ensure the end snapshot of previous_rollup 0 equals the start snapshot of previous_rollup 1 (i.e. ensure they // follow on from one-another). This ensures the low_leaves which were updated in rollup 0 are being used as the // 'starting' pointers in rollup 1. ensure_prev_rollups_follow_on_from_each_other(mergeRollupInputs); - AggregationObject aggregation_object = aggregate_proofs(mergeRollupInputs); + // compute calldata hash: + auto new_calldata_hash = compute_calldata_hash(mergeRollupInputs); - // Check that the constants are the same in both proofs - auto left = mergeRollupInputs.previous_rollup_data[0].merge_rollup_public_inputs; - auto right = mergeRollupInputs.previous_rollup_data[1].merge_rollup_public_inputs; - assert_equal_constants(left.constants, right.constants); + AggregationObject aggregation_object = aggregate_proofs(mergeRollupInputs); MergeRollupPublicInputs public_inputs = { .rollup_type = abis::MERGE_ROLLUP_TYPE, diff --git a/cpp/src/aztec3/circuits/rollup/merge/utils.cpp b/cpp/src/aztec3/circuits/rollup/merge/utils.cpp index d91723d5..7def4b18 100644 --- a/cpp/src/aztec3/circuits/rollup/merge/utils.cpp +++ b/cpp/src/aztec3/circuits/rollup/merge/utils.cpp @@ -1,3 +1,4 @@ +#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" #include "aztec3/circuits/abis/rollup/base/base_rollup_public_inputs.hpp" #include "aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp" #include "aztec3/circuits/abis/rollup/merge/merge_rollup_public_inputs.hpp" @@ -53,33 +54,45 @@ MergeRollupPublicInputs convert_base_public_inputs_to_merge_public_inputs( return mergeRollupPublicInputs; } -PreviousRollupData dummy_previous_rollup_with_vk_proof() +std::array, 2> previous_rollups_with_vk_proof_that_follow_on() { - // MergeInput requires base_rollup_public_inputs. So create a dummy BaseRollupInput object and pass it through the - // base rollup circuit. - auto emptyInputs = base::utils::dummy_base_rollup_inputs_with_vk_proof(); - BaseRollupPublicInputs dummy_base_public_inputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(emptyInputs); + auto input1 = base::utils::dummy_base_rollup_inputs_with_vk_proof(); + BaseRollupPublicInputs base_public_input1 = + aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(input1); + + auto input2 = input1; + input2.start_private_data_tree_snapshot = base_public_input1.end_private_data_tree_snapshot; + input2.start_nullifier_tree_snapshot = base_public_input1.end_nullifier_tree_snapshot; + input2.start_contract_tree_snapshot = base_public_input1.end_contract_tree_snapshot; + BaseRollupPublicInputs base_public_input2 = + aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(input2); // just for mocked vk and proof // Need a way to extract a proof from Base Rollup Circuit. Until then use kernel as a hack. PreviousKernelData mocked_kernel = dummy_previous_kernel_with_vk_proof(); - PreviousRollupData previous_rollup = { - .merge_rollup_public_inputs = convert_base_public_inputs_to_merge_public_inputs(dummy_base_public_inputs), + PreviousRollupData previous_rollup1 = { + .merge_rollup_public_inputs = convert_base_public_inputs_to_merge_public_inputs(base_public_input1), + .proof = mocked_kernel.proof, + .vk = mocked_kernel.vk, + .vk_index = 0, + .vk_sibling_path = MembershipWitness(), + }; + PreviousRollupData previous_rollup2 = { + .merge_rollup_public_inputs = convert_base_public_inputs_to_merge_public_inputs(base_public_input2), .proof = mocked_kernel.proof, .vk = mocked_kernel.vk, .vk_index = 0, .vk_sibling_path = MembershipWitness(), }; - return previous_rollup; + return { previous_rollup1, previous_rollup2 }; } MergeRollupInputs dummy_merge_rollup_inputs_with_vk_proof() { - MergeRollupInputs merge_rollup_inputs = { .previous_rollup_data = { dummy_previous_rollup_with_vk_proof(), - dummy_previous_rollup_with_vk_proof() } }; + MergeRollupInputs merge_rollup_inputs = { .previous_rollup_data = + previous_rollups_with_vk_proof_that_follow_on() }; return merge_rollup_inputs; } } // namespace aztec3::circuits::rollup::merge::utils \ No newline at end of file diff --git a/cpp/src/aztec3/circuits/rollup/merge/utils.hpp b/cpp/src/aztec3/circuits/rollup/merge/utils.hpp index 1a574060..95bf9ea0 100644 --- a/cpp/src/aztec3/circuits/rollup/merge/utils.hpp +++ b/cpp/src/aztec3/circuits/rollup/merge/utils.hpp @@ -16,6 +16,6 @@ using aztec3::circuits::abis::PreviousRollupData; MergeRollupPublicInputs convert_base_public_inputs_to_merge_public_inputs( BaseRollupPublicInputs baseRollupPublicInputs); MergeRollupInputs dummy_merge_rollup_inputs_with_vk_proof(); -PreviousRollupData dummy_previous_rollup_with_vk_proof(); +std::array, 2> previous_rollups_with_vk_proof_that_follow_on(); } // namespace aztec3::circuits::rollup::merge::utils \ No newline at end of file diff --git a/cpp/src/aztec3/circuits/rollup/root/.test.cpp b/cpp/src/aztec3/circuits/rollup/root/.test.cpp index 21e25b73..28c0d2b9 100644 --- a/cpp/src/aztec3/circuits/rollup/root/.test.cpp +++ b/cpp/src/aztec3/circuits/rollup/root/.test.cpp @@ -88,7 +88,7 @@ using aztec3::circuits::kernel::private_kernel::utils::dummy_previous_kernel_wit using aztec3::circuits::mock::mock_kernel_circuit; using aztec3::circuits::rollup::base::utils::dummy_base_rollup_inputs_with_vk_proof; using aztec3::circuits::rollup::merge::utils::convert_base_public_inputs_to_merge_public_inputs; -using aztec3::circuits::rollup::merge::utils::dummy_previous_rollup_with_vk_proof; +using aztec3::circuits::rollup::merge::utils::previous_rollups_with_vk_proof_that_follow_on; // using aztec3::circuits::mock::mock_kernel_inputs; using aztec3::circuits::abis::AppendOnlyTreeSnapshot; @@ -180,16 +180,13 @@ class root_rollup_tests : public ::testing::Test { protected: RootRollupInputs getEmptyRootRollupInputs() { - std::array, 2> previous_rollup_data = { - dummy_previous_rollup_with_vk_proof(), - dummy_previous_rollup_with_vk_proof(), - }; + // std::array, 2> previous_rollup_data = previous_rollups_with_vk_proof_that_follow_on(); - previous_rollup_data[1].merge_rollup_public_inputs.constants = - previous_rollup_data[0].merge_rollup_public_inputs.constants; + // previous_rollup_data[1].merge_rollup_public_inputs.constants = + // previous_rollup_data[0].merge_rollup_public_inputs.constants; RootRollupInputs rootRollupInputs = { - .previous_rollup_data = previous_rollup_data, + .previous_rollup_data = previous_rollups_with_vk_proof_that_follow_on(), .new_historic_private_data_tree_root_sibling_path = { 0 }, .new_historic_contract_tree_root_sibling_path = { 0 }, };