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: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
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
134template <typename PrecomputedCommitments,
135 typename Transcript,
137class NativeVerificationKey_ : public PrecomputedCommitments {
138 public:
139 using Commitment = typename PrecomputedCommitments::DataType;
140 uint64_t log_circuit_size = 0;
141 uint64_t num_public_inputs = 0;
142 uint64_t pub_inputs_offset = 0;
143 bool operator==(const NativeVerificationKey_&) const = default;
144
145#ifndef NDEBUG
146 template <size_t NUM_PRECOMPUTED_ENTITIES, typename StringType>
149 {
150 bool is_equal = true;
151
152 if (this->log_circuit_size != other.log_circuit_size) {
153 info("Log circuit size mismatch: ", this->log_circuit_size, " vs ", other.log_circuit_size);
154 is_equal = false;
155 }
156
157 if (this->num_public_inputs != other.num_public_inputs) {
158 info("Num public inputs mismatch: ", this->num_public_inputs, " vs ", other.num_public_inputs);
159 is_equal = false;
160 }
161
162 if (this->pub_inputs_offset != other.pub_inputs_offset) {
163 info("Pub inputs offset mismatch: ", this->pub_inputs_offset, " vs ", other.pub_inputs_offset);
164 is_equal = false;
165 }
166
167 for (auto [this_comm, other_comm, label] : zip_view(this->get_all(), other.get_all(), commitment_labels)) {
168 if (this_comm != other_comm) {
169 info("Commitment mismatch: ", label);
170 is_equal = false;
171 }
172 }
173 return is_equal;
174 }
175#endif
176
177 virtual ~NativeVerificationKey_() = default;
179 NativeVerificationKey_(const size_t circuit_size, const size_t num_public_inputs)
180 {
181 this->log_circuit_size = numeric::get_msb(circuit_size);
182 this->num_public_inputs = num_public_inputs;
183 };
184
189 static size_t calc_num_data_types()
190 {
191 // Create a temporary instance to get the number of precomputed entities
192 size_t commitments_size =
193 PrecomputedCommitments::size() * Transcript::Codec::template calc_num_fields<Commitment>();
194 size_t metadata_size = 0;
195 if constexpr (SerializeMetadata == VKSerializationMode::FULL) {
196 // 3 metadata fields + commitments
197 metadata_size = 3 * Transcript::Codec::template calc_num_fields<uint64_t>();
198 }
199 // else NO_METADATA: metadata_size remains 0
200 return metadata_size + commitments_size;
201 }
202
209 {
210
211 auto serialize = [](const auto& input, std::vector<typename Transcript::DataType>& buffer) {
213 buffer.insert(buffer.end(), input_fields.begin(), input_fields.end());
214 };
215
217
218 if constexpr (SerializeMetadata == VKSerializationMode::FULL) {
219 serialize(this->log_circuit_size, elements);
220 serialize(this->num_public_inputs, elements);
221 serialize(this->pub_inputs_offset, elements);
222 }
223 // else NO_METADATA: skip metadata serialization
224
225 for (const Commitment& commitment : this->get_all()) {
226 serialize(commitment, elements);
227 }
228
230 key.from_field_elements(elements);
231 return elements;
232 };
233
239 {
240
241 size_t idx = 0;
242 auto deserialize = [&idx, &elements]<typename T>(T& target) {
243 size_t size = Transcript::Codec::template calc_num_fields<T>();
244 target = Transcript::template deserialize<T>(elements.subspan(idx, size));
245 idx += size;
246 };
247
248 if constexpr (SerializeMetadata == VKSerializationMode::FULL) {
249 deserialize(this->log_circuit_size);
250 deserialize(this->num_public_inputs);
251 deserialize(this->pub_inputs_offset);
252 }
253 // else NO_METADATA: skip metadata deserialization
254
255 for (Commitment& commitment : this->get_all()) {
256 deserialize(commitment);
257 }
258 return idx;
259 }
260
265 fr hash() const
266 {
267 fr vk_hash = Transcript::HashFunction::hash(this->to_field_elements());
268 return vk_hash;
269 }
270
281 virtual typename Transcript::DataType hash_with_origin_tagging([[maybe_unused]] const std::string& domain_separator,
282 Transcript& transcript) const
283 {
284 using DataType = typename Transcript::DataType;
285 using Codec = typename Transcript::Codec;
286 std::vector<DataType> vk_elements;
287
288 const OriginTag tag = bb::extract_transcript_tag(transcript);
289
290 // Tag, serialize, and append to vk_elements
291 auto tag_and_append = [&]<typename T>(const T& component) {
292 auto frs = bb::tag_and_serialize<Transcript::in_circuit, Codec>(component, tag);
293 vk_elements.insert(vk_elements.end(), frs.begin(), frs.end());
294 };
295
296 // Tag and serialize VK metadata
297 tag_and_append(this->log_circuit_size);
298 tag_and_append(this->num_public_inputs);
299 tag_and_append(this->pub_inputs_offset);
300
301 // Tag and serialize VK commitments
302 for (const Commitment& commitment : this->get_all()) {
303 tag_and_append(commitment);
304 }
305
306 // Sanitize free witness tags before hashing
307 bb::unset_free_witness_tags<Transcript::in_circuit, DataType>(vk_elements);
308
309 // Hash the tagged elements directly
310 return Transcript::HashFunction::hash(vk_elements);
311 }
312};
313
322template <typename Builder_,
323 typename PrecomputedCommitments,
325class StdlibVerificationKey_ : public PrecomputedCommitments {
326 public:
327 using Builder = Builder_;
329 using Commitment = typename PrecomputedCommitments::DataType;
334
335 bool operator==(const StdlibVerificationKey_&) const = default;
336 virtual ~StdlibVerificationKey_() = default;
338 StdlibVerificationKey_(const size_t circuit_size, const size_t num_public_inputs)
339 {
340 this->log_circuit_size = numeric::get_msb(circuit_size);
341 this->num_public_inputs = num_public_inputs;
342 };
343
349 virtual std::vector<FF> to_field_elements() const
350 {
351 using Codec = stdlib::StdlibCodec<FF>;
352
353 auto serialize_to_field_buffer = []<typename T>(const T& input, std::vector<FF>& buffer) {
354 std::vector<FF> input_fields = Codec::template serialize_to_fields<T>(input);
355 buffer.insert(buffer.end(), input_fields.begin(), input_fields.end());
356 };
357
358 std::vector<FF> elements;
359
360 serialize_to_field_buffer(this->log_circuit_size, elements);
361 serialize_to_field_buffer(this->num_public_inputs, elements);
362 serialize_to_field_buffer(this->pub_inputs_offset, elements);
363
364 for (const Commitment& commitment : this->get_all()) {
365 serialize_to_field_buffer(commitment, elements);
366 }
367
368 return elements;
369 };
370
378 {
380 return vk_hash;
381 }
382
393 virtual FF hash_with_origin_tagging([[maybe_unused]] const std::string& domain_separator,
394 Transcript& transcript) const
395 {
396 using Codec = stdlib::StdlibCodec<FF>;
397 std::vector<FF> vk_elements;
398
399 const OriginTag tag = bb::extract_transcript_tag(transcript);
400
401 // Tag, serialize, and append to vk_elements
402 auto append_tagged = [&]<typename T>(const T& component) {
403 auto frs = bb::tag_and_serialize<Transcript::in_circuit, Codec>(component, tag);
404 vk_elements.insert(vk_elements.end(), frs.begin(), frs.end());
405 };
406
407 // Tag and serialize VK metadata
408 append_tagged(this->log_circuit_size);
409 append_tagged(this->num_public_inputs);
410 append_tagged(this->pub_inputs_offset);
411
412 // Tag and serialize VK commitments
413 for (const Commitment& commitment : this->get_all()) {
414 append_tagged(commitment);
415 }
416
417 // Sanitize free witness tags before hashing
418 bb::unset_free_witness_tags<Transcript::in_circuit, FF>(vk_elements);
419
420 // Hash the tagged elements directly
421 return Transcript::HashFunction::hash(vk_elements);
422 }
423};
424
425template <typename FF, typename VerificationKey> class VKAndHash_ {
426 public:
427 using Builder = VerificationKey::Builder;
428 using NativeVerificationKey = VerificationKey::NativeVerificationKey;
429
430 VKAndHash_() = default;
431 VKAndHash_(const std::shared_ptr<VerificationKey>& vk)
432 : vk(vk)
433 , hash(vk->hash())
434 {}
435
436 VKAndHash_(const std::shared_ptr<VerificationKey>& vk, const FF& hash)
437 : vk(vk)
438 , hash(hash)
439 {}
440
442 : vk(std::make_shared<VerificationKey>(&builder, native_vk))
443 , hash(FF::from_witness(&builder, native_vk->hash()))
444 {}
445 std::shared_ptr<VerificationKey> vk;
447};
448
449// Because of how Gemini is written, it is important to put the polynomials out in this order.
450auto get_unshifted_then_shifted(const auto& all_entities)
451{
452 return concatenate(all_entities.get_unshifted(), all_entities.get_shifted());
453};
454
460template <typename Tuple> constexpr size_t compute_max_partial_relation_length()
461{
463 return []<std::size_t... Is>(std::index_sequence<Is...>) {
464 return std::max({ std::tuple_element_t<Is, Tuple>::RELATION_LENGTH... });
465 }(seq);
466}
467
471template <typename Tuple> constexpr size_t compute_number_of_subrelations()
472{
474 return []<std::size_t... I>(std::index_sequence<I...>) {
475 return (0 + ... + std::tuple_element_t<I, Tuple>::SUBRELATION_PARTIAL_LENGTHS.size());
476 }(seq);
477}
478
485template <typename RelationsTuple> constexpr auto create_sumcheck_tuple_of_tuples_of_univariates()
486{
488 return []<size_t... I>(std::index_sequence<I...>) {
490 typename std::tuple_element_t<I, RelationsTuple>::SumcheckTupleOfUnivariatesOverSubrelations{}...);
491 }(seq);
492}
493
508template <typename RelationsTuple> constexpr auto create_tuple_of_arrays_of_values()
509{
511 return []<size_t... I>(std::index_sequence<I...>) {
513 typename std::tuple_element_t<I, RelationsTuple>::SumcheckArrayOfValuesOverSubrelations{}...);
514 }(seq);
515}
516
517} // namespace bb
518
519// Forward declare honk flavors
520namespace bb {
521class UltraFlavor;
522class UltraZKFlavor;
523class UltraRollupFlavor;
524class ECCVMFlavor;
525class UltraKeccakFlavor;
526#ifdef STARKNET_GARAGA_FLAVORS
527class UltraStarknetFlavor;
528class UltraStarknetZKFlavor;
529#endif
530class UltraKeccakZKFlavor;
531class MegaFlavor;
532class MegaZKFlavor;
533class TranslatorFlavor;
534class ECCVMRecursiveFlavor;
535class TranslatorRecursiveFlavor;
536class AvmRecursiveFlavor;
537class MultilinearBatchingRecursiveFlavor;
538
539template <typename BuilderType> class UltraRecursiveFlavor_;
540template <typename BuilderType> class UltraZKRecursiveFlavor_;
541template <typename BuilderType> class UltraRollupRecursiveFlavor_;
542template <typename BuilderType> class MegaRecursiveFlavor_;
543template <typename BuilderType> class MegaZKRecursiveFlavor_;
544
545// Serialization methods for NativeVerificationKey_.
546// These should cover all base classes that do not need additional members, as long as the appropriate SerializeMetadata
547// is set in the template parameters.
548template <typename PrecomputedCommitments, typename Transcript, VKSerializationMode SerializeMetadata>
550{
551 using serialize::read;
552
553 // Get the size directly from the static method
554 size_t num_frs =
556
557 // Read exactly num_frs field elements from the buffer
558 std::vector<typename Transcript::DataType> field_elements(num_frs);
559 for (auto& element : field_elements) {
560 read(it, element);
561 }
562 // Then use from_field_elements to populate the verification key
563 vk.from_field_elements(field_elements);
564}
565
566template <typename PrecomputedCommitments, typename Transcript, VKSerializationMode SerializeMetadata>
567inline void write(std::vector<uint8_t>& buf,
569{
570 using serialize::write;
571 size_t before = buf.size();
572 // Convert to field elements and write them directly without length prefix
573 auto field_elements = vk.to_field_elements();
574 for (const auto& element : field_elements) {
575 write(buf, element);
576 }
577 size_t after = buf.size();
578 size_t num_frs =
580 BB_ASSERT_EQ(after - before, num_frs * sizeof(bb::fr), "VK serialization mismatch");
581}
582
583namespace avm2 {
584class AvmRecursiveFlavor;
585}
586
587} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
typename Codec::DataType DataType
static std::vector< DataType > serialize(const T &element)
Base Native verification key class.
Definition flavor.hpp:137
static size_t calc_num_data_types()
Calculate the number of field elements needed for serialization.
Definition flavor.hpp:189
bool operator==(const NativeVerificationKey_ &) const =default
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:139
NativeVerificationKey_(const size_t circuit_size, const size_t num_public_inputs)
Definition flavor.hpp:179
size_t from_field_elements(const std::span< const typename Transcript::DataType > &elements)
Populate verification key from field elements.
Definition flavor.hpp:238
fr hash() const
Compute VK hash.
Definition flavor.hpp:265
virtual std::vector< typename Transcript::DataType > to_field_elements() const
Serialize verification key to field elements.
Definition flavor.hpp:208
bool compare(const NativeVerificationKey_ &other, RefArray< StringType, NUM_PRECOMPUTED_ENTITIES > commitment_labels) const
Definition flavor.hpp:147
virtual Transcript::DataType hash_with_origin_tagging(const std::string &domain_separator, Transcript &transcript) const
Tag VK components and hash.
Definition flavor.hpp:281
virtual ~NativeVerificationKey_()=default
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:325
virtual ~StdlibVerificationKey_()=default
virtual std::vector< FF > to_field_elements() const
Serialize verification key to field elements.
Definition flavor.hpp:349
StdlibVerificationKey_(const size_t circuit_size, const size_t num_public_inputs)
Definition flavor.hpp:338
virtual FF hash_with_origin_tagging(const std::string &domain_separator, Transcript &transcript) const
Tag VK components and hash.
Definition flavor.hpp:393
typename PrecomputedCommitments::DataType Commitment
Definition flavor.hpp:329
FF hash()
A model function to show how to compute the VK hash (without the Transcript abstracting things away).
Definition flavor.hpp:377
bool operator==(const StdlibVerificationKey_ &) const =default
VerificationKey::NativeVerificationKey NativeVerificationKey
Definition flavor.hpp:428
VKAndHash_()=default
VKAndHash_(Builder &builder, const std::shared_ptr< NativeVerificationKey > &native_vk)
Definition flavor.hpp:441
std::shared_ptr< VerificationKey > vk
Definition flavor.hpp:445
VKAndHash_(const std::shared_ptr< VerificationKey > &vk, const FF &hash)
Definition flavor.hpp:436
VerificationKey::Builder Builder
Definition flavor.hpp:427
VKAndHash_(const std::shared_ptr< VerificationKey > &vk)
Definition flavor.hpp:431
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
void info(Args... args)
Definition log.hpp:75
AluTraceBuilder builder
Definition alu.test.cpp:124
uint8_t const * buf
Definition data_store.hpp:9
ECCVMFlavor::Transcript Transcript
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 write(std::vector< uint8_t > &buf, Chonk::VerificationKey const &vk)
Definition chonk.hpp:366
OriginTag extract_transcript_tag(const TranscriptType &transcript)
Extract origin tag context from a transcript.
void read(uint8_t const *&it, Chonk::VerificationKey &vk)
Definition chonk.hpp:350
VKSerializationMode
Enum to control verification key metadata serialization.
Definition flavor.hpp:104
RefArray< T,(Ns+...)> constexpr concatenate(const RefArray< T, Ns > &... ref_arrays)
Concatenates multiple RefArray objects into a single RefArray.
constexpr size_t compute_number_of_subrelations()
Utility function to find the number of subrelations.
Definition flavor.hpp:471
constexpr auto create_tuple_of_arrays_of_values()
Definition flavor.hpp:508
constexpr size_t compute_max_partial_relation_length()
Utility function to find max PARTIAL_RELATION_LENGTH tuples of Relations.
Definition flavor.hpp:460
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:485
auto get_unshifted_then_shifted(const auto &all_entities)
Definition flavor.hpp:450
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