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 <typename CycleGroup_T, typename Curve_T, typename PCS_T> class ECCVMBa
 
       public:
         VerifierCommitments(const std::shared_ptr<VerificationKey>& verification_key,
-                            const VerifierTranscript<FF>& transcript)
+                            [[maybe_unused]] const BaseTranscript<FF>& transcript)
         {
             static_cast<void>(transcript);
             Base::lagrange_first = verification_key->lagrange_first;
@@ -856,6 +856,424 @@ template <typename CycleGroup_T, typename Curve_T, typename PCS_T> 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<FF> {
+      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<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>> sumcheck_univariates;
+        std::array<FF, NUM_ALL_ENTITIES> sumcheck_evaluations;
+        std::vector<Commitment> gemini_univariate_comms;
+        std::vector<FF> gemini_a_evals;
+        Commitment shplonk_q_comm;
+        Commitment kzg_w_comm;
+        // the rest are only for Grumpkin
+        uint64_t ipa_poly_degree;
+        std::vector<Commitment> ipa_l_comms;
+        std::vector<Commitment> ipa_r_comms;
+        FF ipa_a_0_eval;
+
+        Transcript() = default;
+
+        Transcript(const std::vector<uint8_t>& proof)
+            : BaseTranscript<FF>(proof)
+        {}
+
+        void deserialize_full_transcript() override
+        {
+            // take current proof and put them into the struct
+            size_t num_bytes_read = 0;
+            circuit_size = BaseTranscript<FF>::template deserialize_from_buffer<uint32_t>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            size_t log_n = numeric::get_msb(circuit_size);
+            transcript_add_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_mul_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_eq_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_collision_check_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_msm_transition_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_pc_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_msm_count_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_x_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_y_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_z1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_z2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_z1zero_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_z2zero_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_op_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_accumulator_x_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_accumulator_y_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_msm_x_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_msm_y_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_pc_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_point_transition_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_round_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_scalar_sum_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s1hi_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s1lo_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s2hi_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s2lo_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s3hi_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s3lo_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s4hi_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_s4lo_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_skew_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_dx_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_dy_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_tx_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_ty_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_transition_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_add_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_double_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_skew_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_accumulator_x_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_accumulator_y_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_pc_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_size_of_msm_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_count_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_round_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_add1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_add2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_add3_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_add4_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_x1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_y1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_x2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_y2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_x3_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_y3_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_x4_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_y4_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_collision_x1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_collision_x2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_collision_x3_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_collision_x4_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_lambda1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_lambda2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_lambda3_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_lambda4_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_slice1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_slice2_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_slice3_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            msm_slice4_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_accumulator_empty_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            transcript_reset_accumulator_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            precompute_select_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            lookup_read_counts_0_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            lookup_read_counts_1_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            lookup_inverses_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            z_perm_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                sumcheck_univariates.emplace_back(BaseTranscript<FF>::template deserialize_from_buffer<
+                                                  barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
+                    BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            sumcheck_evaluations =
+                BaseTranscript<FF>::template deserialize_from_buffer<std::array<FF, NUM_ALL_ENTITIES>>(
+                    BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n - 1; ++i) {
+                gemini_univariate_comms.emplace_back(BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                    BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            for (size_t i = 0; i < log_n; ++i) {
+                gemini_a_evals.emplace_back(BaseTranscript<FF>::template deserialize_from_buffer<FF>(
+                    BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            shplonk_q_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            if (std::is_same<PCS, pcs::kzg::KZG<curve::BN254>>::value) {
+                kzg_w_comm = BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                    BaseTranscript<FF>::proof_data, num_bytes_read);
+            } else if (std::is_same<PCS, pcs::ipa::IPA<curve::Grumpkin>>::value) {
+                ipa_poly_degree = BaseTranscript<FF>::template deserialize_from_buffer<uint64_t>(
+                    BaseTranscript<FF>::proof_data, num_bytes_read);
+                auto log_poly_degree = static_cast<size_t>(numeric::get_msb(ipa_poly_degree));
+                for (size_t i = 0; i < log_poly_degree; ++i) {
+                    ipa_l_comms.emplace_back(BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                        BaseTranscript<FF>::proof_data, num_bytes_read));
+                    ipa_r_comms.emplace_back(BaseTranscript<FF>::template deserialize_from_buffer<Commitment>(
+                        BaseTranscript<FF>::proof_data, num_bytes_read));
+                }
+                ipa_a_0_eval = BaseTranscript<FF>::template deserialize_from_buffer<FF>(BaseTranscript<FF>::proof_data,
+                                                                                        num_bytes_read);
+            } else {
+                throw_or_abort("Unsupported PCS");
+            }
+        }
+
+        void serialize_full_transcript() override
+        {
+            size_t old_proof_length = BaseTranscript<FF>::proof_data.size();
+            BaseTranscript<FF>::proof_data.clear();
+            size_t log_n = numeric::get_msb(circuit_size);
+
+            BaseTranscript<FF>::template serialize_to_buffer(circuit_size, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_add_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_mul_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_eq_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_collision_check_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_msm_transition_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_pc_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_msm_count_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_x_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_y_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_z1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_z2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_z1zero_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_z2zero_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_op_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_accumulator_x_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_accumulator_y_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_msm_x_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_msm_y_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_pc_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_point_transition_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_round_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_scalar_sum_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s1hi_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s1lo_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s2hi_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s2lo_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s3hi_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s3lo_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s4hi_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_s4lo_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_skew_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_dx_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_dy_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_tx_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_ty_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_transition_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_add_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_double_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_skew_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_accumulator_x_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_accumulator_y_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_pc_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_size_of_msm_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_count_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_round_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_add1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_add2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_add3_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_add4_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_x1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_y1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_x2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_y2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_x3_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_y3_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_x4_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_y4_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_collision_x1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_collision_x2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_collision_x3_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_collision_x4_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_lambda1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_lambda2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_lambda3_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_lambda4_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_slice1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_slice2_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_slice3_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(msm_slice4_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_accumulator_empty_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(transcript_reset_accumulator_comm,
+                                                             BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(precompute_select_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(lookup_read_counts_0_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(lookup_read_counts_1_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(lookup_inverses_comm, BaseTranscript<FF>::proof_data);
+            BaseTranscript<FF>::template serialize_to_buffer(z_perm_comm, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < log_n; ++i) {
+                BaseTranscript<FF>::template serialize_to_buffer(sumcheck_univariates[i],
+                                                                 BaseTranscript<FF>::proof_data);
+            }
+            BaseTranscript<FF>::template serialize_to_buffer(sumcheck_evaluations, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < log_n - 1; ++i) {
+                BaseTranscript<FF>::template serialize_to_buffer(gemini_univariate_comms[i],
+                                                                 BaseTranscript<FF>::proof_data);
+            }
+            for (size_t i = 0; i < log_n; ++i) {
+                BaseTranscript<FF>::template serialize_to_buffer(gemini_a_evals[i], BaseTranscript<FF>::proof_data);
+            }
+            BaseTranscript<FF>::template serialize_to_buffer(shplonk_q_comm, BaseTranscript<FF>::proof_data);
+            if (std::is_same<PCS, pcs::kzg::KZG<curve::BN254>>::value) {
+                BaseTranscript<FF>::template serialize_to_buffer(kzg_w_comm, BaseTranscript<FF>::proof_data);
+            } else if (std::is_same<PCS, pcs::ipa::IPA<curve::Grumpkin>>::value) {
+                BaseTranscript<FF>::template serialize_to_buffer(ipa_poly_degree, BaseTranscript<FF>::proof_data);
+                auto log_poly_degree = static_cast<size_t>(numeric::get_msb(ipa_poly_degree));
+                for (size_t i = 0; i < log_poly_degree; ++i) {
+                    BaseTranscript<FF>::template serialize_to_buffer(ipa_l_comms[i], BaseTranscript<FF>::proof_data);
+                    BaseTranscript<FF>::template serialize_to_buffer(ipa_r_comms[i], BaseTranscript<FF>::proof_data);
+                }
+
+                BaseTranscript<FF>::template serialize_to_buffer(ipa_a_0_eval, BaseTranscript<FF>::proof_data);
+            }
+            ASSERT(BaseTranscript<FF>::proof_data.size() == old_proof_length);
+        }
+    };
 };
 
 class ECCVM : public ECCVMBase<grumpkin::g1, curve::BN254, pcs::kzg::KZG<curve::BN254>> {};
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 <size_t mini_circuit_size> class GoblinTranslator_ {
 
     class VerifierCommitments : public AllEntities<Commitment, CommitmentHandle> {
       public:
-        VerifierCommitments(std::shared_ptr<VerificationKey> verification_key, VerifierTranscript<FF> transcript)
+        VerifierCommitments(std::shared_ptr<VerificationKey> verification_key,
+                            [[maybe_unused]] const BaseTranscript<FF>& transcript)
         {
             static_cast<void>(transcript);
-            static_cast<void>(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<Commitment, CommitmentHandle> {
       public:
-        VerifierCommitments(std::shared_ptr<VerificationKey> verification_key, VerifierTranscript<FF> transcript)
+        VerifierCommitments(std::shared_ptr<VerificationKey> verification_key,
+                            [[maybe_unused]] const BaseTranscript<FF>& transcript)
         {
             static_cast<void>(transcript);
             q_m = verification_key->q_m;
@@ -454,6 +455,111 @@ class GoblinUltra {
         std::vector<FF> 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<FF> {
+      public:
+        uint32_t circuit_size;
+        uint32_t public_input_size;
+        uint32_t pub_inputs_offset;
+        std::vector<FF> 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<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>> sumcheck_univariates;
+        std::array<FF, NUM_ALL_ENTITIES> sumcheck_evaluations;
+        std::vector<Commitment> zm_cq_comms;
+        Commitment zm_cq_comm;
+        Commitment zm_pi_comm;
+
+        Transcript() = default;
+
+        Transcript(const std::vector<uint8_t>& proof)
+            : BaseTranscript<FF>(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<uint32_t>(proof_data, num_bytes_read);
+            size_t log_n = numeric::get_msb(circuit_size);
+
+            public_input_size = deserialize_from_buffer<uint32_t>(proof_data, num_bytes_read);
+            pub_inputs_offset = deserialize_from_buffer<uint32_t>(proof_data, num_bytes_read);
+            for (size_t i = 0; i < public_input_size; ++i) {
+                public_inputs.push_back(deserialize_from_buffer<FF>(proof_data, num_bytes_read));
+            }
+            w_l_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            w_r_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            w_o_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            ecc_op_wire_1_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            ecc_op_wire_2_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            ecc_op_wire_3_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            ecc_op_wire_4_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            sorted_accum_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            w_4_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            z_perm_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            z_lookup_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                sumcheck_univariates.push_back(
+                    deserialize_from_buffer<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
+                        proof_data, num_bytes_read));
+            }
+            sumcheck_evaluations =
+                deserialize_from_buffer<std::array<FF, NUM_ALL_ENTITIES>>(proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                zm_cq_comms.push_back(deserialize_from_buffer<Commitment>(proof_data, num_bytes_read));
+            }
+            zm_cq_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            zm_pi_comm = deserialize_from_buffer<Commitment>(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 <typename BuilderType> 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<FF> {
+      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<FF> 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<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>> sumcheck_univariates;
+        std::array<FF, NUM_ALL_ENTITIES> sumcheck_evaluations;
+        std::vector<Commitment> zm_cq_comms;
+        Commitment zm_cq_comm;
+        Commitment zm_pi_comm;
+
+        Transcript() = default;
+
+        // Used by verifier to initialize the transcript
+        Transcript(const std::vector<uint8_t>& proof)
+            : BaseTranscript<FF>(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<uint32_t>("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<uint32_t>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            size_t log_n = numeric::get_msb(circuit_size);
+
+            public_input_size = deserialize_from_buffer<uint32_t>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            pub_inputs_offset = deserialize_from_buffer<uint32_t>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < public_input_size; ++i) {
+                public_inputs.push_back(deserialize_from_buffer<FF>(BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            w_l_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            w_r_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            w_o_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            ecc_op_wire_1_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            ecc_op_wire_2_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            ecc_op_wire_3_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            ecc_op_wire_4_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            sorted_accum_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            w_4_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            z_perm_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            z_lookup_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                sumcheck_univariates.push_back(
+                    deserialize_from_buffer<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
+                        BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            sumcheck_evaluations = deserialize_from_buffer<std::array<FF, NUM_ALL_ENTITIES>>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                zm_cq_comms.push_back(
+                    deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            zm_cq_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            zm_pi_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::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<FF>::proof_data.size();
+            BaseTranscript<FF>::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<FF>::proof_data);
+            serialize_to_buffer(public_input_size, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(pub_inputs_offset, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < public_input_size; ++i) {
+                serialize_to_buffer(public_inputs[i], BaseTranscript<FF>::proof_data);
+            }
+            serialize_to_buffer(w_l_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(w_r_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(w_o_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(ecc_op_wire_1_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(ecc_op_wire_2_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(ecc_op_wire_3_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(ecc_op_wire_4_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(sorted_accum_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(w_4_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(z_perm_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(z_lookup_comm, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < log_n; ++i) {
+                serialize_to_buffer(sumcheck_univariates[i], BaseTranscript<FF>::proof_data);
+            }
+            serialize_to_buffer(sumcheck_evaluations, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < log_n; ++i) {
+                serialize_to_buffer(zm_cq_comms[i], BaseTranscript<FF>::proof_data);
+            }
+            serialize_to_buffer(zm_cq_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(zm_pi_comm, BaseTranscript<FF>::proof_data);
+
+            // sanity check to make sure we generate the same length of proof as before.
+            ASSERT(BaseTranscript<FF>::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<Commitment, CommitmentHandle> {
       public:
-        VerifierCommitments(std::shared_ptr<VerificationKey> verification_key, VerifierTranscript<FF> transcript)
+        VerifierCommitments(std::shared_ptr<VerificationKey> verification_key,
+                            [[maybe_unused]] const BaseTranscript<FF>& transcript)
         {
             static_cast<void>(transcript);
             q_m = verification_key->q_m;
@@ -418,6 +419,127 @@ class Ultra {
         std::vector<FF> 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<FF> {
+      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<FF> 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<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>> sumcheck_univariates;
+        std::array<FF, NUM_ALL_ENTITIES> sumcheck_evaluations;
+        std::vector<Commitment> zm_cq_comms;
+        Commitment zm_cq_comm;
+        Commitment zm_pi_comm;
+
+        Transcript() = default;
+
+        // Used by verifier to initialize the transcript
+        Transcript(const std::vector<uint8_t>& proof)
+            : BaseTranscript<FF>(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<uint32_t>("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<uint32_t>(proof_data, num_bytes_read);
+            size_t log_n = numeric::get_msb(circuit_size);
+
+            public_input_size = deserialize_from_buffer<uint32_t>(proof_data, num_bytes_read);
+            pub_inputs_offset = deserialize_from_buffer<uint32_t>(proof_data, num_bytes_read);
+            for (size_t i = 0; i < public_input_size; ++i) {
+                public_inputs.push_back(deserialize_from_buffer<FF>(proof_data, num_bytes_read));
+            }
+            w_l_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            w_r_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            w_o_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            sorted_accum_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            w_4_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            z_perm_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            z_lookup_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                sumcheck_univariates.push_back(
+                    deserialize_from_buffer<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
+                        proof_data, num_bytes_read));
+            }
+            sumcheck_evaluations =
+                deserialize_from_buffer<std::array<FF, NUM_ALL_ENTITIES>>(proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                zm_cq_comms.push_back(deserialize_from_buffer<Commitment>(proof_data, num_bytes_read));
+            }
+            zm_cq_comm = deserialize_from_buffer<Commitment>(proof_data, num_bytes_read);
+            zm_pi_comm = deserialize_from_buffer<Commitment>(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 <typename BuilderType> 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<FF> {
+      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<FF> 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<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>> sumcheck_univariates;
+        std::array<FF, NUM_ALL_ENTITIES> sumcheck_evaluations;
+        std::vector<Commitment> zm_cq_comms;
+        Commitment zm_cq_comm;
+        Commitment zm_pi_comm;
+
+        Transcript() = default;
+
+        // Used by verifier to initialize the transcript
+        Transcript(const std::vector<uint8_t>& proof)
+            : BaseTranscript<FF>(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<uint32_t>("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<uint32_t>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            size_t log_n = numeric::get_msb(circuit_size);
+
+            public_input_size = deserialize_from_buffer<uint32_t>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            pub_inputs_offset = deserialize_from_buffer<uint32_t>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < public_input_size; ++i) {
+                public_inputs.push_back(deserialize_from_buffer<FF>(BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            w_l_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            w_r_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            w_o_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            sorted_accum_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            w_4_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            z_perm_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            z_lookup_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                sumcheck_univariates.push_back(
+                    deserialize_from_buffer<barretenberg::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
+                        BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            sumcheck_evaluations = deserialize_from_buffer<std::array<FF, NUM_ALL_ENTITIES>>(
+                BaseTranscript<FF>::proof_data, num_bytes_read);
+            for (size_t i = 0; i < log_n; ++i) {
+                zm_cq_comms.push_back(
+                    deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read));
+            }
+            zm_cq_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::proof_data, num_bytes_read);
+            zm_pi_comm = deserialize_from_buffer<Commitment>(BaseTranscript<FF>::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<FF>::proof_data.size();
+            BaseTranscript<FF>::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<FF>::proof_data);
+            serialize_to_buffer(public_input_size, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(pub_inputs_offset, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < public_input_size; ++i) {
+                serialize_to_buffer(public_inputs[i], BaseTranscript<FF>::proof_data);
+            }
+            serialize_to_buffer(w_l_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(w_r_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(w_o_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(sorted_accum_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(w_4_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(z_perm_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(z_lookup_comm, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < log_n; ++i) {
+                serialize_to_buffer(sumcheck_univariates[i], BaseTranscript<FF>::proof_data);
+            }
+            serialize_to_buffer(sumcheck_evaluations, BaseTranscript<FF>::proof_data);
+            for (size_t i = 0; i < log_n; ++i) {
+                serialize_to_buffer(zm_cq_comms[i], BaseTranscript<FF>::proof_data);
+            }
+            serialize_to_buffer(zm_cq_comm, BaseTranscript<FF>::proof_data);
+            serialize_to_buffer(zm_pi_comm, BaseTranscript<FF>::proof_data);
+
+            // sanity check to make sure we generate the same length of proof as before.
+            ASSERT(BaseTranscript<FF>::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 Curve> class GeminiTest : public CommitmentTest<Curve> {
                                           std::vector<GroupElement> multilinear_commitments,
                                           std::vector<GroupElement> multilinear_commitments_to_be_shifted)
     {
-        auto prover_transcript = ProverTranscript<Fr>::init_empty();
+        auto prover_transcript = BaseTranscript<Fr>::prover_init_empty();
 
         const Fr rho = Fr::random_element();
 
@@ -79,7 +79,7 @@ template <class Curve> class GeminiTest : public CommitmentTest<Curve> {
         // 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<Fr>::init_empty(prover_transcript);
+        auto verifier_transcript = BaseTranscript<Fr>::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 <typename Curve> class IPA {
     static void compute_opening_proof(std::shared_ptr<CK> ck,
                                       const OpeningPair<Curve>& opening_pair,
                                       const Polynomial& polynomial,
-                                      ProverTranscript<Fr>& transcript)
+                                      BaseTranscript<Fr>& transcript)
     {
         ASSERT(opening_pair.challenge != 0 && "The challenge point should not be zero");
         auto poly_degree = static_cast<size_t>(polynomial.size());
@@ -134,9 +134,7 @@ template <typename Curve> class IPA {
      *
      * @return true/false depending on if the proof verifies
      */
-    static bool verify(std::shared_ptr<VK> vk,
-                       const OpeningClaim<Curve>& opening_claim,
-                       VerifierTranscript<Fr>& transcript)
+    static bool verify(std::shared_ptr<VK> vk, const OpeningClaim<Curve>& opening_claim, BaseTranscript<Fr>& transcript)
     {
         auto poly_degree = static_cast<size_t>(transcript.template receive_from_prover<uint64_t>("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<Curve> opening_claim{ opening_pair, commitment };
 
     // initialize empty prover transcript
-    ProverTranscript<Fr> prover_transcript;
+    BaseTranscript<Fr> prover_transcript;
     IPA::compute_opening_proof(this->ck(), opening_pair, poly, prover_transcript);
 
     // initialize verifier transcript from proof data
-    VerifierTranscript<Fr> verifier_transcript{ prover_transcript.proof_data };
+    BaseTranscript<Fr> 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<Fr>::init_empty();
+    auto prover_transcript = BaseTranscript<Fr>::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<Fr>::init_empty(prover_transcript);
+    auto verifier_transcript = BaseTranscript<Fr>::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 <typename Curve> class KZG {
     static void compute_opening_proof(std::shared_ptr<CK> ck,
                                       const OpeningPair<Curve>& opening_pair,
                                       const Polynomial& polynomial,
-                                      ProverTranscript<Fr>& prover_trancript)
+                                      BaseTranscript<Fr>& prover_trancript)
     {
         Polynomial quotient(polynomial);
         quotient[0] -= opening_pair.evaluation;
@@ -55,7 +55,7 @@ template <typename Curve> class KZG {
      */
     static bool verify(std::shared_ptr<VK> vk,
                        const OpeningClaim<Curve>& claim,
-                       VerifierTranscript<Fr>& verifier_transcript)
+                       BaseTranscript<Fr>& verifier_transcript)
     {
         auto quotient_commitment = verifier_transcript.template receive_from_prover<Commitment>("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<TypeParam>{ challenge, evaluation };
     auto opening_claim = OpeningClaim<TypeParam>{ opening_pair, commitment };
 
-    auto prover_transcript = ProverTranscript<Fr>::init_empty();
+    auto prover_transcript = BaseTranscript<Fr>::prover_init_empty();
 
     KZG::compute_opening_proof(this->ck(), opening_pair, witness, prover_transcript);
 
-    auto verifier_transcript = VerifierTranscript<Fr>::init_empty(prover_transcript);
+    auto verifier_transcript = BaseTranscript<Fr>::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<Fr>::init_empty();
+    auto prover_transcript = BaseTranscript<Fr>::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<Fr>::init_empty(prover_transcript);
+    auto verifier_transcript = BaseTranscript<Fr>::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<Fr>::init_empty();
+    auto prover_transcript = BaseTranscript<Fr>::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<Fr>::init_empty(prover_transcript);
+    auto verifier_transcript = BaseTranscript<Fr>::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 Curve> class ZeroMorphTest : public CommitmentTest<Curve> {
             g_commitments.emplace_back(f_commitments[i]);
         }
 
-        // Initialize an empty ProverTranscript
-        auto prover_transcript = ProverTranscript<Fr>::init_empty();
+        // Initialize an empty BaseTranscript
+        auto prover_transcript = BaseTranscript<Fr>::prover_init_empty();
 
         // Execute Prover protocol
         {
@@ -147,7 +147,7 @@ template <class Curve> class ZeroMorphTest : public CommitmentTest<Curve> {
             prover_transcript.send_to_verifier("ZM:PI", pi_commitment);
         }
 
-        auto verifier_transcript = VerifierTranscript<Fr>::init_empty(prover_transcript);
+        auto verifier_transcript = BaseTranscript<Fr>::verifier_init_empty(prover_transcript);
 
         // Execute Verifier protocol
         {
@@ -332,8 +332,8 @@ template <class Curve> class ZeroMorphWithConcatenationTest : public CommitmentT
             concatenation_groups_commitments.emplace_back(concatenation_group_commitment);
         }
 
-        // Initialize an empty ProverTranscript
-        auto prover_transcript = ProverTranscript<Fr>::init_empty();
+        // Initialize an empty BaseTranscript
+        auto prover_transcript = BaseTranscript<Fr>::prover_init_empty();
 
         // Execute Prover protocol
         {
@@ -417,7 +417,7 @@ template <class Curve> class ZeroMorphWithConcatenationTest : public CommitmentT
             prover_transcript.send_to_verifier("ZM:PI", pi_commitment);
         }
 
-        auto verifier_transcript = VerifierTranscript<Fr>::init_empty(prover_transcript);
+        auto verifier_transcript = BaseTranscript<Fr>::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 <ECCVMFlavor Flavor> plonk::proof& ECCVMProver_<Flavor>::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 <ECCVMFlavor Flavor> 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<ProvingKey> input_key, std::shared_ptr<PCSCommitmentKey> commitment_key);
@@ -39,7 +40,7 @@ template <ECCVMFlavor Flavor> class ECCVMProver_ {
     plonk::proof& export_proof();
     plonk::proof& construct_proof();
 
-    ProverTranscript<FF> transcript;
+    Transcript transcript;
 
     std::vector<FF> 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 <typename Flavor> bool ECCVMVerifier_<Flavor>::verify_proof(const plonk
     using Shplonk = pcs::shplonk::ShplonkVerifier_<Curve>;
     using VerifierCommitments = typename Flavor::VerifierCommitments;
     using CommitmentLabels = typename Flavor::CommitmentLabels;
+    using Transcript = typename Flavor::Transcript;
 
     RelationParameters<FF> relation_parameters;
 
-    transcript = VerifierTranscript<FF>{ proof.proof_data };
+    transcript = Transcript{ proof.proof_data };
 
     auto commitments = VerifierCommitments(key, transcript);
     auto commitment_labels = CommitmentLabels();
@@ -168,7 +169,7 @@ template <typename Flavor> bool ECCVMVerifier_<Flavor>::verify_proof(const plonk
         transcript.template receive_from_prover<Commitment>(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 <typename Flavor> 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<VerificationKey> verifier_key = nullptr);
@@ -16,7 +17,7 @@ template <typename Flavor> class ECCVMVerifier_ {
                    std::map<std::string, Commitment> commitments,
                    std::map<std::string, FF> pcs_fr_elements,
                    std::shared_ptr<VerifierCommitmentKey> pcs_verification_key,
-                   VerifierTranscript<FF> transcript)
+                   Transcript& transcript)
         : key(std::move(key))
         , commitments(std::move(commitments))
         , pcs_fr_elements(std::move(pcs_fr_elements))
@@ -35,7 +36,7 @@ template <typename Flavor> class ECCVMVerifier_ {
     std::map<std::string, Commitment> commitments;
     std::map<std::string, FF> pcs_fr_elements;
     std::shared_ptr<VerifierCommitmentKey> pcs_verification_key;
-    VerifierTranscript<FF> transcript;
+    Transcript transcript;
 };
 
 extern template class ECCVMVerifier_<honk::flavor::ECCVM>;
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 <typename Flavor> class MergeProver_ {
     using OpeningPair = typename pcs::OpeningPair<Curve>;
 
   public:
-    ProverTranscript<FF> transcript;
+    BaseTranscript<FF> transcript;
     std::shared_ptr<ECCOpQueue> op_queue;
     std::shared_ptr<CommitmentKey> 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_<Flavor>::MergeVerifier_(std::unique_ptr<VerifierCommitmentKey> ve
  */
 template <typename Flavor> bool MergeVerifier_<Flavor>::verify_proof(const plonk::proof& proof)
 {
-    transcript = VerifierTranscript<FF>{ proof.proof_data };
+    transcript = BaseTranscript<FF>{ proof.proof_data };
 
     // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i]
     std::array<Commitment, Flavor::NUM_WIRES> 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 <typename Flavor> class MergeVerifier_ {
     using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey;
 
   public:
-    VerifierTranscript<FF> transcript;
+    BaseTranscript<FF> transcript;
     std::shared_ptr<ECCOpQueue> op_queue;
     std::shared_ptr<VerifierCommitmentKey> 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 ProverInstances_> class ProtoGalaxyProver_ {
     using RelationEvaluations = typename Flavor::TupleOfArraysOfValues;
 
     ProverInstances instances;
-    ProverTranscript<FF> transcript;
+    BaseTranscript<FF> 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 <class VerifierInstances>
 VerifierFoldingResult<typename VerifierInstances::Flavor> ProtoGalaxyVerifier_<
     VerifierInstances>::fold_public_parameters(std::vector<uint8_t> fold_data)
 {
-    transcript = VerifierTranscript<FF>{ fold_data };
+    transcript = BaseTranscript<FF>{ 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 VerifierInstances> class ProtoGalaxyVerifier_ {
     using Instance = typename VerifierInstances::Instance;
     using VerificationKey = typename Flavor::VerificationKey;
     VerifierInstances verifier_instances;
-    VerifierTranscript<FF> transcript;
+    BaseTranscript<FF> 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 <UltraFlavor Flavor> class UltraProver_ {
     using CommitmentLabels = typename Flavor::CommitmentLabels;
     using Curve = typename Flavor::Curve;
     using Instance = ProverInstance_<Flavor>;
+    using Transcript = typename Flavor::Transcript;
 
   public:
     explicit UltraProver_(std::shared_ptr<Instance>);
@@ -33,7 +34,7 @@ template <UltraFlavor Flavor> class UltraProver_ {
     plonk::proof& export_proof();
     plonk::proof& construct_proof();
 
-    ProverTranscript<FF> transcript;
+    Transcript transcript;
 
     std::vector<FF> 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 <typename Flavor> bool UltraVerifier_<Flavor>::verify_proof(const plonk
 
     proof_system::RelationParameters<FF> relation_parameters;
 
-    transcript = VerifierTranscript<FF>{ proof.proof_data };
+    transcript = BaseTranscript<FF>{ 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 <typename Flavor> class UltraVerifier_ {
     std::shared_ptr<VerificationKey> key;
     std::map<std::string, Commitment> commitments;
     std::shared_ptr<VerifierCommitmentKey> pcs_verification_key;
-    VerifierTranscript<FF> transcript;
+    BaseTranscript<FF> transcript;
 };
 
 extern template class UltraVerifier_<honk::flavor::Ultra>;
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<FF>;
+    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<FF, 4> f0 = { v00, v10, v01, v11 };
 
     auto full_polynomials = std::array<std::span<FF>, 1>({ f0 });
-    auto transcript = Transcript::init_empty();
+    Transcript transcript = Transcript::prover_init_empty();
     auto sumcheck = SumcheckProver<Flavor>(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<FF>;
+    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<FF, 4> f0 = { v00, v10, v01, v11 };
 
     auto full_polynomials = std::array<std::span<FF>, 1>({ f0 });
-    auto transcript = Transcript::init_empty();
+    Transcript transcript = Transcript::prover_init_empty();
     auto sumcheck = SumcheckProver<Flavor>(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<FF>;
+    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<FF, 8> f0 = { v000, v100, v010, v110, v001, v101, v011, v111 };
 
     auto full_polynomials = std::array<std::span<FF>, 1>({ f0 });
-    auto transcript = Transcript::init_empty();
+    Transcript transcript = Transcript::prover_init_empty();
     auto sumcheck = SumcheckProver<Flavor>(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<FF>;
+    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<FF, 8> f0 = { v000, v100, v010, v110, v001, v101, v011, v111 };
 
     auto full_polynomials = std::array<std::span<FF>, 1>({ f0 });
-    auto transcript = Transcript::init_empty();
+    Transcript transcript = Transcript::prover_init_empty();
     auto sumcheck = SumcheckProver<Flavor>(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<FF>;
+    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<FF, 8> f2 = { v000[2], v100[2], v010[2], v110[2], v001[2], v101[2], v011[2], v111[2] };
 
     auto full_polynomials = std::array<std::span<FF>, 3>{ f0, f1, f2 };
-    auto transcript = Transcript::init_empty();
+    Transcript transcript = Transcript::prover_init_empty();
     auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript);
 
     std::array<FF, 3> 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 <typename Flavor> 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_<Flavor>;
 
-    ProverTranscript<FF>& transcript;
+    Transcript& transcript;
     const size_t multivariate_n;
     const size_t multivariate_d;
     SumcheckProverRound<Flavor> round;
@@ -59,7 +60,7 @@ template <typename Flavor> class SumcheckProver {
     PartiallyEvaluatedMultivariates partially_evaluated_polynomials;
 
     // prover instantiates sumcheck with circuit size and a prover transcript
-    SumcheckProver(size_t multivariate_n, ProverTranscript<FF>& 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<FF>::init_empty();
+    Flavor::Transcript transcript = Flavor::Transcript::prover_init_empty();
 
     auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript);
 
@@ -169,7 +169,7 @@ TEST_F(SumcheckTests, Prover)
     }
     auto full_polynomials = construct_ultra_full_polynomials(random_polynomials);
 
-    auto transcript = ProverTranscript<FF>::init_empty();
+    Flavor::Transcript transcript = Flavor::Transcript::prover_init_empty();
 
     auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript);
 
@@ -243,13 +243,13 @@ TEST_F(SumcheckTests, ProverAndVerifierSimple)
             .public_input_delta = FF::one(),
         };
 
-        auto prover_transcript = ProverTranscript<FF>::init_empty();
+        Flavor::Transcript prover_transcript = Flavor::Transcript::prover_init_empty();
 
         auto sumcheck_prover = SumcheckProver<Flavor>(multivariate_n, prover_transcript);
 
         auto prover_output = sumcheck_prover.prove(full_polynomials, relation_parameters);
 
-        auto verifier_transcript = VerifierTranscript<FF>::init_empty(prover_transcript);
+        Flavor::Transcript verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript);
 
         auto sumcheck_verifier = SumcheckVerifier<Flavor>(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<FF>::init_empty();
+    Flavor::Transcript prover_transcript = Flavor::Transcript::prover_init_empty();
     auto circuit_size = instance->proving_key->circuit_size;
 
     auto sumcheck_prover = SumcheckProver<Flavor>(circuit_size, prover_transcript);
 
     auto prover_output = sumcheck_prover.prove(instance->prover_polynomials, instance->relation_parameters);
 
-    auto verifier_transcript = VerifierTranscript<FF>::init_empty(prover_transcript);
+    Flavor::Transcript verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript);
 
     auto sumcheck_verifier = SumcheckVerifier<Flavor>(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 <gtest/gtest.h>
+
+using namespace proof_system::honk;
+
+template <typename Flavor> class ECCVMTranscriptTests : public ::testing::Test {
+  public:
+    void SetUp() override
+    {
+        if constexpr (std::is_same<Flavor, flavor::ECCVMGrumpkin>::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<Flavor>) {
+            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<size_t>(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<Flavor> generate_trace(numeric::random::Engine* engine = nullptr)
+    {
+        proof_system::ECCVMCircuitBuilder<Flavor> 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<flavor::ECCVM, flavor::ECCVMGrumpkin>;
+
+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_<Flavor>();
+    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_<Flavor>();
+    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_<Flavor>();
+    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<typename Flavor::Commitment>(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 <gtest/gtest.h>
+
+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<Flavor::Commitment>(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 <typename FF> 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<uint8_t>& 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<uint8_t, HASH_OUTPUT_SIZE> previous_challenge_buffer{}; // default-initialized to zeros
@@ -143,7 +154,44 @@ template <typename FF> 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 <typename T> void serialize_to_buffer(const T& element, std::vector<uint8_t>& 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 <typename T> T deserialize_from_buffer(const std::vector<uint8_t>& 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<T>(element_bytes);
+
+        return element;
+    }
+
   public:
+    // Contains the raw data sent by the prover.
+    std::vector<uint8_t> 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 <typename FF> 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 <typename FF> class ProverTranscript : public BaseTranscript<FF> {
-
-  public:
-    /// Contains the raw data sent by the prover.
-    std::vector<uint8_t> 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 <typename FF> class ProverTranscript : public BaseTranscript<FF> {
         BaseTranscript<FF>::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 <class T> 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<FF>::consume_prover_element_bytes(label, element_bytes);
+
+        T element = from_buffer<T>(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<FF> prover_init_empty()
     {
-        ProverTranscript<FF> transcript;
+        BaseTranscript<FF> transcript;
         constexpr uint32_t init{ 42 }; // arbitrary
         transcript.send_to_verifier("Init", init);
         return transcript;
     };
-};
-
-template <class FF> class VerifierTranscript : public BaseTranscript<FF> {
-
-    /// Contains the raw data sent by the prover.
-    std::vector<uint8_t> proof_data_;
-    size_t num_bytes_read_ = 0;
-
-  public:
-    VerifierTranscript() = default;
-
-    explicit VerifierTranscript(const std::vector<uint8_t>& 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<FF>& transcript)
+    static BaseTranscript<FF> verifier_init_empty(const BaseTranscript<FF>& transcript)
     {
-        VerifierTranscript<FF> verifier_transcript{ transcript.proof_data };
+        BaseTranscript<FF> verifier_transcript{ transcript.proof_data };
         [[maybe_unused]] auto _ = verifier_transcript.template receive_from_prover<uint32_t>("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 <class T> 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<FF>::consume_prover_element_bytes(label, element_bytes);
+    void print() { manifest.print(); }
 
-        T element = from_buffer<T>(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 <gtest/gtest.h>
 
 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<Flavor>) {
-            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<FF>::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<Flavor::Commitment>(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<std::shared_ptr<ProverInstance_<Flavor>>> 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<FF>::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 <typename FF>
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 <typename Builder> class Transcript {
   public:
     using field_ct = field_t<Builder>;
     using FF = barretenberg::fr;
-    using VerifierTranscript = proof_system::honk::VerifierTranscript<FF>;
+    using BaseTranscript = proof_system::honk::BaseTranscript<FF>;
     using StdlibTypes = utility::StdlibTypesUtility<Builder>;
 
-    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_<Builder>;
 using FF = barretenberg::fr;
-using ProverTranscript = ::proof_system::honk::ProverTranscript<FF>;
-using VerifierTranscript = ::proof_system::honk::VerifierTranscript<FF>;
+using BaseTranscript = ::proof_system::honk::BaseTranscript<FF>;
 
 /**
  * @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<UltraFlavor, LENGTH>(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<UltraFlavor, LENGTH>(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<FF>("scalar");
     auto native_commitment = native_transcript.template receive_from_prover<Commitment>("commitment");
     auto native_evaluations = native_transcript.template receive_from_prover<std::array<FF, LENGTH>>("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 <typename BuilderType> 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 <typename BuilderType> 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;