-
Notifications
You must be signed in to change notification settings - Fork 117
/
Copy pathstandard.hpp
309 lines (277 loc) · 13.7 KB
/
standard.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#pragma once
#include "barretenberg/ecc/curves/bn254/g1.hpp"
#include "barretenberg/honk/pcs/kzg/kzg.hpp"
#include "barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp"
#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp"
#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp"
#include "barretenberg/honk/sumcheck/relations/permutation_relation.hpp"
#include "barretenberg/honk/transcript/transcript.hpp"
#include "barretenberg/polynomials/evaluation_domain.hpp"
#include "barretenberg/polynomials/polynomial.hpp"
#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp"
#include "barretenberg/proof_system/flavor/flavor.hpp"
#include "barretenberg/srs/factories/crs_factory.hpp"
#include <array>
#include <concepts>
#include <span>
#include <string>
#include <type_traits>
#include <vector>
namespace proof_system::honk::flavor {
/**
* @brief Standard Honk
* @details We built this flavor first because it is the most basic. Because of this, it will remain useful for testing
* various constructions. Future variants may exist with varying: underlying curve (here we use BN254); commitment
* scheme (here we use Gemini + Shplonk + KZG); zero knowlege property (it's not implemented yet, but in the future we
* will be able to toggle it on or off).
*
*/
class Standard {
public:
using CircuitBuilder = StandardCircuitBuilder;
using Curve = curve::BN254;
using PCS = pcs::kzg::KZG<Curve>;
using GroupElement = Curve::Element;
using Commitment = Curve::AffineElement;
using CommitmentHandle = Curve::AffineElement;
using FF = Curve::ScalarField;
using Polynomial = barretenberg::Polynomial<FF>;
using PolynomialHandle = std::span<FF>;
using CommitmentKey = pcs::CommitmentKey<Curve>;
using VerifierCommitmentKey = pcs::VerifierCommitmentKey<Curve>;
static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES;
// 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`
static constexpr size_t NUM_ALL_ENTITIES = 18;
// 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 = 13;
// The total number of witness entities not including shifts.
static constexpr size_t NUM_WITNESS_ENTITIES = 4;
using GrandProductRelations = std::tuple<sumcheck::PermutationRelation<FF>>;
// define the tuple of Relations that comprise the Sumcheck relation
using Relations = std::tuple<sumcheck::ArithmeticRelation<FF>, sumcheck::PermutationRelation<FF>>;
static constexpr size_t MAX_RELATION_LENGTH = get_max_relation_length<Relations>();
// MAX_RANDOM_RELATION_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` random
// polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation length = 3
static constexpr size_t MAX_RANDOM_RELATION_LENGTH = MAX_RELATION_LENGTH + 1;
static constexpr size_t NUM_RELATIONS = std::tuple_size<Relations>::value;
// define the containers for storing the contributions from each relation in Sumcheck
using RelationUnivariates = decltype(create_relation_univariates_container<FF, Relations>());
using RelationValues = decltype(create_relation_values_container<FF, Relations>());
// Whether or not the first row of the execution trace is reserved for 0s to enable shifts
static constexpr bool has_zero_row = false;
private:
/**
* @brief A base class labelling precomputed entities and (ordered) subsets of interest.
* @details Used to build the proving key and verification key.
*/
template <typename DataType, typename HandleType>
class PrecomputedEntities : public PrecomputedEntities_<DataType, HandleType, NUM_PRECOMPUTED_ENTITIES> {
public:
DataType& q_m = std::get<0>(this->_data);
DataType& q_l = std::get<1>(this->_data);
DataType& q_r = std::get<2>(this->_data);
DataType& q_o = std::get<3>(this->_data);
DataType& q_c = std::get<4>(this->_data);
DataType& sigma_1 = std::get<5>(this->_data);
DataType& sigma_2 = std::get<6>(this->_data);
DataType& sigma_3 = std::get<7>(this->_data);
DataType& id_1 = std::get<8>(this->_data);
DataType& id_2 = std::get<9>(this->_data);
DataType& id_3 = std::get<10>(this->_data);
DataType& lagrange_first = std::get<11>(this->_data);
DataType& lagrange_last = std::get<12>(this->_data); // = LAGRANGE_N-1 whithout ZK, but can be less
static constexpr CircuitType CIRCUIT_TYPE = CircuitBuilder::CIRCUIT_TYPE;
std::vector<HandleType> get_selectors() override { return { q_m, q_l, q_r, q_o, q_c }; };
std::vector<HandleType> get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3 }; };
std::vector<HandleType> get_id_polynomials() override { return { id_1, id_2, id_3 }; };
};
/**
* @brief Container for all witness polynomials used/constructed by the prover.
* @details Shifts are not included here since they do not occupy their own memory.
*/
template <typename DataType, typename HandleType>
class WitnessEntities : public WitnessEntities_<DataType, HandleType, NUM_WITNESS_ENTITIES> {
public:
DataType& w_l = std::get<0>(this->_data);
DataType& w_r = std::get<1>(this->_data);
DataType& w_o = std::get<2>(this->_data);
DataType& z_perm = std::get<3>(this->_data);
std::vector<HandleType> get_wires() override { return { w_l, w_r, w_o }; };
};
/**
* @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during
* sumcheck) in this Honk variant along with particular subsets of interest
* @details Used to build containers for: the prover's polynomial during sumcheck; the sumcheck's folded
* polynomials; the univariates consturcted during during sumcheck; the evaluations produced by sumcheck.
*
* Symbolically we have: AllEntities = PrecomputedEntities + WitnessEntities + "ShiftedEntities". It could be
* implemented as such, but we don't have this now.
*/
template <typename DataType, typename HandleType>
class AllEntities : public AllEntities_<DataType, HandleType, NUM_ALL_ENTITIES> {
public:
DataType& q_c = std::get<0>(this->_data);
DataType& q_l = std::get<1>(this->_data);
DataType& q_r = std::get<2>(this->_data);
DataType& q_o = std::get<3>(this->_data);
DataType& q_m = std::get<4>(this->_data);
DataType& sigma_1 = std::get<5>(this->_data);
DataType& sigma_2 = std::get<6>(this->_data);
DataType& sigma_3 = std::get<7>(this->_data);
DataType& id_1 = std::get<8>(this->_data);
DataType& id_2 = std::get<9>(this->_data);
DataType& id_3 = std::get<10>(this->_data);
DataType& lagrange_first = std::get<11>(this->_data);
DataType& lagrange_last = std::get<12>(this->_data);
DataType& w_l = std::get<13>(this->_data);
DataType& w_r = std::get<14>(this->_data);
DataType& w_o = std::get<15>(this->_data);
DataType& z_perm = std::get<16>(this->_data);
DataType& z_perm_shift = std::get<17>(this->_data);
std::vector<HandleType> get_wires() override { return { w_l, w_r, w_o }; };
// Gemini-specific getters.
std::vector<HandleType> get_unshifted() override
{
return { q_c, q_l, q_r, q_o, q_m, sigma_1, sigma_2, sigma_3, id_1, id_2, id_3, lagrange_first,
lagrange_last, w_l, w_r, w_o, z_perm };
};
std::vector<HandleType> get_to_be_shifted() override { return { z_perm }; };
std::vector<HandleType> get_shifted() override { return { z_perm_shift }; };
// TODO(Cody): It would be nice to define these constructors once in a base class template.
AllEntities() = default;
AllEntities(const AllEntities& other)
: AllEntities_<DataType, HandleType, NUM_ALL_ENTITIES>(other){};
AllEntities(AllEntities&& other)
: AllEntities_<DataType, HandleType, NUM_ALL_ENTITIES>(other){};
AllEntities& operator=(const AllEntities& other)
{
if (this == &other) {
return *this;
}
AllEntities_<DataType, HandleType, NUM_ALL_ENTITIES>::operator=(other);
return *this;
}
AllEntities& operator=(AllEntities&& other)
{
AllEntities_<DataType, HandleType, NUM_ALL_ENTITIES>::operator=(other);
return *this;
}
~AllEntities() = default;
};
public:
/**
* @brief The proving key is responsible for storing the polynomials used by the prover.
* @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve inherit
* from ProvingKey.
*/
class ProvingKey : public ProvingKey_<PrecomputedEntities<Polynomial, PolynomialHandle>,
WitnessEntities<Polynomial, PolynomialHandle>> {
public:
// Expose constructors of the base class
using Base = ProvingKey_<PrecomputedEntities<Polynomial, PolynomialHandle>,
WitnessEntities<Polynomial, PolynomialHandle>>;
using Base::Base;
};
/**
* @brief The verification key is responsible for storing the the commitments to the precomputed (non-witness)
* polynomials used by the verifier.
*
* @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve
* that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our
* circuits.
*/
using VerificationKey = VerificationKey_<PrecomputedEntities<Commitment, CommitmentHandle>>;
/**
* @brief A container for polynomials handles; only stores spans.
*/
using ProverPolynomials = AllEntities<PolynomialHandle, PolynomialHandle>;
/**
* @brief A container for storing the partially evaluated multivariates produced by sumcheck.
*/
class PartiallyEvaluatedMultivariates : public AllEntities<Polynomial, PolynomialHandle> {
public:
PartiallyEvaluatedMultivariates() = default;
PartiallyEvaluatedMultivariates(const size_t circuit_size)
{
// Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2)
for (auto& poly : this->_data) {
poly = Polynomial(circuit_size / 2);
}
}
};
/**
* @brief A container for univariates produced during the hot loop in sumcheck.
* @todo TODO(#390): Simplify this by moving MAX_RELATION_LENGTH?
*/
template <size_t MAX_RELATION_LENGTH>
using ExtendedEdges =
AllEntities<sumcheck::Univariate<FF, MAX_RELATION_LENGTH>, sumcheck::Univariate<FF, MAX_RELATION_LENGTH>>;
/**
* @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the
* evaluations of polynomials committed in earlier rounds.
*/
class ClaimedEvaluations : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
ClaimedEvaluations(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};
/**
* @brief A container for commitment labels.
* @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It
* has, however, been useful during debugging to have these labels available.
*
*/
class CommitmentLabels : public AllEntities<std::string, std::string> {
public:
CommitmentLabels()
: AllEntities<std::string, std::string>()
{
w_l = "W_1";
w_r = "W_2";
w_o = "W_3";
z_perm = "Z_PERM";
// The ones beginning with "__" are only used for debugging
z_perm_shift = "__Z_PERM_SHIFT";
q_m = "__Q_M";
q_l = "__Q_L";
q_r = "__Q_R";
q_o = "__Q_O";
q_c = "__Q_C";
sigma_1 = "__SIGMA_1";
sigma_2 = "__SIGMA_2";
sigma_3 = "__SIGMA_3";
id_1 = "__ID_1";
id_2 = "__ID_2";
id_3 = "__ID_3";
lagrange_first = "__LAGRANGE_FIRST";
lagrange_last = "__LAGRANGE_LAST";
};
};
/**
* @brief A container for all commitments used by the verifier.
*/
class VerifierCommitments : public AllEntities<Commitment, CommitmentHandle> {
public:
VerifierCommitments(std::shared_ptr<VerificationKey> verification_key)
{
// Initialize pre-computed commitments here, witness commitments during proof verification.
q_m = verification_key->q_m;
q_l = verification_key->q_l;
q_r = verification_key->q_r;
q_o = verification_key->q_o;
q_c = verification_key->q_c;
sigma_1 = verification_key->sigma_1;
sigma_2 = verification_key->sigma_2;
sigma_3 = verification_key->sigma_3;
id_1 = verification_key->id_1;
id_2 = verification_key->id_2;
id_3 = verification_key->id_3;
lagrange_first = verification_key->lagrange_first;
lagrange_last = verification_key->lagrange_last;
}
};
};
} // namespace proof_system::honk::flavor