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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] 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 [[maybe_unused]] const auto instant_death_tag = \
63 OriginTag::poisoned(); /* A tag that causes an abort on any arithmetic*/
64
65namespace bb {
66
67void check_round_provenance(const uint256_t& provenance_a, const uint256_t& provenance_b);
68#ifndef AZTEC_NO_ORIGIN_TAGS
69struct OriginTag {
70
71 static constexpr size_t CONSTANT = static_cast<size_t>(-1);
72 static constexpr size_t FREE_WITNESS = static_cast<size_t>(-2);
73 // transcript_index represents the index of a unique transcript object that generated the value. It uses
74 // a concrete index, not bits for now, since we never expect two different indices to be used in the same
75 // computation apart from equality assertion
76 // transcript_index is set to CONSTANT if the value is just a constant
77 // transcript_index is set to FREE_WITNESS if the value is a free witness (not a constant and not from the
78 // transcript)
79 // NOTE: The default is FREE_WITNESS so that if we forget to set the tag, it will be treated as a witness,
80 // which is safer (can trigger errors if misused) than treating it as a constant (which would be silently accepted)
82
83 // round_provenance specifies which submitted values and challenges have been used to generate this element
84 // The lower 128 bits represent using a submitted value from a corresponding round (the shift represents the
85 // round) The higher 128 bits represent using a challenge value from an corresponding round (the shift
86 // represents the round)
88
89 // Instant death is used for poisoning values we should never use in arithmetic
90 bool instant_death = false;
92 // Default Origin Tag has everything set to zero and can't cause any issues
93 OriginTag() = default;
94 OriginTag(const OriginTag& other) = default;
95 OriginTag(OriginTag&& other) = default;
96 OriginTag& operator=(const OriginTag& other) = default;
97 OriginTag& operator=(OriginTag&& other) noexcept
98 {
99
101 round_provenance = other.round_provenance;
102 instant_death = other.instant_death;
103 return *this;
104 }
112 OriginTag(size_t transcript_idx, size_t round_number, bool is_submitted = true)
113 : transcript_index(transcript_idx)
114 , round_provenance((static_cast<uint256_t>(1) << (round_number + (is_submitted ? 0 : 128))))
115 {
116 BB_ASSERT_LT(round_number, 128U);
117 }
118
128 OriginTag(const OriginTag& tag_a, const OriginTag& tag_b);
129
139 template <class... T>
140 OriginTag(const OriginTag& tag, const T&... rest)
144 {
145
146 OriginTag merged_tag = *this;
147 for (const auto& next_tag : { rest... }) {
148 merged_tag = OriginTag(merged_tag, next_tag);
149 }
150 *this = merged_tag;
152 ~OriginTag() = default;
153 bool operator==(const OriginTag& other) const;
154 void poison() { instant_death = true; }
155 void unpoison() { instant_death = false; }
156 bool is_poisoned() const { return instant_death; }
157 bool is_empty() const { return !instant_death && transcript_index == CONSTANT; };
158
159 bool is_free_witness() const { return transcript_index == FREE_WITNESS; }
160 void set_free_witness()
166 {
169 }
170
171 bool is_constant() const { return transcript_index == CONSTANT && !instant_death; }
172 void set_constant()
173 {
176 }
177
178 // Static factory methods for cleaner syntax
179 static OriginTag constant()
180 {
183 return tag;
184 }
185
186 static OriginTag free_witness()
187 {
190 return tag;
191 }
192
193 static OriginTag poisoned()
194 {
196 tag.instant_death = true;
197 return tag;
198 }
204};
205inline std::ostream& operator<<(std::ostream& os, OriginTag const& v)
206{
207 return os << "{ transcript_idx: " << v.transcript_index << ", round_prov: " << v.round_provenance
208 << ", instadeath: " << v.instant_death << " }";
209}
210
211#else
212
213struct OriginTag {
214 OriginTag() = default;
215 OriginTag(const OriginTag& other) = default;
216 OriginTag(OriginTag&& other) = default;
217 OriginTag& operator=(const OriginTag& other) = default;
218 OriginTag& operator=(OriginTag&& other) = default;
219 ~OriginTag() = default;
220
221 OriginTag(size_t transcript_idx [[maybe_unused]],
222 size_t round_number [[maybe_unused]],
223 bool is_submitted [[maybe_unused]] = true)
224 {}
225
226 OriginTag(const OriginTag&, const OriginTag&) {}
227 template <class... T> OriginTag(const OriginTag&, const T&...) {}
228 bool operator==(const OriginTag& other) const;
229 void poison() {}
230 void unpoison() {}
231 static bool is_poisoned() { return false; }
232 static bool is_empty() { return true; };
233 bool is_free_witness() const { return false; }
234 void set_free_witness() {}
235 void unset_free_witness() {}
236 bool is_constant() const { return true; }
237 void set_constant() {}
238 void clear_round_provenance() {}
239
240 // Static factory methods (no-ops in release builds)
241 static OriginTag constant() { return OriginTag(); }
242 static OriginTag free_witness() { return OriginTag(); }
243 static OriginTag poisoned() { return OriginTag(); }
244};
245inline std::ostream& operator<<(std::ostream& os, OriginTag const&)
246{
247 return os << "{ Origin Tag tracking is disabled in release builds }";
248}
249#endif
250
251// Helper functions for working with origin tags
260template <bool in_circuit, typename T> inline void assign_origin_tag(T& elem, const OriginTag& tag)
261{
262 if constexpr (in_circuit) {
263 if constexpr (is_iterable_v<T>) {
264 for (auto& e : elem) {
265 e.set_origin_tag(tag);
266 }
267 } else {
268 elem.set_origin_tag(tag);
269 }
270 }
271}
272
281template <bool in_circuit, typename T> inline void check_origin_tag(T& elem, const OriginTag& tag)
282{
283 if constexpr (in_circuit) {
284 if constexpr (is_iterable_v<T>) {
285 for (auto& e : elem) {
286 BB_ASSERT(e.get_origin_tag() == tag);
287 };
288 } else {
289 BB_ASSERT(elem.get_origin_tag() == tag);
290 }
291 }
292}
293
301template <bool in_circuit, typename DataType> inline void unset_free_witness_tags(std::vector<DataType>& input)
302{
303 if constexpr (in_circuit) {
304 for (auto& entry : input) {
305 entry.unset_free_witness_tag();
306 }
307 }
308}
309
320template <bool in_circuit, typename Codec, typename T>
321inline std::vector<typename Codec::DataType> tag_and_serialize(const T& component, const OriginTag& tag)
322{
323 if constexpr (in_circuit) {
324 assign_origin_tag<in_circuit>(const_cast<T&>(component), tag);
325 }
326 // Serialize to field elements
327 return Codec::serialize_to_fields(component);
328}
329
338template <typename TranscriptType> inline OriginTag extract_transcript_tag(const TranscriptType& transcript)
339{
340 return OriginTag(transcript.transcript_index, transcript.round_index, /*is_submitted=*/true);
342
343} // namespace bb
344template <typename T>
345concept 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:258
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