diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index a148d2117bb..f2dee5b9055 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -115,12 +115,13 @@ std::string to_json(std::vector& data) return format("[", join(map(data, [](auto fr) { return format("\"", fr, "\""); })), "]"); } -std::string vk_to_json(std::vector& data) +std::string vk_to_json(std::vector const& data) { // We need to move vk_hash to the front... - std::rotate(data.begin(), data.end() - 1, data.end()); + std::vector rotated(data.begin(), data.end() - 1); + rotated.insert(rotated.begin(), data.at(data.size() - 1)); - return format("[", join(map(data, [](auto fr) { return format("\"", fr, "\""); })), "]"); + return format("[", join(map(rotated, [](auto fr) { return format("\"", fr, "\""); })), "]"); } std::string honk_vk_to_json(std::vector& data) @@ -950,18 +951,25 @@ void avm_prove(const std::filesystem::path& bytecode_path, auto const [verification_key, proof] = AVM_TRACK_TIME_V("prove/all", avm_trace::Execution::prove(bytecode, calldata, public_inputs_vec, avm_hints)); - // TODO(ilyas): <#4887>: Currently we only need these two parts of the vk, look into pcs_verification key reqs - std::vector vk_vector = { verification_key.circuit_size, verification_key.num_public_inputs }; - std::vector vk_as_fields = { verification_key.circuit_size, verification_key.num_public_inputs }; - std::string vk_json = vk_to_json(vk_as_fields); + std::vector vk_as_fields = { fr(verification_key.circuit_size), fr(verification_key.num_public_inputs) }; + + for (auto const& comm : verification_key.get_all()) { + std::vector comm_as_fields = field_conversion::convert_to_bn254_frs(comm); + vk_as_fields.insert(vk_as_fields.end(), comm_as_fields.begin(), comm_as_fields.end()); + } + + vinfo("vk fields size: ", vk_as_fields.size()); + vinfo("circuit size: ", vk_as_fields[0]); + vinfo("num of pub inputs: ", vk_as_fields[1]); + std::string vk_json = to_json(vk_as_fields); const auto proof_path = output_path / "proof"; const auto vk_path = output_path / "vk"; const auto vk_fields_path = output_path / "vk_fields.json"; write_file(proof_path, to_buffer(proof)); vinfo("proof written to: ", proof_path); - write_file(vk_path, to_buffer(vk_vector)); + write_file(vk_path, to_buffer(vk_as_fields)); vinfo("vk written to: ", vk_path); write_file(vk_fields_path, { vk_json.begin(), vk_json.end() }); vinfo("vk as fields written to: ", vk_fields_path); @@ -988,11 +996,34 @@ void avm_prove(const std::filesystem::path& bytecode_path, */ bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& vk_path) { + using Commitment = AvmFlavorSettings::Commitment; std::vector const proof = many_from_buffer(read_file(proof_path)); std::vector vk_bytes = read_file(vk_path); - auto circuit_size = from_buffer(vk_bytes, 0); - auto num_public_inputs = from_buffer(vk_bytes, sizeof(size_t)); - auto vk = AvmFlavor::VerificationKey(circuit_size, num_public_inputs); + std::vector vk_as_fields = many_from_buffer(vk_bytes); + + vinfo("initializing crs with size: ", 1); + init_bn254_crs(1); + + auto circuit_size = uint64_t(vk_as_fields[0]); + auto num_public_inputs = uint64_t(vk_as_fields[1]); + std::span vk_span(vk_as_fields); + + vinfo("vk fields size: ", vk_as_fields.size()); + vinfo("circuit size: ", circuit_size); + vinfo("num of pub inputs: ", num_public_inputs); + + // Each commitment (precomputed entity) is represented as 2 Fq field elements. + // Each Fq element is split into two limbs of Fr elements. + // We therefore need 2 (circuit_size, num_public_inputs) + 4 * NUM_PRECOMPUTED_ENTITIES fr elements. + ASSERT(vk_as_fields.size() == 4 * AvmFlavor::NUM_PRECOMPUTED_ENTITIES + 2); + + std::array precomputed_cmts; + for (size_t i = 0; i < AvmFlavor::NUM_PRECOMPUTED_ENTITIES; i++) { + // Start at offset 2 and adds 4 fr elements per commitment. Therefore, index = 4 * i + 2. + precomputed_cmts[i] = field_conversion::convert_from_bn254_frs(vk_span.subspan(4 * i + 2, 4)); + } + + auto vk = AvmFlavor::VerificationKey(circuit_size, num_public_inputs, precomputed_cmts); const bool verified = AVM_TRACK_TIME_V("verify/all", avm_trace::Execution::verify(vk, proof)); vinfo("verified: ", verified); diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp index 42ce7e2c30e..d0938f30602 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp @@ -13,12 +13,12 @@ using namespace bb::srs::factories; class MemVerifierCrs : public VerifierCrs { public: - MemVerifierCrs(g2::affine_element const& g2_point) - : g2_x(g2_point) + MemVerifierCrs(g2::affine_element g2_point, g1::affine_element const& g1_identity) + : g1_identityx(g1_identity) + , g2_x(std::move(g2_point)) , precomputed_g2_lines( static_cast(aligned_alloc(64, sizeof(bb::pairing::miller_lines) * 2))) { - bb::pairing::precompute_miller_lines(bb::g2::one, precomputed_g2_lines[0]); bb::pairing::precompute_miller_lines(g2_x, precomputed_g2_lines[1]); } @@ -43,8 +43,14 @@ namespace bb::srs::factories { MemBn254CrsFactory::MemBn254CrsFactory(std::vector const& points, g2::affine_element const& g2_point) : prover_crs_(std::make_shared>(points)) - , verifier_crs_(std::make_shared(g2_point)) -{} +{ + auto g1_identity = g1::affine_element(); + if (!points.empty()) { + g1_identity = points[0]; + } + + verifier_crs_ = std::make_shared(g2_point, g1_identity); +} std::shared_ptr> MemBn254CrsFactory::get_prover_crs(size_t) { diff --git a/barretenberg/cpp/src/barretenberg/srs/io.hpp b/barretenberg/cpp/src/barretenberg/srs/io.hpp index 24397f47608..893f5bdd443 100644 --- a/barretenberg/cpp/src/barretenberg/srs/io.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/io.hpp @@ -285,7 +285,11 @@ template class IO { size_t num_read = 0; std::string path = get_transcript_path(dir, num); - while (is_file_exist(path) && num_read < degree) { + if (!is_file_exist(path)) { + throw_or_abort(format("File path for transcript g1 ", path, " is invalid.")); + } + + while (num_read < degree) { Manifest manifest; read_manifest(path, manifest); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/composer.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/composer.cpp index dbbb2736140..baaebcea2f7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/composer.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/composer.cpp @@ -39,14 +39,7 @@ AvmProver AvmComposer::create_prover(CircuitConstructor& circuit_constructor) AvmVerifier AvmComposer::create_verifier(CircuitConstructor& circuit_constructor) { auto verification_key = compute_verification_key(circuit_constructor); - - AvmVerifier output_state(verification_key); - - auto pcs_verification_key = std::make_unique(); - - output_state.pcs_verification_key = std::move(pcs_verification_key); - - return output_state; + return AvmVerifier(std::move(verification_key)); } std::shared_ptr AvmComposer::compute_proving_key(CircuitConstructor& circuit_constructor) @@ -76,8 +69,7 @@ std::shared_ptr AvmComposer::compute_verification_key(C compute_proving_key(circuit_constructor); } - verification_key = - std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); + verification_key = std::make_shared(proving_key); return verification_key; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp index 0e7bb68207b..da57edf4b8d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp @@ -308,7 +308,30 @@ class AvmFlavor { auto get_to_be_shifted() { return AvmFlavor::get_to_be_shifted(*this); } }; - using VerificationKey = VerificationKey_, VerifierCommitmentKey>; + // Note(md): required for instantiation from the proving key - im sure there are other ways to construct this + class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { + public: + VerificationKey() = default; + + VerificationKey(const std::shared_ptr& proving_key) + : VerificationKey_(proving_key->circuit_size, proving_key->num_public_inputs) + { + for (auto [polynomial, commitment] : + zip_view(proving_key->get_precomputed_polynomials(), this->get_all())) { + commitment = proving_key->commitment_key->commit(polynomial); + } + } + + VerificationKey(const size_t circuit_size, + const size_t num_public_inputs, + std::array const& precomputed_cmts) + : VerificationKey_(circuit_size, num_public_inputs) + { + for (auto [vk_cmt, cmt] : zip_view(this->get_all(), precomputed_cmts)) { + vk_cmt = cmt; + } + } + }; class AllValues : public AllEntities { public: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp index d452c718c44..cde64c811e4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp @@ -10,7 +10,7 @@ namespace bb { AvmVerifier::AvmVerifier(std::shared_ptr verifier_key) - : key(verifier_key) + : key(std::move(verifier_key)) {} AvmVerifier::AvmVerifier(AvmVerifier&& other) noexcept @@ -21,7 +21,7 @@ AvmVerifier::AvmVerifier(AvmVerifier&& other) noexcept AvmVerifier& AvmVerifier::operator=(AvmVerifier&& other) noexcept { key = other.key; - pcs_verification_key = (std::move(other.pcs_verification_key)); + pcs_verification_key = other.pcs_verification_key; commitments.clear(); return *this; } @@ -53,9 +53,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, using Flavor = AvmFlavor; using FF = Flavor::FF; using Commitment = Flavor::Commitment; - // using PCS = Flavor::PCS; - // using Curve = Flavor::Curve; - // using ZeroMorph = ZeroMorphVerifier_; + using PCS = Flavor::PCS; + using Curve = Flavor::Curve; + using ZeroMorph = ZeroMorphVerifier_; using VerifierCommitments = Flavor::VerifierCommitments; using CommitmentLabels = Flavor::CommitmentLabels; @@ -138,20 +138,19 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - // NOTE: temporarily disabled - facing integration issues - // auto opening_claim = ZeroMorph::verify(circuit_size, - // commitments.get_unshifted(), - // commitments.get_to_be_shifted(), - // claimed_evaluations.get_unshifted(), - // claimed_evaluations.get_shifted(), - // multivariate_challenge, - // pcs_verification_key->get_g1_identity(), - // transcript); - - // auto pairing_points = PCS::reduce_verify(opening_claim, transcript); - // auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - // return sumcheck_verified.value() && verified; - return sumcheck_verified.value(); + + auto opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + pcs_verification_key.get_g1_identity(), + transcript); + + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); + auto verified = pcs_verification_key.pairing_check(pairing_points[0], pairing_points[1]); + return sumcheck_verified.value() && verified; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.hpp index 72317356217..09569deff31 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.hpp @@ -27,7 +27,7 @@ class AvmVerifier { std::shared_ptr key; std::map commitments; - std::shared_ptr pcs_verification_key; + VerifierCommitmentKey pcs_verification_key; std::shared_ptr transcript; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 1606df51a8d..36e0aba65a3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -325,13 +325,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) { - auto verification_key = std::make_shared(vk); - AvmVerifier verifier(verification_key); - - // todo: not needed for now until we verify the PCS/pairing of the proof - // auto pcs_verification_key = std::make_unique(verification_key->circuit_size, - // crs_factory_); - // output_state.pcs_verification_key = std::move(pcs_verification_key); + AvmVerifier verifier(std::make_shared(vk)); // Proof structure: public_inputs | calldata_size | calldata | returndata_size | returndata | raw proof std::vector public_inputs_vec; diff --git a/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs index 0633cd7e532..f4776a7121e 100644 --- a/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs @@ -39,14 +39,7 @@ void {{name}}Composer::compute_witness(CircuitConstructor& circuit) {{name}}Verifier {{name}}Composer::create_verifier(CircuitConstructor& circuit_constructor) { auto verification_key = compute_verification_key(circuit_constructor); - - {{name}}Verifier output_state(verification_key); - - auto pcs_verification_key = std::make_unique(); - - output_state.pcs_verification_key = std::move(pcs_verification_key); - - return output_state; + return {{name}}Verifier(std::move(verification_key)); } std::shared_ptr {{name}}Composer::compute_proving_key(CircuitConstructor& circuit_constructor) @@ -76,8 +69,7 @@ std::shared_ptr {{name}}Composer::compute_verification_ compute_proving_key(circuit_constructor); } - verification_key = - std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); + verification_key = std::make_shared(proving_key); return verification_key; } diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs index 8318a084de8..416257d5dcd 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs @@ -164,7 +164,30 @@ class {{name}}Flavor { } }; - using VerificationKey = VerificationKey_, VerifierCommitmentKey>; + // Note(md): required for instantiation from the proving key - im sure there are other ways to construct this + class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { + public: + VerificationKey() = default; + + VerificationKey(const std::shared_ptr& proving_key) + : VerificationKey_(proving_key->circuit_size, proving_key->num_public_inputs) + { + for (auto [polynomial, commitment] : + zip_view(proving_key->get_precomputed_polynomials(), this->get_all())) { + commitment = proving_key->commitment_key->commit(polynomial); + } + } + + VerificationKey(const size_t circuit_size, + const size_t num_public_inputs, + std::array const& precomputed_cmts) + : VerificationKey_(circuit_size, num_public_inputs) + { + for (auto [vk_cmt, cmt] : zip_view(this->get_all(), precomputed_cmts)) { + vk_cmt = cmt; + } + } + }; {{!-- Used by sumcheck --}} class AllValues : public AllEntities { diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs index 57910fa1adb..9fa328e47b2 100644 --- a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs @@ -10,7 +10,7 @@ namespace bb { {{name}}Verifier::{{name}}Verifier(std::shared_ptr verifier_key) - : key(verifier_key) + : key(std::move(verifier_key)) {} {{name}}Verifier::{{name}}Verifier({{name}}Verifier&& other) noexcept @@ -21,7 +21,7 @@ namespace bb { {{name}}Verifier& {{name}}Verifier::operator=({{name}}Verifier&& other) noexcept { key = other.key; - pcs_verification_key = (std::move(other.pcs_verification_key)); + pcs_verification_key = other.pcs_verification_key; commitments.clear(); return *this; } @@ -52,9 +52,9 @@ bool {{name}}Verifier::verify_proof(const HonkProof& proof, [[maybe_unused]] con using Flavor = {{name}}Flavor; using FF = Flavor::FF; using Commitment = Flavor::Commitment; - // using PCS = Flavor::PCS; - // using Curve = Flavor::Curve; - // using ZeroMorph = ZeroMorphVerifier_; + using PCS = Flavor::PCS; + using Curve = Flavor::Curve; + using ZeroMorph = ZeroMorphVerifier_; using VerifierCommitments = Flavor::VerifierCommitments; using CommitmentLabels = Flavor::CommitmentLabels; @@ -117,20 +117,19 @@ bool {{name}}Verifier::verify_proof(const HonkProof& proof, [[maybe_unused]] con // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - // NOTE: temporarily disabled - facing integration issues - // auto opening_claim = ZeroMorph::verify(circuit_size, - // commitments.get_unshifted(), - // commitments.get_to_be_shifted(), - // claimed_evaluations.get_unshifted(), - // claimed_evaluations.get_shifted(), - // multivariate_challenge, - // pcs_verification_key->get_g1_identity(), - // transcript); - - // auto pairing_points = PCS::reduce_verify(opening_claim, transcript); - // auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - // return sumcheck_verified.value() && verified; - return sumcheck_verified.value(); + + auto opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + pcs_verification_key.get_g1_identity(), + transcript); + + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); + auto verified = pcs_verification_key.pairing_check(pairing_points[0], pairing_points[1]); + return sumcheck_verified.value() && verified; } } // namespace bb diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs index b20fc9ecf2e..05514fbb9e4 100644 --- a/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs @@ -27,7 +27,7 @@ class {{name}}Verifier { std::shared_ptr key; std::map commitments; - std::shared_ptr pcs_verification_key; + VerifierCommitmentKey pcs_verification_key; std::shared_ptr transcript; }; diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 4cf5b70dded..28a5122618c 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -282,7 +282,15 @@ const proveAndVerifyAvmTestContract = async ( // Then we test VK extraction. const succeededRes = proofRes as BBSuccess; const verificationKey = await extractVkData(succeededRes.vkPath!); - expect(verificationKey.keyAsBytes).toHaveLength(16); + + // VK is composed of + // - circuit size encoded as a fr field element (32 bytes) + // - num of inputs encoded as a fr field element (32 bytes) + // - 16 affine elements (curve base field fq) encoded as fr elements takes (16 * 4 * 32 bytes) + // 16 above refers to the constant AvmFlavor::NUM_PRECOMPUTED_ENTITIES + // Total number of bytes = 2112 + const NUM_PRECOMPUTED_ENTITIES = 16; + expect(verificationKey.keyAsBytes).toHaveLength(NUM_PRECOMPUTED_ENTITIES * 4 * 32 + 2 * 32); // Then we verify. const rawVkPath = path.join(succeededRes.vkPath!, 'vk');