diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index 2c195baea85..bf94b36b65d 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -32,12 +32,13 @@ class GoblinUltra { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 48; // 43 (UH) + 4 op wires + 1 op wire "selector" + // NUM = 43 (UH) + 4 op wires + 1 op wire "selector" + 3 (calldata + calldata_read_counts + q_busread) + static constexpr size_t NUM_ALL_ENTITIES = 51; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 26; // 25 (UH) + 1 op wire "selector" + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 27; // 25 (UH) + 1 op wire "selector" + q_busread // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 15; // 11 (UH) + 4 op wires + static constexpr size_t NUM_WITNESS_ENTITIES = 17; // 11 (UH) + 4 op wires + (calldata + calldata_read_counts) using GrandProductRelations = std::tuple, proof_system::LookupRelation>; @@ -89,27 +90,28 @@ class GoblinUltra { DataType& q_elliptic = std::get<8>(this->_data); DataType& q_aux = std::get<9>(this->_data); DataType& q_lookup = std::get<10>(this->_data); - DataType& sigma_1 = std::get<11>(this->_data); - DataType& sigma_2 = std::get<12>(this->_data); - DataType& sigma_3 = std::get<13>(this->_data); - DataType& sigma_4 = std::get<14>(this->_data); - DataType& id_1 = std::get<15>(this->_data); - DataType& id_2 = std::get<16>(this->_data); - DataType& id_3 = std::get<17>(this->_data); - DataType& id_4 = std::get<18>(this->_data); - DataType& table_1 = std::get<19>(this->_data); - DataType& table_2 = std::get<20>(this->_data); - DataType& table_3 = std::get<21>(this->_data); - DataType& table_4 = std::get<22>(this->_data); - DataType& lagrange_first = std::get<23>(this->_data); - DataType& lagrange_last = std::get<24>(this->_data); - DataType& lagrange_ecc_op = std::get<25>(this->_data); // indicator poly for ecc op gates + DataType& q_busread = std::get<11>(this->_data); + DataType& sigma_1 = std::get<12>(this->_data); + DataType& sigma_2 = std::get<13>(this->_data); + DataType& sigma_3 = std::get<14>(this->_data); + DataType& sigma_4 = std::get<15>(this->_data); + DataType& id_1 = std::get<16>(this->_data); + DataType& id_2 = std::get<17>(this->_data); + DataType& id_3 = std::get<18>(this->_data); + DataType& id_4 = std::get<19>(this->_data); + DataType& table_1 = std::get<20>(this->_data); + DataType& table_2 = std::get<21>(this->_data); + DataType& table_3 = std::get<22>(this->_data); + DataType& table_4 = std::get<23>(this->_data); + DataType& lagrange_first = std::get<24>(this->_data); + DataType& lagrange_last = std::get<25>(this->_data); + DataType& lagrange_ecc_op = std::get<26>(this->_data); // indicator poly for ecc op gates static constexpr CircuitType CIRCUIT_TYPE = CircuitBuilder::CIRCUIT_TYPE; std::vector get_selectors() override { - return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup }; + return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup, q_busread }; }; std::vector get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3, sigma_4 }; }; std::vector get_id_polynomials() override { return { id_1, id_2, id_3, id_4 }; }; @@ -139,6 +141,8 @@ class GoblinUltra { DataType& ecc_op_wire_2 = std::get<12>(this->_data); DataType& ecc_op_wire_3 = std::get<13>(this->_data); DataType& ecc_op_wire_4 = std::get<14>(this->_data); + DataType& calldata = std::get<15>(this->_data); + DataType& calldata_read_counts = std::get<16>(this->_data); std::vector get_wires() override { return { w_l, w_r, w_o, w_4 }; }; std::vector get_ecc_op_wires() @@ -172,43 +176,46 @@ class GoblinUltra { DataType& q_elliptic = std::get<8>(this->_data); DataType& q_aux = std::get<9>(this->_data); DataType& q_lookup = std::get<10>(this->_data); - DataType& sigma_1 = std::get<11>(this->_data); - DataType& sigma_2 = std::get<12>(this->_data); - DataType& sigma_3 = std::get<13>(this->_data); - DataType& sigma_4 = std::get<14>(this->_data); - DataType& id_1 = std::get<15>(this->_data); - DataType& id_2 = std::get<16>(this->_data); - DataType& id_3 = std::get<17>(this->_data); - DataType& id_4 = std::get<18>(this->_data); - DataType& table_1 = std::get<19>(this->_data); - DataType& table_2 = std::get<20>(this->_data); - DataType& table_3 = std::get<21>(this->_data); - DataType& table_4 = std::get<22>(this->_data); - DataType& lagrange_first = std::get<23>(this->_data); - DataType& lagrange_last = std::get<24>(this->_data); - DataType& lagrange_ecc_op = std::get<25>(this->_data); - DataType& w_l = std::get<26>(this->_data); - DataType& w_r = std::get<27>(this->_data); - DataType& w_o = std::get<28>(this->_data); - DataType& w_4 = std::get<29>(this->_data); - DataType& sorted_accum = std::get<30>(this->_data); - DataType& z_perm = std::get<31>(this->_data); - DataType& z_lookup = std::get<32>(this->_data); - DataType& ecc_op_wire_1 = std::get<33>(this->_data); - DataType& ecc_op_wire_2 = std::get<34>(this->_data); - DataType& ecc_op_wire_3 = std::get<35>(this->_data); - DataType& ecc_op_wire_4 = std::get<36>(this->_data); - DataType& table_1_shift = std::get<37>(this->_data); - DataType& table_2_shift = std::get<38>(this->_data); - DataType& table_3_shift = std::get<39>(this->_data); - DataType& table_4_shift = std::get<40>(this->_data); - DataType& w_l_shift = std::get<41>(this->_data); - DataType& w_r_shift = std::get<42>(this->_data); - DataType& w_o_shift = std::get<43>(this->_data); - DataType& w_4_shift = std::get<44>(this->_data); - DataType& sorted_accum_shift = std::get<45>(this->_data); - DataType& z_perm_shift = std::get<46>(this->_data); - DataType& z_lookup_shift = std::get<47>(this->_data); + DataType& q_busread = std::get<11>(this->_data); + DataType& sigma_1 = std::get<12>(this->_data); + DataType& sigma_2 = std::get<13>(this->_data); + DataType& sigma_3 = std::get<14>(this->_data); + DataType& sigma_4 = std::get<15>(this->_data); + DataType& id_1 = std::get<16>(this->_data); + DataType& id_2 = std::get<17>(this->_data); + DataType& id_3 = std::get<18>(this->_data); + DataType& id_4 = std::get<19>(this->_data); + DataType& table_1 = std::get<20>(this->_data); + DataType& table_2 = std::get<21>(this->_data); + DataType& table_3 = std::get<22>(this->_data); + DataType& table_4 = std::get<23>(this->_data); + DataType& lagrange_first = std::get<24>(this->_data); + DataType& lagrange_last = std::get<25>(this->_data); + DataType& lagrange_ecc_op = std::get<26>(this->_data); + DataType& w_l = std::get<27>(this->_data); + DataType& w_r = std::get<28>(this->_data); + DataType& w_o = std::get<29>(this->_data); + DataType& w_4 = std::get<30>(this->_data); + DataType& sorted_accum = std::get<31>(this->_data); + DataType& z_perm = std::get<32>(this->_data); + DataType& z_lookup = std::get<33>(this->_data); + DataType& ecc_op_wire_1 = std::get<34>(this->_data); + DataType& ecc_op_wire_2 = std::get<35>(this->_data); + DataType& ecc_op_wire_3 = std::get<36>(this->_data); + DataType& ecc_op_wire_4 = std::get<37>(this->_data); + DataType& calldata = std::get<38>(this->_data); + DataType& calldata_read_counts = std::get<39>(this->_data); + DataType& table_1_shift = std::get<40>(this->_data); + DataType& table_2_shift = std::get<41>(this->_data); + DataType& table_3_shift = std::get<42>(this->_data); + DataType& table_4_shift = std::get<43>(this->_data); + DataType& w_l_shift = std::get<44>(this->_data); + DataType& w_r_shift = std::get<45>(this->_data); + DataType& w_o_shift = std::get<46>(this->_data); + DataType& w_4_shift = std::get<47>(this->_data); + DataType& sorted_accum_shift = std::get<48>(this->_data); + DataType& z_perm_shift = std::get<49>(this->_data); + DataType& z_lookup_shift = std::get<50>(this->_data); std::vector get_wires() override { return { w_l, w_r, w_o, w_4 }; }; std::vector get_ecc_op_wires() @@ -218,25 +225,46 @@ class GoblinUltra { // Gemini-specific getters. std::vector get_unshifted() override { - return { q_c, q_l, - q_r, q_o, - q_4, q_m, - q_arith, q_sort, - q_elliptic, q_aux, - q_lookup, sigma_1, - sigma_2, sigma_3, - sigma_4, id_1, - id_2, id_3, - id_4, table_1, - table_2, table_3, - table_4, lagrange_first, - lagrange_last, lagrange_ecc_op, - w_l, w_r, - w_o, w_4, - sorted_accum, z_perm, - z_lookup, ecc_op_wire_1, - ecc_op_wire_2, ecc_op_wire_3, - ecc_op_wire_4 }; + return { q_c, + q_l, + q_r, + q_o, + q_4, + q_m, + q_arith, + q_sort, + q_elliptic, + q_aux, + q_lookup, + q_busread, + sigma_1, + sigma_2, + sigma_3, + sigma_4, + id_1, + id_2, + id_3, + id_4, + table_1, + table_2, + table_3, + table_4, + lagrange_first, + lagrange_last, + lagrange_ecc_op, + w_l, + w_r, + w_o, + w_4, + sorted_accum, + z_perm, + z_lookup, + ecc_op_wire_1, + ecc_op_wire_2, + ecc_op_wire_3, + ecc_op_wire_4, + calldata, + calldata_read_counts }; }; std::vector get_to_be_shifted() override { @@ -384,6 +412,8 @@ class GoblinUltra { ecc_op_wire_2 = "ECC_OP_WIRE_2"; ecc_op_wire_3 = "ECC_OP_WIRE_3"; ecc_op_wire_4 = "ECC_OP_WIRE_4"; + calldata = "CALLDATA"; + calldata_read_counts = "CALLDATA_READ_COUNTS"; // The ones beginning with "__" are only used for debugging q_c = "__Q_C"; @@ -397,6 +427,7 @@ class GoblinUltra { q_elliptic = "__Q_ELLIPTIC"; q_aux = "__Q_AUX"; q_lookup = "__Q_LOOKUP"; + q_busread = "__Q_BUSREAD"; sigma_1 = "__SIGMA_1"; sigma_2 = "__SIGMA_2"; sigma_3 = "__SIGMA_3"; @@ -432,6 +463,7 @@ class GoblinUltra { q_elliptic = verification_key->q_elliptic; q_aux = verification_key->q_aux; q_lookup = verification_key->q_lookup; + q_busread = verification_key->q_busread; sigma_1 = verification_key->sigma_1; sigma_2 = verification_key->sigma_2; sigma_3 = verification_key->sigma_3; @@ -473,6 +505,8 @@ class GoblinUltra { Commitment ecc_op_wire_2_comm; Commitment ecc_op_wire_3_comm; Commitment ecc_op_wire_4_comm; + Commitment calldata_comm; + Commitment calldata_read_counts_comm; Commitment sorted_accum_comm; Commitment w_4_comm; Commitment z_perm_comm; @@ -507,6 +541,8 @@ class GoblinUltra { ecc_op_wire_2_comm = deserialize_from_buffer(proof_data, num_bytes_read); ecc_op_wire_3_comm = deserialize_from_buffer(proof_data, num_bytes_read); ecc_op_wire_4_comm = deserialize_from_buffer(proof_data, num_bytes_read); + calldata_comm = deserialize_from_buffer(proof_data, num_bytes_read); + calldata_read_counts_comm = deserialize_from_buffer(proof_data, num_bytes_read); sorted_accum_comm = deserialize_from_buffer(proof_data, num_bytes_read); w_4_comm = deserialize_from_buffer(proof_data, num_bytes_read); z_perm_comm = deserialize_from_buffer(proof_data, num_bytes_read); @@ -543,6 +579,8 @@ class GoblinUltra { 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(calldata_comm, proof_data); + serialize_to_buffer(calldata_read_counts_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); diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp index 9fcdbfcba3b..0e452c3ff62 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp @@ -61,12 +61,13 @@ template class GoblinUltraRecursive_ { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 48; // 43 (UH) + 4 op wires + 1 op wire "selector" + // NUM = 43 (UH) + 4 op wires + 1 op wire "selector" + 3 (calldata + calldata_read_counts + q_busread) + static constexpr size_t NUM_ALL_ENTITIES = 51; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 26; // 25 (UH) + 1 op wire "selector" + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 27; // 25 (UH) + 1 op wire "selector" + q_busread // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 15; // 11 (UH) + 4 op wires + static constexpr size_t NUM_WITNESS_ENTITIES = 17; // 11 (UH) + 4 op wires + (calldata + calldata_read_counts) // define the tuple of Relations that comprise the Sumcheck relation using Relations = std::tuple, @@ -108,27 +109,28 @@ template class GoblinUltraRecursive_ { DataType& q_elliptic = std::get<8>(this->_data); DataType& q_aux = std::get<9>(this->_data); DataType& q_lookup = std::get<10>(this->_data); - DataType& sigma_1 = std::get<11>(this->_data); - DataType& sigma_2 = std::get<12>(this->_data); - DataType& sigma_3 = std::get<13>(this->_data); - DataType& sigma_4 = std::get<14>(this->_data); - DataType& id_1 = std::get<15>(this->_data); - DataType& id_2 = std::get<16>(this->_data); - DataType& id_3 = std::get<17>(this->_data); - DataType& id_4 = std::get<18>(this->_data); - DataType& table_1 = std::get<19>(this->_data); - DataType& table_2 = std::get<20>(this->_data); - DataType& table_3 = std::get<21>(this->_data); - DataType& table_4 = std::get<22>(this->_data); - DataType& lagrange_first = std::get<23>(this->_data); - DataType& lagrange_last = std::get<24>(this->_data); - DataType& lagrange_ecc_op = std::get<25>(this->_data); // indicator poly for ecc op gates + DataType& q_busread = std::get<11>(this->_data); + DataType& sigma_1 = std::get<12>(this->_data); + DataType& sigma_2 = std::get<13>(this->_data); + DataType& sigma_3 = std::get<14>(this->_data); + DataType& sigma_4 = std::get<15>(this->_data); + DataType& id_1 = std::get<16>(this->_data); + DataType& id_2 = std::get<17>(this->_data); + DataType& id_3 = std::get<18>(this->_data); + DataType& id_4 = std::get<19>(this->_data); + DataType& table_1 = std::get<20>(this->_data); + DataType& table_2 = std::get<21>(this->_data); + DataType& table_3 = std::get<22>(this->_data); + DataType& table_4 = std::get<23>(this->_data); + DataType& lagrange_first = std::get<24>(this->_data); + DataType& lagrange_last = std::get<25>(this->_data); + DataType& lagrange_ecc_op = std::get<26>(this->_data); // indicator poly for ecc op gates static constexpr CircuitType CIRCUIT_TYPE = CircuitBuilder::CIRCUIT_TYPE; std::vector get_selectors() override { - return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup }; + return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup, q_busread }; }; std::vector get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3, sigma_4 }; }; std::vector get_id_polynomials() override { return { id_1, id_2, id_3, id_4 }; }; @@ -158,6 +160,8 @@ template class GoblinUltraRecursive_ { DataType& ecc_op_wire_2 = std::get<12>(this->_data); DataType& ecc_op_wire_3 = std::get<13>(this->_data); DataType& ecc_op_wire_4 = std::get<14>(this->_data); + DataType& calldata = std::get<15>(this->_data); + DataType& calldata_read_counts = std::get<16>(this->_data); std::vector get_wires() override { return { w_l, w_r, w_o, w_4 }; }; std::vector get_ecc_op_wires() @@ -191,43 +195,46 @@ template class GoblinUltraRecursive_ { DataType& q_elliptic = std::get<8>(this->_data); DataType& q_aux = std::get<9>(this->_data); DataType& q_lookup = std::get<10>(this->_data); - DataType& sigma_1 = std::get<11>(this->_data); - DataType& sigma_2 = std::get<12>(this->_data); - DataType& sigma_3 = std::get<13>(this->_data); - DataType& sigma_4 = std::get<14>(this->_data); - DataType& id_1 = std::get<15>(this->_data); - DataType& id_2 = std::get<16>(this->_data); - DataType& id_3 = std::get<17>(this->_data); - DataType& id_4 = std::get<18>(this->_data); - DataType& table_1 = std::get<19>(this->_data); - DataType& table_2 = std::get<20>(this->_data); - DataType& table_3 = std::get<21>(this->_data); - DataType& table_4 = std::get<22>(this->_data); - DataType& lagrange_first = std::get<23>(this->_data); - DataType& lagrange_last = std::get<24>(this->_data); - DataType& lagrange_ecc_op = std::get<25>(this->_data); - DataType& w_l = std::get<26>(this->_data); - DataType& w_r = std::get<27>(this->_data); - DataType& w_o = std::get<28>(this->_data); - DataType& w_4 = std::get<29>(this->_data); - DataType& sorted_accum = std::get<30>(this->_data); - DataType& z_perm = std::get<31>(this->_data); - DataType& z_lookup = std::get<32>(this->_data); - DataType& ecc_op_wire_1 = std::get<33>(this->_data); - DataType& ecc_op_wire_2 = std::get<34>(this->_data); - DataType& ecc_op_wire_3 = std::get<35>(this->_data); - DataType& ecc_op_wire_4 = std::get<36>(this->_data); - DataType& table_1_shift = std::get<37>(this->_data); - DataType& table_2_shift = std::get<38>(this->_data); - DataType& table_3_shift = std::get<39>(this->_data); - DataType& table_4_shift = std::get<40>(this->_data); - DataType& w_l_shift = std::get<41>(this->_data); - DataType& w_r_shift = std::get<42>(this->_data); - DataType& w_o_shift = std::get<43>(this->_data); - DataType& w_4_shift = std::get<44>(this->_data); - DataType& sorted_accum_shift = std::get<45>(this->_data); - DataType& z_perm_shift = std::get<46>(this->_data); - DataType& z_lookup_shift = std::get<47>(this->_data); + DataType& q_busread = std::get<11>(this->_data); + DataType& sigma_1 = std::get<12>(this->_data); + DataType& sigma_2 = std::get<13>(this->_data); + DataType& sigma_3 = std::get<14>(this->_data); + DataType& sigma_4 = std::get<15>(this->_data); + DataType& id_1 = std::get<16>(this->_data); + DataType& id_2 = std::get<17>(this->_data); + DataType& id_3 = std::get<18>(this->_data); + DataType& id_4 = std::get<19>(this->_data); + DataType& table_1 = std::get<20>(this->_data); + DataType& table_2 = std::get<21>(this->_data); + DataType& table_3 = std::get<22>(this->_data); + DataType& table_4 = std::get<23>(this->_data); + DataType& lagrange_first = std::get<24>(this->_data); + DataType& lagrange_last = std::get<25>(this->_data); + DataType& lagrange_ecc_op = std::get<26>(this->_data); + DataType& w_l = std::get<27>(this->_data); + DataType& w_r = std::get<28>(this->_data); + DataType& w_o = std::get<29>(this->_data); + DataType& w_4 = std::get<30>(this->_data); + DataType& sorted_accum = std::get<31>(this->_data); + DataType& z_perm = std::get<32>(this->_data); + DataType& z_lookup = std::get<33>(this->_data); + DataType& ecc_op_wire_1 = std::get<34>(this->_data); + DataType& ecc_op_wire_2 = std::get<35>(this->_data); + DataType& ecc_op_wire_3 = std::get<36>(this->_data); + DataType& ecc_op_wire_4 = std::get<37>(this->_data); + DataType& calldata = std::get<38>(this->_data); + DataType& calldata_read_counts = std::get<39>(this->_data); + DataType& table_1_shift = std::get<40>(this->_data); + DataType& table_2_shift = std::get<41>(this->_data); + DataType& table_3_shift = std::get<42>(this->_data); + DataType& table_4_shift = std::get<43>(this->_data); + DataType& w_l_shift = std::get<44>(this->_data); + DataType& w_r_shift = std::get<45>(this->_data); + DataType& w_o_shift = std::get<46>(this->_data); + DataType& w_4_shift = std::get<47>(this->_data); + DataType& sorted_accum_shift = std::get<48>(this->_data); + DataType& z_perm_shift = std::get<49>(this->_data); + DataType& z_lookup_shift = std::get<50>(this->_data); std::vector get_wires() override { return { w_l, w_r, w_o, w_4 }; }; std::vector get_ecc_op_wires() @@ -237,25 +244,46 @@ template class GoblinUltraRecursive_ { // Gemini-specific getters. std::vector get_unshifted() override { - return { q_c, q_l, - q_r, q_o, - q_4, q_m, - q_arith, q_sort, - q_elliptic, q_aux, - q_lookup, sigma_1, - sigma_2, sigma_3, - sigma_4, id_1, - id_2, id_3, - id_4, table_1, - table_2, table_3, - table_4, lagrange_first, - lagrange_last, lagrange_ecc_op, - w_l, w_r, - w_o, w_4, - sorted_accum, z_perm, - z_lookup, ecc_op_wire_1, - ecc_op_wire_2, ecc_op_wire_3, - ecc_op_wire_4 }; + return { q_c, + q_l, + q_r, + q_o, + q_4, + q_m, + q_arith, + q_sort, + q_elliptic, + q_aux, + q_lookup, + q_busread, + sigma_1, + sigma_2, + sigma_3, + sigma_4, + id_1, + id_2, + id_3, + id_4, + table_1, + table_2, + table_3, + table_4, + lagrange_first, + lagrange_last, + lagrange_ecc_op, + w_l, + w_r, + w_o, + w_4, + sorted_accum, + z_perm, + z_lookup, + ecc_op_wire_1, + ecc_op_wire_2, + ecc_op_wire_3, + ecc_op_wire_4, + calldata, + calldata_read_counts }; }; std::vector get_to_be_shifted() override { @@ -325,6 +353,7 @@ template class GoblinUltraRecursive_ { this->q_elliptic = Commitment::from_witness(builder, native_key->q_elliptic); this->q_aux = Commitment::from_witness(builder, native_key->q_aux); this->q_lookup = Commitment::from_witness(builder, native_key->q_lookup); + this->q_busread = Commitment::from_witness(builder, native_key->q_busread); this->sigma_1 = Commitment::from_witness(builder, native_key->sigma_1); this->sigma_2 = Commitment::from_witness(builder, native_key->sigma_2); this->sigma_3 = Commitment::from_witness(builder, native_key->sigma_3); @@ -375,6 +404,8 @@ template class GoblinUltraRecursive_ { this->ecc_op_wire_2 = "ECC_OP_WIRE_2"; this->ecc_op_wire_3 = "ECC_OP_WIRE_3"; this->ecc_op_wire_4 = "ECC_OP_WIRE_4"; + this->calldata = "CALLDATA"; + this->calldata_read_counts = "CALLDATA_READ_COUNTS"; // The ones beginning with "__" are only used for debugging this->q_c = "__Q_C"; @@ -388,6 +419,7 @@ template class GoblinUltraRecursive_ { this->q_elliptic = "__Q_ELLIPTIC"; this->q_aux = "__Q_AUX"; this->q_lookup = "__Q_LOOKUP"; + this->q_busread = "__Q_BUSREAD"; this->sigma_1 = "__SIGMA_1"; this->sigma_2 = "__SIGMA_2"; this->sigma_3 = "__SIGMA_3"; @@ -421,6 +453,7 @@ template class GoblinUltraRecursive_ { this->q_elliptic = verification_key->q_elliptic; this->q_aux = verification_key->q_aux; this->q_lookup = verification_key->q_lookup; + this->q_busread = verification_key->q_busread; this->sigma_1 = verification_key->sigma_1; this->sigma_2 = verification_key->sigma_2; this->sigma_3 = verification_key->sigma_3; @@ -446,7 +479,6 @@ template class GoblinUltraRecursive_ { */ class Transcript : public BaseTranscript { public: - // Transcript objects defined as public member variables for easy access and modification uint32_t circuit_size; uint32_t public_input_size; uint32_t pub_inputs_offset; @@ -458,6 +490,8 @@ template class GoblinUltraRecursive_ { Commitment ecc_op_wire_2_comm; Commitment ecc_op_wire_3_comm; Commitment ecc_op_wire_4_comm; + Commitment calldata_comm; + Commitment calldata_read_counts_comm; Commitment sorted_accum_comm; Commitment w_4_comm; Commitment z_perm_comm; @@ -470,26 +504,9 @@ template class GoblinUltraRecursive_ { Transcript() = default; - // Used by verifier to initialize the transcript Transcript(const std::vector& proof) : BaseTranscript(proof) {} - - static Transcript prover_init_empty() - { - Transcript transcript; - constexpr uint32_t init{ 42 }; // arbitrary - transcript.send_to_verifier("Init", init); - return transcript; - }; - - static Transcript verifier_init_empty(const Transcript& transcript) - { - Transcript verifier_transcript{ transcript.proof_data }; - [[maybe_unused]] auto _ = verifier_transcript.template receive_from_prover("Init"); - return verifier_transcript; - }; - /** * @brief Takes a FULL GoblinUltraRecursive proof and deserializes it into the public member variables that * compose the structure. Must be called in order to access the structure of the proof. @@ -514,6 +531,9 @@ template class GoblinUltraRecursive_ { ecc_op_wire_2_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); ecc_op_wire_3_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); ecc_op_wire_4_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + calldata_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + calldata_read_counts_comm = + deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); sorted_accum_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); w_4_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); z_perm_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); @@ -532,6 +552,7 @@ template class GoblinUltraRecursive_ { zm_cq_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); zm_pi_comm = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); } + /** * @brief Serializes the structure variables into a FULL GoblinUltraRecursive proof. Should be called only if * deserialize_full_transcript() was called and some transcript variable was modified. @@ -540,7 +561,7 @@ template class GoblinUltraRecursive_ { void serialize_full_transcript() override { size_t old_proof_length = BaseTranscript::proof_data.size(); - BaseTranscript::proof_data.clear(); // clear proof_data so the rest of the function can replace it + BaseTranscript::proof_data.clear(); size_t log_n = numeric::get_msb(circuit_size); serialize_to_buffer(circuit_size, BaseTranscript::proof_data); serialize_to_buffer(public_input_size, BaseTranscript::proof_data); @@ -555,6 +576,8 @@ template class GoblinUltraRecursive_ { serialize_to_buffer(ecc_op_wire_2_comm, BaseTranscript::proof_data); serialize_to_buffer(ecc_op_wire_3_comm, BaseTranscript::proof_data); serialize_to_buffer(ecc_op_wire_4_comm, BaseTranscript::proof_data); + serialize_to_buffer(calldata_comm, BaseTranscript::proof_data); + serialize_to_buffer(calldata_read_counts_comm, BaseTranscript::proof_data); serialize_to_buffer(sorted_accum_comm, BaseTranscript::proof_data); serialize_to_buffer(w_4_comm, BaseTranscript::proof_data); serialize_to_buffer(z_perm_comm, BaseTranscript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp index e58bb4b9fbe..f5fd968ca36 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp @@ -647,7 +647,7 @@ TYPED_TEST(ultra_plonk_composer, non_native_field_multiplication) const auto q_indices = get_limb_witness_indices(split_into_limbs(uint256_t(q))); const auto r_indices = get_limb_witness_indices(split_into_limbs(uint256_t(r))); - proof_system::UltraCircuitBuilder::non_native_field_witnesses inputs{ + proof_system::non_native_field_witnesses inputs{ a_indices, b_indices, q_indices, r_indices, modulus_limbs, fr(uint256_t(modulus)), }; const auto [lo_1_idx, hi_1_idx] = builder.evaluate_non_native_field_multiplication(inputs); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index d62bc2b52e0..c6dffdeaa3a 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -35,7 +35,7 @@ namespace arithmetization { template class Standard { public: static constexpr size_t NUM_WIRES = 3; - static constexpr size_t num_selectors = 5; + static constexpr size_t NUM_SELECTORS = 5; using FF = FF_; using SelectorType = std::vector>; @@ -48,7 +48,7 @@ template class Standard { SelectorType& q_c() { return selectors[4]; }; Standard() - : selectors(num_selectors) + : selectors(NUM_SELECTORS) {} const auto& get() const { return selectors; }; @@ -67,12 +67,14 @@ template class Standard { template class Ultra { public: static constexpr size_t NUM_WIRES = 4; - static constexpr size_t num_selectors = 11; + static constexpr size_t NUM_SELECTORS = 11; using FF = FF_; using SelectorType = std::vector>; - std::vector selectors; + private: + std::array selectors; + public: SelectorType& q_m() { return selectors[0]; }; SelectorType& q_c() { return selectors[1]; }; SelectorType& q_1() { return selectors[2]; }; @@ -85,28 +87,82 @@ template class Ultra { SelectorType& q_aux() { return selectors[9]; }; SelectorType& q_lookup_type() { return selectors[10]; }; - Ultra() - : selectors(num_selectors) - {} - const auto& get() const { return selectors; }; void reserve(size_t size_hint) { - for (auto& p : selectors) { - p.reserve(size_hint); + for (auto& vec : selectors) { + vec.reserve(size_hint); } } + /** + * @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization + * @details Does nothing for this class since this IS the conventional Ultra arithmetization + * + */ + void pad_additional(){}; + // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. inline static const std::vector selector_names = { "q_m", "q_c", "q_1", "q_2", "q_3", "q_4", "q_arith", "q_sort", "q_elliptic", "q_aux", "table_type" }; }; +/** + * @brief Ultra Honk arithmetization + * @details Extends the conventional Ultra arithmetization with a new selector related to databus lookups + * + * @tparam FF_ + */ +template class UltraHonk { + public: + static constexpr size_t NUM_WIRES = 4; + static constexpr size_t NUM_SELECTORS = 12; + using FF = FF_; + using SelectorType = std::vector>; + + private: + std::array selectors; + + public: + SelectorType& q_m() { return selectors[0]; }; + SelectorType& q_c() { return selectors[1]; }; + SelectorType& q_1() { return selectors[2]; }; + SelectorType& q_2() { return selectors[3]; }; + SelectorType& q_3() { return selectors[4]; }; + SelectorType& q_4() { return selectors[5]; }; + SelectorType& q_arith() { return selectors[6]; }; + SelectorType& q_sort() { return selectors[7]; }; + SelectorType& q_elliptic() { return selectors[8]; }; + SelectorType& q_aux() { return selectors[9]; }; + SelectorType& q_lookup_type() { return selectors[10]; }; + SelectorType& q_busread() { return this->selectors[11]; }; + + const auto& get() const { return selectors; }; + + void reserve(size_t size_hint) + { + for (auto& vec : selectors) { + vec.reserve(size_hint); + } + } + + /** + * @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization + * @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the conventional + * Ultra arithmetization + * + */ + void pad_additional() { q_busread().emplace_back(0); }; + + // Note: Unused. Needed only for consistency with Ultra arith (which is used by Plonk) + inline static const std::vector selector_names = {}; +}; + class GoblinTranslator { public: static constexpr size_t NUM_WIRES = 81; - static constexpr size_t num_selectors = 0; + static constexpr size_t NUM_SELECTORS = 0; }; } // namespace arithmetization \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index 9ef30610de8..5611b7ec5a0 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -9,7 +9,7 @@ namespace proof_system { template void GoblinUltraCircuitBuilder_::finalize_circuit() { - UltraCircuitBuilder_>::finalize_circuit(); + UltraCircuitBuilder_>::finalize_circuit(); } /** @@ -22,7 +22,31 @@ template void GoblinUltraCircuitBuilder_::finalize_circuit() // polynomials is zero, which is required for them to be shiftable. template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero() { - UltraCircuitBuilder_>::add_gates_to_ensure_all_polys_are_non_zero(); + UltraCircuitBuilder_>::add_gates_to_ensure_all_polys_are_non_zero(); + + // Additional gate to add a nonzero value to q_busread + this->w_l.emplace_back(this->zero_idx); + this->w_r.emplace_back(this->zero_idx); + this->w_o.emplace_back(this->zero_idx); + this->w_4.emplace_back(this->zero_idx); + this->q_m.emplace_back(0); + this->q_1.emplace_back(0); + this->q_2.emplace_back(0); + this->q_3.emplace_back(0); + this->q_c.emplace_back(0); + this->q_sort.emplace_back(0); + + this->q_arith.emplace_back(0); + this->q_4.emplace_back(0); + this->q_lookup_type.emplace_back(0); + this->q_elliptic.emplace_back(0); + this->q_aux.emplace_back(0); + q_busread.emplace_back(1); + ++this->num_gates; + + // Add some nonzero values to the calldata and corresponding read counts + public_calldata.emplace_back(this->one_idx); + calldata_read_counts.emplace_back(this->one_idx); } /** diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index b7a60f03f1e..f4532a31895 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -13,12 +13,12 @@ namespace proof_system { using namespace barretenberg; -template class GoblinUltraCircuitBuilder_ : public UltraCircuitBuilder_> { +template class GoblinUltraCircuitBuilder_ : public UltraCircuitBuilder_> { public: static constexpr std::string_view NAME_STRING = "GoblinUltraArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = - UltraCircuitBuilder_>::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; + UltraCircuitBuilder_>::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; size_t num_ecc_op_gates = 0; // number of ecc op "gates" (rows); these are placed at the start of the circuit @@ -32,15 +32,23 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui uint32_t equality_op_idx; using WireVector = std::vector>; + using SelectorVector = std::vector>; // Wires storing ecc op queue data; values are indices into the variables array - std::array::NUM_WIRES> ecc_op_wires; + std::array::NUM_WIRES> ecc_op_wires; WireVector& ecc_op_wire_1 = std::get<0>(ecc_op_wires); WireVector& ecc_op_wire_2 = std::get<1>(ecc_op_wires); WireVector& ecc_op_wire_3 = std::get<2>(ecc_op_wires); WireVector& ecc_op_wire_4 = std::get<3>(ecc_op_wires); + SelectorVector& q_busread = this->selectors.q_busread(); + + // DataBus call/return data arrays + std::vector public_calldata; + std::vector calldata_read_counts; + std::vector public_return_data; + // Functions for adding ECC op queue "gates" ecc_op_tuple queue_ecc_add_accum(const g1::affine_element& point); ecc_op_tuple queue_ecc_mul_accum(const g1::affine_element& point, const FF& scalar); @@ -53,7 +61,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui public: GoblinUltraCircuitBuilder_(const size_t size_hint = 0, std::shared_ptr op_queue_in = std::make_shared()) - : UltraCircuitBuilder_>(size_hint) + : UltraCircuitBuilder_>(size_hint) , op_queue(op_queue_in) { // Set indices to constants corresponding to Goblin ECC op codes @@ -83,7 +91,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui */ size_t get_num_gates() const override { - auto num_ultra_gates = UltraCircuitBuilder_>::get_num_gates(); + auto num_ultra_gates = UltraCircuitBuilder_>::get_num_gates(); return num_ultra_gates + num_ecc_op_gates; } @@ -98,7 +106,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui size_t romcount = 0; size_t ramcount = 0; size_t nnfcount = 0; - UltraCircuitBuilder_>::get_num_gates_split_into_components( + UltraCircuitBuilder_>::get_num_gates_split_into_components( count, rangecount, romcount, ramcount, nnfcount); size_t total = count + romcount + ramcount + rangecount + num_ecc_op_gates; @@ -106,6 +114,24 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui << ", range " << rangecount << ", non native field gates " << nnfcount << ", goblin ecc op gates " << num_ecc_op_gates << "), pubinp = " << this->public_inputs.size() << std::endl; } + + /** + * Make a witness variable a member of the public calldata. + * + * @param witness_index The index of the witness. + * */ + void set_public_calldata(const uint32_t witness_index) + { + for (const uint32_t calldata : public_calldata) { + if (calldata == witness_index) { + if (!this->failed()) { + this->failure("Attempted to redundantly set a public calldata!"); + } + return; + } + } + public_calldata.emplace_back(witness_index); + } }; extern template class GoblinUltraCircuitBuilder_; using GoblinUltraCircuitBuilder = GoblinUltraCircuitBuilder_; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp index 015fcb3a143..819bc5a3c51 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp @@ -15,7 +15,7 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase static constexpr size_t NUM_WIRES = Arithmetization::NUM_WIRES; // Keeping NUM_WIRES, at least temporarily, for backward compatibility static constexpr size_t program_width = Arithmetization::NUM_WIRES; - static constexpr size_t num_selectors = Arithmetization::num_selectors; + static constexpr size_t num_selectors = Arithmetization::NUM_SELECTORS; std::vector selector_names = Arithmetization::selector_names; static constexpr std::string_view NAME_STRING = "StandardArithmetization"; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp index 9a31f23f015..da96bd1cf86 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp @@ -79,6 +79,7 @@ void UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_no q_lookup_type.emplace_back(0); q_elliptic.emplace_back(1); q_aux.emplace_back(1); + selectors.pad_additional(); ++this->num_gates; // Some relations depend on wire shifts so we add another gate with @@ -138,6 +139,7 @@ void UltraCircuitBuilder_::create_add_gate(const add_triple_num_gates; } @@ -169,6 +171,7 @@ void UltraCircuitBuilder_::create_big_add_gate(const add_quad_< q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -262,6 +265,7 @@ void UltraCircuitBuilder_::create_big_mul_gate(const mul_quad_< q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -287,6 +291,7 @@ void UltraCircuitBuilder_::create_balanced_add_gate(const add_q q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; // Why 3? TODO: return to this // The purpose of this gate is to do enable lazy 32-bit addition. @@ -328,6 +333,7 @@ void UltraCircuitBuilder_::create_mul_gate(const mul_triple_num_gates; } /** @@ -356,6 +362,7 @@ void UltraCircuitBuilder_::create_bool_gate(const uint32_t vari q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -386,6 +393,7 @@ void UltraCircuitBuilder_::create_poly_gate(const poly_triple_< q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -439,6 +447,7 @@ void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_ga q_lookup_type.emplace_back(0); q_elliptic.emplace_back(1); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } w_l.emplace_back(in.x2); @@ -456,6 +465,7 @@ void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_ga q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -501,6 +511,7 @@ void UltraCircuitBuilder_::create_ecc_dbl_gate(const ecc_dbl_ga q_sort.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -519,6 +530,7 @@ void UltraCircuitBuilder_::create_ecc_dbl_gate(const ecc_dbl_ga q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -548,6 +560,7 @@ void UltraCircuitBuilder_::fix_witness(const uint32_t witness_i q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } @@ -622,6 +635,7 @@ plookup::ReadData UltraCircuitBuilder_::create_gates_ q_sort.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); ++this->num_gates; } return read_data; @@ -930,6 +944,7 @@ void UltraCircuitBuilder_::create_sort_constraint(const std::ve q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } // dummy gate needed because of sort widget's check of next row w_l.emplace_back(variable_index[variable_index.size() - 1]); @@ -948,6 +963,7 @@ void UltraCircuitBuilder_::create_sort_constraint(const std::ve q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } // useful to put variables in the witness that aren't already used - e.g. the dummy variables of the range constraint in @@ -981,6 +997,7 @@ void UltraCircuitBuilder_::create_dummy_constraints(const std:: q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } } @@ -1011,6 +1028,7 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges( q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); // enforce range check for middle rows for (size_t i = gate_width; i < variable_index.size() - gate_width; i += gate_width) { @@ -1030,6 +1048,7 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges( q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } // enforce range checks of last row and ending at end if (variable_index.size() > gate_width) { @@ -1049,6 +1068,7 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges( q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } // dummy gate needed because of sort widget's check of next row @@ -1069,6 +1089,7 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges( q_elliptic.emplace_back(0); q_lookup_type.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } // range constraint a value by decomposing it into limbs whose size should be the default range constraint size @@ -1184,6 +1205,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::LIMB_ACCUMULATE_2: { @@ -1194,6 +1216,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(1); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_1: { @@ -1204,6 +1227,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_2: { @@ -1214,6 +1238,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_3: { @@ -1224,6 +1249,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(1); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::ROM_CONSISTENCY_CHECK: { @@ -1238,6 +1264,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::RAM_CONSISTENCY_CHECK: { @@ -1253,6 +1280,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(1); + selectors.pad_additional(); break; } case AUX_SELECTORS::RAM_TIMESTAMP_CHECK: { @@ -1265,6 +1293,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::ROM_READ: { @@ -1278,6 +1307,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(1); // validate record witness is correctly computed q_c.emplace_back(0); // read/write flag stored in q_c q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::RAM_READ: { @@ -1291,6 +1321,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(1); // validate record witness is correctly computed q_c.emplace_back(0); // read/write flag stored in q_c q_arith.emplace_back(0); + selectors.pad_additional(); break; } case AUX_SELECTORS::RAM_WRITE: { @@ -1304,6 +1335,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(1); // validate record witness is correctly computed q_c.emplace_back(1); // read/write flag stored in q_c q_arith.emplace_back(0); + selectors.pad_additional(); break; } default: { @@ -1314,6 +1346,7 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT q_m.emplace_back(0); q_c.emplace_back(0); q_arith.emplace_back(0); + selectors.pad_additional(); break; } } @@ -1461,7 +1494,7 @@ std::array UltraCircuitBuilder_::decompose_non_nat template std::array UltraCircuitBuilder_::evaluate_non_native_field_multiplication( - const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder) + const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder) { std::array a{ @@ -1682,7 +1715,7 @@ void UltraCircuitBuilder_::process_non_native_field_multiplicat template std::array UltraCircuitBuilder_::queue_partial_non_native_field_multiplication( - const non_native_field_witnesses& input) + const non_native_field_witnesses& input) { std::array a{ @@ -1842,6 +1875,7 @@ std::array UltraCircuitBuilder_::evaluate_non_nati q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } this->num_gates += 4; @@ -1963,6 +1997,7 @@ std::array UltraCircuitBuilder_::evaluate_non_nati q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); + selectors.pad_additional(); } this->num_gates += 4; @@ -3423,6 +3458,7 @@ template bool UltraCircuitBuilder_:: return result; } template class UltraCircuitBuilder_>; +template class UltraCircuitBuilder_>; // To enable this we need to template plookup // template class UltraCircuitBuilder_; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp index 059934bc93d..ae3b25ab436 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp @@ -14,6 +14,17 @@ namespace proof_system { +template struct non_native_field_witnesses { + // first 4 array elements = limbs + // 5th element = prime basis limb + std::array a; + std::array b; + std::array q; + std::array r; + std::array neg_modulus; + FF modulus; +}; + using namespace barretenberg; template @@ -23,7 +34,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase selector_names = Arithmetization::selector_names; static constexpr std::string_view NAME_STRING = "UltraArithmetization"; @@ -45,17 +56,6 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase a; - std::array b; - std::array q; - std::array r; - std::array neg_modulus; - FF modulus; - }; - enum AUX_SELECTORS { NONE, LIMB_ACCUMULATE_1, @@ -946,8 +946,8 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase decompose_non_native_field_double_width_limb( const uint32_t limb_idx, const size_t num_limb_bits = (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS)); std::array evaluate_non_native_field_multiplication( - const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder = true); - std::array queue_partial_non_native_field_multiplication(const non_native_field_witnesses& input); + const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder = true); + std::array queue_partial_non_native_field_multiplication(const non_native_field_witnesses& input); typedef std::pair scaled_witness; typedef std::tuple add_simple; std::array evaluate_non_native_field_subtraction(add_simple limb0, @@ -1049,5 +1049,6 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase>; +extern template class UltraCircuitBuilder_>; using UltraCircuitBuilder = UltraCircuitBuilder_>; } // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp index bce39f0535c..608727c812a 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp @@ -620,7 +620,7 @@ TEST(ultra_circuit_constructor, non_native_field_multiplication) const auto q_indices = get_limb_witness_indices(split_into_limbs(uint256_t(q))); const auto r_indices = get_limb_witness_indices(split_into_limbs(uint256_t(r))); - proof_system::UltraCircuitBuilder::non_native_field_witnesses inputs{ + proof_system::non_native_field_witnesses inputs{ a_indices, b_indices, q_indices, r_indices, modulus_limbs, fr(uint256_t(modulus)), }; const auto [lo_1_idx, hi_1_idx] = circuit_constructor.evaluate_non_native_field_multiplication(inputs); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp index 3ab74f3b439..07e400b3774 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp @@ -22,7 +22,8 @@ void construct_selector_polynomials(const typename Flavor::CircuitBuilder& circu size_t gate_offset = zero_row_offset + circuit_constructor.public_inputs.size(); // If Goblin, (1) update the conventional gate offset to account for ecc op gates at the top of the execution trace, - // and (2) construct ecc op gate selector polynomial. + // and (2) construct ecc op gate selector polynomial. This selector is handled separately from the others since it + // is computable based simply on num_ecc_op_gates and thus is not constructed explicitly in the builder. // Note 1: All other selectors will be automatically and correctly initialized to 0 on this domain. // Note 2: If applicable, the ecc op gates are shifted down by 1 to account for a zero row. if constexpr (IsGoblinFlavor) { @@ -30,11 +31,11 @@ void construct_selector_polynomials(const typename Flavor::CircuitBuilder& circu gate_offset += num_ecc_op_gates; const size_t op_gate_offset = zero_row_offset; // The op gate selector is simply the indicator on the domain [offset, num_ecc_op_gates + offset - 1] - barretenberg::polynomial selector_poly_lagrange(proving_key->circuit_size); + barretenberg::polynomial ecc_op_selector(proving_key->circuit_size); for (size_t i = 0; i < num_ecc_op_gates; ++i) { - selector_poly_lagrange[i + op_gate_offset] = 1; + ecc_op_selector[i + op_gate_offset] = 1; } - proving_key->lagrange_ecc_op = selector_poly_lagrange; + proving_key->lagrange_ecc_op = ecc_op_selector; } // TODO(#398): Loose coupling here! Would rather build up pk from arithmetization diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp index 42177e199bb..5d78358dfe3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp @@ -2026,7 +2026,7 @@ void bigfield::unsafe_evaluate_multiply_add(const bigfield& input_le }; field_t remainder_prime_limb = field_t::accumulate(prime_limb_accumulator); - proof_system::UltraCircuitBuilder::non_native_field_witnesses witnesses{ + proof_system::non_native_field_witnesses witnesses{ { left.binary_basis_limbs[0].element.normalize().witness_index, left.binary_basis_limbs[1].element.normalize().witness_index, @@ -2366,7 +2366,7 @@ void bigfield::unsafe_evaluate_multiple_multiply_add(const std::vect } if (i > 0) { - proof_system::UltraCircuitBuilder::non_native_field_witnesses mul_witnesses = { + proof_system::non_native_field_witnesses mul_witnesses = { { left[i].binary_basis_limbs[0].element.normalize().witness_index, left[i].binary_basis_limbs[1].element.normalize().witness_index, @@ -2462,7 +2462,7 @@ void bigfield::unsafe_evaluate_multiple_multiply_add(const std::vect }; field_t remainder_prime_limb = field_t::accumulate(prime_limb_accumulator); - proof_system::UltraCircuitBuilder::non_native_field_witnesses witnesses{ + proof_system::non_native_field_witnesses witnesses{ { left[0].binary_basis_limbs[0].element.normalize().witness_index, left[0].binary_basis_limbs[1].element.normalize().witness_index, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp index 53ce85d0108..c4d91dbf987 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp @@ -57,7 +57,7 @@ std::array UltraRecursiveVerifier_::ve commitments.w_r = transcript.template receive_from_prover(commitment_labels.w_r); commitments.w_o = transcript.template receive_from_prover(commitment_labels.w_o); - // If Goblin, get commitments to ECC op wire polynomials + // If Goblin, get commitments to ECC op wire polynomials and DataBus columns if constexpr (IsGoblinFlavor) { commitments.ecc_op_wire_1 = transcript.template receive_from_prover(commitment_labels.ecc_op_wire_1); @@ -67,6 +67,9 @@ std::array UltraRecursiveVerifier_::ve transcript.template receive_from_prover(commitment_labels.ecc_op_wire_3); commitments.ecc_op_wire_4 = transcript.template receive_from_prover(commitment_labels.ecc_op_wire_4); + commitments.calldata = transcript.template receive_from_prover(commitment_labels.calldata); + commitments.calldata_read_counts = + transcript.template receive_from_prover(commitment_labels.calldata_read_counts); } // Get challenge for sorted list batching and wire four memory records diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 29e5de759de..d64ae7629aa 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -59,9 +59,10 @@ template void ProverInstance_::compute_witness(Circuit& c proving_key->w_o = wire_polynomials[2]; proving_key->w_4 = wire_polynomials[3]; - // If Goblin, construct the ECC op queue wire polynomials + // If Goblin, construct the ECC op queue wire and databus polynomials if constexpr (IsGoblinFlavor) { construct_ecc_op_wire_polynomials(wire_polynomials); + construct_databus_polynomials(circuit); } // Construct the sorted concatenated list polynomials for the lookup argument @@ -184,6 +185,30 @@ template void ProverInstance_::construct_ecc_op_wire_poly proving_key->ecc_op_wire_4 = op_wire_polynomials[3]; } +/** + * @brief + * @details + * + * @tparam Flavor + * @param circuit + */ +template +void ProverInstance_::construct_databus_polynomials(Circuit& circuit) + requires IsGoblinFlavor +{ + polynomial public_calldata(dyadic_circuit_size); + polynomial calldata_read_counts(dyadic_circuit_size); + + const size_t offset = Flavor::has_zero_row ? 1 : 0; + for (size_t idx = 0; idx < circuit.public_calldata.size(); ++idx) { + public_calldata[idx + offset] = circuit.get_variable(circuit.public_calldata[idx]); + calldata_read_counts[idx + offset] = circuit.get_variable(circuit.calldata_read_counts[idx]); + } + + proving_key->calldata = public_calldata; + proving_key->calldata_read_counts = calldata_read_counts; +} + template std::shared_ptr ProverInstance_::compute_proving_key(Circuit& circuit) { @@ -300,6 +325,10 @@ template void ProverInstance_::initialise_prover_polynomi prover_polynomials.ecc_op_wire_3 = proving_key->ecc_op_wire_3; prover_polynomials.ecc_op_wire_4 = proving_key->ecc_op_wire_4; prover_polynomials.lagrange_ecc_op = proving_key->lagrange_ecc_op; + // DataBus polynomials + prover_polynomials.calldata = proving_key->calldata; + prover_polynomials.calldata_read_counts = proving_key->calldata_read_counts; + prover_polynomials.q_busread = proving_key->q_busread; } std::span public_wires_source = prover_polynomials.w_r; @@ -464,6 +493,7 @@ std::shared_ptr ProverInstance_::compu // due to its simple structure. Handling it in the same way as the lagrange polys for now for simplicity. if constexpr (IsGoblinFlavor) { verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); + verification_key->q_busread = commitment_key->commit(proving_key->q_busread); } // // See `add_recusrive_proof()` for how this recursive data is assigned. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index b54ee42ae2d..a004587fefc 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -93,6 +93,9 @@ template class ProverInstance_ { void construct_ecc_op_wire_polynomials(auto&); + void construct_databus_polynomials(Circuit&) + requires IsGoblinFlavor; + void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial& small, const std::string& tag); void add_plookup_memory_records_to_wire_4(FF); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/databus_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/databus_composer.test.cpp new file mode 100644 index 00000000000..4ee34bab917 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/databus_composer.test.cpp @@ -0,0 +1,99 @@ +#include +#include +#include + +#include "barretenberg/common/log.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" +#include "barretenberg/ultra_honk/ultra_prover.hpp" + +using namespace proof_system::honk; + +namespace test_ultra_honk_composer { + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +class DataBusComposerTests : public ::testing::Test { + protected: + static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } + + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using Point = Curve::AffineElement; + using CommitmentKey = pcs::CommitmentKey; + + /** + * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates + * + * @param builder + */ + void generate_test_circuit(auto& builder) + { + // Add some ecc op gates + for (size_t i = 0; i < 3; ++i) { + auto point = Point::one() * FF::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_mul_accum(point, scalar); + } + builder.queue_ecc_eq(); + + // Add some conventional gates that utilize public inputs + for (size_t i = 0; i < 10; ++i) { + 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 Construct and a verify a Honk proof + * + */ + bool construct_and_verify_honk_proof(auto& composer, auto& builder) + { + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + + return verified; + } +}; + +/** + * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic + * gates + * @note We simulate op queue interactions with a previous circuit so the actual circuit under test utilizes an op queue + * with non-empty 'previous' data. This avoid complications with zero-commitments etc. + * + */ +TEST_F(DataBusComposerTests, SingleCircuit) +{ + auto op_queue = std::make_shared(); + + // Add mock data to op queue to simulate interaction with a previous circuit + op_queue->populate_with_mock_initital_data(); + + auto builder = proof_system::GoblinUltraCircuitBuilder{ op_queue }; + + generate_test_circuit(builder); + + auto composer = GoblinUltraComposer(); + + // Construct and verify Honk proof + auto honk_verified = construct_and_verify_honk_proof(composer, builder); + EXPECT_TRUE(honk_verified); +} + +} // namespace test_ultra_honk_composer diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp index 02dcb467a28..611110de27d 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp @@ -51,6 +51,8 @@ class GoblinUltraTranscriptTests : public ::testing::Test { 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_entry(round, "CALLDATA", size_G); + manifest_expected.add_entry(round, "CALLDATA_READ_COUNTS", size_G); manifest_expected.add_challenge(round, "eta"); round++; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp index 6b9cdbd7484..0f1e0e274a8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp @@ -716,7 +716,7 @@ TEST_F(UltraHonkComposerTests, non_native_field_multiplication) const auto q_indices = get_limb_witness_indices(split_into_limbs(uint256_t(q))); const auto r_indices = get_limb_witness_indices(split_into_limbs(uint256_t(r))); - proof_system::UltraCircuitBuilder::non_native_field_witnesses inputs{ + proof_system::non_native_field_witnesses inputs{ a_indices, b_indices, q_indices, r_indices, modulus_limbs, fr(uint256_t(modulus)), }; const auto [lo_1_idx, hi_1_idx] = circuit_builder.evaluate_non_native_field_multiplication(inputs); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index e29f3c63be3..d7fe84acf87 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -54,11 +54,17 @@ template void UltraProver_::execute_wire_commitment } if constexpr (IsGoblinFlavor) { + // Commit to Goblin ECC op wires auto op_wire_polys = instance->proving_key->get_ecc_op_wires(); auto labels = commitment_labels.get_ecc_op_wires(); for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { transcript.send_to_verifier(labels[idx], commitment_key->commit(op_wire_polys[idx])); } + // Commit to DataBus columns + transcript.send_to_verifier(commitment_labels.calldata, + commitment_key->commit(instance->proving_key->calldata)); + transcript.send_to_verifier(commitment_labels.calldata_read_counts, + commitment_key->commit(instance->proving_key->calldata_read_counts)); } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 4bdcde80193..3dc1bcafa67 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -70,7 +70,7 @@ template bool UltraVerifier_::verify_proof(const plonk commitments.w_r = transcript.template receive_from_prover(commitment_labels.w_r); commitments.w_o = transcript.template receive_from_prover(commitment_labels.w_o); - // If Goblin, get commitments to ECC op wire polynomials + // If Goblin, get commitments to ECC op wire polynomials and DataBus columns if constexpr (IsGoblinFlavor) { commitments.ecc_op_wire_1 = transcript.template receive_from_prover(commitment_labels.ecc_op_wire_1); @@ -80,6 +80,9 @@ template bool UltraVerifier_::verify_proof(const plonk transcript.template receive_from_prover(commitment_labels.ecc_op_wire_3); commitments.ecc_op_wire_4 = transcript.template receive_from_prover(commitment_labels.ecc_op_wire_4); + commitments.calldata = transcript.template receive_from_prover(commitment_labels.calldata); + commitments.calldata_read_counts = + transcript.template receive_from_prover(commitment_labels.calldata_read_counts); } // Get challenge for sorted list batching and wire four memory records