diff --git a/barretenberg/src/aztec/dsl/standard_format/standard_format.hpp b/barretenberg/src/aztec/dsl/standard_format/standard_format.hpp index e4fa373de..0e64a69a7 100644 --- a/barretenberg/src/aztec/dsl/standard_format/standard_format.hpp +++ b/barretenberg/src/aztec/dsl/standard_format/standard_format.hpp @@ -49,14 +49,12 @@ void read_witness(TurboComposer& composer, std::vector witness } } -TurboComposer create_circuit(const standard_format& constraint_system) +void create_circuit(TurboComposer& composer, const standard_format& constraint_system) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { std::cout << "too many public inputs!" << std::endl; } - auto composer = TurboComposer(); - for (size_t i = 1; i < constraint_system.varnum; ++i) { // If the index is in the public inputs vector, then we add it as a public input @@ -129,8 +127,6 @@ TurboComposer create_circuit(const standard_format& constraint_system) for (const auto& constraint : constraint_system.hash_to_field_constraints) { create_hash_to_field_constraints(composer, constraint); } - - return composer; } TurboComposer create_circuit(const standard_format& constraint_system, diff --git a/barretenberg/src/aztec/plonk/composer/turbo_composer.cpp b/barretenberg/src/aztec/plonk/composer/turbo_composer.cpp index 42a61296f..f9b62fb0b 100644 --- a/barretenberg/src/aztec/plonk/composer/turbo_composer.cpp +++ b/barretenberg/src/aztec/plonk/composer/turbo_composer.cpp @@ -951,6 +951,7 @@ std::shared_ptr TurboComposer::compute_verification_key() circuit_verification_key = turbo_composer::compute_verification_key(circuit_proving_key, crs_factory_->get_verifier_crs()); + circuit_verification_key->composer_type = type; circuit_verification_key->recursive_proof_public_input_indices = std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); diff --git a/barretenberg/src/aztec/plonk/proof_system/verification_key/verification_key.hpp b/barretenberg/src/aztec/plonk/proof_system/verification_key/verification_key.hpp index bcf1898c4..e3c456f36 100644 --- a/barretenberg/src/aztec/plonk/proof_system/verification_key/verification_key.hpp +++ b/barretenberg/src/aztec/plonk/proof_system/verification_key/verification_key.hpp @@ -84,6 +84,17 @@ struct verification_key { size_t program_width = 3; }; +template inline void read(B& buf, verification_key const& key) +{ + using serialize::read; + read(buf, key.composer_type); + read(buf, static_cast(key.n)); + read(buf, static_cast(key.num_public_inputs)); + read(buf, key.constraint_selectors); + read(buf, key.permutation_selectors); + read(buf, key.contains_recursive_proof); + read(buf, key.recursive_proof_public_input_indices); +} template inline void write(B& buf, verification_key const& key) { using serialize::write; diff --git a/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.cpp b/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.cpp index 7cfae5f63..a83efaeeb 100644 --- a/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.cpp +++ b/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.cpp @@ -61,6 +61,39 @@ WASM_EXPORT bool standard_example__verify_proof(uint8_t* proof, uint32_t length) } } +extern "C" { + +WASM_EXPORT size_t c_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf) +{ + return rollup::proofs::standard_example::c_init_proving_key(constraint_system_buf, pk_buf); +} + +WASM_EXPORT size_t c_init_verification_key(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const** vk_buf) +{ + return rollup::proofs::standard_example::c_init_verification_key(pippenger, g2x, pk_buf, vk_buf); +} + +WASM_EXPORT size_t c_new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf) +{ + return rollup::proofs::standard_example::c_new_proof( + pippenger, g2x, pk_buf, constraint_system_buf, witness_buf, proof_data_buf); +} + +WASM_EXPORT bool c_verify_proof( + uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length) +{ + return rollup::proofs::standard_example::c_verify_proof(g2x, vk_buf, constraint_system_buf, proof, length); +} +} + // standard format stuff using namespace waffle; diff --git a/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.h b/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.h index 7cdadca70..1c7e1b070 100644 --- a/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.h +++ b/barretenberg/src/aztec/rollup/proofs/standard_example/c_bind.h @@ -33,4 +33,23 @@ WASM_EXPORT size_t composer__new_proof(void* pippenger, uint8_t** proof_data_buf); WASM_EXPORT bool composer__verify_proof( void* pippenger, uint8_t const* g2x, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length); + +// Construct composer using prover and verifier key buffers +WASM_EXPORT size_t c_init_proving_key(uint8_t const* constraint_system_buf, + uint8_t const** pk_buf); +WASM_EXPORT size_t c_init_verification_key(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const** vk_buf); +WASM_EXPORT size_t c_new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf); +WASM_EXPORT bool c_verify_proof(uint8_t const* g2x, + uint8_t const* vk_buf, + uint8_t const* constraint_system_buf, + uint8_t* proof, + uint32_t length); } \ No newline at end of file diff --git a/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.cpp b/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.cpp index bfe1295e5..5707fee91 100644 --- a/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.cpp +++ b/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -170,6 +172,120 @@ uint32_t c_composer__smart_contract(void* pippenger, return static_cast(buffer.size()); } +size_t c_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf) +{ + auto constraint_system = from_buffer(constraint_system_buf); + // We know that we don't actually need any CRS to create a proving key, so just feed in a nothing. + // Hacky, but, right now it needs *something*. + auto crs_factory = std::make_unique(); + auto composer = create_circuit(constraint_system, std::move(crs_factory)); + auto proving_key = composer.compute_proving_key(); + + // Computing the size of the serialized key is non trivial. We know it's ~331mb. + // Allocate a buffer large enough to hold it, and abort if we overflow. + // This is to keep memory usage down. + size_t total_buf_len = 350 * 1024 * 1024; + auto raw_buf = (uint8_t*)malloc(total_buf_len); + auto raw_buf_end = raw_buf; + write(raw_buf_end, *proving_key); + *pk_buf = raw_buf; + auto len = static_cast(raw_buf_end - raw_buf); + if (len > total_buf_len) { + info("Buffer overflow serializing proving key."); + std::abort(); + } + return len; +} + +size_t c_init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, uint8_t const** vk_buf) +{ + std::shared_ptr crs; + waffle::proving_key_data pk_data; + read(pk_buf, pk_data); + auto proving_key = std::make_shared(std::move(pk_data), crs); + + auto crs_factory = std::make_unique( + reinterpret_cast(pippenger), g2x); + proving_key->reference_string = crs_factory->get_prover_crs(proving_key->n); + + waffle::TurboComposer composer(proving_key, nullptr); + auto verification_key = + waffle::turbo_composer::compute_verification_key(proving_key, crs_factory->get_verifier_crs()); + + // The composer_type has not yet been set. We need to set the composer_type for when we later read in and + // construct the verification key so that we have the correct polynomial manifest + verification_key->composer_type = waffle::ComposerType::TURBO; + + auto buffer = to_buffer(*verification_key); + auto raw_buf = (uint8_t*)malloc(buffer.size()); + memcpy(raw_buf, (void*)buffer.data(), buffer.size()); + *vk_buf = raw_buf; + + return buffer.size(); +} + +size_t c_new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf) +{ + auto constraint_system = from_buffer(constraint_system_buf); + + std::shared_ptr crs; + waffle::proving_key_data pk_data; + read(pk_buf, pk_data); + auto proving_key = std::make_shared(std::move(pk_data), crs); + + auto witness = from_buffer>(witness_buf); + + auto crs_factory = std::make_unique( + reinterpret_cast(pippenger), g2x); + proving_key->reference_string = crs_factory->get_prover_crs(proving_key->n); + + waffle::TurboComposer composer(proving_key, nullptr); + create_circuit_with_witness(composer, constraint_system, witness); + + auto prover = composer.create_prover(); + auto heapProver = new Prover(std::move(prover)); + auto& proof_data = heapProver->construct_proof().proof_data; + *proof_data_buf = proof_data.data(); + + return proof_data.size(); +} + +bool c_verify_proof( + uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length) +{ + bool verified = false; + +#ifndef __wasm__ + try { +#endif + auto constraint_system = from_buffer(constraint_system_buf); + + auto crs = std::make_shared(g2x); + waffle::verification_key_data vk_data; + read(vk_buf, vk_data); + auto verification_key = std::make_shared(std::move(vk_data), crs); + + waffle::TurboComposer composer(nullptr, verification_key); + create_circuit(composer, constraint_system); + waffle::plonk_proof pp = { std::vector(proof, proof + length) }; + + auto verifier = composer.create_verifier(); + + verified = verifier.verify_proof(pp); +#ifndef __wasm__ + } catch (const std::exception& e) { + verified = false; + info(e.what()); + } +#endif + return verified; +} + } // namespace standard_example } // namespace proofs } // namespace rollup \ No newline at end of file diff --git a/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.hpp b/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.hpp index ffcd11f7d..c96ea4589 100644 --- a/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.hpp +++ b/barretenberg/src/aztec/rollup/proofs/standard_example/standard_example.hpp @@ -44,6 +44,18 @@ uint32_t c_composer__smart_contract(void* pippenger, uint8_t const* g2x, uint8_t const* constraint_system_buf, uint8_t** output_buf); + +size_t c_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf); +size_t c_init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, uint8_t const** vk_buf); +size_t c_new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf); +bool c_verify_proof( + uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length); + } // namespace standard_example } // namespace proofs } // namespace rollup \ No newline at end of file diff --git a/barretenberg_wrapper/build.rs b/barretenberg_wrapper/build.rs index 298a3053e..20359fc43 100644 --- a/barretenberg_wrapper/build.rs +++ b/barretenberg_wrapper/build.rs @@ -214,17 +214,17 @@ fn link_lib_omp(toolchain: &'static str) { match toolchain { INTEL_LINUX | ARM_LINUX => { let llvm_dir = find_llvm_linux_path(); - println!("cargo:rustc-link-search={}/lib", llvm_dir) + println!("cargo:rustc-link-search={llvm_dir}/lib") } INTEL_APPLE => { let brew_prefix = find_brew_prefix(); - println!("cargo:rustc-link-search={}/opt/libomp/lib", brew_prefix) + println!("cargo:rustc-link-search={brew_prefix}/opt/libomp/lib") } ARM_APPLE => { let brew_prefix = find_brew_prefix(); - println!("cargo:rustc-link-search={}/opt/libomp/lib", brew_prefix) + println!("cargo:rustc-link-search={brew_prefix}/opt/libomp/lib") } - &_ => unimplemented!("lomp linking of {} is not supported", toolchain), + &_ => unimplemented!("lomp linking of {toolchain} is not supported"), } match toolchain { ARM_LINUX | INTEL_APPLE | ARM_APPLE => { diff --git a/barretenberg_wrapper/src/composer.rs b/barretenberg_wrapper/src/composer.rs index 7d8204be2..16eca2334 100644 --- a/barretenberg_wrapper/src/composer.rs +++ b/barretenberg_wrapper/src/composer.rs @@ -66,3 +66,62 @@ pub unsafe fn verify( proof.len() as u32, ) } + +/// # Safety +/// cs_prt must point to a valid constraints system structure of type standard_format +pub unsafe fn init_proving_key(cs_ptr: &[u8], pk_data_ptr: *mut *mut u8) -> u64 { + let cs_ptr = cs_ptr.as_ptr() as *const u8; + c_init_proving_key(cs_ptr, pk_data_ptr as *const *mut u8 as *mut *const u8) +} + +/// # Safety +/// pippenger must point to a valid Pippenger object +pub unsafe fn init_verification_key( + pippenger: *mut ::std::os::raw::c_void, + g2_ptr: &[u8], + pk_ptr: &[u8], + vk_data_ptr: *mut *mut u8, +) -> u64 { + c_init_verification_key( + pippenger, + g2_ptr.as_ptr() as *const u8, + pk_ptr.as_ptr() as *const u8, + vk_data_ptr as *const *mut u8 as *mut *const u8, + ) +} + +/// # Safety +/// pippenger must point to a valid Pippenger object +pub unsafe fn create_proof_with_pk( + pippenger: *mut ::std::os::raw::c_void, + g2_ptr: &[u8], + pk_ptr: &[u8], + cs_ptr: &[u8], + witness_ptr: &[u8], + proof_data_ptr: *mut *mut u8, +) -> u64 { + let cs_ptr = cs_ptr.as_ptr() as *const u8; + let pk_ptr = pk_ptr.as_ptr() as *const u8; + c_new_proof( + pippenger, + g2_ptr.as_ptr() as *const u8, + pk_ptr, + cs_ptr, + witness_ptr.as_ptr() as *const u8, + proof_data_ptr as *const *mut u8 as *mut *mut u8, + ) +} + +/// # Safety +/// cs_prt must point to a valid constraints system structure of type standard_format +pub unsafe fn verify_with_vk(g2_ptr: &[u8], vk_ptr: &[u8], cs_ptr: &[u8], proof: &[u8]) -> bool { + let proof_ptr = proof.as_ptr() as *const u8; + + c_verify_proof( + g2_ptr.as_ptr() as *const u8, + vk_ptr.as_ptr() as *const u8, + cs_ptr.as_ptr() as *const u8, + proof_ptr as *mut u8, + proof.len() as u32, + ) +}