diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index 2af498e3585..5fbd1af77c9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -11,6 +11,7 @@ #include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" #include "barretenberg/serialize/msgpack.hpp" #include "barretenberg/srs/global_crs.hpp" +#include "honk_contract.hpp" #include #include @@ -320,6 +321,23 @@ WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, bool const* r *out = to_heap_buffer(to_buffer(vk)); } +WASM_EXPORT void get_honk_solidity_verifier_vk(uint8_t const* acir_vec, bool const* recursive, uint8_t** out) +{ + using DeciderProvingKey = DeciderProvingKey_; + using VerificationKey = UltraFlavor::VerificationKey; + + auto constraint_system = + acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/true); + auto builder = + acir_format::create_circuit(constraint_system, *recursive, 0, {}, /*honk_recursion=*/true); + + DeciderProvingKey proving_key(builder); + VerificationKey vk(proving_key.proving_key); + + auto str = get_honk_solidity_verifier(&vk); + *out = to_heap_buffer(str); +} + WASM_EXPORT void acir_proof_as_fields_ultra_honk(uint8_t const* proof_buf, fr::vec_out_buf out) { auto proof = from_buffer>(from_buffer>(proof_buf)); @@ -342,4 +360,4 @@ WASM_EXPORT void acir_vk_as_fields_mega_honk(uint8_t const* vk_buf, fr::vec_out_ auto verification_key = std::make_shared(from_buffer(vk_buf)); std::vector vkey_as_fields = verification_key->to_field_elements(); *out_vkey = to_heap_buffer(vkey_as_fields); -} \ No newline at end of file +} diff --git a/barretenberg/ts/src/barretenberg/backend.ts b/barretenberg/ts/src/barretenberg/backend.ts index 4d8e89116b3..db292c1a926 100644 --- a/barretenberg/ts/src/barretenberg/backend.ts +++ b/barretenberg/ts/src/barretenberg/backend.ts @@ -125,12 +125,20 @@ export class UltraPlonkBackend { return await this.api.acirVerifyProof(this.acirComposer, proof); } + /** @description Returns the verification key */ async getVerificationKey(): Promise { await this.instantiate(); await this.api.acirInitVerificationKey(this.acirComposer); return await this.api.acirGetVerificationKey(this.acirComposer); } + /** @description Returns a solidity verifier */ + async getSolidityVerifier(): Promise { + await this.instantiate(); + await this.api.acirInitVerificationKey(this.acirComposer); + return await this.api.acirGetSolidityVerifier(this.acirComposer); + } + async destroy(): Promise { if (!this.api) { return; @@ -218,6 +226,13 @@ export class UltraHonkBackend { return await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive); } + /** @description Returns a solidity verifier */ + async getSolidityVerifier(): Promise { + await this.instantiate(); + await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive); + return await this.api.getHonkSolidityVerifier(this.acirUncompressedBytecode, this.circuitOptions.recursive); + } + // TODO(https://github.com/noir-lang/noir/issues/5661): Update this to handle Honk recursive aggregation in the browser once it is ready in the backend itself async generateRecursiveProofArtifacts( // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index 4d95dfa1887..202239039dc 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -593,6 +593,18 @@ export class BarretenbergApi { return out[0]; } + async getHonkSolidityVerifier(acirVec: Uint8Array, recursive: boolean): Promise { + const inArgs = [acirVec, recursive].map(serializeBufferable); + const outTypes: OutputType[] = [BufferDeserializer()]; + const result = await this.wasm.callWasmExport( + 'get_honk_solidity_verifier_vk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + async acirProofAsFieldsUltraHonk(proofBuf: Uint8Array): Promise { const inArgs = [proofBuf].map(serializeBufferable); const outTypes: OutputType[] = [VectorDeserializer(Fr)];