Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
flavor.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Completed, auditors: [Sergei], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
22#pragma once
33
34#include <array>
35#include <cstddef>
36#include <vector>
37
38// ===== Flavor forward declarations =====
39namespace bb {
40class UltraFlavor;
41class UltraZKFlavor;
42class ECCVMFlavor;
43class UltraKeccakFlavor;
44#ifdef STARKNET_GARAGA_FLAVORS
45class UltraStarknetFlavor;
46class UltraStarknetZKFlavor;
47#endif
48class UltraKeccakZKFlavor;
49class MegaFlavor;
50class MegaZKFlavor;
51class MegaAvmFlavor;
52class TranslatorFlavor;
53class TranslatorShortMonomialFlavor;
54class ECCVMShortMonomialFlavor;
55class ECCVMRecursiveFlavor;
56class TranslatorRecursiveFlavor;
57
58template <typename BuilderType> class UltraRecursiveFlavor_;
59template <typename BuilderType> class UltraZKRecursiveFlavor_;
60template <typename BuilderType> class MegaRecursiveFlavor_;
61template <typename BuilderType> class MegaZKRecursiveFlavor_;
62template <typename BuilderType> class MegaAvmRecursiveFlavor_;
63class MegaAppRecursiveFlavor;
64class MegaKernelRecursiveFlavor;
65namespace avm2 {
66class AvmRecursiveFlavor;
67}
68} // namespace bb
69
70namespace bb {
71
72// ===== Trace metadata & precomputed data =====
73
77struct MetaData {
78 static constexpr size_t NUM_FIELDS = 3;
79 size_t dyadic_size = 0; // power-of-2 size of the execution trace
82};
83
87template <typename Polynomial, size_t NUM_PRECOMPUTED_ENTITIES> struct PrecomputedData_ {
88 RefArray<Polynomial, NUM_PRECOMPUTED_ENTITIES> polynomials; // polys whose commitments comprise the VK
89 MetaData metadata; // execution trace metadata
90};
91
92// ===== Fixed verification keys (ECCVM, Translator, AVM) =====
93
103template <typename PrecomputedCommitments, typename HashType, typename HardcodedVKAndHash>
104class FixedVKAndHash_ : public PrecomputedCommitments {
105 public:
106 using Commitment = typename PrecomputedCommitments::DataType;
107
108 bool operator==(const FixedVKAndHash_&) const = default;
109
110 // Default construct the fixed VK from hardcoded commitments and precomputed hash
112 : hash(HardcodedVKAndHash::vk_hash())
113 {
114 for (auto [vk_commitment, fixed_commitment] : zip_view(this->get_all(), HardcodedVKAndHash::get_all())) {
115 vk_commitment = fixed_commitment;
116 }
117 }
118
119 HashType get_hash() const { return hash; }
120
121 private:
122 HashType hash{};
123};
124
125// ===== Native verification key =====
126
137template <typename PrecomputedCommitments, typename Codec, typename HashFunction, typename CommitmentKey = void>
138class NativeVerificationKey_ : public PrecomputedCommitments {
139 public:
140 using Commitment = typename PrecomputedCommitments::DataType;
141 using DataType = typename Codec::DataType;
142 uint64_t log_circuit_size = 0;
143 uint64_t num_public_inputs = 0;
144 uint64_t pub_inputs_offset = 0;
145 bool operator==(const NativeVerificationKey_&) const = default;
146
147#ifndef NDEBUG
148 template <typename CommitmentLabels>
149 bool compare(const NativeVerificationKey_& other, CommitmentLabels commitment_labels) const
150 {
151 bool is_equal = true;
152
153 if (this->log_circuit_size != other.log_circuit_size) {
154 info("Log circuit size mismatch: ", this->log_circuit_size, " vs ", other.log_circuit_size);
155 is_equal = false;
156 }
157
158 if (this->num_public_inputs != other.num_public_inputs) {
159 info("Num public inputs mismatch: ", this->num_public_inputs, " vs ", other.num_public_inputs);
160 is_equal = false;
161 }
162
163 if (this->pub_inputs_offset != other.pub_inputs_offset) {
164 info("Pub inputs offset mismatch: ", this->pub_inputs_offset, " vs ", other.pub_inputs_offset);
165 is_equal = false;
166 }
167
168 for (auto [this_comm, other_comm, label] : zip_view(this->get_all(), other.get_all(), commitment_labels)) {
169 if (this_comm != other_comm) {
170 info("Commitment mismatch: ", label);
171 is_equal = false;
172 }
173 }
174 return is_equal;
175 }
176#endif
177
178 virtual ~NativeVerificationKey_() = default;
180
185 template <typename PrecomputedData>
187 explicit NativeVerificationKey_(const PrecomputedData& precomputed)
188 : log_circuit_size(numeric::get_msb(precomputed.metadata.dyadic_size))
189 , num_public_inputs(precomputed.metadata.num_public_inputs)
190 , pub_inputs_offset(precomputed.metadata.pub_inputs_offset)
191 {
192 CommitmentKey commitment_key{ precomputed.metadata.dyadic_size };
193 for (auto [polynomial, commitment] : zip_view(precomputed.polynomials, this->get_all())) {
194 commitment = commitment_key.commit(polynomial);
195 }
196 }
197
202 static constexpr size_t calc_num_data_types()
203 {
204 size_t commitments_size = PrecomputedCommitments::size() * Codec::template calc_num_fields<Commitment>();
205 size_t metadata_size = MetaData::NUM_FIELDS * Codec::template calc_num_fields<uint64_t>();
206 return metadata_size + commitments_size;
207 }
208
214 virtual std::vector<DataType> to_field_elements() const
215 {
216
217 auto serialize = [](const auto& input, std::vector<DataType>& buffer) {
218 std::vector<DataType> input_fields = Codec::serialize_to_fields(input);
219 buffer.insert(buffer.end(), input_fields.begin(), input_fields.end());
220 };
221
222 std::vector<DataType> elements;
223 elements.reserve(calc_num_data_types());
224
225 serialize(this->log_circuit_size, elements);
226 serialize(this->num_public_inputs, elements);
227 serialize(this->pub_inputs_offset, elements);
228
229 for (const Commitment& commitment : this->get_all()) {
230 serialize(commitment, elements);
231 }
232
233 return elements;
234 };
235
241 {
242 BB_ASSERT_EQ(elements.size(),
244 "VerificationKey::from_field_elements received the wrong number of field elements");
245
246 size_t idx = 0;
247 auto deserialize = [&idx, &elements]<typename T>(T& target) {
248 size_t size = Codec::template calc_num_fields<T>();
249 target = Codec::template deserialize_from_fields<T>(elements.subspan(idx, size));
250 idx += size;
251 };
252
253 deserialize(this->log_circuit_size);
254 deserialize(this->num_public_inputs);
255 deserialize(this->pub_inputs_offset);
256
257 for (Commitment& commitment : this->get_all()) {
258 deserialize(commitment);
259 }
260 return idx;
261 }
262
267 fr hash() const
268 {
269 fr vk_hash = HashFunction::hash(this->to_field_elements());
270 return vk_hash;
271 }
272
283 {
284 static constexpr bool in_circuit = InCircuit<DataType>;
285 std::vector<DataType> vk_elements;
286 vk_elements.reserve(calc_num_data_types());
287
288 // Tag, serialize, and append to vk_elements
289 auto tag_and_append = [&]<typename T>(const T& component) {
290 auto frs = bb::tag_and_serialize<in_circuit, Codec>(component, tag);
291 vk_elements.insert(vk_elements.end(), frs.begin(), frs.end());
292 };
293
294 // Tag and serialize VK metadata
295 tag_and_append(this->log_circuit_size);
296 tag_and_append(this->num_public_inputs);
297 tag_and_append(this->pub_inputs_offset);
298
299 // Tag and serialize VK commitments. Point-at-infinity canonicalization to (0,0) is handled by
300 // FrCodec::serialize_to_fields on the native path.
301 for (const Commitment& commitment : this->get_all()) {
302 tag_and_append(commitment);
303 }
304
305 // Sanitize free witness tags before hashing
306 bb::unset_free_witness_tags<in_circuit, DataType>(vk_elements);
307
308 // Hash the tagged elements directly
309 return HashFunction::hash(vk_elements);
310 }
311
318 template <typename Transcript> DataType hash_with_origin_tagging(const Transcript& transcript) const
319 {
320 const OriginTag tag = bb::extract_transcript_tag(transcript);
322 }
323};
324
325// ===== Fixed stdlib verification key (ECCVM, Translator, AVM) =====
326
336template <typename Builder_, typename PrecomputedCommitments, typename NativeVerificationKey>
337class FixedStdlibVKAndHash_ : public PrecomputedCommitments {
338 public:
339 using Builder = Builder_;
340 using Commitment = typename PrecomputedCommitments::DataType;
342
343 bool operator==(const FixedStdlibVKAndHash_&) const = default;
345
350 : hash(FF::from_witness(builder, native_key->get_hash()))
351 {
352 for (auto [native_comm, comm] : zip_view(native_key->get_all(), this->get_all())) {
353 comm = Commitment::from_witness(builder, native_comm);
354 }
355 // Fix all witnesses since fixed VKs are always constant
357 for (Commitment& commitment : this->get_all()) {
358 commitment.fix_witness();
359 }
360 }
361
362 FF get_hash() const { return hash; }
363
364 private:
366};
367
368// ===== Stdlib verification key =====
369
377template <typename Builder_, typename PrecomputedCommitments, typename NativeVerificationKey_ = void>
378class StdlibVerificationKey_ : public PrecomputedCommitments {
379 public:
380 using Builder = Builder_;
382 using Commitment = typename PrecomputedCommitments::DataType;
388
389 bool operator==(const StdlibVerificationKey_&) const = default;
390 virtual ~StdlibVerificationKey_() = default;
392
397 template <typename T = NativeVerificationKey_>
398 requires(!std::is_void_v<T>)
400 : log_circuit_size(FF::from_witness(builder, typename FF::native(native_key->log_circuit_size)))
401 , num_public_inputs(FF::from_witness(builder, typename FF::native(native_key->num_public_inputs)))
402 , pub_inputs_offset(FF::from_witness(builder, typename FF::native(native_key->pub_inputs_offset)))
403 {
404
405 for (auto [commitment, native_commitment] : zip_view(this->get_all(), native_key->get_all())) {
406 commitment = Commitment::from_witness(builder, native_commitment);
407 }
408 }
409
414 {
415 using Codec = stdlib::StdlibCodec<FF>;
416
417 size_t num_frs_read = 0;
418
419 this->log_circuit_size = Codec::template deserialize_from_frs<FF>(elements, num_frs_read);
420 this->num_public_inputs = Codec::template deserialize_from_frs<FF>(elements, num_frs_read);
421 this->pub_inputs_offset = Codec::template deserialize_from_frs<FF>(elements, num_frs_read);
422
423 for (Commitment& commitment : this->get_all()) {
424 commitment = Codec::template deserialize_from_frs<Commitment>(elements, num_frs_read);
425 }
426 BB_ASSERT_EQ(num_frs_read,
427 elements.size(),
428 "StdlibVerificationKey deserialization received the wrong number of field elements");
429 }
430
435 const std::span<const uint32_t>& witness_indices)
436 {
437 std::vector<FF> vk_fields;
438 vk_fields.reserve(witness_indices.size());
439 for (const auto& idx : witness_indices) {
440 vk_fields.emplace_back(FF::from_witness_index(&builder, idx));
441 }
442 return StdlibVerificationKey_(vk_fields);
443 }
444
449 {
450 this->log_circuit_size.fix_witness();
451 this->num_public_inputs.fix_witness();
452 this->pub_inputs_offset.fix_witness();
453 for (Commitment& commitment : this->get_all()) {
454 commitment.fix_witness();
455 }
456 }
457
458#ifndef NDEBUG
463 template <typename T = NativeVerificationKey_>
464 requires(!std::is_void_v<T>)
465 T get_value() const
466 {
467 T native_vk;
468 native_vk.log_circuit_size = static_cast<uint64_t>(this->log_circuit_size.get_value());
469 native_vk.num_public_inputs = static_cast<uint64_t>(this->num_public_inputs.get_value());
470 native_vk.pub_inputs_offset = static_cast<uint64_t>(this->pub_inputs_offset.get_value());
471 for (auto [commitment, native_commitment] : zip_view(this->get_all(), native_vk.get_all())) {
472 native_commitment = commitment.get_value();
473 }
474 return native_vk;
475 }
476#endif
477
488 {
489 using Codec = stdlib::StdlibCodec<FF>;
490 static constexpr bool in_circuit = true; // StdlibVerificationKey_ is always in-circuit
491 std::vector<FF> vk_elements;
492
493 // Tag, serialize, and append to vk_elements
494 auto append_tagged = [&]<typename T>(const T& component) {
495 auto frs = bb::tag_and_serialize<in_circuit, Codec>(component, tag);
496 vk_elements.insert(vk_elements.end(), frs.begin(), frs.end());
497 };
498
499 // Tag and serialize VK metadata
500 append_tagged(this->log_circuit_size);
501 append_tagged(this->num_public_inputs);
502 append_tagged(this->pub_inputs_offset);
503
504 // Tag and serialize VK commitments.
505 // Note that commitments have been already deserialized and the point at infinity is constrained to (0,0)).
506 for (const Commitment& commitment : this->get_all()) {
507 append_tagged(commitment);
508 }
509
510 // Sanitize free witness tags before hashing
511 bb::unset_free_witness_tags<in_circuit, FF>(vk_elements);
512
513 // Hash the tagged elements directly
514 return stdlib::poseidon2<Builder>::hash(vk_elements);
515 }
516
523 template <typename Transcript> FF hash_with_origin_tagging(const Transcript& transcript) const
524 {
525 const OriginTag tag = bb::extract_transcript_tag(transcript);
527 }
528};
529
530// ===== VK + hash wrapper =====
531
551template <typename FF, typename VerificationKey> class VKAndHash_ {
552 public:
553 template <typename T = VerificationKey>
554 using Builder = typename std::enable_if_t<requires { typename T::Builder; }, T>::Builder;
555
556 template <typename T = VerificationKey>
558 typename std::enable_if_t<requires { typename T::NativeVerificationKey; }, T>::NativeVerificationKey;
559
560 VKAndHash_() = default;
561
565 VKAndHash_(const std::shared_ptr<VerificationKey>& vk)
566 : vk(vk)
567 , hash(vk->hash())
568 {}
569
573 VKAndHash_(const std::shared_ptr<VerificationKey>& vk, const FF& hash)
574 : vk(vk)
575 , hash(hash)
576 {}
577
581 template <typename VK = VerificationKey,
582 typename B = typename VK::Builder,
583 typename NVK = typename VK::NativeVerificationKey>
585 : vk(std::make_shared<VerificationKey>(&builder, native_vk))
586 , hash(FF::from_witness(&builder, native_vk->hash()))
587 {}
588 std::shared_ptr<VerificationKey> vk;
590};
591
592// ===== NativeVerificationKey_ Serde =====
593
594template <typename PrecomputedCommitments, typename Codec, typename HashFunction, typename CommitmentKey>
595inline void read(uint8_t const*& it,
597{
598 using serialize::read;
600
601 // Get the size directly from the static method
602 size_t num_frs = VK::calc_num_data_types();
603
604 // Read exactly num_frs field elements from the buffer
605 std::vector<typename Codec::DataType> field_elements(num_frs);
606 for (auto& element : field_elements) {
607 read(it, element);
608 }
609 // Then use from_field_elements to populate the verification key
610 vk.from_field_elements(field_elements);
611}
612
613template <typename PrecomputedCommitments, typename Codec, typename HashFunction, typename CommitmentKey>
614inline void write(std::vector<uint8_t>& buf,
616{
617 using serialize::write;
619
620 size_t before = buf.size();
621 // Convert to field elements and write them directly without length prefix
622 auto field_elements = vk.to_field_elements();
623 for (const auto& element : field_elements) {
624 write(buf, element);
625 }
626 size_t after = buf.size();
627 size_t num_frs = VK::calc_num_data_types();
628 BB_ASSERT_EQ(after - before, num_frs * sizeof(bb::fr), "VK serialization mismatch");
629}
630
631} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial, bool has_duplicates_hint=false) const
Uses the ProverSRS to create a commitment to p(X)
Simple stdlib verification key class for fixed-size circuits (ECCVM, Translator, AVM).
Definition flavor.hpp:337
FixedStdlibVKAndHash_(Builder *builder, const std::shared_ptr< NativeVerificationKey > &native_key)
Construct from native verification key and fix all witnesses (VK is constant for fixed circuits)
Definition flavor.hpp:349
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:340
bool operator==(const FixedStdlibVKAndHash_ &) const =default
Simple verification key class for fixed-size circuits (ECCVM, Translator, AVM).
Definition flavor.hpp:104
bool operator==(const FixedVKAndHash_ &) const =default
HashType get_hash() const
Definition flavor.hpp:119
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:106
Base Native verification key class.
Definition flavor.hpp:138
bool operator==(const NativeVerificationKey_ &) const =default
bool compare(const NativeVerificationKey_ &other, CommitmentLabels commitment_labels) const
Definition flavor.hpp:149
static constexpr size_t calc_num_data_types()
Calculate the number of field elements needed for serialization.
Definition flavor.hpp:202
typename Codec::DataType DataType
Definition flavor.hpp:141
virtual DataType hash_with_origin_tagging(const OriginTag &tag) const
Tag VK components and hash.
Definition flavor.hpp:282
fr hash() const
Compute VK hash.
Definition flavor.hpp:267
DataType hash_with_origin_tagging(const Transcript &transcript) const
An overload that accepts a transcript and extracts the tag internally.
Definition flavor.hpp:318
size_t from_field_elements(const std::span< const DataType > &elements)
Populate verification key from field elements.
Definition flavor.hpp:240
NativeVerificationKey_(const PrecomputedData &precomputed)
Construct VK from precomputed data by committing to polynomials.
Definition flavor.hpp:187
virtual ~NativeVerificationKey_()=default
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:140
virtual std::vector< DataType > to_field_elements() const
Serialize verification key to field elements.
Definition flavor.hpp:214
A template class for a reference array. Behaves as if std::array<T&, N> was possible.
Definition ref_array.hpp:23
Base Stdlib verification key class.
Definition flavor.hpp:378
bool operator==(const StdlibVerificationKey_ &) const =default
T get_value() const
Get the native verification key corresponding to this stdlib verification key.
Definition flavor.hpp:465
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:382
void fix_witness()
Fixes witnesses of VK to be constants.
Definition flavor.hpp:448
StdlibVerificationKey_(Builder *builder, const std::shared_ptr< T > &native_key)
Construct a new Verification Key with stdlib types from a provided native verification key.
Definition flavor.hpp:399
StdlibVerificationKey_(std::span< FF > elements)
Deserialize a verification key from a vector of field elements.
Definition flavor.hpp:413
FF hash_with_origin_tagging(const Transcript &transcript) const
An overload that accepts a transcript and extracts the tag internally.
Definition flavor.hpp:523
virtual FF hash_with_origin_tagging(const OriginTag &tag) const
Tag VK components and hash.
Definition flavor.hpp:487
virtual ~StdlibVerificationKey_()=default
static StdlibVerificationKey_ from_witness_indices(Builder &builder, const std::span< const uint32_t > &witness_indices)
Construct a VerificationKey from a set of corresponding witness indices.
Definition flavor.hpp:434
Wrapper holding a verification key and its precomputed hash.
Definition flavor.hpp:551
VKAndHash_(B &builder, const std::shared_ptr< NVK > &native_vk)
Construct stdlib VKAndHash from a native VK (recursive verification keys only).
Definition flavor.hpp:584
VKAndHash_()=default
typename std::enable_if_t< requires { typename T::NativeVerificationKey NativeVerificationKey
Definition flavor.hpp:558
std::shared_ptr< VerificationKey > vk
Definition flavor.hpp:588
typename std::enable_if_t< requires { typename T::Builder Builder
Definition flavor.hpp:554
VKAndHash_(const std::shared_ptr< VerificationKey > &vk, const FF &hash)
Construct from VK and pre-provided hash.
Definition flavor.hpp:573
VKAndHash_(const std::shared_ptr< VerificationKey > &vk)
Construct from VK, auto-computing the hash.
Definition flavor.hpp:565
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:67
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:838
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:480
#define info(...)
Definition log.hpp:93
AluTraceBuilder builder
Definition alu.test.cpp:124
std::string label
std::unique_ptr< uint8_t[]> buffer
Definition engine.cpp:60
UltraKeccakFlavor::VerificationKey VerificationKey
constexpr T get_msb(const T in)
Definition get_msb.hpp:50
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
void read(B &it, field2< base_field, Params > &value)
void write(B &buf, field2< base_field, Params > const &value)
OriginTag extract_transcript_tag(const TranscriptType &transcript)
Extract origin tag context from a transcript.
VerifierCommitmentKey< Curve > vk
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by SERIALIZATIO...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by SERIALIZATI...
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< Instruction > target
StdlibCodec for in-circuit (recursive) verification transcript handling.
Dyadic trace size and public inputs metadata; Common between prover and verifier keys.
Definition flavor.hpp:77
size_t pub_inputs_offset
Definition flavor.hpp:81
size_t num_public_inputs
Definition flavor.hpp:80
static constexpr size_t NUM_FIELDS
Definition flavor.hpp:78
size_t dyadic_size
Definition flavor.hpp:79
The precomputed data needed to compute a Honk VK.
Definition flavor.hpp:87
RefArray< Polynomial, NUM_PRECOMPUTED_ENTITIES > polynomials
Definition flavor.hpp:88
BB_VF_LOAD_LIMBS * this