diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/ecc_vm.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/ecc_vm.hpp index 3e966d8c833..3bb83245049 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/ecc_vm.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/ecc_vm.hpp @@ -848,7 +848,7 @@ template class ECCVMBa public: VerifierCommitments(const std::shared_ptr& verification_key, - const VerifierTranscript& transcript) + [[maybe_unused]] const BaseTranscript& transcript) { static_cast(transcript); Base::lagrange_first = verification_key->lagrange_first; @@ -856,6 +856,424 @@ template class ECCVMBa Base::lagrange_last = verification_key->lagrange_last; } }; + + /** + * @brief Derived class that defines proof structure for ECCVM proofs, as well as supporting functions. + * + */ + class Transcript : public BaseTranscript { + public: + uint32_t circuit_size; + Commitment transcript_add_comm; + Commitment transcript_mul_comm; + Commitment transcript_eq_comm; + Commitment transcript_collision_check_comm; + Commitment transcript_msm_transition_comm; + Commitment transcript_pc_comm; + Commitment transcript_msm_count_comm; + Commitment transcript_x_comm; + Commitment transcript_y_comm; + Commitment transcript_z1_comm; + Commitment transcript_z2_comm; + Commitment transcript_z1zero_comm; + Commitment transcript_z2zero_comm; + Commitment transcript_op_comm; + Commitment transcript_accumulator_x_comm; + Commitment transcript_accumulator_y_comm; + Commitment transcript_msm_x_comm; + Commitment transcript_msm_y_comm; + Commitment precompute_pc_comm; + Commitment precompute_point_transition_comm; + Commitment precompute_round_comm; + Commitment precompute_scalar_sum_comm; + Commitment precompute_s1hi_comm; + Commitment precompute_s1lo_comm; + Commitment precompute_s2hi_comm; + Commitment precompute_s2lo_comm; + Commitment precompute_s3hi_comm; + Commitment precompute_s3lo_comm; + Commitment precompute_s4hi_comm; + Commitment precompute_s4lo_comm; + Commitment precompute_skew_comm; + Commitment precompute_dx_comm; + Commitment precompute_dy_comm; + Commitment precompute_tx_comm; + Commitment precompute_ty_comm; + Commitment msm_transition_comm; + Commitment msm_add_comm; + Commitment msm_double_comm; + Commitment msm_skew_comm; + Commitment msm_accumulator_x_comm; + Commitment msm_accumulator_y_comm; + Commitment msm_pc_comm; + Commitment msm_size_of_msm_comm; + Commitment msm_count_comm; + Commitment msm_round_comm; + Commitment msm_add1_comm; + Commitment msm_add2_comm; + Commitment msm_add3_comm; + Commitment msm_add4_comm; + Commitment msm_x1_comm; + Commitment msm_y1_comm; + Commitment msm_x2_comm; + Commitment msm_y2_comm; + Commitment msm_x3_comm; + Commitment msm_y3_comm; + Commitment msm_x4_comm; + Commitment msm_y4_comm; + Commitment msm_collision_x1_comm; + Commitment msm_collision_x2_comm; + Commitment msm_collision_x3_comm; + Commitment msm_collision_x4_comm; + Commitment msm_lambda1_comm; + Commitment msm_lambda2_comm; + Commitment msm_lambda3_comm; + Commitment msm_lambda4_comm; + Commitment msm_slice1_comm; + Commitment msm_slice2_comm; + Commitment msm_slice3_comm; + Commitment msm_slice4_comm; + Commitment transcript_accumulator_empty_comm; + Commitment transcript_reset_accumulator_comm; + Commitment precompute_select_comm; + Commitment lookup_read_counts_0_comm; + Commitment lookup_read_counts_1_comm; + Commitment z_perm_comm; + Commitment lookup_inverses_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector gemini_univariate_comms; + std::vector gemini_a_evals; + Commitment shplonk_q_comm; + Commitment kzg_w_comm; + // the rest are only for Grumpkin + uint64_t ipa_poly_degree; + std::vector ipa_l_comms; + std::vector ipa_r_comms; + FF ipa_a_0_eval; + + Transcript() = default; + + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + + void deserialize_full_transcript() override + { + // take current proof and put them into the struct + size_t num_bytes_read = 0; + circuit_size = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + size_t log_n = numeric::get_msb(circuit_size); + transcript_add_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_mul_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_eq_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_collision_check_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_msm_transition_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_pc_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_msm_count_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_x_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_y_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_z1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_z2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_z1zero_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_z2zero_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_op_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_accumulator_x_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_accumulator_y_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_msm_x_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_msm_y_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_pc_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_point_transition_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_round_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_scalar_sum_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s1hi_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s1lo_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s2hi_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s2lo_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s3hi_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s3lo_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s4hi_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_s4lo_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_skew_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_dx_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_dy_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_tx_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_ty_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_transition_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_add_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_double_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_skew_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_accumulator_x_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_accumulator_y_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_pc_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_size_of_msm_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_count_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_round_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_add1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_add2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_add3_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_add4_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_x1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_y1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_x2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_y2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_x3_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_y3_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_x4_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_y4_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_collision_x1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_collision_x2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_collision_x3_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_collision_x4_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_lambda1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_lambda2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_lambda3_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_lambda4_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_slice1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_slice2_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_slice3_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + msm_slice4_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_accumulator_empty_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + transcript_reset_accumulator_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + precompute_select_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + lookup_read_counts_0_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + lookup_read_counts_1_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + lookup_inverses_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + z_perm_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.emplace_back(BaseTranscript::template deserialize_from_buffer< + barretenberg::Univariate>( + BaseTranscript::proof_data, num_bytes_read)); + } + sumcheck_evaluations = + BaseTranscript::template deserialize_from_buffer>( + BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < log_n - 1; ++i) { + gemini_univariate_comms.emplace_back(BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read)); + } + for (size_t i = 0; i < log_n; ++i) { + gemini_a_evals.emplace_back(BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read)); + } + shplonk_q_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + if (std::is_same>::value) { + kzg_w_comm = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + } else if (std::is_same>::value) { + ipa_poly_degree = BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read); + auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); + for (size_t i = 0; i < log_poly_degree; ++i) { + ipa_l_comms.emplace_back(BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read)); + ipa_r_comms.emplace_back(BaseTranscript::template deserialize_from_buffer( + BaseTranscript::proof_data, num_bytes_read)); + } + ipa_a_0_eval = BaseTranscript::template deserialize_from_buffer(BaseTranscript::proof_data, + num_bytes_read); + } else { + throw_or_abort("Unsupported PCS"); + } + } + + void serialize_full_transcript() override + { + size_t old_proof_length = BaseTranscript::proof_data.size(); + BaseTranscript::proof_data.clear(); + size_t log_n = numeric::get_msb(circuit_size); + + BaseTranscript::template serialize_to_buffer(circuit_size, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_add_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_mul_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_eq_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_collision_check_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_msm_transition_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_pc_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_msm_count_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_x_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_y_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_z1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_z2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_z1zero_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_z2zero_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_op_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_accumulator_x_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_accumulator_y_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_msm_x_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_msm_y_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_pc_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_point_transition_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_round_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_scalar_sum_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s1hi_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s1lo_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s2hi_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s2lo_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s3hi_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s3lo_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s4hi_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_s4lo_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_skew_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_dx_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_dy_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_tx_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_ty_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_transition_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_add_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_double_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_skew_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_accumulator_x_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_accumulator_y_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_pc_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_size_of_msm_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_count_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_round_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_add1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_add2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_add3_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_add4_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_x1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_y1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_x2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_y2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_x3_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_y3_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_x4_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_y4_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_collision_x1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_collision_x2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_collision_x3_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_collision_x4_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_lambda1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_lambda2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_lambda3_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_lambda4_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_slice1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_slice2_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_slice3_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(msm_slice4_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_accumulator_empty_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(transcript_reset_accumulator_comm, + BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(precompute_select_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(lookup_read_counts_0_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(lookup_read_counts_1_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(lookup_inverses_comm, BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(z_perm_comm, BaseTranscript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + BaseTranscript::template serialize_to_buffer(sumcheck_univariates[i], + BaseTranscript::proof_data); + } + BaseTranscript::template serialize_to_buffer(sumcheck_evaluations, BaseTranscript::proof_data); + for (size_t i = 0; i < log_n - 1; ++i) { + BaseTranscript::template serialize_to_buffer(gemini_univariate_comms[i], + BaseTranscript::proof_data); + } + for (size_t i = 0; i < log_n; ++i) { + BaseTranscript::template serialize_to_buffer(gemini_a_evals[i], BaseTranscript::proof_data); + } + BaseTranscript::template serialize_to_buffer(shplonk_q_comm, BaseTranscript::proof_data); + if (std::is_same>::value) { + BaseTranscript::template serialize_to_buffer(kzg_w_comm, BaseTranscript::proof_data); + } else if (std::is_same>::value) { + BaseTranscript::template serialize_to_buffer(ipa_poly_degree, BaseTranscript::proof_data); + auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); + for (size_t i = 0; i < log_poly_degree; ++i) { + BaseTranscript::template serialize_to_buffer(ipa_l_comms[i], BaseTranscript::proof_data); + BaseTranscript::template serialize_to_buffer(ipa_r_comms[i], BaseTranscript::proof_data); + } + + BaseTranscript::template serialize_to_buffer(ipa_a_0_eval, BaseTranscript::proof_data); + } + ASSERT(BaseTranscript::proof_data.size() == old_proof_length); + } + }; }; class ECCVM : public ECCVMBase> {}; diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_translator.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_translator.hpp index f68a3ff54eb..6de0d85fe03 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_translator.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_translator.hpp @@ -1618,10 +1618,10 @@ template class GoblinTranslator_ { class VerifierCommitments : public AllEntities { public: - VerifierCommitments(std::shared_ptr verification_key, VerifierTranscript transcript) + VerifierCommitments(std::shared_ptr verification_key, + [[maybe_unused]] const BaseTranscript& transcript) { static_cast(transcript); - static_cast(verification_key); this->lagrange_first = verification_key->lagrange_first; this->lagrange_last = verification_key->lagrange_last; this->lagrange_odd_in_minicircuit = verification_key->lagrange_odd_in_minicircuit; diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp index faf55851306..628a910b21b 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp @@ -417,7 +417,8 @@ class GoblinUltra { class VerifierCommitments : public AllEntities { public: - VerifierCommitments(std::shared_ptr verification_key, VerifierTranscript transcript) + VerifierCommitments(std::shared_ptr verification_key, + [[maybe_unused]] const BaseTranscript& transcript) { static_cast(transcript); q_m = verification_key->q_m; @@ -454,6 +455,111 @@ class GoblinUltra { std::vector gate_separation_challenges; FF target_sum; }; + + /** + * @brief Derived class that defines proof structure for GoblinUltra proofs, as well as supporting functions. + * + */ + class Transcript : public BaseTranscript { + public: + uint32_t circuit_size; + uint32_t public_input_size; + uint32_t pub_inputs_offset; + std::vector public_inputs; + Commitment w_l_comm; + Commitment w_r_comm; + Commitment w_o_comm; + Commitment ecc_op_wire_1_comm; + Commitment ecc_op_wire_2_comm; + Commitment ecc_op_wire_3_comm; + Commitment ecc_op_wire_4_comm; + Commitment sorted_accum_comm; + Commitment w_4_comm; + Commitment z_perm_comm; + Commitment z_lookup_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + void deserialize_full_transcript() override + { + // take current proof and put them into the struct + size_t num_bytes_read = 0; + circuit_size = deserialize_from_buffer(proof_data, num_bytes_read); + size_t log_n = numeric::get_msb(circuit_size); + + public_input_size = deserialize_from_buffer(proof_data, num_bytes_read); + pub_inputs_offset = deserialize_from_buffer(proof_data, num_bytes_read); + for (size_t i = 0; i < public_input_size; ++i) { + public_inputs.push_back(deserialize_from_buffer(proof_data, num_bytes_read)); + } + w_l_comm = deserialize_from_buffer(proof_data, num_bytes_read); + w_r_comm = deserialize_from_buffer(proof_data, num_bytes_read); + w_o_comm = deserialize_from_buffer(proof_data, num_bytes_read); + ecc_op_wire_1_comm = deserialize_from_buffer(proof_data, num_bytes_read); + ecc_op_wire_2_comm = deserialize_from_buffer(proof_data, num_bytes_read); + ecc_op_wire_3_comm = deserialize_from_buffer(proof_data, num_bytes_read); + ecc_op_wire_4_comm = deserialize_from_buffer(proof_data, num_bytes_read); + sorted_accum_comm = deserialize_from_buffer(proof_data, num_bytes_read); + w_4_comm = deserialize_from_buffer(proof_data, num_bytes_read); + z_perm_comm = deserialize_from_buffer(proof_data, num_bytes_read); + z_lookup_comm = deserialize_from_buffer(proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.push_back( + deserialize_from_buffer>( + proof_data, num_bytes_read)); + } + sumcheck_evaluations = + deserialize_from_buffer>(proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_bytes_read)); + } + zm_cq_comm = deserialize_from_buffer(proof_data, num_bytes_read); + zm_pi_comm = deserialize_from_buffer(proof_data, num_bytes_read); + } + + void serialize_full_transcript() override + { + size_t old_proof_length = proof_data.size(); + proof_data.clear(); + size_t log_n = numeric::get_msb(circuit_size); + serialize_to_buffer(circuit_size, proof_data); + serialize_to_buffer(public_input_size, proof_data); + serialize_to_buffer(pub_inputs_offset, proof_data); + for (size_t i = 0; i < public_input_size; ++i) { + serialize_to_buffer(public_inputs[i], proof_data); + } + serialize_to_buffer(w_l_comm, proof_data); + serialize_to_buffer(w_r_comm, proof_data); + serialize_to_buffer(w_o_comm, proof_data); + serialize_to_buffer(ecc_op_wire_1_comm, proof_data); + serialize_to_buffer(ecc_op_wire_2_comm, proof_data); + serialize_to_buffer(ecc_op_wire_3_comm, proof_data); + serialize_to_buffer(ecc_op_wire_4_comm, proof_data); + serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(z_perm_comm, proof_data); + serialize_to_buffer(z_lookup_comm, proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], proof_data); + } + serialize_to_buffer(sumcheck_evaluations, proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], proof_data); + } + serialize_to_buffer(zm_cq_comm, proof_data); + serialize_to_buffer(zm_pi_comm, proof_data); + + ASSERT(proof_data.size() == old_proof_length); + } + }; }; } // namespace proof_system::honk::flavor diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra_recursive.hpp index e4affda825a..ee4479fe7d1 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra_recursive.hpp @@ -438,6 +438,141 @@ template class GoblinUltraRecursive_ { this->lagrange_ecc_op = verification_key->lagrange_ecc_op; } }; + + /** + * @brief Derived class that defines proof structure for GoblinUltraRecursive proofs, as well as supporting + * functions. + * + */ + class Transcript : public BaseTranscript { + public: + // Transcript objects defined as public member variables for easy access and modification + uint32_t circuit_size; + uint32_t public_input_size; + uint32_t pub_inputs_offset; + std::vector public_inputs; + Commitment w_l_comm; + Commitment w_r_comm; + Commitment w_o_comm; + Commitment ecc_op_wire_1_comm; + Commitment ecc_op_wire_2_comm; + Commitment ecc_op_wire_3_comm; + Commitment ecc_op_wire_4_comm; + Commitment sorted_accum_comm; + Commitment w_4_comm; + Commitment z_perm_comm; + Commitment z_lookup_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + // Used by verifier to initialize the transcript + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + + static Transcript prover_init_empty() + { + Transcript transcript; + constexpr uint32_t init{ 42 }; // arbitrary + transcript.send_to_verifier("Init", init); + return transcript; + }; + + static Transcript verifier_init_empty(const Transcript& transcript) + { + Transcript verifier_transcript{ transcript.proof_data }; + [[maybe_unused]] auto _ = verifier_transcript.template receive_from_prover("Init"); + return verifier_transcript; + }; + + /** + * @brief Takes a FULL GoblinUltraRecursive proof and deserializes it into the public member variables that + * compose the structure. Must be called in order to access the structure of the proof. + * + */ + void deserialize_full_transcript() override + { + // take current proof and put them into the struct + size_t num_bytes_read = 0; + circuit_size = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + size_t log_n = numeric::get_msb(circuit_size); + + public_input_size = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + pub_inputs_offset = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < public_input_size; ++i) { + public_inputs.push_back(deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read)); + } + w_l_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + w_r_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + w_o_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + ecc_op_wire_1_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + ecc_op_wire_2_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + ecc_op_wire_3_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + ecc_op_wire_4_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + sorted_accum_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + w_4_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + z_perm_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + z_lookup_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.push_back( + deserialize_from_buffer>( + BaseTranscript::proof_data, num_bytes_read)); + } + sumcheck_evaluations = deserialize_from_buffer>( + BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back( + deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read)); + } + zm_cq_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + zm_pi_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + } + /** + * @brief Serializes the structure variables into a FULL GoblinUltraRecursive proof. Should be called only if + * deserialize_full_transcript() was called and some transcript variable was modified. + * + */ + void serialize_full_transcript() override + { + size_t old_proof_length = BaseTranscript::proof_data.size(); + BaseTranscript::proof_data.clear(); // clear proof_data so the rest of the function can replace it + size_t log_n = numeric::get_msb(circuit_size); + serialize_to_buffer(circuit_size, BaseTranscript::proof_data); + serialize_to_buffer(public_input_size, BaseTranscript::proof_data); + serialize_to_buffer(pub_inputs_offset, BaseTranscript::proof_data); + for (size_t i = 0; i < public_input_size; ++i) { + serialize_to_buffer(public_inputs[i], BaseTranscript::proof_data); + } + serialize_to_buffer(w_l_comm, BaseTranscript::proof_data); + serialize_to_buffer(w_r_comm, BaseTranscript::proof_data); + serialize_to_buffer(w_o_comm, BaseTranscript::proof_data); + serialize_to_buffer(ecc_op_wire_1_comm, BaseTranscript::proof_data); + serialize_to_buffer(ecc_op_wire_2_comm, BaseTranscript::proof_data); + serialize_to_buffer(ecc_op_wire_3_comm, BaseTranscript::proof_data); + serialize_to_buffer(ecc_op_wire_4_comm, BaseTranscript::proof_data); + serialize_to_buffer(sorted_accum_comm, BaseTranscript::proof_data); + serialize_to_buffer(w_4_comm, BaseTranscript::proof_data); + serialize_to_buffer(z_perm_comm, BaseTranscript::proof_data); + serialize_to_buffer(z_lookup_comm, BaseTranscript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], BaseTranscript::proof_data); + } + serialize_to_buffer(sumcheck_evaluations, BaseTranscript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], BaseTranscript::proof_data); + } + serialize_to_buffer(zm_cq_comm, BaseTranscript::proof_data); + serialize_to_buffer(zm_pi_comm, BaseTranscript::proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(BaseTranscript::proof_data.size() == old_proof_length); + } + }; }; } // namespace proof_system::honk::flavor diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp index 13540b04056..36c7aff3301 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp @@ -382,7 +382,8 @@ class Ultra { class VerifierCommitments : public AllEntities { public: - VerifierCommitments(std::shared_ptr verification_key, VerifierTranscript transcript) + VerifierCommitments(std::shared_ptr verification_key, + [[maybe_unused]] const BaseTranscript& transcript) { static_cast(transcript); q_m = verification_key->q_m; @@ -418,6 +419,127 @@ class Ultra { std::vector gate_separation_challenges; FF target_sum; }; + + /** + * @brief Derived class that defines proof structure for Ultra proofs, as well as supporting functions. + * + */ + class Transcript : public BaseTranscript { + public: + // Transcript objects defined as public member variables for easy access and modification + uint32_t circuit_size; + uint32_t public_input_size; + uint32_t pub_inputs_offset; + std::vector public_inputs; + Commitment w_l_comm; + Commitment w_r_comm; + Commitment w_o_comm; + Commitment sorted_accum_comm; + Commitment w_4_comm; + Commitment z_perm_comm; + Commitment z_lookup_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + // Used by verifier to initialize the transcript + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + + static Transcript prover_init_empty() + { + Transcript transcript; + constexpr uint32_t init{ 42 }; // arbitrary + transcript.send_to_verifier("Init", init); + return transcript; + }; + + static Transcript verifier_init_empty(const Transcript& transcript) + { + Transcript verifier_transcript{ transcript.proof_data }; + [[maybe_unused]] auto _ = verifier_transcript.template receive_from_prover("Init"); + return verifier_transcript; + }; + + /** + * @brief Takes a FULL Ultra proof and deserializes it into the public member variables that compose the + * structure. Must be called in order to access the structure of the proof. + * + */ + void deserialize_full_transcript() override + { + // take current proof and put them into the struct + size_t num_bytes_read = 0; + circuit_size = deserialize_from_buffer(proof_data, num_bytes_read); + size_t log_n = numeric::get_msb(circuit_size); + + public_input_size = deserialize_from_buffer(proof_data, num_bytes_read); + pub_inputs_offset = deserialize_from_buffer(proof_data, num_bytes_read); + for (size_t i = 0; i < public_input_size; ++i) { + public_inputs.push_back(deserialize_from_buffer(proof_data, num_bytes_read)); + } + w_l_comm = deserialize_from_buffer(proof_data, num_bytes_read); + w_r_comm = deserialize_from_buffer(proof_data, num_bytes_read); + w_o_comm = deserialize_from_buffer(proof_data, num_bytes_read); + sorted_accum_comm = deserialize_from_buffer(proof_data, num_bytes_read); + w_4_comm = deserialize_from_buffer(proof_data, num_bytes_read); + z_perm_comm = deserialize_from_buffer(proof_data, num_bytes_read); + z_lookup_comm = deserialize_from_buffer(proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.push_back( + deserialize_from_buffer>( + proof_data, num_bytes_read)); + } + sumcheck_evaluations = + deserialize_from_buffer>(proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_bytes_read)); + } + zm_cq_comm = deserialize_from_buffer(proof_data, num_bytes_read); + zm_pi_comm = deserialize_from_buffer(proof_data, num_bytes_read); + } + /** + * @brief Serializes the structure variables into a FULL Ultra proof. Should be called only if + * deserialize_full_transcript() was called and some transcript variable was modified. + * + */ + void serialize_full_transcript() override + { + size_t old_proof_length = proof_data.size(); + proof_data.clear(); // clear proof_data so the rest of the function can replace it + size_t log_n = numeric::get_msb(circuit_size); + serialize_to_buffer(circuit_size, proof_data); + serialize_to_buffer(public_input_size, proof_data); + serialize_to_buffer(pub_inputs_offset, proof_data); + for (size_t i = 0; i < public_input_size; ++i) { + serialize_to_buffer(public_inputs[i], proof_data); + } + serialize_to_buffer(w_l_comm, proof_data); + serialize_to_buffer(w_r_comm, proof_data); + serialize_to_buffer(w_o_comm, proof_data); + serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(z_perm_comm, proof_data); + serialize_to_buffer(z_lookup_comm, proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], proof_data); + } + serialize_to_buffer(sumcheck_evaluations, proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], proof_data); + } + serialize_to_buffer(zm_cq_comm, proof_data); + serialize_to_buffer(zm_pi_comm, proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(proof_data.size() == old_proof_length); + } + }; }; } // namespace proof_system::honk::flavor diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_recursive.hpp index 316dff3c1ba..077d5a49c9c 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_recursive.hpp @@ -397,6 +397,128 @@ template class UltraRecursive_ { this->lagrange_last = verification_key->lagrange_last; } }; + + /** + * @brief Derived class that defines proof structure for UltraRecursive proofs, as well as supporting functions. + * + */ + class Transcript : public BaseTranscript { + public: + // Transcript objects defined as public member variables for easy access and modification + uint32_t circuit_size; + uint32_t public_input_size; + uint32_t pub_inputs_offset; + std::vector public_inputs; + Commitment w_l_comm; + Commitment w_r_comm; + Commitment w_o_comm; + Commitment sorted_accum_comm; + Commitment w_4_comm; + Commitment z_perm_comm; + Commitment z_lookup_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + // Used by verifier to initialize the transcript + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + + static Transcript prover_init_empty() + { + Transcript transcript; + constexpr uint32_t init{ 42 }; // arbitrary + transcript.send_to_verifier("Init", init); + return transcript; + }; + + static Transcript verifier_init_empty(const Transcript& transcript) + { + Transcript verifier_transcript{ transcript.proof_data }; + [[maybe_unused]] auto _ = verifier_transcript.template receive_from_prover("Init"); + return verifier_transcript; + }; + + /** + * @brief Takes a FULL UltraRecursive proof and deserializes it into the public member variables that compose + * the structure. Must be called in order to access the structure of the proof. + * + */ + void deserialize_full_transcript() override + { + // take current proof and put them into the struct + size_t num_bytes_read = 0; + circuit_size = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + size_t log_n = numeric::get_msb(circuit_size); + + public_input_size = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + pub_inputs_offset = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < public_input_size; ++i) { + public_inputs.push_back(deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read)); + } + w_l_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + w_r_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + w_o_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + sorted_accum_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + w_4_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + z_perm_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + z_lookup_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.push_back( + deserialize_from_buffer>( + BaseTranscript::proof_data, num_bytes_read)); + } + sumcheck_evaluations = deserialize_from_buffer>( + BaseTranscript::proof_data, num_bytes_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back( + deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read)); + } + zm_cq_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + zm_pi_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + } + /** + * @brief Serializes the structure variables into a FULL UltraRecursive proof. Should be called only if + * deserialize_full_transcript() was called and some transcript variable was modified. + * + */ + void serialize_full_transcript() override + { + size_t old_proof_length = BaseTranscript::proof_data.size(); + BaseTranscript::proof_data.clear(); // clear proof_data so the rest of the function can replace it + size_t log_n = numeric::get_msb(circuit_size); + serialize_to_buffer(circuit_size, BaseTranscript::proof_data); + serialize_to_buffer(public_input_size, BaseTranscript::proof_data); + serialize_to_buffer(pub_inputs_offset, BaseTranscript::proof_data); + for (size_t i = 0; i < public_input_size; ++i) { + serialize_to_buffer(public_inputs[i], BaseTranscript::proof_data); + } + serialize_to_buffer(w_l_comm, BaseTranscript::proof_data); + serialize_to_buffer(w_r_comm, BaseTranscript::proof_data); + serialize_to_buffer(w_o_comm, BaseTranscript::proof_data); + serialize_to_buffer(sorted_accum_comm, BaseTranscript::proof_data); + serialize_to_buffer(w_4_comm, BaseTranscript::proof_data); + serialize_to_buffer(z_perm_comm, BaseTranscript::proof_data); + serialize_to_buffer(z_lookup_comm, BaseTranscript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], BaseTranscript::proof_data); + } + serialize_to_buffer(sumcheck_evaluations, BaseTranscript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], BaseTranscript::proof_data); + } + serialize_to_buffer(zm_cq_comm, BaseTranscript::proof_data); + serialize_to_buffer(zm_pi_comm, BaseTranscript::proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(BaseTranscript::proof_data.size() == old_proof_length); + } + }; }; } // namespace proof_system::honk::flavor diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp index 117b35d3cc4..d5c6fa7e2a1 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp @@ -25,7 +25,7 @@ template class GeminiTest : public CommitmentTest { std::vector multilinear_commitments, std::vector multilinear_commitments_to_be_shifted) { - auto prover_transcript = ProverTranscript::init_empty(); + auto prover_transcript = BaseTranscript::prover_init_empty(); const Fr rho = Fr::random_element(); @@ -79,7 +79,7 @@ template class GeminiTest : public CommitmentTest { // Check that the Fold polynomials have been evaluated correctly in the prover this->verify_batch_opening_pair(prover_output.opening_pairs, prover_output.witnesses); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Compute: // - Single opening pair: {r, \hat{a}_0} diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.hpp index ae5b2fcfb24..aeafa456ec7 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.hpp @@ -35,7 +35,7 @@ template class IPA { static void compute_opening_proof(std::shared_ptr ck, const OpeningPair& opening_pair, const Polynomial& polynomial, - ProverTranscript& transcript) + BaseTranscript& transcript) { ASSERT(opening_pair.challenge != 0 && "The challenge point should not be zero"); auto poly_degree = static_cast(polynomial.size()); @@ -134,9 +134,7 @@ template class IPA { * * @return true/false depending on if the proof verifies */ - static bool verify(std::shared_ptr vk, - const OpeningClaim& opening_claim, - VerifierTranscript& transcript) + static bool verify(std::shared_ptr vk, const OpeningClaim& opening_claim, BaseTranscript& transcript) { auto poly_degree = static_cast(transcript.template receive_from_prover("IPA:poly_degree")); Fr generator_challenge = transcript.get_challenge("IPA:generator_challenge"); diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp index d015bfa6d21..e6d0333a8ab 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp @@ -70,11 +70,11 @@ TEST_F(IPATest, Open) const OpeningClaim opening_claim{ opening_pair, commitment }; // initialize empty prover transcript - ProverTranscript prover_transcript; + BaseTranscript prover_transcript; IPA::compute_opening_proof(this->ck(), opening_pair, poly, prover_transcript); // initialize verifier transcript from proof data - VerifierTranscript verifier_transcript{ prover_transcript.proof_data }; + BaseTranscript verifier_transcript{ prover_transcript.proof_data }; auto result = IPA::verify(this->vk(), opening_claim, verifier_transcript); EXPECT_TRUE(result); @@ -129,7 +129,7 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) batched_commitment_unshifted = commitment1 * rhos[0] + commitment2 * rhos[1]; batched_commitment_to_be_shifted = commitment2 * rhos[2]; - auto prover_transcript = ProverTranscript::init_empty(); + auto prover_transcript = BaseTranscript::prover_init_empty(); auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); @@ -162,7 +162,7 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) IPA::compute_opening_proof(this->ck(), shplonk_opening_pair, shplonk_witness, prover_transcript); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); auto gemini_verifier_claim = GeminiVerifier::reduce_verification(mle_opening_point, batched_evaluation, diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp b/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp index 6bd41ac7bef..5fe179482e3 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp @@ -31,7 +31,7 @@ template class KZG { static void compute_opening_proof(std::shared_ptr ck, const OpeningPair& opening_pair, const Polynomial& polynomial, - ProverTranscript& prover_trancript) + BaseTranscript& prover_trancript) { Polynomial quotient(polynomial); quotient[0] -= opening_pair.evaluation; @@ -55,7 +55,7 @@ template class KZG { */ static bool verify(std::shared_ptr vk, const OpeningClaim& claim, - VerifierTranscript& verifier_transcript) + BaseTranscript& verifier_transcript) { auto quotient_commitment = verifier_transcript.template receive_from_prover("KZG:W"); auto lhs = claim.commitment - (GroupElement::one() * claim.opening_pair.evaluation) + diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp index 6fe4d1b2641..673ccddd7f7 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp @@ -39,11 +39,11 @@ TYPED_TEST(KZGTest, single) auto opening_pair = OpeningPair{ challenge, evaluation }; auto opening_claim = OpeningClaim{ opening_pair, commitment }; - auto prover_transcript = ProverTranscript::init_empty(); + auto prover_transcript = BaseTranscript::prover_init_empty(); KZG::compute_opening_proof(this->ck(), opening_pair, witness, prover_transcript); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); bool verified = KZG::verify(this->vk(), opening_claim, verifier_transcript); EXPECT_EQ(verified, true); @@ -109,7 +109,7 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) batched_commitment_unshifted = commitment1 * rhos[0] + commitment2 * rhos[1]; batched_commitment_to_be_shifted = commitment2 * rhos[2]; - auto prover_transcript = ProverTranscript::init_empty(); + auto prover_transcript = BaseTranscript::prover_init_empty(); // Run the full prover PCS protocol: @@ -154,7 +154,7 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Gemini verifier output: // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp index a700b3b594c..5e607d2f038 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp @@ -28,7 +28,7 @@ TYPED_TEST(ShplonkTest, ShplonkSimple) const size_t n = 16; - auto prover_transcript = ProverTranscript::init_empty(); + auto prover_transcript = BaseTranscript::prover_init_empty(); // Generate two random (unrelated) polynomials of two different sizes, as well as their evaluations at a (single but // different) random point and their commitments. @@ -64,7 +64,7 @@ TYPED_TEST(ShplonkTest, ShplonkSimple) opening_claims.emplace_back(OpeningClaim{ opening_pairs[0], commitment1 }); opening_claims.emplace_back(OpeningClaim{ opening_pairs[1], commitment2 }); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Execute the shplonk verifier functionality const auto verifier_claim = ShplonkVerifier::reduce_verification(this->vk(), opening_claims, verifier_transcript); diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.test.cpp index c4c4dd95984..2af0af8c2ed 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.test.cpp @@ -76,8 +76,8 @@ template class ZeroMorphTest : public CommitmentTest { g_commitments.emplace_back(f_commitments[i]); } - // Initialize an empty ProverTranscript - auto prover_transcript = ProverTranscript::init_empty(); + // Initialize an empty BaseTranscript + auto prover_transcript = BaseTranscript::prover_init_empty(); // Execute Prover protocol { @@ -147,7 +147,7 @@ template class ZeroMorphTest : public CommitmentTest { prover_transcript.send_to_verifier("ZM:PI", pi_commitment); } - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Execute Verifier protocol { @@ -332,8 +332,8 @@ template class ZeroMorphWithConcatenationTest : public CommitmentT concatenation_groups_commitments.emplace_back(concatenation_group_commitment); } - // Initialize an empty ProverTranscript - auto prover_transcript = ProverTranscript::init_empty(); + // Initialize an empty BaseTranscript + auto prover_transcript = BaseTranscript::prover_init_empty(); // Execute Prover protocol { @@ -417,7 +417,7 @@ template class ZeroMorphWithConcatenationTest : public CommitmentT prover_transcript.send_to_verifier("ZM:PI", pi_commitment); } - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Execute Verifier protocol { diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp index 9f5143ba028..b2561b7fdca 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp @@ -329,7 +329,7 @@ template plonk::proof& ECCVMProver_::construct_proo // Compute sorted list accumulator and commitment execute_log_derivative_commitments_round(); - // Fiat-Shamir: bbeta & gamma + // Fiat-Shamir: beta & gamma // Compute grand product(s) and commitments. execute_grand_product_computation_round(); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp index d781fcb86c2..b0e63b907d2 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp @@ -21,6 +21,7 @@ template class ECCVMProver_ { using ProverPolynomials = typename Flavor::ProverPolynomials; using CommitmentLabels = typename Flavor::CommitmentLabels; using Curve = typename Flavor::Curve; + using Transcript = typename Flavor::Transcript; public: explicit ECCVMProver_(std::shared_ptr input_key, std::shared_ptr commitment_key); @@ -39,7 +40,7 @@ template class ECCVMProver_ { plonk::proof& export_proof(); plonk::proof& construct_proof(); - ProverTranscript transcript; + Transcript transcript; std::vector public_inputs; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp index 80ff34bd587..76d17e59e54 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp @@ -44,10 +44,11 @@ template bool ECCVMVerifier_::verify_proof(const plonk using Shplonk = pcs::shplonk::ShplonkVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using CommitmentLabels = typename Flavor::CommitmentLabels; + using Transcript = typename Flavor::Transcript; RelationParameters relation_parameters; - transcript = VerifierTranscript{ proof.proof_data }; + transcript = Transcript{ proof.proof_data }; auto commitments = VerifierCommitments(key, transcript); auto commitment_labels = CommitmentLabels(); @@ -168,7 +169,7 @@ template bool ECCVMVerifier_::verify_proof(const plonk transcript.template receive_from_prover(commitment_labels.lookup_read_counts_1); // Get challenge for sorted list batching and wire four memory records - auto [beta, gamma] = transcript.get_challenges("bbeta", "gamma"); + auto [beta, gamma] = transcript.get_challenges("beta", "gamma"); relation_parameters.gamma = gamma; auto beta_sqr = beta * beta; relation_parameters.beta = beta; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.hpp index c44ae39589c..b24fb024313 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.hpp @@ -9,6 +9,7 @@ template class ECCVMVerifier_ { using Commitment = typename Flavor::Commitment; using VerificationKey = typename Flavor::VerificationKey; using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; + using Transcript = typename Flavor::Transcript; public: explicit ECCVMVerifier_(std::shared_ptr verifier_key = nullptr); @@ -16,7 +17,7 @@ template class ECCVMVerifier_ { std::map commitments, std::map pcs_fr_elements, std::shared_ptr pcs_verification_key, - VerifierTranscript transcript) + Transcript& transcript) : key(std::move(key)) , commitments(std::move(commitments)) , pcs_fr_elements(std::move(pcs_fr_elements)) @@ -35,7 +36,7 @@ template class ECCVMVerifier_ { std::map commitments; std::map pcs_fr_elements; std::shared_ptr pcs_verification_key; - VerifierTranscript transcript; + Transcript transcript; }; extern template class ECCVMVerifier_; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_prover.hpp index 7462018ec51..7d0d2cc05fd 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_prover.hpp @@ -25,7 +25,7 @@ template class MergeProver_ { using OpeningPair = typename pcs::OpeningPair; public: - ProverTranscript transcript; + BaseTranscript transcript; std::shared_ptr op_queue; std::shared_ptr pcs_commitment_key; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.cpp index ca477c49eb6..bfac4182d6d 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.cpp @@ -19,7 +19,7 @@ MergeVerifier_::MergeVerifier_(std::unique_ptr ve */ template bool MergeVerifier_::verify_proof(const plonk::proof& proof) { - transcript = VerifierTranscript{ proof.proof_data }; + transcript = BaseTranscript{ proof.proof_data }; // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] std::array C_T_prev; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.hpp index b195cd92a1e..c0ff00b2cab 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/goblin_merge/merge_verifier.hpp @@ -26,7 +26,7 @@ template class MergeVerifier_ { using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; public: - VerifierTranscript transcript; + BaseTranscript transcript; std::shared_ptr op_queue; std::shared_ptr pcs_verification_key; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp index c4a87be54b7..abc4bc0059b 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp @@ -36,7 +36,7 @@ template class ProtoGalaxyProver_ { using RelationEvaluations = typename Flavor::TupleOfArraysOfValues; ProverInstances instances; - ProverTranscript transcript; + BaseTranscript transcript; ProtoGalaxyProver_() = default; ProtoGalaxyProver_(ProverInstances insts) diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp index 57397318541..707855ee58d 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp @@ -5,7 +5,7 @@ template VerifierFoldingResult ProtoGalaxyVerifier_< VerifierInstances>::fold_public_parameters(std::vector fold_data) { - transcript = VerifierTranscript{ fold_data }; + transcript = BaseTranscript{ fold_data }; auto index = 0; for (auto it = verifier_instances.begin(); it != verifier_instances.end(); it++, index++) { auto inst = *it; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp index 309fcadcdd5..faa6993cec7 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp @@ -14,7 +14,7 @@ template class ProtoGalaxyVerifier_ { using Instance = typename VerifierInstances::Instance; using VerificationKey = typename Flavor::VerificationKey; VerifierInstances verifier_instances; - VerifierTranscript transcript; + BaseTranscript transcript; // should the PG verifier be given the VerifierInstances, nah this makes sense yo me ProtoGalaxyVerifier_(VerifierInstances insts) diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp index a592fde4755..1bb0f391e11 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp @@ -20,6 +20,7 @@ template class UltraProver_ { using CommitmentLabels = typename Flavor::CommitmentLabels; using Curve = typename Flavor::Curve; using Instance = ProverInstance_; + using Transcript = typename Flavor::Transcript; public: explicit UltraProver_(std::shared_ptr); @@ -33,7 +34,7 @@ template class UltraProver_ { plonk::proof& export_proof(); plonk::proof& construct_proof(); - ProverTranscript transcript; + Transcript transcript; std::vector public_inputs; size_t pub_inputs_offset; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp index b876b31947b..ab2fb367b91 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp @@ -42,7 +42,7 @@ template bool UltraVerifier_::verify_proof(const plonk proof_system::RelationParameters relation_parameters; - transcript = VerifierTranscript{ proof.proof_data }; + transcript = BaseTranscript{ proof.proof_data }; auto commitments = VerifierCommitments(key, transcript); auto commitment_labels = CommitmentLabels(); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp index 34c524672d5..51d0066ab07 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp @@ -23,7 +23,7 @@ template class UltraVerifier_ { std::shared_ptr key; std::map commitments; std::shared_ptr pcs_verification_key; - VerifierTranscript transcript; + BaseTranscript transcript; }; extern template class UltraVerifier_; diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp index 49560829db9..2a5e49c4cf7 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp @@ -41,7 +41,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsSpecial) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = proof_system::honk::ProverTranscript; + using Transcript = typename Flavor::Transcript; // values here are chosen to check another test const size_t multivariate_d(2); @@ -55,7 +55,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsSpecial) std::array f0 = { v00, v10, v01, v11 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript::init_empty(); + Transcript transcript = Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); FF round_challenge_0 = { 0x6c7301b49d85a46c, 0x44311531e39c64f6, 0xb13d66d8d6c1a24c, 0x04410c360230a295 }; @@ -79,7 +79,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsGeneric) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = proof_system::honk::ProverTranscript; + using Transcript = typename Flavor::Transcript; const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); @@ -92,7 +92,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsGeneric) std::array f0 = { v00, v10, v01, v11 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript::init_empty(); + Transcript transcript = Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); FF round_challenge_0 = FF::random_element(); @@ -136,7 +136,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsSpecial) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = proof_system::honk::ProverTranscript; + using Transcript = typename Flavor::Transcript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -153,7 +153,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsSpecial) std::array f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript::init_empty(); + Transcript transcript = Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); FF round_challenge_0 = 1; @@ -187,7 +187,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGeneric) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = proof_system::honk::ProverTranscript; + using Transcript = typename Flavor::Transcript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -204,7 +204,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGeneric) std::array f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript::init_empty(); + Transcript transcript = Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); FF round_challenge_0 = FF::random_element(); @@ -238,7 +238,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGenericMultiplePolys) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = proof_system::honk::ProverTranscript; + using Transcript = typename Flavor::Transcript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -266,7 +266,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGenericMultiplePolys) std::array f2 = { v000[2], v100[2], v010[2], v110[2], v001[2], v101[2], v011[2], v111[2] }; auto full_polynomials = std::array, 3>{ f0, f1, f2 }; - auto transcript = Transcript::init_empty(); + Transcript transcript = Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); std::array expected_q1; diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp index 033401f6361..4282bce0a30 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp @@ -18,9 +18,10 @@ template class SumcheckProver { using ProverPolynomials = typename Flavor::ProverPolynomials; using PartiallyEvaluatedMultivariates = typename Flavor::PartiallyEvaluatedMultivariates; using ClaimedEvaluations = typename Flavor::AllValues; + using Transcript = typename Flavor::Transcript; using Instance = ProverInstance_; - ProverTranscript& transcript; + Transcript& transcript; const size_t multivariate_n; const size_t multivariate_d; SumcheckProverRound round; @@ -59,7 +60,7 @@ template class SumcheckProver { PartiallyEvaluatedMultivariates partially_evaluated_polynomials; // prover instantiates sumcheck with circuit size and a prover transcript - SumcheckProver(size_t multivariate_n, ProverTranscript& transcript) + SumcheckProver(size_t multivariate_n, Transcript& transcript) : transcript(transcript) , multivariate_n(multivariate_n) , multivariate_d(numeric::get_msb(multivariate_n)) diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp index dace121aa68..dd3867664ce 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp @@ -104,7 +104,7 @@ TEST_F(SumcheckTests, PolynomialNormalization) info(full_polynomials.w_l[2]); info(full_polynomials.w_l[3]); - auto transcript = ProverTranscript::init_empty(); + Flavor::Transcript transcript = Flavor::Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); @@ -169,7 +169,7 @@ TEST_F(SumcheckTests, Prover) } auto full_polynomials = construct_ultra_full_polynomials(random_polynomials); - auto transcript = ProverTranscript::init_empty(); + Flavor::Transcript transcript = Flavor::Transcript::prover_init_empty(); auto sumcheck = SumcheckProver(multivariate_n, transcript); @@ -243,13 +243,13 @@ TEST_F(SumcheckTests, ProverAndVerifierSimple) .public_input_delta = FF::one(), }; - auto prover_transcript = ProverTranscript::init_empty(); + Flavor::Transcript prover_transcript = Flavor::Transcript::prover_init_empty(); auto sumcheck_prover = SumcheckProver(multivariate_n, prover_transcript); auto prover_output = sumcheck_prover.prove(full_polynomials, relation_parameters); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + Flavor::Transcript verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript); auto sumcheck_verifier = SumcheckVerifier(multivariate_n); @@ -396,14 +396,14 @@ TEST_F(SumcheckTests, RealCircuitUltra) instance->compute_sorted_accumulator_polynomials(eta); instance->compute_grand_product_polynomials(beta, gamma); - auto prover_transcript = ProverTranscript::init_empty(); + Flavor::Transcript prover_transcript = Flavor::Transcript::prover_init_empty(); auto circuit_size = instance->proving_key->circuit_size; auto sumcheck_prover = SumcheckProver(circuit_size, prover_transcript); auto prover_output = sumcheck_prover.prove(instance->prover_polynomials, instance->relation_parameters); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + Flavor::Transcript verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript); auto sumcheck_verifier = SumcheckVerifier(circuit_size); diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/honk/transcript/eccvm_transcript.test.cpp new file mode 100644 index 00000000000..bd4b88b8df3 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/eccvm_transcript.test.cpp @@ -0,0 +1,341 @@ +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/honk/composer/eccvm_composer.hpp" +#include "barretenberg/numeric/bitop/get_msb.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "transcript.hpp" +#include + +using namespace proof_system::honk; + +template class ECCVMTranscriptTests : public ::testing::Test { + public: + void SetUp() override + { + if constexpr (std::is_same::value) { + barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } else { + barretenberg::srs::init_crs_factory("../srs_db/ignition"); + } + }; + using FF = typename Flavor::FF; + + /** + * @brief Construct a manifest for a ECCVM Honk proof + * + * @details This is where we define the "Manifest" for a ECCVM 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. + * + * @return TranscriptManifest + */ + TranscriptManifest construct_eccvm_honk_manifest(size_t circuit_size, size_t ipa_poly_degree) + { + TranscriptManifest manifest_expected; + + auto log_n = numeric::get_msb(circuit_size); + + size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; + size_t size_FF = sizeof(FF); + size_t size_G = 2 * size_FF; + size_t size_uni = MAX_PARTIAL_RELATION_LENGTH * size_FF; + size_t size_evals = (Flavor::NUM_ALL_ENTITIES)*size_FF; + size_t size_uint32 = 4; + size_t size_uint64 = 8; + + size_t round = 0; + manifest_expected.add_entry(round, "circuit_size", size_uint32); + manifest_expected.add_entry(round, "TRANSCRIPT_ADD", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MUL", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_EQ", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_COLLISION_CHECK", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MSM_TRANSITION", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_PC", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MSM_COUNT", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_X", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_Y", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_Z1", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_Z2", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_Z1ZERO", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_Z2ZERO", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_OP", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_X", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_Y", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MSM_X", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MSM_Y", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_PC", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_POINT_TRANSITION", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_ROUND", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_SCALAR_SUM", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S1HI", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S1LO", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S2HI", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S2LO", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S3HI", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S3LO", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S4HI", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S4LO", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_SKEW", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_DX", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_DY", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_TX", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_TY", size_G); + manifest_expected.add_entry(round, "MSM_TRANSITION", size_G); + manifest_expected.add_entry(round, "MSM_ADD", size_G); + manifest_expected.add_entry(round, "MSM_DOUBLE", size_G); + manifest_expected.add_entry(round, "MSM_SKEW", size_G); + manifest_expected.add_entry(round, "MSM_ACCUMULATOR_X", size_G); + manifest_expected.add_entry(round, "MSM_ACCUMULATOR_Y", size_G); + manifest_expected.add_entry(round, "MSM_PC", size_G); + manifest_expected.add_entry(round, "MSM_SIZE_OF_MSM", size_G); + manifest_expected.add_entry(round, "MSM_COUNT", size_G); + manifest_expected.add_entry(round, "MSM_ROUND", size_G); + manifest_expected.add_entry(round, "MSM_ADD1", size_G); + manifest_expected.add_entry(round, "MSM_ADD2", size_G); + manifest_expected.add_entry(round, "MSM_ADD3", size_G); + manifest_expected.add_entry(round, "MSM_ADD4", size_G); + manifest_expected.add_entry(round, "MSM_X1", size_G); + manifest_expected.add_entry(round, "MSM_Y1", size_G); + manifest_expected.add_entry(round, "MSM_X2", size_G); + manifest_expected.add_entry(round, "MSM_Y2", size_G); + manifest_expected.add_entry(round, "MSM_X3", size_G); + manifest_expected.add_entry(round, "MSM_Y3", size_G); + manifest_expected.add_entry(round, "MSM_X4", size_G); + manifest_expected.add_entry(round, "MSM_Y4", size_G); + manifest_expected.add_entry(round, "MSM_COLLISION_X1", size_G); + manifest_expected.add_entry(round, "MSM_COLLISION_X2", size_G); + manifest_expected.add_entry(round, "MSM_COLLISION_X3", size_G); + manifest_expected.add_entry(round, "MSM_COLLISION_X4", size_G); + manifest_expected.add_entry(round, "MSM_LAMBDA1", size_G); + manifest_expected.add_entry(round, "MSM_LAMBDA2", size_G); + manifest_expected.add_entry(round, "MSM_LAMBDA3", size_G); + manifest_expected.add_entry(round, "MSM_LAMBDA4", size_G); + manifest_expected.add_entry(round, "MSM_SLICE1", size_G); + manifest_expected.add_entry(round, "MSM_SLICE2", size_G); + manifest_expected.add_entry(round, "MSM_SLICE3", size_G); + manifest_expected.add_entry(round, "MSM_SLICE4", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_EMPTY", size_G); + manifest_expected.add_entry(round, "TRANSCRIPT_RESET_ACCUMULATOR", size_G); + manifest_expected.add_entry(round, "PRECOMPUTE_SELECT", size_G); + manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS_0", size_G); + manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS_1", size_G); + manifest_expected.add_challenge(round, "beta", "gamma"); + + round++; + manifest_expected.add_entry(round, "LOOKUP_INVERSES", size_G); + manifest_expected.add_entry(round, "Z_PERM", size_G); + manifest_expected.add_challenge(round, "Sumcheck:alpha", "Sumcheck:zeta"); + + for (size_t i = 0; i < log_n; ++i) { + round++; + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, size_uni); + std::string label = "Sumcheck:u_" + idx; + manifest_expected.add_challenge(round, label); + } + + round++; + manifest_expected.add_entry(round, "Sumcheck:evaluations", size_evals); + manifest_expected.add_challenge(round, "rho"); + + round++; + for (size_t i = 1; i < log_n; ++i) { + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "Gemini:FOLD_" + idx, size_G); + } + manifest_expected.add_challenge(round, "Gemini:r"); + + round++; + for (size_t i = 0; i < log_n; ++i) { + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "Gemini:a_" + idx, size_FF); + } + manifest_expected.add_challenge(round, "Shplonk:nu"); + + round++; + manifest_expected.add_entry(round, "Shplonk:Q", size_G); + manifest_expected.add_challenge(round, "Shplonk:z"); + + // TODO(Mara): Make testing more flavor agnostic so we can test this with all flavors + if constexpr (proof_system::IsGrumpkinFlavor) { + round++; + manifest_expected.add_entry(round, "IPA:poly_degree", size_uint64); + manifest_expected.add_challenge(round, "IPA:generator_challenge"); + + auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); + for (size_t i = 0; i < log_poly_degree; ++i) { + round++; + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "IPA:L_" + idx, size_G); + manifest_expected.add_entry(round, "IPA:R_" + idx, size_G); + std::string label = "IPA:round_challenge_" + idx; + manifest_expected.add_challenge(round, label); + } + + round++; + manifest_expected.add_entry(round, "IPA:a_0", size_FF); + } else { + round++; + manifest_expected.add_entry(round, "KZG:W", size_G); + } + + return manifest_expected; + } + proof_system::ECCVMCircuitBuilder generate_trace(numeric::random::Engine* engine = nullptr) + { + proof_system::ECCVMCircuitBuilder result; + using G1 = typename Flavor::CycleGroup; + using Fr = typename G1::Fr; + + auto generators = G1::derive_generators("test generators", 3); + + typename G1::element a = generators[0]; + typename G1::element b = generators[1]; + typename G1::element c = generators[2]; + Fr x = Fr::random_element(engine); + Fr y = Fr::random_element(engine); + + typename G1::element expected_1 = (a * x) + a + a + (b * y) + (b * x) + (b * x); + typename G1::element expected_2 = (a * x) + c + (b * x); + + result.add_accumulate(a); + result.mul_accumulate(a, x); + result.mul_accumulate(b, x); + result.mul_accumulate(b, y); + result.add_accumulate(a); + result.mul_accumulate(b, x); + result.eq_and_reset(expected_1); + result.add_accumulate(c); + result.mul_accumulate(a, x); + result.mul_accumulate(b, x); + result.eq_and_reset(expected_2); + result.mul_accumulate(a, x); + result.mul_accumulate(b, x); + result.mul_accumulate(c, x); + + return result; + } +}; + +numeric::random::Engine& engine = numeric::random::get_debug_engine(); + +using FlavorTypes = testing::Types; + +TYPED_TEST_SUITE(ECCVMTranscriptTests, FlavorTypes); +/** + * @brief Ensure consistency between the manifest hard coded in this testing suite and the one generated by the + * standard honk prover over the course of proof construction. + */ +TYPED_TEST(ECCVMTranscriptTests, ProverManifestConsistency) +{ + using Flavor = TypeParam; + + // Construct a simple circuit + auto builder = this->generate_trace(&engine); + + // Automatically generate a transcript manifest by constructing a proof + auto composer = ECCVMComposer_(); + auto prover = composer.create_prover(builder); + auto proof = prover.construct_proof(); + + // Check that the prover generated manifest agrees with the manifest hard coded in this suite + auto manifest_expected = + this->construct_eccvm_honk_manifest(prover.key->circuit_size, prover.shplonk_output.witness.size()); + auto prover_manifest = prover.transcript.get_manifest(); + + // Note: a manifest can be printed using manifest.print() + for (size_t round = 0; round < manifest_expected.size(); ++round) { + ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepency in round " << round; + } +} + +/** + * @brief Ensure consistency between the manifest generated by the ECCVM honk prover over the course of proof + * construction and the one generated by the verifier over the course of proof verification. + * + */ +TYPED_TEST(ECCVMTranscriptTests, VerifierManifestConsistency) +{ + using Flavor = TypeParam; + + // Construct a simple circuit + auto builder = this->generate_trace(&engine); + + // Automatically generate a transcript manifest in the prover by constructing a proof + auto composer = ECCVMComposer_(); + auto prover = composer.create_prover(builder); + auto proof = prover.construct_proof(); + + // Automatically generate a transcript manifest in the verifier by verifying a proof + auto verifier = composer.create_verifier(builder); + verifier.verify_proof(proof); + + // 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(); + + // Note: a manifest can be printed using manifest.print() + 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; + } +} + +/** + * @brief Check that multiple challenges can be generated and sanity check + * @details We generate 6 challenges that are each 128 bits, and check that they are not 0. + * + */ +TYPED_TEST(ECCVMTranscriptTests, ChallengeGenerationTest) +{ + using Flavor = TypeParam; + // initialized with random value sent to verifier + auto transcript = Flavor::Transcript::prover_init_empty(); + // test a bunch of challenges + auto challenges = transcript.get_challenges("a", "b", "c", "d", "e", "f"); + // check they are not 0 + for (size_t i = 0; i < challenges.size(); ++i) { + ASSERT_NE(challenges[i], 0) << "Challenge " << i << " is 0"; + } + constexpr uint32_t random_val{ 17 }; // arbitrary + transcript.send_to_verifier("random val", random_val); + // test more challenges + auto [a, b, c] = transcript.get_challenges("a", "b", "c"); + ASSERT_NE(a, 0) << "Challenge a is 0"; + ASSERT_NE(b, 0) << "Challenge a is 0"; + ASSERT_NE(b, 0) << "Challenge a is 0"; +} + +TYPED_TEST(ECCVMTranscriptTests, StructureTest) +{ + using Flavor = TypeParam; + + // Construct a simple circuit + auto builder = this->generate_trace(&engine); + + // Automatically generate a transcript manifest by constructing a proof + auto composer = ECCVMComposer_(); + auto prover = composer.create_prover(builder); + auto proof = prover.construct_proof(); + auto verifier = composer.create_verifier(builder); + EXPECT_TRUE(verifier.verify_proof(proof)); + + // try deserializing and serializing with no changes and check proof is still valid + prover.transcript.deserialize_full_transcript(); + prover.transcript.serialize_full_transcript(); + EXPECT_TRUE(verifier.verify_proof(prover.export_proof())); // we have changed nothing so proof is still valid + + typename Flavor::Commitment one_group_val = Flavor::Commitment::one(); + typename Flavor::FF rand_val = Flavor::FF::random_element(); + prover.transcript.transcript_x_comm = one_group_val * rand_val; // choose random object to modify + EXPECT_TRUE(verifier.verify_proof( + prover.export_proof())); // we have not serialized it back to the proof so it should still be fine + + prover.transcript.serialize_full_transcript(); + EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it + + prover.transcript.deserialize_full_transcript(); + EXPECT_EQ(static_cast(prover.transcript.transcript_x_comm), one_group_val * rand_val); +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/goblin_ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/honk/transcript/goblin_ultra_transcript.test.cpp new file mode 100644 index 00000000000..c1d07a642f5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/goblin_ultra_transcript.test.cpp @@ -0,0 +1,233 @@ +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/honk/composer/ultra_composer.hpp" +#include "barretenberg/numeric/bitop/get_msb.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "transcript.hpp" +#include + +using namespace proof_system::honk; + +class GoblinUltraTranscriptTests : public ::testing::Test { + public: + static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } + + using Flavor = proof_system::honk::flavor::GoblinUltra; + using FF = Flavor::FF; + + /** + * @brief Construct a manifest for a GoblinUltra Honk proof + * + * @details This is where we define the "Manifest" for a GoblinUltra 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. + * + * @return TranscriptManifest + */ + TranscriptManifest construct_goblin_ultra_honk_manifest(size_t circuit_size) + { + TranscriptManifest manifest_expected; + + auto log_n = numeric::get_msb(circuit_size); + + size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; + size_t size_FF = sizeof(FF); + size_t size_G = 2 * size_FF; + size_t size_uni = MAX_PARTIAL_RELATION_LENGTH * size_FF; + size_t size_evals = (Flavor::NUM_ALL_ENTITIES)*size_FF; + size_t size_uint32 = 4; + + size_t round = 0; + manifest_expected.add_entry(round, "circuit_size", size_uint32); + manifest_expected.add_entry(round, "public_input_size", size_uint32); + manifest_expected.add_entry(round, "pub_inputs_offset", size_uint32); + manifest_expected.add_entry(round, "public_input_0", size_FF); + manifest_expected.add_entry(round, "W_L", size_G); + manifest_expected.add_entry(round, "W_R", size_G); + manifest_expected.add_entry(round, "W_O", size_G); + manifest_expected.add_entry(round, "ECC_OP_WIRE_1", size_G); + manifest_expected.add_entry(round, "ECC_OP_WIRE_2", size_G); + manifest_expected.add_entry(round, "ECC_OP_WIRE_3", size_G); + manifest_expected.add_entry(round, "ECC_OP_WIRE_4", size_G); + manifest_expected.add_challenge(round, "eta"); + + round++; + manifest_expected.add_entry(round, "SORTED_ACCUM", size_G); + manifest_expected.add_entry(round, "W_4", size_G); + manifest_expected.add_challenge(round, "beta", "gamma"); + + round++; + manifest_expected.add_entry(round, "Z_PERM", size_G); + manifest_expected.add_entry(round, "Z_LOOKUP", size_G); + manifest_expected.add_challenge(round, "Sumcheck:alpha", "Sumcheck:zeta"); + + for (size_t i = 0; i < log_n; ++i) { + round++; + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, size_uni); + std::string label = "Sumcheck:u_" + idx; + manifest_expected.add_challenge(round, label); + } + + round++; + manifest_expected.add_entry(round, "Sumcheck:evaluations", size_evals); + manifest_expected.add_challenge(round, "rho"); + + round++; + for (size_t i = 0; i < log_n; ++i) { + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "ZM:C_q_" + idx, size_G); + } + manifest_expected.add_challenge(round, "ZM:y"); + + round++; + manifest_expected.add_entry(round, "ZM:C_q", size_G); + manifest_expected.add_challenge(round, "ZM:x", "ZM:z"); + + round++; + // TODO(Mara): Make testing more flavor agnostic so we can test this with all flavors + manifest_expected.add_entry(round, "ZM:PI", size_G); + manifest_expected.add_challenge(round); // no challenge + + return manifest_expected; + } + + void generate_test_circuit(auto& builder) + { + // Add some ecc op gates + for (size_t i = 0; i < 3; ++i) { + auto point = Flavor::Curve::AffineElement::one() * FF::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_mul_accum(point, scalar); + } + builder.queue_ecc_eq(); + + // Add one conventional gates that utilize public inputs + FF a = FF::random_element(); + FF b = FF::random_element(); + FF c = FF::random_element(); + FF d = a + b + c; + uint32_t a_idx = builder.add_public_variable(a); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); + uint32_t d_idx = builder.add_variable(d); + + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); + } +}; + +/** + * @brief Ensure consistency between the manifest hard coded in this testing suite and the one generated by the + * standard honk prover over the course of proof construction. + */ +TEST_F(GoblinUltraTranscriptTests, ProverManifestConsistency) +{ + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) + auto builder = typename Flavor::CircuitBuilder(); + generate_test_circuit(builder); + + // Automatically generate a transcript manifest by constructing a proof + auto composer = GoblinUltraComposer(); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto proof = prover.construct_proof(); + + // Check that the prover generated manifest agrees with the manifest hard coded in this suite + auto manifest_expected = construct_goblin_ultra_honk_manifest(instance->proving_key->circuit_size); + auto prover_manifest = prover.transcript.get_manifest(); + // Note: a manifest can be printed using manifest.print() + for (size_t round = 0; round < manifest_expected.size(); ++round) { + ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepency in round " << round; + } +} + +/** + * @brief Ensure consistency between the manifest generated by the goblin ultra honk prover over the course of proof + * construction and the one generated by the verifier over the course of proof verification. + * + */ +TEST_F(GoblinUltraTranscriptTests, VerifierManifestConsistency) +{ + + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) + auto builder = Flavor::CircuitBuilder(); + generate_test_circuit(builder); + + // Automatically generate a transcript manifest in the prover by constructing a proof + auto composer = GoblinUltraComposer(); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto proof = prover.construct_proof(); + + // Automatically generate a transcript manifest in the verifier by verifying a proof + auto verifier = composer.create_verifier(instance); + verifier.verify_proof(proof); + + // 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(); + + // Note: a manifest can be printed using manifest.print() + 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; + } +} + +/** + * @brief Check that multiple challenges can be generated and sanity check + * @details We generate 6 challenges that are each 128 bits, and check that they are not 0. + * + */ +TEST_F(GoblinUltraTranscriptTests, ChallengeGenerationTest) +{ + // initialized with random value sent to verifier + auto transcript = Flavor::Transcript::prover_init_empty(); + // test a bunch of challenges + auto challenges = transcript.get_challenges("a", "b", "c", "d", "e", "f"); + // check they are not 0 + for (size_t i = 0; i < challenges.size(); ++i) { + ASSERT_NE(challenges[i], 0) << "Challenge " << i << " is 0"; + } + constexpr uint32_t random_val{ 17 }; // arbitrary + transcript.send_to_verifier("random val", random_val); + // test more challenges + auto [a, b, c] = transcript.get_challenges("a", "b", "c"); + ASSERT_NE(a, 0) << "Challenge a is 0"; + ASSERT_NE(b, 0) << "Challenge a is 0"; + ASSERT_NE(b, 0) << "Challenge a is 0"; +} + +TEST_F(GoblinUltraTranscriptTests, StructureTest) +{ + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) + auto builder = typename Flavor::CircuitBuilder(); + generate_test_circuit(builder); + + // Automatically generate a transcript manifest by constructing a proof + auto composer = GoblinUltraComposer(); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto proof = prover.construct_proof(); + auto verifier = composer.create_verifier(instance); + EXPECT_TRUE(verifier.verify_proof(proof)); + + // try deserializing and serializing with no changes and check proof is still valid + prover.transcript.deserialize_full_transcript(); + prover.transcript.serialize_full_transcript(); + EXPECT_TRUE(verifier.verify_proof(prover.export_proof())); // we have changed nothing so proof is still valid + + Flavor::Commitment one_group_val = Flavor::Commitment::one(); + FF rand_val = FF::random_element(); + prover.transcript.sorted_accum_comm = one_group_val * rand_val; // choose random object to modify + EXPECT_TRUE(verifier.verify_proof( + prover.export_proof())); // we have not serialized it back to the proof so it should still be fine + + prover.transcript.serialize_full_transcript(); + EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it + + prover.transcript.deserialize_full_transcript(); + EXPECT_EQ(static_cast(prover.transcript.sorted_accum_comm), one_group_val * rand_val); +} diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp index d6189d6268c..c7d4123a332 100644 --- a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp @@ -58,7 +58,7 @@ class TranscriptManifest { }; /** - * @brief Common transcript functionality for both parties. Stores the data for the current round, as well as the + * @brief Common transcript class for both parties. Stores the data for the current round, as well as the * manifest. * * @tparam FF Field from which we sample challenges. @@ -66,11 +66,22 @@ class TranscriptManifest { template class BaseTranscript { // TODO(Adrian): Make these tweakable public: + BaseTranscript() = default; + + /** + * @brief Construct a new Base Transcript object for Verifier using proof_data + * + * @param proof_data + */ + explicit BaseTranscript(const std::vector& proof_data) + : proof_data(proof_data.begin(), proof_data.end()) + {} static constexpr size_t HASH_OUTPUT_SIZE = 32; private: static constexpr size_t MIN_BYTES_PER_CHALLENGE = 128 / 8; // 128 bit challenges + size_t num_bytes_read = 0; // keeps track of number of bytes read from proof_data by the verifier size_t round_number = 0; // current round for manifest bool is_first_challenge = true; // indicates if this is the first challenge this transcript is generating std::array previous_challenge_buffer{}; // default-initialized to zeros @@ -143,7 +154,44 @@ template class BaseTranscript { current_round_data.insert(current_round_data.end(), element_bytes.begin(), element_bytes.end()); } + /** + * @brief Serializes object and appends it to proof_data + * @details Calls to_buffer on element to serialize, and modifies proof_data object by appending the serialized + * bytes to it. + * @tparam T + * @param element + * @param proof_data + */ + template void serialize_to_buffer(const T& element, std::vector& proof_data) + { + auto element_bytes = to_buffer(element); + proof_data.insert(proof_data.end(), element_bytes.begin(), element_bytes.end()); + } + /** + * @brief Deserializes the bytes starting at offset into the typed element and returns that element. + * @details Using the template parameter and the offset argument, this function deserializes the bytes with + * from_buffer and then increments the offset appropriately based on the number of bytes that were deserialized. + * @tparam T + * @param proof_data + * @param offset + * @return T + */ + template T deserialize_from_buffer(const std::vector& proof_data, size_t& offset) const + { + constexpr size_t element_size = sizeof(T); + ASSERT(offset + element_size <= proof_data.size()); + + auto element_bytes = std::span{ proof_data }.subspan(offset, element_size); + offset += element_size; + + T element = from_buffer(element_bytes); + + return element; + } + public: + // Contains the raw data sent by the prover. + std::vector proof_data; /** * @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. @@ -186,23 +234,11 @@ template class BaseTranscript { return challenges; } - FF get_challenge(const std::string& label) { return get_challenges(label)[0]; } - - [[nodiscard]] TranscriptManifest get_manifest() const { return manifest; }; - - void print() { manifest.print(); } -}; - -template class ProverTranscript : public BaseTranscript { - - public: - /// Contains the raw data sent by the prover. - std::vector proof_data; - /** - * @brief Adds a prover message to the transcript. + * @brief Adds a prover message to the transcript, only intended to be used by the prover. * - * @details Serializes the provided object into `proof_data`, and updates the current round state. + * @details Serializes the provided object into `proof_data`, and updates the current round state in + * consume_prover_element_bytes. * * @param label Description/name of the object being added. * @param element Serializable object that will be added to the transcript @@ -223,67 +259,73 @@ template class ProverTranscript : public BaseTranscript { BaseTranscript::consume_prover_element_bytes(label, element_bytes); } + /** + * @brief Reads the next element of type `T` from the transcript, with a predefined label, only used by verifier. + * + * @param label Human readable name for the challenge. + * @return deserialized element of type T + */ + template T receive_from_prover(const std::string& label) + { + constexpr size_t element_size = sizeof(T); + ASSERT(num_bytes_read + element_size <= proof_data.size()); + + auto element_bytes = std::span{ proof_data }.subspan(num_bytes_read, element_size); + num_bytes_read += element_size; + + BaseTranscript::consume_prover_element_bytes(label, element_bytes); + + T element = from_buffer(element_bytes); + + return element; + } + /** * @brief For testing: initializes transcript with some arbitrary data so that a challenge can be generated after - * initialization + * initialization. Only intended to be used by Prover. * - * @return ProverTranscript + * @return BaseTranscript */ - static ProverTranscript init_empty() + static BaseTranscript prover_init_empty() { - ProverTranscript transcript; + BaseTranscript transcript; constexpr uint32_t init{ 42 }; // arbitrary transcript.send_to_verifier("Init", init); return transcript; }; -}; - -template class VerifierTranscript : public BaseTranscript { - - /// Contains the raw data sent by the prover. - std::vector proof_data_; - size_t num_bytes_read_ = 0; - - public: - VerifierTranscript() = default; - - explicit VerifierTranscript(const std::vector& proof_data) - : proof_data_(proof_data.begin(), proof_data.end()) - {} /** * @brief For testing: initializes transcript based on proof data then receives junk data produced by - * ProverTranscript::init_empty() + * BaseTranscript::prover_init_empty(). Only intended to be used by Verifier. * * @param transcript - * @return VerifierTranscript + * @return BaseTranscript */ - static VerifierTranscript init_empty(const ProverTranscript& transcript) + static BaseTranscript verifier_init_empty(const BaseTranscript& transcript) { - VerifierTranscript verifier_transcript{ transcript.proof_data }; + BaseTranscript verifier_transcript{ transcript.proof_data }; [[maybe_unused]] auto _ = verifier_transcript.template receive_from_prover("Init"); return verifier_transcript; }; - /** - * @brief Reads the next element of type `T` from the transcript, with a predefined label. - * - * @param label Human readable name for the challenge. - * @return deserialized element of type T - */ - template T receive_from_prover(const std::string& label) - { - constexpr size_t element_size = sizeof(T); - ASSERT(num_bytes_read_ + element_size <= proof_data_.size()); + FF get_challenge(const std::string& label) { return get_challenges(label)[0]; } - auto element_bytes = std::span{ proof_data_ }.subspan(num_bytes_read_, element_size); - num_bytes_read_ += element_size; + [[nodiscard]] TranscriptManifest get_manifest() const { return manifest; }; - BaseTranscript::consume_prover_element_bytes(label, element_bytes); + void print() { manifest.print(); } - T element = from_buffer(element_bytes); + /** + * @brief Deserializes the FULL transcript into the struct defined by each flavor derivedclass. + * @details Not supported for base transcript class because it does not have a defined structure. The current + * proof_data object must represent the whole proof and not a partial proof or it will throw an error. + */ + virtual void deserialize_full_transcript() { throw_or_abort("Cannot deserialize transcript"); } - return element; - } + /** + * @brief Serializes the FULL transcript from the defined derived class back into proof_data. + * @details Only works if the struct is populated (usually from a call to deserialize_full_transcript). Allows for + * modified transcript objects to be updated in the actual proof for testing purposes. + */ + virtual void serialize_full_transcript() { throw_or_abort("Cannot serialize transcript"); } }; } // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp b/barretenberg/cpp/src/barretenberg/honk/transcript/ultra_transcript.test.cpp similarity index 80% rename from barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp rename to barretenberg/cpp/src/barretenberg/honk/transcript/ultra_transcript.test.cpp index 246e11e92e1..331418d4746 100644 --- a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/ultra_transcript.test.cpp @@ -1,9 +1,9 @@ -#include "transcript.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" #include "barretenberg/honk/composer/ultra_composer.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" +#include "transcript.hpp" #include using namespace proof_system::honk; @@ -38,7 +38,6 @@ class UltraTranscriptTests : public ::testing::Test { size_t size_uni = MAX_PARTIAL_RELATION_LENGTH * size_FF; size_t size_evals = (Flavor::NUM_ALL_ENTITIES)*size_FF; size_t size_uint32 = 4; - size_t size_uint64 = 8; size_t round = 0; manifest_expected.add_entry(round, "circuit_size", size_uint32); @@ -85,29 +84,27 @@ class UltraTranscriptTests : public ::testing::Test { round++; // TODO(Mara): Make testing more flavor agnostic so we can test this with all flavors - if constexpr (proof_system::IsGrumpkinFlavor) { - manifest_expected.add_entry(round, "IPA:poly_degree", size_uint64); - manifest_expected.add_challenge(round, "IPA:generator_challenge"); - - for (size_t i = 0; i < log_n; i++) { - round++; - std::string idx = std::to_string(i); - manifest_expected.add_entry(round, "IPA:L_" + idx, size_G); - manifest_expected.add_entry(round, "IPA:R_" + idx, size_G); - std::string label = "IPA:round_challenge_" + idx; - manifest_expected.add_challenge(round, label); - } - - round++; - manifest_expected.add_entry(round, "IPA:a_0", size_FF); - } else { - manifest_expected.add_entry(round, "ZM:PI", size_G); - } - + manifest_expected.add_entry(round, "ZM:PI", size_G); manifest_expected.add_challenge(round); // no challenge return manifest_expected; } + + void generate_test_circuit(auto& builder) + { + FF a = 1; + builder.add_variable(a); + builder.add_public_variable(a); + } + + void generate_random_test_circuit(auto& builder) + { + auto a = FF::random_element(); + auto b = FF::random_element(); + builder.add_variable(a); + builder.add_public_variable(a); + builder.add_public_variable(b); + } }; /** @@ -117,10 +114,8 @@ class UltraTranscriptTests : public ::testing::Test { TEST_F(UltraTranscriptTests, ProverManifestConsistency) { // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) - typename Flavor::FF a = 1; auto builder = typename Flavor::CircuitBuilder(); - builder.add_variable(a); - builder.add_public_variable(a); + generate_test_circuit(builder); // Automatically generate a transcript manifest by constructing a proof auto composer = UltraComposer(); @@ -146,11 +141,8 @@ TEST_F(UltraTranscriptTests, VerifierManifestConsistency) { // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) - auto builder = proof_system::UltraCircuitBuilder(); - - auto a = 2; - builder.add_variable(a); - builder.add_public_variable(a); + auto builder = Flavor::CircuitBuilder(); + generate_test_circuit(builder); // Automatically generate a transcript manifest in the prover by constructing a proof auto composer = UltraComposer(); @@ -181,7 +173,7 @@ TEST_F(UltraTranscriptTests, VerifierManifestConsistency) TEST_F(UltraTranscriptTests, ChallengeGenerationTest) { // initialized with random value sent to verifier - auto transcript = ProverTranscript::init_empty(); + auto transcript = Flavor::Transcript::prover_init_empty(); // test a bunch of challenges auto challenges = transcript.get_challenges("a", "b", "c", "d", "e", "f"); // check they are not 0 @@ -197,6 +189,38 @@ TEST_F(UltraTranscriptTests, ChallengeGenerationTest) ASSERT_NE(b, 0) << "Challenge a is 0"; } +TEST_F(UltraTranscriptTests, StructureTest) +{ + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) + auto builder = typename Flavor::CircuitBuilder(); + generate_test_circuit(builder); + + // Automatically generate a transcript manifest by constructing a proof + auto composer = UltraComposer(); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto proof = prover.construct_proof(); + auto verifier = composer.create_verifier(instance); + EXPECT_TRUE(verifier.verify_proof(proof)); + + // try deserializing and serializing with no changes and check proof is still valid + prover.transcript.deserialize_full_transcript(); + prover.transcript.serialize_full_transcript(); + EXPECT_TRUE(verifier.verify_proof(prover.export_proof())); // we have changed nothing so proof is still valid + + Flavor::Commitment one_group_val = Flavor::Commitment::one(); + FF rand_val = FF::random_element(); + prover.transcript.sorted_accum_comm = one_group_val * rand_val; // choose random object to modify + EXPECT_TRUE(verifier.verify_proof( + prover.export_proof())); // we have not serialized it back to the proof so it should still be fine + + prover.transcript.serialize_full_transcript(); + EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it + + prover.transcript.deserialize_full_transcript(); + EXPECT_EQ(static_cast(prover.transcript.sorted_accum_comm), one_group_val * rand_val); +} + TEST_F(UltraTranscriptTests, FoldingManifestTest) { using Flavor = flavor::Ultra; @@ -205,11 +229,7 @@ TEST_F(UltraTranscriptTests, FoldingManifestTest) std::vector>> insts(2); std::generate(insts.begin(), insts.end(), [&]() { auto builder = proof_system::UltraCircuitBuilder(); - auto a = FF::random_element(); - auto b = FF::random_element(); - builder.add_variable(a); - builder.add_public_variable(a); - builder.add_public_variable(b); + generate_random_test_circuit(builder); return composer.create_instance(builder); }); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_set_relation.cpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_set_relation.cpp index 3663c61087f..40fff3619b5 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_set_relation.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_set_relation.cpp @@ -359,7 +359,7 @@ Accumulator ECCVMSetRelationBase::compute_permutation_denominator(const AllE * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Accumulator edges. - * @param parameters contains bbeta, gamma, and public_input_delta, .... + * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ template diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.hpp index 3b25af820c1..7393b5e5112 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.hpp @@ -18,12 +18,12 @@ template class Transcript { public: using field_ct = field_t; using FF = barretenberg::fr; - using VerifierTranscript = proof_system::honk::VerifierTranscript; + using BaseTranscript = proof_system::honk::BaseTranscript; using StdlibTypes = utility::StdlibTypesUtility; - static constexpr size_t HASH_OUTPUT_SIZE = VerifierTranscript::HASH_OUTPUT_SIZE; + static constexpr size_t HASH_OUTPUT_SIZE = BaseTranscript::HASH_OUTPUT_SIZE; - VerifierTranscript native_transcript; + BaseTranscript native_transcript; Builder* builder; Transcript() = default; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.test.cpp index b91139f7fbf..159b34e31e1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/transcript/transcript.test.cpp @@ -14,8 +14,7 @@ using Builder = UltraCircuitBuilder; using UltraFlavor = ::proof_system::honk::flavor::Ultra; using UltraRecursiveFlavor = ::proof_system::honk::flavor::UltraRecursive_; using FF = barretenberg::fr; -using ProverTranscript = ::proof_system::honk::ProverTranscript; -using VerifierTranscript = ::proof_system::honk::VerifierTranscript; +using BaseTranscript = ::proof_system::honk::BaseTranscript; /** * @brief Create some mock data; add it to the provided prover transcript in various mock rounds @@ -97,11 +96,11 @@ TEST(RecursiveHonkTranscript, InterfacesMatch) constexpr size_t LENGTH = 8; // arbitrary length of Univariate to be serialized // Instantiate a Prover Transcript and use it to generate some mock proof data - ProverTranscript prover_transcript; + BaseTranscript prover_transcript; auto proof_data = generate_mock_proof_data(prover_transcript); // Instantiate a (native) Verifier Transcript with the proof data and perform some mock transcript operations - VerifierTranscript native_transcript(proof_data); + BaseTranscript native_transcript(proof_data); perform_mock_verifier_transcript_operations(native_transcript); // Confirm that Prover and Verifier transcripts have generated the same manifest via the operations performed @@ -145,7 +144,7 @@ TEST(RecursiveHonkTranscript, ReturnValuesMatch) } // Construct a mock proof via the prover transcript - ProverTranscript prover_transcript; + BaseTranscript prover_transcript; prover_transcript.send_to_verifier("scalar", scalar); prover_transcript.send_to_verifier("commitment", commitment); prover_transcript.send_to_verifier("evaluations", evaluations); @@ -153,7 +152,7 @@ TEST(RecursiveHonkTranscript, ReturnValuesMatch) auto proof_data = prover_transcript.proof_data; // Perform the corresponding operations with the native verifier transcript - VerifierTranscript native_transcript(proof_data); + BaseTranscript native_transcript(proof_data); auto native_scalar = native_transcript.template receive_from_prover("scalar"); auto native_commitment = native_transcript.template receive_from_prover("commitment"); auto native_evaluations = native_transcript.template receive_from_prover>("evaluations"); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp index df9afcf9e4e..00a59673563 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp @@ -216,7 +216,10 @@ template class GoblinRecursiveVerifierTest : public testi const auto native_verification_key = instance->compute_verification_key(); // Arbitrarily tamper with the proof to be verified - inner_proof.proof_data[10] = 25; + inner_prover.transcript.deserialize_full_transcript(); + inner_prover.transcript.sorted_accum_comm = Flavor::Commitment::one() * Flavor::FF::random_element(); + inner_prover.transcript.serialize_full_transcript(); + inner_proof = inner_prover.export_proof(); // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp index 1c0a69ca3a7..83c7230544a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp @@ -201,7 +201,10 @@ template class RecursiveVerifierTest : public testing::Te const auto native_verification_key = instance->compute_verification_key(); // Arbitrarily tamper with the proof to be verified - inner_proof.proof_data[10] = 25; + inner_prover.transcript.deserialize_full_transcript(); + inner_prover.transcript.sorted_accum_comm = Flavor::Commitment::one() * Flavor::FF::random_element(); + inner_prover.transcript.serialize_full_transcript(); + inner_proof = inner_prover.export_proof(); // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit;