From a8b8072950c4fa10ab4aaca32be9da1f6e9cab37 Mon Sep 17 00:00:00 2001 From: jeanmon Date: Fri, 8 Sep 2023 12:10:08 +0000 Subject: [PATCH] 2116 - migrate cbind routine for merge rollup to msgpack --- .../aztec3/circuits/rollup/merge/.test.cpp | 82 ++-- .../aztec3/circuits/rollup/merge/c_bind.cpp | 26 +- .../src/aztec3/circuits/rollup/merge/c_bind.h | 7 +- .../src/kernel_prover/proof_creator.ts | 6 +- .../circuits.js/src/cbind/circuits.gen.ts | 355 ++++++++++++++++++ yarn-project/circuits.js/src/cbind/types.ts | 23 ++ .../src/rollup/rollup_wasm_wrapper.test.ts | 64 ++-- .../src/rollup/rollup_wasm_wrapper.ts | 20 +- .../base_or_merge_rollup_public_inputs.ts | 10 +- .../src/structs/rollup/base_rollup.ts | 16 +- .../structs/rollup/previous_rollup_data.ts | 4 +- .../circuits.js/src/tests/factories.ts | 6 +- .../src/block_builder/solo_block_builder.ts | 8 +- .../sequencer-client/src/simulator/rollup.ts | 12 +- 14 files changed, 496 insertions(+), 143 deletions(-) diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp index 845cc9b90e6b..5aa4a30e6194 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp @@ -28,46 +28,46 @@ class merge_rollup_tests : public ::testing::Test { protected: static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } - static void run_cbind(MergeRollupInputs& merge_rollup_inputs, - BaseOrMergeRollupPublicInputs& expected_public_inputs, - bool compare_pubins = true) - { - info("Retesting via cbinds...."); - std::vector merge_rollup_inputs_vec; - serialize::write(merge_rollup_inputs_vec, merge_rollup_inputs); - - uint8_t const* public_inputs_buf = nullptr; - // info("simulating circuit via cbind"); - size_t public_inputs_size = 0; - info("creating proof"); - auto* circuit_failure_ptr = - merge_rollup__sim(merge_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); - ASSERT_TRUE(circuit_failure_ptr == nullptr); - // 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*)public_inputs_buf); - } + // static void run_cbind(MergeRollupInputs& merge_rollup_inputs, + // BaseOrMergeRollupPublicInputs& expected_public_inputs, + // bool compare_pubins = true) + // { + // info("Retesting via cbinds...."); + // std::vector merge_rollup_inputs_vec; + // serialize::write(merge_rollup_inputs_vec, merge_rollup_inputs); + + // uint8_t const* public_inputs_buf = nullptr; + // // info("simulating circuit via cbind"); + // size_t public_inputs_size = 0; + // info("creating proof"); + // auto* circuit_failure_ptr = + // merge_rollup__sim(merge_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); + // ASSERT_TRUE(circuit_failure_ptr == nullptr); + // // 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*)public_inputs_buf); + // } }; TEST_F(merge_rollup_tests, native_different_rollup_type_fails) @@ -299,6 +299,6 @@ TEST_F(merge_rollup_tests, native_merge_cbind) ASSERT_FALSE(builder.failed()); BaseOrMergeRollupPublicInputs ignored_public_inputs; - run_cbind(inputs, ignored_public_inputs, false); + // run_cbind(inputs, ignored_public_inputs, false); } } // namespace aztec3::circuits::rollup::merge::native_merge_rollup_circuit diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp index fe93b3ac07e0..cd52451cc6ce 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp @@ -9,32 +9,14 @@ namespace { using NT = aztec3::utils::types::NativeTypes; using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::BaseOrMergeRollupPublicInputs; using aztec3::circuits::abis::MergeRollupInputs; using aztec3::circuits::rollup::merge::merge_rollup_circuit; } // namespace // WASM Cbinds -extern "C" { -WASM_EXPORT uint8_t* merge_rollup__sim(uint8_t const* merge_rollup_inputs_buf, - size_t* merge_rollup_public_inputs_size_out, - uint8_t const** merge_rollup_public_inputs_buf) -{ +CBIND(merge_rollup__sim, [](MergeRollupInputs const& merge_rollup_inputs) { DummyCircuitBuilder builder = DummyCircuitBuilder("merge_rollup__sim"); - MergeRollupInputs merge_rollup_inputs; - serialize::read(merge_rollup_inputs_buf, merge_rollup_inputs); - - BaseOrMergeRollupPublicInputs const public_inputs = merge_rollup_circuit(builder, merge_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()); - *merge_rollup_public_inputs_buf = raw_public_inputs_buf; - *merge_rollup_public_inputs_size_out = public_inputs_vec.size(); - return builder.alloc_and_serialize_first_failure(); -} -} // extern "C" \ No newline at end of file + auto const& public_inputs = merge_rollup_circuit(builder, merge_rollup_inputs); + return builder.result_or_error(public_inputs); +}); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h b/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h index c16fdc190e61..5063715b6310 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h +++ b/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h @@ -5,9 +5,4 @@ #include #include -extern "C" { - -WASM_EXPORT uint8_t* merge_rollup__sim(uint8_t const* merge_rollup_inputs_buf, - size_t* merge_rollup_public_inputs_size_out, - uint8_t const** merge_rollup_public_inputs_buf); -} \ No newline at end of file +CBIND_DECL(merge_rollup__sim); \ No newline at end of file diff --git a/yarn-project/aztec-rpc/src/kernel_prover/proof_creator.ts b/yarn-project/aztec-rpc/src/kernel_prover/proof_creator.ts index 99b7e4647114..cbf02be23d38 100644 --- a/yarn-project/aztec-rpc/src/kernel_prover/proof_creator.ts +++ b/yarn-project/aztec-rpc/src/kernel_prover/proof_creator.ts @@ -154,11 +154,9 @@ export class KernelProofCreator implements ProofCreator { const proof = makeEmptyProof(); this.log('Ordering Kernel Prover Ordering Completed!'); - const publicInputs = result as KernelCircuitPublicInputsFinal; - return { - publicInputs, - proof, + publicInputs: result, + proof: proof, }; } } diff --git a/yarn-project/circuits.js/src/cbind/circuits.gen.ts b/yarn-project/circuits.js/src/cbind/circuits.gen.ts index b1a272ddc9d4..2a1722fc7578 100644 --- a/yarn-project/circuits.js/src/cbind/circuits.gen.ts +++ b/yarn-project/circuits.js/src/cbind/circuits.gen.ts @@ -9,10 +9,13 @@ import mapValues from 'lodash.mapvalues'; import { callCbind } from './cbind.js'; import { Address, + AppendOnlyTreeSnapshot, + BaseOrMergeRollupPublicInputs, CallContext, CircuitError, CombinedAccumulatedData, CombinedConstantData, + ConstantRollupData, ContractDeploymentData, ContractStorageRead, ContractStorageUpdateRequest, @@ -27,12 +30,15 @@ import { KernelCircuitPublicInputs, KernelCircuitPublicInputsFinal, MembershipWitness4, + MembershipWitness8, MembershipWitness16, + MergeRollupInputs, NativeAggregationState, NewContractData, OptionallyRevealedData, Point, PreviousKernelData, + PreviousRollupData, PrivateCallData, PrivateCallStackItem, PrivateCircuitPublicInputs, @@ -2228,6 +2234,346 @@ export function fromPublicKernelInputs(o: PublicKernelInputs): MsgpackPublicKern }; } +interface MsgpackAppendOnlyTreeSnapshot { + root: Buffer; + next_available_leaf_index: number; +} + +export function toAppendOnlyTreeSnapshot(o: MsgpackAppendOnlyTreeSnapshot): AppendOnlyTreeSnapshot { + if (o.root === undefined) { + throw new Error('Expected root in AppendOnlyTreeSnapshot deserialization'); + } + if (o.next_available_leaf_index === undefined) { + throw new Error('Expected next_available_leaf_index in AppendOnlyTreeSnapshot deserialization'); + } + return new AppendOnlyTreeSnapshot(Fr.fromBuffer(o.root), o.next_available_leaf_index); +} + +export function fromAppendOnlyTreeSnapshot(o: AppendOnlyTreeSnapshot): MsgpackAppendOnlyTreeSnapshot { + if (o.root === undefined) { + throw new Error('Expected root in AppendOnlyTreeSnapshot serialization'); + } + if (o.nextAvailableLeafIndex === undefined) { + throw new Error('Expected nextAvailableLeafIndex in AppendOnlyTreeSnapshot serialization'); + } + return { + root: toBuffer(o.root), + next_available_leaf_index: o.nextAvailableLeafIndex, + }; +} + +interface MsgpackConstantRollupData { + start_historic_blocks_tree_roots_snapshot: MsgpackAppendOnlyTreeSnapshot; + private_kernel_vk_tree_root: Buffer; + public_kernel_vk_tree_root: Buffer; + base_rollup_vk_hash: Buffer; + merge_rollup_vk_hash: Buffer; + global_variables: MsgpackGlobalVariables; +} + +export function toConstantRollupData(o: MsgpackConstantRollupData): ConstantRollupData { + if (o.start_historic_blocks_tree_roots_snapshot === undefined) { + throw new Error('Expected start_historic_blocks_tree_roots_snapshot in ConstantRollupData deserialization'); + } + if (o.private_kernel_vk_tree_root === undefined) { + throw new Error('Expected private_kernel_vk_tree_root in ConstantRollupData deserialization'); + } + if (o.public_kernel_vk_tree_root === undefined) { + throw new Error('Expected public_kernel_vk_tree_root in ConstantRollupData deserialization'); + } + if (o.base_rollup_vk_hash === undefined) { + throw new Error('Expected base_rollup_vk_hash in ConstantRollupData deserialization'); + } + if (o.merge_rollup_vk_hash === undefined) { + throw new Error('Expected merge_rollup_vk_hash in ConstantRollupData deserialization'); + } + if (o.global_variables === undefined) { + throw new Error('Expected global_variables in ConstantRollupData deserialization'); + } + return new ConstantRollupData( + toAppendOnlyTreeSnapshot(o.start_historic_blocks_tree_roots_snapshot), + Fr.fromBuffer(o.private_kernel_vk_tree_root), + Fr.fromBuffer(o.public_kernel_vk_tree_root), + Fr.fromBuffer(o.base_rollup_vk_hash), + Fr.fromBuffer(o.merge_rollup_vk_hash), + toGlobalVariables(o.global_variables), + ); +} + +export function fromConstantRollupData(o: ConstantRollupData): MsgpackConstantRollupData { + if (o.startHistoricBlocksTreeRootsSnapshot === undefined) { + throw new Error('Expected startHistoricBlocksTreeRootsSnapshot in ConstantRollupData serialization'); + } + if (o.privateKernelVkTreeRoot === undefined) { + throw new Error('Expected privateKernelVkTreeRoot in ConstantRollupData serialization'); + } + if (o.publicKernelVkTreeRoot === undefined) { + throw new Error('Expected publicKernelVkTreeRoot in ConstantRollupData serialization'); + } + if (o.baseRollupVkHash === undefined) { + throw new Error('Expected baseRollupVkHash in ConstantRollupData serialization'); + } + if (o.mergeRollupVkHash === undefined) { + throw new Error('Expected mergeRollupVkHash in ConstantRollupData serialization'); + } + if (o.globalVariables === undefined) { + throw new Error('Expected globalVariables in ConstantRollupData serialization'); + } + return { + start_historic_blocks_tree_roots_snapshot: fromAppendOnlyTreeSnapshot(o.startHistoricBlocksTreeRootsSnapshot), + private_kernel_vk_tree_root: toBuffer(o.privateKernelVkTreeRoot), + public_kernel_vk_tree_root: toBuffer(o.publicKernelVkTreeRoot), + base_rollup_vk_hash: toBuffer(o.baseRollupVkHash), + merge_rollup_vk_hash: toBuffer(o.mergeRollupVkHash), + global_variables: fromGlobalVariables(o.globalVariables), + }; +} + +interface MsgpackBaseOrMergeRollupPublicInputs { + rollup_type: number; + rollup_subtree_height: Buffer; + end_aggregation_object: MsgpackNativeAggregationState; + constants: MsgpackConstantRollupData; + start_private_data_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + end_private_data_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + start_nullifier_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + end_nullifier_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + start_contract_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + end_contract_tree_snapshot: MsgpackAppendOnlyTreeSnapshot; + start_public_data_tree_root: Buffer; + end_public_data_tree_root: Buffer; + calldata_hash: Tuple; +} + +export function toBaseOrMergeRollupPublicInputs( + o: MsgpackBaseOrMergeRollupPublicInputs, +): BaseOrMergeRollupPublicInputs { + if (o.rollup_type === undefined) { + throw new Error('Expected rollup_type in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.rollup_subtree_height === undefined) { + throw new Error('Expected rollup_subtree_height in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.end_aggregation_object === undefined) { + throw new Error('Expected end_aggregation_object in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.constants === undefined) { + throw new Error('Expected constants in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.start_private_data_tree_snapshot === undefined) { + throw new Error('Expected start_private_data_tree_snapshot in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.end_private_data_tree_snapshot === undefined) { + throw new Error('Expected end_private_data_tree_snapshot in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.start_nullifier_tree_snapshot === undefined) { + throw new Error('Expected start_nullifier_tree_snapshot in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.end_nullifier_tree_snapshot === undefined) { + throw new Error('Expected end_nullifier_tree_snapshot in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.start_contract_tree_snapshot === undefined) { + throw new Error('Expected start_contract_tree_snapshot in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.end_contract_tree_snapshot === undefined) { + throw new Error('Expected end_contract_tree_snapshot in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.start_public_data_tree_root === undefined) { + throw new Error('Expected start_public_data_tree_root in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.end_public_data_tree_root === undefined) { + throw new Error('Expected end_public_data_tree_root in BaseOrMergeRollupPublicInputs deserialization'); + } + if (o.calldata_hash === undefined) { + throw new Error('Expected calldata_hash in BaseOrMergeRollupPublicInputs deserialization'); + } + return new BaseOrMergeRollupPublicInputs( + o.rollup_type, + Fr.fromBuffer(o.rollup_subtree_height), + toNativeAggregationState(o.end_aggregation_object), + toConstantRollupData(o.constants), + toAppendOnlyTreeSnapshot(o.start_private_data_tree_snapshot), + toAppendOnlyTreeSnapshot(o.end_private_data_tree_snapshot), + toAppendOnlyTreeSnapshot(o.start_nullifier_tree_snapshot), + toAppendOnlyTreeSnapshot(o.end_nullifier_tree_snapshot), + toAppendOnlyTreeSnapshot(o.start_contract_tree_snapshot), + toAppendOnlyTreeSnapshot(o.end_contract_tree_snapshot), + Fr.fromBuffer(o.start_public_data_tree_root), + Fr.fromBuffer(o.end_public_data_tree_root), + mapTuple(o.calldata_hash, (v: Buffer) => Fr.fromBuffer(v)), + ); +} + +export function fromBaseOrMergeRollupPublicInputs( + o: BaseOrMergeRollupPublicInputs, +): MsgpackBaseOrMergeRollupPublicInputs { + if (o.rollupType === undefined) { + throw new Error('Expected rollupType in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.rollupSubtreeHeight === undefined) { + throw new Error('Expected rollupSubtreeHeight in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.endAggregationObject === undefined) { + throw new Error('Expected endAggregationObject in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.constants === undefined) { + throw new Error('Expected constants in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.startPrivateDataTreeSnapshot === undefined) { + throw new Error('Expected startPrivateDataTreeSnapshot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.endPrivateDataTreeSnapshot === undefined) { + throw new Error('Expected endPrivateDataTreeSnapshot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.startNullifierTreeSnapshot === undefined) { + throw new Error('Expected startNullifierTreeSnapshot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.endNullifierTreeSnapshot === undefined) { + throw new Error('Expected endNullifierTreeSnapshot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.startContractTreeSnapshot === undefined) { + throw new Error('Expected startContractTreeSnapshot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.endContractTreeSnapshot === undefined) { + throw new Error('Expected endContractTreeSnapshot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.startPublicDataTreeRoot === undefined) { + throw new Error('Expected startPublicDataTreeRoot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.endPublicDataTreeRoot === undefined) { + throw new Error('Expected endPublicDataTreeRoot in BaseOrMergeRollupPublicInputs serialization'); + } + if (o.calldataHash === undefined) { + throw new Error('Expected calldataHash in BaseOrMergeRollupPublicInputs serialization'); + } + return { + rollup_type: o.rollupType, + rollup_subtree_height: toBuffer(o.rollupSubtreeHeight), + end_aggregation_object: fromNativeAggregationState(o.endAggregationObject), + constants: fromConstantRollupData(o.constants), + start_private_data_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startPrivateDataTreeSnapshot), + end_private_data_tree_snapshot: fromAppendOnlyTreeSnapshot(o.endPrivateDataTreeSnapshot), + start_nullifier_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startNullifierTreeSnapshot), + end_nullifier_tree_snapshot: fromAppendOnlyTreeSnapshot(o.endNullifierTreeSnapshot), + start_contract_tree_snapshot: fromAppendOnlyTreeSnapshot(o.startContractTreeSnapshot), + end_contract_tree_snapshot: fromAppendOnlyTreeSnapshot(o.endContractTreeSnapshot), + start_public_data_tree_root: toBuffer(o.startPublicDataTreeRoot), + end_public_data_tree_root: toBuffer(o.endPublicDataTreeRoot), + calldata_hash: mapTuple(o.calldataHash, (v: Fr) => toBuffer(v)), + }; +} + +interface MsgpackMembershipWitness8 { + leaf_index: Buffer; + sibling_path: Tuple; +} + +export function toMembershipWitness8(o: MsgpackMembershipWitness8): MembershipWitness8 { + if (o.leaf_index === undefined) { + throw new Error('Expected leaf_index in MembershipWitness8 deserialization'); + } + if (o.sibling_path === undefined) { + throw new Error('Expected sibling_path in MembershipWitness8 deserialization'); + } + return new MembershipWitness8( + Fr.fromBuffer(o.leaf_index), + mapTuple(o.sibling_path, (v: Buffer) => Fr.fromBuffer(v)), + ); +} + +export function fromMembershipWitness8(o: MembershipWitness8): MsgpackMembershipWitness8 { + if (o.leafIndex === undefined) { + throw new Error('Expected leafIndex in MembershipWitness8 serialization'); + } + if (o.siblingPath === undefined) { + throw new Error('Expected siblingPath in MembershipWitness8 serialization'); + } + return { + leaf_index: toBuffer(o.leafIndex), + sibling_path: mapTuple(o.siblingPath, (v: Fr) => toBuffer(v)), + }; +} + +interface MsgpackPreviousRollupData { + base_or_merge_rollup_public_inputs: MsgpackBaseOrMergeRollupPublicInputs; + proof: Buffer; + vk: MsgpackVerificationKeyData; + vk_index: number; + vk_sibling_path: MsgpackMembershipWitness8; +} + +export function toPreviousRollupData(o: MsgpackPreviousRollupData): PreviousRollupData { + if (o.base_or_merge_rollup_public_inputs === undefined) { + throw new Error('Expected base_or_merge_rollup_public_inputs in PreviousRollupData deserialization'); + } + if (o.proof === undefined) { + throw new Error('Expected proof in PreviousRollupData deserialization'); + } + if (o.vk === undefined) { + throw new Error('Expected vk in PreviousRollupData deserialization'); + } + if (o.vk_index === undefined) { + throw new Error('Expected vk_index in PreviousRollupData deserialization'); + } + if (o.vk_sibling_path === undefined) { + throw new Error('Expected vk_sibling_path in PreviousRollupData deserialization'); + } + return new PreviousRollupData( + toBaseOrMergeRollupPublicInputs(o.base_or_merge_rollup_public_inputs), + Proof.fromMsgpackBuffer(o.proof), + toVerificationKeyData(o.vk), + o.vk_index, + toMembershipWitness8(o.vk_sibling_path), + ); +} + +export function fromPreviousRollupData(o: PreviousRollupData): MsgpackPreviousRollupData { + if (o.baseOrMergeRollupPublicInputs === undefined) { + throw new Error('Expected baseOrMergeRollupPublicInputs in PreviousRollupData serialization'); + } + if (o.proof === undefined) { + throw new Error('Expected proof in PreviousRollupData serialization'); + } + if (o.vk === undefined) { + throw new Error('Expected vk in PreviousRollupData serialization'); + } + if (o.vkIndex === undefined) { + throw new Error('Expected vkIndex in PreviousRollupData serialization'); + } + if (o.vkSiblingPath === undefined) { + throw new Error('Expected vkSiblingPath in PreviousRollupData serialization'); + } + return { + base_or_merge_rollup_public_inputs: fromBaseOrMergeRollupPublicInputs(o.baseOrMergeRollupPublicInputs), + proof: o.proof.toMsgpackBuffer(), + vk: fromVerificationKeyData(o.vk), + vk_index: o.vkIndex, + vk_sibling_path: fromMembershipWitness8(o.vkSiblingPath), + }; +} + +interface MsgpackMergeRollupInputs { + previous_rollup_data: Tuple; +} + +export function toMergeRollupInputs(o: MsgpackMergeRollupInputs): MergeRollupInputs { + if (o.previous_rollup_data === undefined) { + throw new Error('Expected previous_rollup_data in MergeRollupInputs deserialization'); + } + return new MergeRollupInputs( + mapTuple(o.previous_rollup_data, (v: MsgpackPreviousRollupData) => toPreviousRollupData(v)), + ); +} + +export function fromMergeRollupInputs(o: MergeRollupInputs): MsgpackMergeRollupInputs { + if (o.previousRollupData === undefined) { + throw new Error('Expected previousRollupData in MergeRollupInputs serialization'); + } + return { + previous_rollup_data: mapTuple(o.previousRollupData, (v: PreviousRollupData) => fromPreviousRollupData(v)), + }; +} + export function abisComputeCommitmentNonce(wasm: IWasmModule, arg0: Fr, arg1: Fr): Fr { return Fr.fromBuffer(callCbind(wasm, 'abis__compute_commitment_nonce', [toBuffer(arg0), toBuffer(arg1)])); } @@ -2325,3 +2671,12 @@ export function publicKernelSim(wasm: IWasmModule, arg0: PublicKernelInputs): Ci callCbind(wasm, 'public_kernel__sim', [fromPublicKernelInputs(arg0)]), ); } +export function mergeRollupSim( + wasm: IWasmModule, + arg0: MergeRollupInputs, +): CircuitError | BaseOrMergeRollupPublicInputs { + return ((v: MsgpackCircuitError | MsgpackBaseOrMergeRollupPublicInputs) => + isCircuitError(v) ? toCircuitError(v) : toBaseOrMergeRollupPublicInputs(v))( + callCbind(wasm, 'merge_rollup__sim', [fromMergeRollupInputs(arg0)]), + ); +} diff --git a/yarn-project/circuits.js/src/cbind/types.ts b/yarn-project/circuits.js/src/cbind/types.ts index e7f4d009f3e0..c3f7a5eac9ed 100644 --- a/yarn-project/circuits.js/src/cbind/types.ts +++ b/yarn-project/circuits.js/src/cbind/types.ts @@ -25,6 +25,24 @@ export class MembershipWitness16 extends MembershipWitness<16> { } } +/** + * Alias for msgpack which expects a MembershipWitness + N name. + */ +export class MembershipWitness8 extends MembershipWitness<8> { + constructor( + /** + * Index of a leaf in the Merkle tree. + */ + leafIndex: Fr, + /** + * Sibling path of the leaf in the Merkle tree. + */ + siblingPath: Tuple, + ) { + super(8, leafIndex.toBigInt(), siblingPath); + } +} + /** * Alias for msgpack which expects a MembershipWitness + N name. */ @@ -99,6 +117,11 @@ export { PrivateKernelInputsInit, PrivateKernelInputsInner, TxRequest, + PreviousRollupData, + AppendOnlyTreeSnapshot, + BaseOrMergeRollupPublicInputs, + ConstantRollupData, + MergeRollupInputs, } from '../structs/index.js'; export { FunctionSelector } from '@aztec/foundation/abi'; 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 6b023b6e01fd..abbcbf241e67 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,7 +1,7 @@ import { AggregationObject, CircuitError, MergeRollupInputs, RootRollupInputs, VerificationKey } from '../index.js'; import { makeBaseRollupInputs, makeMergeRollupInputs, makeRootRollupInputs } from '../tests/factories.js'; import { CircuitsWasm } from '../wasm/circuits_wasm.js'; -import { RollupWasmWrapper } from './rollup_wasm_wrapper.js'; +import { RollupWasmWrapper, mergeRollupSim } from './rollup_wasm_wrapper.js'; describe('rollup/rollup_wasm_wrapper', () => { let wasm: CircuitsWasm; @@ -22,22 +22,23 @@ describe('rollup/rollup_wasm_wrapper', () => { }; const fixPreviousRollupInputs = (input: MergeRollupInputs | RootRollupInputs) => { - input.previousRollupData[1].publicInputs.constants = input.previousRollupData[0].publicInputs.constants; - input.previousRollupData[1].publicInputs.startPrivateDataTreeSnapshot = - input.previousRollupData[0].publicInputs.endPrivateDataTreeSnapshot; - input.previousRollupData[1].publicInputs.startNullifierTreeSnapshot = - input.previousRollupData[0].publicInputs.endNullifierTreeSnapshot; - input.previousRollupData[1].publicInputs.startContractTreeSnapshot = - input.previousRollupData[0].publicInputs.endContractTreeSnapshot; - input.previousRollupData[1].publicInputs.startPublicDataTreeRoot = - input.previousRollupData[0].publicInputs.endPublicDataTreeRoot; + input.previousRollupData[1].baseOrMergeRollupPublicInputs.constants = + input.previousRollupData[0].baseOrMergeRollupPublicInputs.constants; + input.previousRollupData[1].baseOrMergeRollupPublicInputs.startPrivateDataTreeSnapshot = + input.previousRollupData[0].baseOrMergeRollupPublicInputs.endPrivateDataTreeSnapshot; + input.previousRollupData[1].baseOrMergeRollupPublicInputs.startNullifierTreeSnapshot = + input.previousRollupData[0].baseOrMergeRollupPublicInputs.endNullifierTreeSnapshot; + input.previousRollupData[1].baseOrMergeRollupPublicInputs.startContractTreeSnapshot = + input.previousRollupData[0].baseOrMergeRollupPublicInputs.endContractTreeSnapshot; + input.previousRollupData[1].baseOrMergeRollupPublicInputs.startPublicDataTreeRoot = + input.previousRollupData[0].baseOrMergeRollupPublicInputs.endPublicDataTreeRoot; }; const makeMergeRollupInputsForCircuit = () => { const input = makeMergeRollupInputs(); for (const previousData of input.previousRollupData) { previousData.vk = VerificationKey.makeFake(); - previousData.publicInputs.endAggregationObject = AggregationObject.makeFake(); + previousData.baseOrMergeRollupPublicInputs.endAggregationObject = AggregationObject.makeFake(); } fixPreviousRollupInputs(input); return input; @@ -56,35 +57,38 @@ describe('rollup/rollup_wasm_wrapper', () => { it('calls merge_rollup__sim', () => { const input = makeMergeRollupInputsForCircuit(); - const output = rollupWasm.simulateMergeRollup(input); + const output = mergeRollupSim(wasm, input); + if (output instanceof CircuitError) { + throw new CircuitError(output.code, output.message); + } + expect(output.rollupType).toEqual(1); expect(output.startContractTreeSnapshot).toEqual( - input.previousRollupData[0].publicInputs.startContractTreeSnapshot, + input.previousRollupData[0].baseOrMergeRollupPublicInputs.startContractTreeSnapshot, ); expect(output.startNullifierTreeSnapshot).toEqual( - input.previousRollupData[0].publicInputs.startNullifierTreeSnapshot, + input.previousRollupData[0].baseOrMergeRollupPublicInputs.startNullifierTreeSnapshot, ); expect(output.startPrivateDataTreeSnapshot).toEqual( - input.previousRollupData[0].publicInputs.startPrivateDataTreeSnapshot, + input.previousRollupData[0].baseOrMergeRollupPublicInputs.startPrivateDataTreeSnapshot, ); expect(output.endPrivateDataTreeSnapshot).toEqual( - input.previousRollupData[1].publicInputs.endPrivateDataTreeSnapshot, + input.previousRollupData[1].baseOrMergeRollupPublicInputs.endPrivateDataTreeSnapshot, ); }); it('calling merge_rollup__sim with different constants should fail', () => { const input = makeMergeRollupInputs(); - try { - rollupWasm.simulateMergeRollup(input); - } catch (e) { - expect(e).toBeInstanceOf(CircuitError); - const err = e as CircuitError; - expect(err.message).toEqual( - `input proofs have different constants -Refer to https://docs.aztec.network/aztec/protocol/errors for more information.`, - ); - expect(err.code).toEqual(7003); - } + + const output = mergeRollupSim(wasm, input); + expect(output instanceof CircuitError).toBeTruthy(); + + const err = output as CircuitError; + expect(err.message).toEqual( + `input proofs have different constants`, + // Refer to https://docs.aztec.network/aztec/protocol/errors for more information.`, + ); + expect(err.code).toEqual(7003); }); // Task to repair this test: https://github.com/AztecProtocol/aztec-packages/issues/1586 @@ -92,14 +96,14 @@ Refer to https://docs.aztec.network/aztec/protocol/errors for more information.` const input = makeRootRollupInputs(); for (const rd of input.previousRollupData) { rd.vk = VerificationKey.makeFake(); - rd.publicInputs.endAggregationObject = AggregationObject.makeFake(); - rd.publicInputs = rollupWasm.simulateBaseRollup(makeBaseRollupInputsForCircuit()); + rd.baseOrMergeRollupPublicInputs.endAggregationObject = AggregationObject.makeFake(); + rd.baseOrMergeRollupPublicInputs = rollupWasm.simulateBaseRollup(makeBaseRollupInputsForCircuit()); } fixPreviousRollupInputs(input); const output = rollupWasm.simulateRootRollup(input); expect(output.startNullifierTreeSnapshot).toEqual( - input.previousRollupData[0].publicInputs.startNullifierTreeSnapshot, + input.previousRollupData[0].baseOrMergeRollupPublicInputs.startNullifierTreeSnapshot, ); }, 15_000); }); diff --git a/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts b/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts index 99f286d8f668..0518ba021805 100644 --- a/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts +++ b/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.ts @@ -1,13 +1,9 @@ -import { - BaseOrMergeRollupPublicInputs, - BaseRollupInputs, - MergeRollupInputs, - RootRollupInputs, - RootRollupPublicInputs, -} from '../index.js'; +import { BaseOrMergeRollupPublicInputs, BaseRollupInputs, RootRollupInputs, RootRollupPublicInputs } from '../index.js'; import { callWasm } from '../utils/call_wasm.js'; import { CircuitsWasm } from '../wasm/circuits_wasm.js'; +export { mergeRollupSim } from '../cbind/circuits.gen.js'; + /** * A wrapper around `CircuitsWasm` used to expose only the functions relevant for rollup circuits. */ @@ -24,16 +20,6 @@ export class RollupWasmWrapper { return callWasm(this.wasm, 'base_rollup__sim', baseRollupInputs, BaseOrMergeRollupPublicInputs); } - /** - * Simulates the merge rollup circuit from its inputs. - * @param mergeRollupInputs - 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 simulateMergeRollup(mergeRollupInputs: MergeRollupInputs): BaseOrMergeRollupPublicInputs { - return callWasm(this.wasm, 'merge_rollup__sim', mergeRollupInputs, BaseOrMergeRollupPublicInputs); - } - /** * Simulates the root rollup circuit from its inputs. * @param rootRollupInputs - Inputs to the circuit. diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts index 446c4e2d668d..7f616bcabf7e 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -6,7 +6,7 @@ import { serializeToBuffer } from '../../utils/serialize.js'; import { AggregationObject } from '../aggregation_object.js'; import { RollupTypes } from '../shared.js'; import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; -import { ConstantBaseRollupData } from './base_rollup.js'; +import { ConstantRollupData } from './base_rollup.js'; /** * Output of the base and merge rollup circuits. @@ -22,7 +22,7 @@ export class BaseOrMergeRollupPublicInputs { * Note 1: Base rollup circuit always have a sub tree height of 0. * Note 2: With each merge, the sub tree height increases by 1. */ - public rollupSubTreeHeight: Fr, + public rollupSubtreeHeight: Fr, /** * Native aggregation state at the end of the rollup circuit. */ @@ -30,7 +30,7 @@ export class BaseOrMergeRollupPublicInputs { /** * Data which is forwarded through the rollup circuits unchanged. */ - public constants: ConstantBaseRollupData, + public constants: ConstantRollupData, /** * Snapshot of the private data tree at the start of the rollup circuit. @@ -87,7 +87,7 @@ export class BaseOrMergeRollupPublicInputs { reader.readNumber(), reader.readFr(), reader.readObject(AggregationObject), - reader.readObject(ConstantBaseRollupData), + reader.readObject(ConstantRollupData), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), @@ -107,7 +107,7 @@ export class BaseOrMergeRollupPublicInputs { toBuffer() { return serializeToBuffer( this.rollupType, - this.rollupSubTreeHeight, + this.rollupSubtreeHeight, this.endAggregationObject, this.constants, 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 467cf463ef28..7f3fed8f22fd 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts @@ -53,7 +53,7 @@ export class NullifierLeafPreimage { /** * Data which is forwarded through the base rollup circuits unchanged. */ -export class ConstantBaseRollupData { +export class ConstantRollupData { constructor( /** * Snapshot of the historic blocks roots tree at the start of the rollup. @@ -82,13 +82,13 @@ export class ConstantBaseRollupData { public globalVariables: GlobalVariables, ) {} - static from(fields: FieldsOf): ConstantBaseRollupData { - return new ConstantBaseRollupData(...ConstantBaseRollupData.getFields(fields)); + static from(fields: FieldsOf): ConstantRollupData { + return new ConstantRollupData(...ConstantRollupData.getFields(fields)); } - static fromBuffer(buffer: Buffer | BufferReader): ConstantBaseRollupData { + static fromBuffer(buffer: Buffer | BufferReader): ConstantRollupData { const reader = BufferReader.asReader(buffer); - return new ConstantBaseRollupData( + return new ConstantRollupData( reader.readObject(AppendOnlyTreeSnapshot), reader.readFr(), reader.readFr(), @@ -98,7 +98,7 @@ export class ConstantBaseRollupData { ); } - static getFields(fields: FieldsOf) { + static getFields(fields: FieldsOf) { return [ fields.startHistoricBlocksTreeRootsSnapshot, fields.privateKernelVkTreeRoot, @@ -110,7 +110,7 @@ export class ConstantBaseRollupData { } toBuffer() { - return serializeToBuffer(...ConstantBaseRollupData.getFields(this)); + return serializeToBuffer(...ConstantRollupData.getFields(this)); } } @@ -203,7 +203,7 @@ export class BaseRollupInputs { /** * Data which is not modified by the base rollup circuit. */ - public constants: ConstantBaseRollupData, + public constants: ConstantRollupData, ) { assertMemberLength(this, 'lowNullifierLeafPreimages', 2 * MAX_NEW_NULLIFIERS_PER_TX); assertMemberLength(this, 'lowNullifierMembershipWitness', 2 * MAX_NEW_NULLIFIERS_PER_TX); diff --git a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts index c112e541cf93..db7c2da556fc 100644 --- a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts @@ -14,7 +14,7 @@ export class PreviousRollupData { /** * Public inputs to the base or merge rollup circuit. */ - public publicInputs: BaseOrMergeRollupPublicInputs, + public baseOrMergeRollupPublicInputs: BaseOrMergeRollupPublicInputs, /** * The proof of the base or merge rollup circuit. */ @@ -38,6 +38,6 @@ export class PreviousRollupData { * @returns The buffer of the serialized previous rollup data. */ public toBuffer(): Buffer { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkSiblingPath); + return serializeToBuffer(this.baseOrMergeRollupPublicInputs, this.proof, this.vk, this.vkIndex, this.vkSiblingPath); } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 9c6a3656ba60..ad0beb0c05c3 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -16,7 +16,7 @@ import { CircuitsWasm, CombinedAccumulatedData, CombinedConstantData, - ConstantBaseRollupData, + ConstantRollupData, ContractDeploymentData, ContractStorageRead, ContractStorageUpdateRequest, @@ -704,8 +704,8 @@ export function makeGlobalVariables(seed = 1, blockNumber: number | undefined = export function makeConstantBaseRollupData( seed = 1, globalVariables: GlobalVariables | undefined = undefined, -): ConstantBaseRollupData { - return ConstantBaseRollupData.from({ +): ConstantRollupData { + return ConstantRollupData.from({ startHistoricBlocksTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(seed + 0x300), privateKernelVkTreeRoot: fr(seed + 0x401), publicKernelVkTreeRoot: fr(seed + 0x402), 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 bd9ef821a129..292988368520 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 @@ -3,7 +3,7 @@ import { BaseOrMergeRollupPublicInputs, BaseRollupInputs, CircuitsWasm, - ConstantBaseRollupData, + ConstantRollupData, GlobalVariables, HISTORIC_BLOCKS_TREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_HEIGHT, @@ -528,8 +528,8 @@ export class SoloBlockBuilder implements BlockBuilder { return this.getMembershipWitnessFor(blockHash, MerkleTreeId.BLOCKS_TREE, HISTORIC_BLOCKS_TREE_HEIGHT); } - protected async getConstantBaseRollupData(globalVariables: GlobalVariables): Promise { - return ConstantBaseRollupData.from({ + protected async getConstantRollupData(globalVariables: GlobalVariables): Promise { + return ConstantRollupData.from({ baseRollupVkHash: DELETE_FR, mergeRollupVkHash: DELETE_FR, privateKernelVkTreeRoot: FUTURE_FR, @@ -604,7 +604,7 @@ export class SoloBlockBuilder implements BlockBuilder { const wasm = await CircuitsWasm.get(); // Get trees info before any changes hit - const constants = await this.getConstantBaseRollupData(globalVariables); + const constants = await this.getConstantRollupData(globalVariables); const startNullifierTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); const startContractTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); const startPrivateDataTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); diff --git a/yarn-project/sequencer-client/src/simulator/rollup.ts b/yarn-project/sequencer-client/src/simulator/rollup.ts index 787f0c467846..addd8590e199 100644 --- a/yarn-project/sequencer-client/src/simulator/rollup.ts +++ b/yarn-project/sequencer-client/src/simulator/rollup.ts @@ -1,11 +1,13 @@ import { BaseOrMergeRollupPublicInputs, BaseRollupInputs, + CircuitError, CircuitsWasm, MergeRollupInputs, RollupWasmWrapper, RootRollupInputs, RootRollupPublicInputs, + mergeRollupSim, } from '@aztec/circuits.js'; import { RollupSimulator } from './index.js'; @@ -15,9 +17,11 @@ import { RollupSimulator } from './index.js'; */ export class WasmRollupCircuitSimulator implements RollupSimulator { private rollupWasmWrapper: RollupWasmWrapper; + private wasm: CircuitsWasm; constructor(wasm: CircuitsWasm) { this.rollupWasmWrapper = new RollupWasmWrapper(wasm); + this.wasm = wasm; } /** @@ -42,8 +46,14 @@ export class WasmRollupCircuitSimulator implements RollupSimulator { * @returns The public inputs as outputs of the simulation. */ mergeRollupCircuit(input: MergeRollupInputs): Promise { - return Promise.resolve(this.rollupWasmWrapper.simulateMergeRollup(input)); + const result = mergeRollupSim(this.wasm, input); + if (result instanceof CircuitError) { + throw new CircuitError(result.code, result.message); + } + + return Promise.resolve(result); } + /** * Simulates the root rollup circuit from its inputs. * @param input - Inputs to the circuit.