Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
origin_tag.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
7#pragma once
19#include <cstddef>
20#include <iterator>
21#include <ostream>
22#include <type_traits>
23#include <vector>
24
25// Trait to detect if a type is iterable
26template <typename T, typename = void> struct is_iterable : std::false_type {};
27
28// this gets used only when we can call std::begin() and std::end() on that type
29template <typename T>
30struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T&>())), decltype(std::end(std::declval<T&>()))>>
31 : std::true_type {};
32
33template <typename T> constexpr bool is_iterable_v = is_iterable<T>::value;
34
35#define STANDARD_TESTING_TAGS /*Tags reused in tests*/ \
36 const size_t parent_id = 0; \
37 [[maybe_unused]] const auto clear_tag = OriginTag::constant(); /* A tag representing a constant value */ \
38 [[maybe_unused]] const auto constant_tag = OriginTag::constant(); /* Alias for clear_tag */ \
39 const auto submitted_value_origin_tag = OriginTag( \
40 parent_id, /*round_id=*/0, /*is_submitted=*/true); /*A tag describing a value submitted in the 0th round*/ \
41 const auto next_submitted_value_origin_tag = OriginTag( \
42 parent_id, /*round_id=*/1, /*is_submitted=*/true); /*A tag describing a value submitted in the 1st round*/ \
43 const auto challenge_origin_tag = OriginTag( \
44 parent_id, /*round_id=*/0, /*is_submitted=*/false); /*A tag describing a challenge derived in the 0th round*/ \
45 const auto next_challenge_tag = OriginTag( \
46 parent_id, /*round_id=*/1, /*is_submitted=*/false); /*A tag describing a challenge derived in the 1st round*/ \
47 const auto first_two_merged_tag = \
48 OriginTag(submitted_value_origin_tag, \
49 challenge_origin_tag); /*A tag describing a value constructed from values submitted by the prover in \
50 the 0th round and challenges from the same round */ \
51 const auto first_and_third_merged_tag = \
52 OriginTag(submitted_value_origin_tag, \
53 next_challenge_tag); /* A tag describing a value constructed from values submitted in the 0th round \
54 and challenges computed in the 1st round*/ \
55 const auto first_second_third_merged_tag = OriginTag( \
56 first_two_merged_tag, next_challenge_tag); /* A tag describing a value computed from values submitted in the \
57 0th round and challenges generated in the 0th and 1st round*/ \
58 const auto first_to_fourth_merged_tag = \
59 OriginTag(first_second_third_merged_tag, \
60 next_submitted_value_origin_tag); /* A tag describing a value computed from values submitted in the \
61 0th and 1st round and challenges generated in the 0th and 1st round*/ \
62 const auto instant_death_tag = OriginTag::poisoned(); /* A tag that causes an abort on any arithmetic*/
63
64namespace bb {
65
66void check_round_provenance(const uint256_t& provenance_a, const uint256_t& provenance_b);
67#ifndef AZTEC_NO_ORIGIN_TAGS
68struct OriginTag {
69
70 static constexpr size_t CONSTANT = static_cast<size_t>(-1);
71 static constexpr size_t FREE_WITNESS = static_cast<size_t>(-2);
72 // transcript_index represents the index of a unique transcript object that generated the value. It uses
73 // a concrete index, not bits for now, since we never expect two different indices to be used in the same
74 // computation apart from equality assertion
75 // transcript_index is set to CONSTANT if the value is just a constant
76 // transcript_index is set to FREE_WITNESS if the value is a free witness (not a constant and not from the
77 // transcript)
78 // NOTE: The default is FREE_WITNESS so that if we forget to set the tag, it will be treated as a witness,
79 // which is safer (can trigger errors if misused) than treating it as a constant (which would be silently accepted)
81
82 // round_provenance specifies which submitted values and challenges have been used to generate this element
83 // The lower 128 bits represent using a submitted value from a corresponding round (the shift represents the
84 // round) The higher 128 bits represent using a challenge value from an corresponding round (the shift
85 // represents the round)
87
88 // Instant death is used for poisoning values we should never use in arithmetic
89 bool instant_death = false;
91 // Default Origin Tag has everything set to zero and can't cause any issues
92 OriginTag() = default;
93 OriginTag(const OriginTag& other) = default;
94 OriginTag(OriginTag&& other) = default;
95 OriginTag& operator=(const OriginTag& other) = default;
96 OriginTag& operator=(OriginTag&& other) noexcept
97 {
98
100 round_provenance = other.round_provenance;
101 instant_death = other.instant_death;
102 return *this;
103 }
111 OriginTag(size_t transcript_idx, size_t round_number, bool is_submitted = true)
112 : transcript_index(transcript_idx)
113 , round_provenance((static_cast<uint256_t>(1) << (round_number + (is_submitted ? 0 : 128))))
114 {
115 BB_ASSERT_LT(round_number, 128U);
116 }
117
127 OriginTag(const OriginTag& tag_a, const OriginTag& tag_b);
128
138 template <class... T>
139 OriginTag(const OriginTag& tag, const T&... rest)
143 {
144
145 OriginTag merged_tag = *this;
146 for (const auto& next_tag : { rest... }) {
147 merged_tag = OriginTag(merged_tag, next_tag);
148 }
149 *this = merged_tag;
151 ~OriginTag() = default;
152 bool operator==(const OriginTag& other) const;
153 void poison() { instant_death = true; }
154 void unpoison() { instant_death = false; }
155 bool is_poisoned() const { return instant_death; }
156 bool is_empty() const { return !instant_death && transcript_index == CONSTANT; };
157
158 bool is_free_witness() const { return transcript_index == FREE_WITNESS; }
159 void set_free_witness()
165 {
168 }
169
170 bool is_constant() const { return transcript_index == CONSTANT && !instant_death; }
171 void set_constant()
172 {
175 }
176
177 // Static factory methods for cleaner syntax
178 static OriginTag constant()
179 {
182 return tag;
183 }
184
185 static OriginTag free_witness()
186 {
189 return tag;
190 }
191
192 static OriginTag poisoned()
193 {
195 tag.instant_death = true;
196 return tag;
197 }
203};
204inline std::ostream& operator<<(std::ostream& os, OriginTag const& v)
205{
206 return os << "{ transcript_idx: " << v.transcript_index << ", round_prov: " << v.round_provenance
207 << ", instadeath: " << v.instant_death << " }";
208}
209
210#else
211
212struct OriginTag {
213 OriginTag() = default;
214 OriginTag(const OriginTag& other) = default;
215 OriginTag(OriginTag&& other) = default;
216 OriginTag& operator=(const OriginTag& other) = default;
217 OriginTag& operator=(OriginTag&& other) = default;
218 ~OriginTag() = default;
219
220 OriginTag(size_t transcript_idx [[maybe_unused]],
221 size_t round_number [[maybe_unused]],
222 bool is_submitted [[maybe_unused]] = true)
223 {}
224
225 OriginTag(const OriginTag&, const OriginTag&) {}
226 template <class... T> OriginTag(const OriginTag&, const T&...) {}
227 bool operator==(const OriginTag& other) const;
228 void poison() {}
229 void unpoison() {}
230 static bool is_poisoned() { return false; }
231 static bool is_empty() { return true; };
232 bool is_free_witness() const { return false; }
233 void set_free_witness() {}
234 void unset_free_witness() {}
235 bool is_constant() const { return true; }
236 void set_constant() {}
237 void clear_round_provenance() {}
238
239 // Static factory methods (no-ops in release builds)
240 static OriginTag constant() { return OriginTag(); }
241 static OriginTag free_witness() { return OriginTag(); }
242 static OriginTag poisoned() { return OriginTag(); }
243};
244inline std::ostream& operator<<(std::ostream& os, OriginTag const&)
245{
246 return os << "{ Origin Tag tracking is disabled in release builds }";
247}
248#endif
249
250// Helper functions for working with origin tags
259template <bool in_circuit, typename T> inline void assign_origin_tag(T& elem, const OriginTag& tag)
260{
261 if constexpr (in_circuit) {
262 if constexpr (is_iterable_v<T>) {
263 for (auto& e : elem) {
264 e.set_origin_tag(tag);
265 }
266 } else {
267 elem.set_origin_tag(tag);
268 }
269 }
270}
271
280template <bool in_circuit, typename T> inline void check_origin_tag(T& elem, const OriginTag& tag)
281{
282 if constexpr (in_circuit) {
283 if constexpr (is_iterable_v<T>) {
284 for (auto& e : elem) {
285 BB_ASSERT(e.get_origin_tag() == tag);
286 };
287 } else {
288 BB_ASSERT(elem.get_origin_tag() == tag);
289 }
290 }
291}
292
300template <bool in_circuit, typename DataType> inline void unset_free_witness_tags(std::vector<DataType>& input)
301{
302 if constexpr (in_circuit) {
303 for (auto& entry : input) {
304 entry.unset_free_witness_tag();
305 }
306 }
307}
308
319template <bool in_circuit, typename Codec, typename T>
320inline std::vector<typename Codec::DataType> tag_and_serialize(const T& component, const OriginTag& tag)
321{
322 if constexpr (in_circuit) {
323 assign_origin_tag<in_circuit>(const_cast<T&>(component), tag);
324 }
325 // Serialize to field elements
326 return Codec::serialize_to_fields(component);
327}
328
337template <typename TranscriptType> inline OriginTag extract_transcript_tag(const TranscriptType& transcript)
338{
339 return OriginTag(transcript.transcript_index, transcript.round_index, /*is_submitted=*/true);
341
342} // namespace bb
343template <typename T>
344concept usesTag = requires(T x, const bb::OriginTag& tag) { x.set_origin_tag(tag); };
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:143
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:255
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::vector< typename Codec::DataType > tag_and_serialize(const T &component, const OriginTag &tag)
Tag a component with a given origin tag and serialize it to field elements.
void check_round_provenance(const uint256_t &provenance_a, const uint256_t &provenance_b)
Detect if two elements from the same transcript are performing a suspicious interaction.
OriginTag extract_transcript_tag(const TranscriptType &transcript)
Extract origin tag context from a transcript.
void unset_free_witness_tags(std::vector< DataType > &input)
Unsets free witness tags on all elements in a vector.
void assign_origin_tag(T &elem, const OriginTag &tag)
Assigns an origin tag to an element or all elements in an iterable container.
void check_origin_tag(T &elem, const OriginTag &tag)
Checks that an element or all elements in an iterable container have the expected origin tag.
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
constexpr bool is_iterable_v
size_t transcript_index
void unset_free_witness()
OriginTag()=default
static OriginTag constant()
bool is_poisoned() const
void set_constant()
~OriginTag()=default
static OriginTag poisoned()
void set_free_witness()
static constexpr size_t CONSTANT
OriginTag & operator=(const OriginTag &other)=default
static constexpr size_t FREE_WITNESS
bool is_constant() const
bool is_empty() const
void clear_round_provenance()
Clear the round_provenance to address round provenance false positives.
bool is_free_witness() const
numeric::uint256_t round_provenance
static OriginTag free_witness()
bool operator==(const OriginTag &other) const