diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.cpp index 4dec56ca8dbc..fb257d9ec073 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.cpp @@ -160,7 +160,7 @@ template void Instance_::construct_ecc_op_wire_poly { std::array op_wire_polynomials; for (auto& poly : op_wire_polynomials) { - poly = polynomial(dyadic_circuit_size); + poly = static_cast(dyadic_circuit_size); } // The ECC op wires are constructed to contain the op data on the appropriate range and to vanish everywhere else. diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.hpp index a2230df10bb2..fc9b9582dcf0 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/instance.hpp @@ -2,22 +2,25 @@ #include "barretenberg/honk/flavor/goblin_ultra.hpp" #include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/honk/flavor/ultra_grumpkin.hpp" +#include "barretenberg/honk/proof_system/folding_result.hpp" #include "barretenberg/proof_system/composer/composer_lib.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" #include "barretenberg/proof_system/relations/relation_parameters.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" - #include #include #include #include namespace proof_system::honk { -// Need verifier instance as well -// An Instance is created from a Circuit and we ini tialise all the data structure that rely on information from a -// circuit Then a Prover and a Verifier is created from an Instance or several instances and each manages their own -// polynomials -// The responsability of a Prover is to commit, add to transcript while the Instance manages its polynomials -// TODO: we might wanna have a specialisaition of the Instance class for the Accumulator +/** + * @brief An Instance is normally constructed from a finalised circuit and it's role is to compute all the polynomials + * involved in creating a proof and, if requested, the verification key. + * In case of folded Instance, this will be created from the FoldingResult, the aggregated work from the folding prover + * and verifier. More specifically, a folded instance will be constructed from the complete set of folded polynomials + * and folded public inputs and its FoldingParams are expected to be non-zero + * + */ + template class Instance_ { public: using Circuit = typename Flavor::CircuitBuilder; @@ -39,9 +42,8 @@ template class Instance_ { ProverPolynomials prover_polynomials; - // After instances have been folded, the pub_inputs_offset will become irrelevant as it's used for computing the 4th - // wire polynomial and a folded instance does not care about wires anymore. - // Furthermore, folding limits us to having the same number of public inputs. + // The number of public inputs has to be the same for all instances because they are + // folded element by element. std::vector public_inputs; size_t pub_inputs_offset; @@ -68,11 +70,11 @@ template class Instance_ { compute_witness(circuit); } - Instance_(ProverPolynomials polys, std::vector public_inputs, std::shared_ptr vk) - : verification_key(std::move(vk)) - , prover_polynomials(polys) - , public_inputs(public_inputs) - {} + Instance_(FoldingResult result) + : verification_key(std::move(result.verification_key)) + , prover_polynomials(result.folded_prover_polynomials) + , public_inputs(result.folded_public_inputs) + , folding_params(result.params){}; Instance_(Instance_&& other) noexcept = default; Instance_(Instance_ const& other) noexcept = default; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/verifier_instance.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/instance/verifier_instance.cpp deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp index a504a515566c..95e5032bd8bb 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp @@ -14,9 +14,24 @@ template struct VerifierFoldingResult { using FF = typename Flavor::FF; using VerificationKey = typename Flavor::VerificationKey; using FoldingParameters = typename Flavor::FoldingParameters; - // TODO: what happens to the public input offsets std::vector folded_public_inputs; - VerificationKey verification_key; + VerificationKey folded_verification_key; + FoldingParameters parameters; +}; + +/** + * @brief The aggregated result from the prover and verifier after a round of folding, used to create a new Instance. + * + * @tparam Flavor + */ +template struct FoldingResult { + using FF = typename Flavor::FF; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using VerificationKey = typename Flavor::VerificationKey; + using FoldingParameters = typename Flavor::FoldingParameters; + ProverPolynomials folded_prover_polynomials; + std::vector folded_public_inputs; + std::shared_ptr verification_key; FoldingParameters params; }; } // namespace proof_system::honk \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp index ba70a46d0ed8..1fdaa03d308d 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp @@ -6,10 +6,12 @@ ProtoGalaxyProver_::ProtoGalaxyProver_(std::vector void ProtoGalaxyProver_::prepare_for_folding() { for (const auto& instance : instances) { @@ -21,21 +23,30 @@ template void ProtoGalaxyProver_::prepare_for_foldi transcript.send_to_verifier(instance_index + "_circuit_size", circuit_size); transcript.send_to_verifier(instance_index + "_public_input_size", num_public_inputs); - // transcript.send_to_verifier(instance_index + "_pub_inputs_offset", - // static_cast(instance.pub_inputs_offset)); + transcript.send_to_verifier(instance_index + "_pub_inputs_offset", + static_cast(instance->pub_inputs_offset)); for (size_t i = 0; i < instance->proving_key->num_public_inputs; ++i) { auto public_input_i = instance->public_inputs[i]; transcript.send_to_verifier(instance_index + "_public_input_" + std::to_string(i), public_input_i); } - auto eta = transcript.get_challenge(instance_index + "_eta"); + auto [eta, beta, gamma] = + transcript.get_challenges(instance_index + "_eta", instance_index + "_beta", instance_index + "_gamma"); instance->compute_sorted_accumulator_polynomials(eta); - auto [beta, gamma] = transcript.get_challenges(instance_index + "_beta", instance_index + "_gamma"); instance->compute_grand_product_polynomials(beta, gamma); } } +// TODO(#689): implement this function +template ProverFoldingResult ProtoGalaxyProver_::fold_instances() +{ + prepare_for_folding(); + ProverFoldingResult res; + res.folding_data = transcript.proof_data; + return res; +} + template class ProtoGalaxyProver_; template class ProtoGalaxyProver_; template class ProtoGalaxyProver_; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp index ca0507df274c..315598f0c068 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp @@ -26,11 +26,10 @@ VerifierFoldingResult ProtoGalaxyVerifier_::fold_public_paramete for (size_t i = 0; i < inst.public_input_size; ++i) { auto public_input_i = - transcript.template receive_from_prover(idx + "public_input_" + std::to_string(i)); + transcript.template receive_from_prover(idx + "_public_input_" + std::to_string(i)); inst.public_inputs.emplace_back(public_input_i); } - auto eta = transcript.get_challenge(idx + "_eta"); - auto [beta, gamma] = transcript.get_challenges(idx + "_beta", idx + "_gamma"); + auto [eta, beta, gamma] = transcript.get_challenges(idx + "_eta", idx + "_beta", idx + "_gamma"); const FF public_input_delta = compute_public_input_delta( inst.public_inputs, beta, gamma, inst.circuit_size, inst.pub_inputs_offset); const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, inst.circuit_size); @@ -38,6 +37,8 @@ VerifierFoldingResult ProtoGalaxyVerifier_::fold_public_paramete RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; verifier_instances.emplace_back(inst); } + + // TODO(#722): implement the Protogalaxy verifier logic VerifierFoldingResult res; return res; } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp index 0690bbff4814..50d3f1f11a55 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp @@ -30,7 +30,6 @@ template class UltraProver_ { void execute_wire_commitments_round(); void execute_sorted_list_accumulator_round(); void execute_grand_product_computation_round(); - void execute_commitment_finalisation_round(); void execute_relation_check_rounds(); void execute_univariatization_round(); void execute_pcs_evaluation_round(); @@ -60,7 +59,6 @@ template class UltraProver_ { Instance& instance; - // this should be ProverOutput sumcheck::SumcheckOutput sumcheck_output; pcs::gemini::ProverOutput gemini_output; pcs::shplonk::ProverOutput shplonk_output; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp index 586ac1bc4c2e..0c8ce6d72b22 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp @@ -28,7 +28,7 @@ template UltraVerifier_& UltraVerifier_::opera } /** - * @brief This function verifies an Ultra Honk proof for given program settings. + * @brief This function verifies an Ultra Honk proof for a given Flavor. * */ template bool UltraVerifier_::verify_proof(const plonk::proof& proof) @@ -68,8 +68,6 @@ template bool UltraVerifier_::verify_proof(const plonk public_inputs.emplace_back(public_input_i); } - // up to here in the folding verifier as well - // Get commitments to first three wire polynomials commitments.w_l = transcript.template receive_from_prover(commitment_labels.w_l); commitments.w_r = transcript.template receive_from_prover(commitment_labels.w_r); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp index ca36c393bdef..4b99ce00b56b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp @@ -130,8 +130,9 @@ template class BaseTranscript { public: /** - * @brief After all the prover messages have been sent, finalize the round by hashing all the data, create the field - * elements and reset the state in preparation for the next round. + * @brief After all the prover messages have been sent, finalize the round by hashing all the data and then create + * the number of requested challenges which will be increasing powers of the first challenge. Finally, reset the + * state in preparation for the next round. * * @param labels human-readable names for the challenges for the manifest * @return std::array challenges for this round. @@ -139,10 +140,6 @@ template class BaseTranscript { template std::array get_challenges(const Strings&... labels) { constexpr size_t num_challenges = sizeof...(Strings); - constexpr size_t bytes_per_challenge = HASH_OUTPUT_SIZE / num_challenges; - - // Ensure we have enough entropy from the hash function to construct each challenge. - static_assert(bytes_per_challenge >= MIN_BYTES_PER_CHALLENGE, "requested too many challenges in this round"); // Add challenge labels for current round to the manifest manifest.add_challenge(round_number, labels...); @@ -152,17 +149,16 @@ template class BaseTranscript { // Create challenges from bytes. std::array challenges{}; - for (size_t i = 0; i < num_challenges; ++i) { - // Initialize the buffer for the i-th challenge with 0s. - std::array field_element_buffer{}; - // Copy the i-th chunk of size `bytes_per_challenge` to the start of `field_element_buffer` - // The last bytes will be 0, - std::copy_n(next_challenge_buffer.begin() + i * bytes_per_challenge, - bytes_per_challenge, - field_element_buffer.begin()); - - // Create a FF element from a slice of bytes of next_challenge_buffer. - challenges[i] = from_buffer(field_element_buffer); + + std::array field_element_buffer{}; + std::copy_n(next_challenge_buffer.begin(), HASH_OUTPUT_SIZE, field_element_buffer.begin()); + + challenges[0] = from_buffer(field_element_buffer); + + // TODO(#583): rework the transcript to have a better structure and be able to produce a variable amount of + // challenges that are not powers of each other + for (size_t i = 1; i < num_challenges; i++) { + challenges[i] = challenges[i - 1] * challenges[0]; } // Prepare for next round. diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp index 4eca5f051259..732e56797d90 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp @@ -11,16 +11,25 @@ using namespace proof_system::honk; template class TranscriptTests : public testing::Test { - public: + protected: + // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. + virtual void SetUp() + { + if constexpr (IsGrumpkinFlavor) { + barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } else { + barretenberg::srs::init_crs_factory("../srs_db/ignition"); + } + }; + using FF = typename Flavor::FF; - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } /** * @brief Construct a manifest for a standard Honk proof * - * @details This is where we define the "Manifest" for a Standard Honk proof. The tests in this suite are intented - * to warn the developer if the Prover/Verifier has deviated from this manifest, however, the Transcript class is - * not otherwise contrained to follow the manifest. + * @details This is where we define the "Manifest" for a Standard Honk proof. The tests in this suite are + * intented to warn the developer if the Prover/Verifier has deviated from this manifest, however, the + * Transcript class is not otherwise contrained to follow the manifest. * * @note Entries in the manifest consist of a name string and a size (bytes), NOT actual data. * @@ -282,17 +291,16 @@ TYPED_TEST(TranscriptTests, VerifierMistake) * construction and the one generated by the verifier over the course of proof verification. * */ -// TODO(Mara): This is not a typed test and we should have a construct_ultra_honk_manifest as well. -TYPED_TEST(TranscriptTests, UltraVerifierManifestConsistency) +TEST(TranscriptTests, UltraVerifierManifestConsistency) { + barretenberg::srs::init_crs_factory("../srs_db/ignition"); + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) auto circuit_constructor = proof_system::UltraCircuitBuilder(); - // fr a = 2; - // circuit_constructor.add_variable(a); - // circuit_constructor.add_public_variable(a); - - circuit_constructor.add_gates_to_ensure_all_polys_are_non_zero(); + fr a = 2; + circuit_constructor.add_variable(a); + circuit_constructor.add_public_variable(a); // Automatically generate a transcript manifest in the prover by constructing a proof auto composer = UltraComposer(); @@ -317,3 +325,48 @@ TYPED_TEST(TranscriptTests, UltraVerifierManifestConsistency) << "Prover/Verifier manifest discrepency in round " << round; } } + +TEST(TranscriptTests, FoldingManifestTest) +{ + barretenberg::srs::init_crs_factory("../srs_db/ignition"); + + auto builder_one = proof_system::UltraCircuitBuilder(); + fr a = 2; + fr b = 3; + builder_one.add_variable(a); + builder_one.add_public_variable(a); + builder_one.add_public_variable(b); + + auto builder_two = proof_system::UltraCircuitBuilder(); + a = 3; + b = 4; + builder_two.add_variable(a); + builder_two.add_variable(b); + builder_two.add_public_variable(a); + builder_two.add_public_variable(b); + + auto composer = UltraComposer(); + auto instance_one = composer.create_instance(builder_one); + auto instance_two = composer.create_instance(builder_two); + + std::vector> insts; + insts.emplace_back(std::make_shared(instance_one)); + insts.emplace_back(std::make_shared(instance_two)); + auto prover = composer.create_folding_prover(insts); + auto verifier = composer.create_folding_verifier(insts); + + auto prover_res = prover.fold_instances(); + verifier.fold_public_parameters(prover_res.folding_data); + + prover.transcript.print(); + verifier.transcript.print(); + + // Check consistency between the manifests generated by the prover and verifier + auto prover_manifest = prover.transcript.get_manifest(); + auto verifier_manifest = verifier.transcript.get_manifest(); + + for (size_t round = 0; round < prover_manifest.size(); ++round) { + ASSERT_EQ(prover_manifest[round], verifier_manifest[round]) + << "Prover/Verifier manifest discrepency in round " << round; + } +}