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: Planned, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
72#pragma once
91
92#include <array>
93#include <concepts>
94#include <cstddef>
95#include <numeric>
96#include <utility>
97#include <vector>
98
99namespace bb {
100
105 FULL, // Serialize all metadata (log_circuit_size, num_public_inputs, pub_inputs_offset)
106 NO_METADATA // Serialize only commitments, no metadata
107};
108
112struct MetaData {
113 size_t dyadic_size = 0; // power-of-2 size of the execution trace
116};
117
121template <typename Polynomial, size_t NUM_PRECOMPUTED_ENTITIES> struct PrecomputedData_ {
122 RefArray<Polynomial, NUM_PRECOMPUTED_ENTITIES> polynomials; // polys whose commitments comprise the VK
123 MetaData metadata; // execution trace metadata
124};
125
136template <typename PrecomputedCommitments,
137 typename Codec,
138 typename HashFunction,
139 typename CommitmentKey = void,
141class NativeVerificationKey_ : public PrecomputedCommitments {
142 public:
143 using Commitment = typename PrecomputedCommitments::DataType;
144 using DataType = typename Codec::DataType;
145 uint64_t log_circuit_size = 0;
146 uint64_t num_public_inputs = 0;
147 uint64_t pub_inputs_offset = 0;
148 bool operator==(const NativeVerificationKey_&) const = default;
149
150#ifndef NDEBUG
151 template <size_t NUM_PRECOMPUTED_ENTITIES, typename StringType>
154 {
155 bool is_equal = true;
156
157 if (this->log_circuit_size != other.log_circuit_size) {
158 info("Log circuit size mismatch: ", this->log_circuit_size, " vs ", other.log_circuit_size);
159 is_equal = false;
160 }
161
162 if (this->num_public_inputs != other.num_public_inputs) {
163 info("Num public inputs mismatch: ", this->num_public_inputs, " vs ", other.num_public_inputs);
164 is_equal = false;
165 }
166
167 if (this->pub_inputs_offset != other.pub_inputs_offset) {
168 info("Pub inputs offset mismatch: ", this->pub_inputs_offset, " vs ", other.pub_inputs_offset);
169 is_equal = false;
170 }
171
172 for (auto [this_comm, other_comm, label] : zip_view(this->get_all(), other.get_all(), commitment_labels)) {
173 if (this_comm != other_comm) {
174 info("Commitment mismatch: ", label);
175 is_equal = false;
176 }
177 }
178 return is_equal;
179 }
180#endif
181
182 virtual ~NativeVerificationKey_() = default;
184 NativeVerificationKey_(const size_t circuit_size, const size_t num_public_inputs)
185 : log_circuit_size(numeric::get_msb(circuit_size))
187
192 template <typename PrecomputedData>
194 explicit NativeVerificationKey_(const PrecomputedData& precomputed)
195 : log_circuit_size(numeric::get_msb(precomputed.metadata.dyadic_size))
196 , num_public_inputs(precomputed.metadata.num_public_inputs)
197 , pub_inputs_offset(precomputed.metadata.pub_inputs_offset)
198 {
199 CommitmentKey commitment_key{ precomputed.metadata.dyadic_size };
200 for (auto [polynomial, commitment] : zip_view(precomputed.polynomials, this->get_all())) {
201 commitment = commitment_key.commit(polynomial);
202 }
203 }
204
209 static size_t calc_num_data_types()
210 {
211 // Create a temporary instance to get the number of precomputed entities
212 size_t commitments_size = PrecomputedCommitments::size() * Codec::template calc_num_fields<Commitment>();
213 size_t metadata_size = 0;
214 if constexpr (SerializeMetadata == VKSerializationMode::FULL) {
215 // 3 metadata fields + commitments
216 metadata_size = 3 * Codec::template calc_num_fields<uint64_t>();
217 }
218 // else NO_METADATA: metadata_size remains 0
219 return metadata_size + commitments_size;
220 }
221
227 virtual std::vector<DataType> to_field_elements() const
228 {
229
230 auto serialize = [](const auto& input, std::vector<DataType>& buffer) {
231 std::vector<DataType> input_fields = Codec::serialize_to_fields(input);
232 buffer.insert(buffer.end(), input_fields.begin(), input_fields.end());
233 };
234
235 std::vector<DataType> elements;
236
237 if constexpr (SerializeMetadata == VKSerializationMode::FULL) {
238 serialize(this->log_circuit_size, elements);
239 serialize(this->num_public_inputs, elements);
240 serialize(this->pub_inputs_offset, elements);
241 }
242 // else NO_METADATA: skip metadata serialization
243
244 for (const Commitment& commitment : this->get_all()) {
245 serialize(commitment, elements);
246 }
247
249 key.from_field_elements(elements);
250 return elements;
251 };
252
258 {
259
260 size_t idx = 0;
261 auto deserialize = [&idx, &elements]<typename T>(T& target) {
262 size_t size = Codec::template calc_num_fields<T>();
263 target = Codec::template deserialize_from_fields<T>(elements.subspan(idx, size));
264 idx += size;
265 };
266
267 if constexpr (SerializeMetadata == VKSerializationMode::FULL) {
268 deserialize(this->log_circuit_size);
269 deserialize(this->num_public_inputs);
270 deserialize(this->pub_inputs_offset);
271 }
272 // else NO_METADATA: skip metadata deserialization
273
274 for (Commitment& commitment : this->get_all()) {
275 deserialize(commitment);
276 }
277 return idx;
278 }
279
284 fr hash() const
285 {
286 fr vk_hash = HashFunction::hash(this->to_field_elements());
287 return vk_hash;
288 }
289
301 {
302 static constexpr bool in_circuit = InCircuit<DataType>;
303 std::vector<DataType> vk_elements;
304
305 // Tag, serialize, and append to vk_elements
306 auto tag_and_append = [&]<typename T>(const T& component) {
307 auto frs = bb::tag_and_serialize<in_circuit, Codec>(component, tag);
308 vk_elements.insert(vk_elements.end(), frs.begin(), frs.end());
309 };
310
311 // Tag and serialize VK metadata
312 tag_and_append(this->log_circuit_size);
313 tag_and_append(this->num_public_inputs);
314 tag_and_append(this->pub_inputs_offset);
315
316 // Tag and serialize VK commitments
317 for (const Commitment& commitment : this->get_all()) {
318 tag_and_append(commitment);
319 }
320
321 // Sanitize free witness tags before hashing
322 bb::unset_free_witness_tags<in_circuit, DataType>(vk_elements);
323
324 // Hash the tagged elements directly
325 return HashFunction::hash(vk_elements);
326 }
327
334 template <typename Transcript> DataType hash_with_origin_tagging(const Transcript& transcript) const
335 {
336 const OriginTag tag = bb::extract_transcript_tag(transcript);
338 }
339};
340
349template <typename Builder_,
350 typename PrecomputedCommitments,
351 typename NativeVerificationKey_ = void,
353class StdlibVerificationKey_ : public PrecomputedCommitments {
354 public:
355 using Builder = Builder_;
357 using Commitment = typename PrecomputedCommitments::DataType;
363
364 bool operator==(const StdlibVerificationKey_&) const = default;
365 virtual ~StdlibVerificationKey_() = default;
367
372 template <typename T = NativeVerificationKey_>
373 requires(!std::is_void_v<T>)
375 : log_circuit_size(FF::from_witness(builder, typename FF::native(native_key->log_circuit_size)))
376 , num_public_inputs(FF::from_witness(builder, typename FF::native(native_key->num_public_inputs)))
377 , pub_inputs_offset(FF::from_witness(builder, typename FF::native(native_key->pub_inputs_offset)))
378 {
379
380 for (auto [commitment, native_commitment] : zip_view(this->get_all(), native_key->get_all())) {
381 commitment = Commitment::from_witness(builder, native_commitment);
382 }
383 }
384
389 {
390 using Codec = stdlib::StdlibCodec<FF>;
391
392 size_t num_frs_read = 0;
393
394 this->log_circuit_size = Codec::template deserialize_from_frs<FF>(elements, num_frs_read);
395 this->num_public_inputs = Codec::template deserialize_from_frs<FF>(elements, num_frs_read);
396 this->pub_inputs_offset = Codec::template deserialize_from_frs<FF>(elements, num_frs_read);
397
398 for (Commitment& commitment : this->get_all()) {
399 commitment = Codec::template deserialize_from_frs<Commitment>(elements, num_frs_read);
400 }
401 }
402
407 const std::span<const uint32_t>& witness_indices)
408 {
409 std::vector<FF> vk_fields;
410 vk_fields.reserve(witness_indices.size());
411 for (const auto& idx : witness_indices) {
412 vk_fields.emplace_back(FF::from_witness_index(&builder, idx));
413 }
414 return StdlibVerificationKey_(vk_fields);
415 }
416
421 {
422 this->log_circuit_size.fix_witness();
423 this->num_public_inputs.fix_witness();
424 this->pub_inputs_offset.fix_witness();
425 for (Commitment& commitment : this->get_all()) {
426 commitment.fix_witness();
427 }
428 }
429
430#ifndef NDEBUG
435 template <typename T = NativeVerificationKey_>
436 requires(!std::is_void_v<T>)
437 T get_value() const
438 {
439 T native_vk;
440 native_vk.log_circuit_size = static_cast<uint64_t>(this->log_circuit_size.get_value());
441 native_vk.num_public_inputs = static_cast<uint64_t>(this->num_public_inputs.get_value());
442 native_vk.pub_inputs_offset = static_cast<uint64_t>(this->pub_inputs_offset.get_value());
443 for (auto [commitment, native_commitment] : zip_view(this->get_all(), native_vk.get_all())) {
444 native_commitment = commitment.get_value();
445 }
446 return native_vk;
447 }
448#endif
449
461 {
462 using Codec = stdlib::StdlibCodec<FF>;
463 static constexpr bool in_circuit = true; // StdlibVerificationKey_ is always in-circuit
464 std::vector<FF> vk_elements;
465
466 // Tag, serialize, and append to vk_elements
467 auto append_tagged = [&]<typename T>(const T& component) {
468 auto frs = bb::tag_and_serialize<in_circuit, Codec>(component, tag);
469 vk_elements.insert(vk_elements.end(), frs.begin(), frs.end());
470 };
471
472 // Tag and serialize VK metadata
473 append_tagged(this->log_circuit_size);
474 append_tagged(this->num_public_inputs);
475 append_tagged(this->pub_inputs_offset);
476
477 // Tag and serialize VK commitments
478 for (const Commitment& commitment : this->get_all()) {
479 append_tagged(commitment);
480 }
481
482 // Sanitize free witness tags before hashing
483 bb::unset_free_witness_tags<in_circuit, FF>(vk_elements);
484
485 // Hash the tagged elements directly
486 return stdlib::poseidon2<Builder>::hash(vk_elements);
487 }
488
495 template <typename Transcript> FF hash_with_origin_tagging(const Transcript& transcript) const
496 {
497 const OriginTag tag = bb::extract_transcript_tag(transcript);
499 }
500};
501
521template <typename FF, typename VerificationKey> class VKAndHash_ {
522 public:
523 template <typename T = VerificationKey>
524 using Builder = typename std::enable_if_t<requires { typename T::Builder; }, T>::Builder;
525
526 template <typename T = VerificationKey>
528 typename std::enable_if_t<requires { typename T::NativeVerificationKey; }, T>::NativeVerificationKey;
529
530 VKAndHash_() = default;
531
535 VKAndHash_(const std::shared_ptr<VerificationKey>& vk)
536 : vk(vk)
537 , hash(vk->hash())
538 {}
539
543 VKAndHash_(const std::shared_ptr<VerificationKey>& vk, const FF& hash)
544 : vk(vk)
545 , hash(hash)
546 {}
547
551 template <typename VK = VerificationKey,
552 typename B = typename VK::Builder,
553 typename NVK = typename VK::NativeVerificationKey>
555 : vk(std::make_shared<VerificationKey>(&builder, native_vk))
556 , hash(FF::from_witness(&builder, native_vk->hash()))
557 {}
558 std::shared_ptr<VerificationKey> vk;
560};
561
567template <typename Tuple> constexpr size_t compute_max_partial_relation_length()
568{
570 return []<std::size_t... Is>(std::index_sequence<Is...>) {
571 return std::max({ std::tuple_element_t<Is, Tuple>::RELATION_LENGTH... });
572 }(seq);
573}
574
578template <typename Tuple> constexpr size_t compute_number_of_subrelations()
579{
581 return []<std::size_t... I>(std::index_sequence<I...>) {
582 return (0 + ... + std::tuple_element_t<I, Tuple>::SUBRELATION_PARTIAL_LENGTHS.size());
583 }(seq);
584}
585
592template <typename RelationsTuple> constexpr auto create_sumcheck_tuple_of_tuples_of_univariates()
593{
595 return []<size_t... I>(std::index_sequence<I...>) {
597 typename std::tuple_element_t<I, RelationsTuple>::SumcheckTupleOfUnivariatesOverSubrelations{}...);
598 }(seq);
599}
600
615template <typename RelationsTuple> constexpr auto create_tuple_of_arrays_of_values()
616{
618 return []<size_t... I>(std::index_sequence<I...>) {
620 typename std::tuple_element_t<I, RelationsTuple>::SumcheckArrayOfValuesOverSubrelations{}...);
621 }(seq);
622}
623
624} // namespace bb
625
626// Forward declare honk flavors
627namespace bb {
628class UltraFlavor;
629class UltraZKFlavor;
630class UltraRollupFlavor;
631class ECCVMFlavor;
632class UltraKeccakFlavor;
633#ifdef STARKNET_GARAGA_FLAVORS
634class UltraStarknetFlavor;
635class UltraStarknetZKFlavor;
636#endif
637class UltraKeccakZKFlavor;
638class MegaFlavor;
639class MegaZKFlavor;
640class MegaAvmFlavor;
641class TranslatorFlavor;
642class ECCVMRecursiveFlavor;
643class TranslatorRecursiveFlavor;
644class AvmRecursiveFlavor;
645class MultilinearBatchingRecursiveFlavor;
646
647template <typename BuilderType> class UltraRecursiveFlavor_;
648template <typename BuilderType> class UltraZKRecursiveFlavor_;
649template <typename BuilderType> class UltraRollupRecursiveFlavor_;
650template <typename BuilderType> class MegaRecursiveFlavor_;
651template <typename BuilderType> class MegaZKRecursiveFlavor_;
652template <typename BuilderType> class MegaAvmRecursiveFlavor_;
653
654// Serialization methods for NativeVerificationKey_.
655// These should cover all base classes that do not need additional members, as long as the appropriate SerializeMetadata
656// is set in the template parameters.
657template <typename PrecomputedCommitments,
658 typename Codec,
659 typename HashFunction,
660 typename CommitmentKey,
661 VKSerializationMode SerializeMetadata>
662inline void read(
663 uint8_t const*& it,
665{
666 using serialize::read;
668
669 // Get the size directly from the static method
670 size_t num_frs = VK::calc_num_data_types();
671
672 // Read exactly num_frs field elements from the buffer
673 std::vector<typename Codec::DataType> field_elements(num_frs);
674 for (auto& element : field_elements) {
675 read(it, element);
676 }
677 // Then use from_field_elements to populate the verification key
678 vk.from_field_elements(field_elements);
679}
680
681template <typename PrecomputedCommitments,
682 typename Codec,
683 typename HashFunction,
684 typename CommitmentKey,
685 VKSerializationMode SerializeMetadata>
686inline void write(
687 std::vector<uint8_t>& buf,
689{
690 using serialize::write;
692
693 size_t before = buf.size();
694 // Convert to field elements and write them directly without length prefix
695 auto field_elements = vk.to_field_elements();
696 for (const auto& element : field_elements) {
697 write(buf, element);
698 }
699 size_t after = buf.size();
700 size_t num_frs = VK::calc_num_data_types();
701 BB_ASSERT_EQ(after - before, num_frs * sizeof(bb::fr), "VK serialization mismatch");
702}
703
704namespace avm2 {
705class AvmRecursiveFlavor;
706}
707
708} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:93
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
CommitmentKey object over a pairing group 𝔾₁.
Base Native verification key class.
Definition flavor.hpp:141
DataType hash_with_origin_tagging(const Transcript &transcript) const
An overload that accepts a transcript and extracts the tag internally.
Definition flavor.hpp:334
fr hash() const
Compute VK hash.
Definition flavor.hpp:284
static size_t calc_num_data_types()
Calculate the number of field elements needed for serialization.
Definition flavor.hpp:209
bool operator==(const NativeVerificationKey_ &) const =default
size_t from_field_elements(const std::span< const DataType > &elements)
Populate verification key from field elements.
Definition flavor.hpp:257
virtual ~NativeVerificationKey_()=default
bool compare(const NativeVerificationKey_ &other, RefArray< StringType, NUM_PRECOMPUTED_ENTITIES > commitment_labels) const
Definition flavor.hpp:152
typename Codec::DataType DataType
Definition flavor.hpp:144
virtual DataType hash_with_origin_tagging(const OriginTag &tag) const
Tag VK components and hash.
Definition flavor.hpp:300
NativeVerificationKey_(const PrecomputedData &precomputed)
Construct VK from precomputed data by committing to polynomials.
Definition flavor.hpp:194
virtual std::vector< DataType > to_field_elements() const
Serialize verification key to field elements.
Definition flavor.hpp:227
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:143
NativeVerificationKey_(const size_t circuit_size, const size_t num_public_inputs)
Definition flavor.hpp:184
A template class for a reference array. Behaves as if std::array<T&, N> was possible.
Definition ref_array.hpp:22
Base Stdlib verification key class.
Definition flavor.hpp:353
StdlibVerificationKey_(std::span< FF > elements)
Deserialize a verification key from a vector of field elements.
Definition flavor.hpp:388
void fix_witness()
Fixes witnesses of VK to be constants.
Definition flavor.hpp:420
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:357
FF hash_with_origin_tagging(const Transcript &transcript) const
An overload that accepts a transcript and extracts the tag internally.
Definition flavor.hpp:495
bool operator==(const StdlibVerificationKey_ &) const =default
T get_value() const
Get the native verification key corresponding to this stdlib verification key.
Definition flavor.hpp:437
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:406
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:374
virtual FF hash_with_origin_tagging(const OriginTag &tag) const
Tag VK components and hash.
Definition flavor.hpp:460
virtual ~StdlibVerificationKey_()=default
Wrapper holding a verification key and its precomputed hash.
Definition flavor.hpp:521
VKAndHash_(B &builder, const std::shared_ptr< NVK > &native_vk)
Construct stdlib VKAndHash from a native VK (recursive verification keys only).
Definition flavor.hpp:554
VKAndHash_()=default
typename std::enable_if_t< requires { typename T::NativeVerificationKey NativeVerificationKey
Definition flavor.hpp:528
std::shared_ptr< VerificationKey > vk
Definition flavor.hpp:558
typename std::enable_if_t< requires { typename T::Builder Builder
Definition flavor.hpp:524
VKAndHash_(const std::shared_ptr< VerificationKey > &vk, const FF &hash)
Construct from VK and pre-provided hash.
Definition flavor.hpp:543
VKAndHash_(const std::shared_ptr< VerificationKey > &vk)
Construct from VK, auto-computing the hash.
Definition flavor.hpp:535
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:62
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:828
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:454
void info(Args... args)
Definition log.hpp:89
AluTraceBuilder builder
Definition alu.test.cpp:124
uint8_t const * buf
Definition data_store.hpp:9
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
UltraKeccakFlavor::VerificationKey VerificationKey
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
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.
VKSerializationMode
Enum to control verification key metadata serialization.
Definition flavor.hpp:104
constexpr size_t compute_number_of_subrelations()
Utility function to find the number of subrelations.
Definition flavor.hpp:578
constexpr auto create_tuple_of_arrays_of_values()
Definition flavor.hpp:615
constexpr size_t compute_max_partial_relation_length()
Utility function to find max PARTIAL_RELATION_LENGTH tuples of Relations.
Definition flavor.hpp:567
constexpr auto create_sumcheck_tuple_of_tuples_of_univariates()
Utility function to construct a container for the subrelation accumulators of sumcheck proving.
Definition flavor.hpp:592
VerifierCommitmentKey< Curve > vk
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by MSGPACK_FIEL...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by MSGPACK_FIE...
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
TUPLET_INLINE constexpr auto make_tuple(Ts &&... args)
Definition tuplet.hpp:1062
Dyadic trace size and public inputs metadata; Common between prover and verifier keys.
Definition flavor.hpp:112
size_t pub_inputs_offset
Definition flavor.hpp:115
size_t num_public_inputs
Definition flavor.hpp:114
size_t dyadic_size
Definition flavor.hpp:113
The precomputed data needed to compute a Honk VK.
Definition flavor.hpp:121
RefArray< Polynomial, NUM_PRECOMPUTED_ENTITIES > polynomials
Definition flavor.hpp:122