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: 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
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(); \
38 const auto submitted_value_origin_tag = OriginTag( \
39 parent_id, /*round_id=*/0, /*is_submitted=*/true); /*A tag describing a value submitted in the 0th round*/ \
40 const auto next_submitted_value_origin_tag = OriginTag( \
41 parent_id, /*round_id=*/1, /*is_submitted=*/true); /*A tag describing a value submitted in the 1st round*/ \
42 const auto challenge_origin_tag = OriginTag( \
43 parent_id, /*round_id=*/0, /*is_submitted=*/false); /*A tag describing a challenge derived in the 0th round*/ \
44 const auto next_challenge_tag = OriginTag( \
45 parent_id, /*round_id=*/1, /*is_submitted=*/false); /*A tag describing a challenge derived in the 1st round*/ \
46 const auto first_two_merged_tag = \
47 OriginTag(submitted_value_origin_tag, \
48 challenge_origin_tag); /*A tag describing a value constructed from values submitted by the prover in \
49 the 0th round and challenges from the same round */ \
50 const auto first_and_third_merged_tag = \
51 OriginTag(submitted_value_origin_tag, \
52 next_challenge_tag); /* A tag describing a value constructed from values submitted in the 0th round \
53 and challenges computed in the 1st round*/ \
54 const auto first_second_third_merged_tag = OriginTag( \
55 first_two_merged_tag, next_challenge_tag); /* A tag describing a value computed from values submitted in the \
56 0th round and challenges generated in the 0th and 1st round*/ \
57 const auto first_to_fourth_merged_tag = \
58 OriginTag(first_second_third_merged_tag, \
59 next_submitted_value_origin_tag); /* A tag describing a value computed from values submitted in the \
60 0th and 1st round and challenges generated in the 0th and 1st round*/ \
61 const auto instant_death_tag = []() { \
62 auto some_tag = OriginTag(); \
63 some_tag.poison(); \
64 return some_tag; \
65 }(); /* A tag that causes and abort on any arithmetic*/
66
67namespace bb {
68
69void check_round_provenance(const uint256_t& provenance_a, const uint256_t& provenance_b);
70#ifndef AZTEC_NO_ORIGIN_TAGS
71struct OriginTag {
72
73 static constexpr size_t CONSTANT = static_cast<size_t>(-1);
74 static constexpr size_t FREE_WITNESS = static_cast<size_t>(-2);
75 // transcript_index represents the index of a unique transcript object that generated the value. It uses
76 // a concrete index, not bits for now, since we never expect two different indices to be used in the same
77 // computation apart from equality assertion
78 // transcript_index is set to CONSTANT if the value is just a constant
79 // transcript_index is set to FREE_WITNESS if the value is a free witness (not a constant and not from the
80 // transcript)
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 }
175};
176inline std::ostream& operator<<(std::ostream& os, OriginTag const& v)
177{
178 return os << "{ transcript_idx: " << v.transcript_index << ", round_prov: " << v.round_provenance
179 << ", instadeath: " << v.instant_death << " }";
180}
181
182#else
183
184struct OriginTag {
185 OriginTag() = default;
186 OriginTag(const OriginTag& other) = default;
187 OriginTag(OriginTag&& other) = default;
188 OriginTag& operator=(const OriginTag& other) = default;
189 OriginTag& operator=(OriginTag&& other) = default;
190 ~OriginTag() = default;
191
192 OriginTag(size_t transcript_idx [[maybe_unused]],
193 size_t round_number [[maybe_unused]],
194 bool is_submitted [[maybe_unused]] = true)
195 {}
196
197 OriginTag(const OriginTag&, const OriginTag&) {}
198 template <class... T> OriginTag(const OriginTag&, const T&...) {}
199 bool operator==(const OriginTag& other) const;
200 void poison() {}
201 void unpoison() {}
202 static bool is_poisoned() { return false; }
203 static bool is_empty() { return true; };
204 bool is_free_witness() const { return false; }
205 void set_free_witness() {}
206 void unset_free_witness() {}
207 void clear_round_provenance() {}
208};
209inline std::ostream& operator<<(std::ostream& os, OriginTag const&)
210{
211 return os << "{ Origin Tag tracking is disabled in release builds }";
212}
213#endif
214
215// Helper functions for working with origin tags
224template <bool in_circuit, typename T> inline void assign_origin_tag(T& elem, const OriginTag& tag)
225{
226 if constexpr (in_circuit) {
227 if constexpr (is_iterable_v<T>) {
228 for (auto& e : elem) {
229 e.set_origin_tag(tag);
230 }
231 } else {
232 elem.set_origin_tag(tag);
233 }
234 }
235}
236
245template <bool in_circuit, typename T> inline void check_origin_tag(T& elem, const OriginTag& tag)
246{
247 if constexpr (in_circuit) {
248 if constexpr (is_iterable_v<T>) {
249 for (auto& e : elem) {
250 BB_ASSERT(e.get_origin_tag() == tag);
251 };
252 } else {
253 BB_ASSERT(elem.get_origin_tag() == tag);
254 }
255 }
256}
257
265template <bool in_circuit, typename DataType> inline void unset_free_witness_tags(std::vector<DataType>& input)
266{
267 if constexpr (in_circuit) {
268 for (auto& entry : input) {
269 entry.unset_free_witness_tag();
270 }
271 }
272}
273
284template <bool in_circuit, typename Codec, typename T>
285inline std::vector<typename Codec::DataType> tag_and_serialize(const T& component, const OriginTag& tag)
286{
287 if constexpr (in_circuit) {
288 assign_origin_tag<in_circuit>(const_cast<T&>(component), tag);
289 }
290 // Serialize to field elements
291 return Codec::serialize_to_fields(component);
292}
293
302template <typename TranscriptType> inline OriginTag extract_transcript_tag(const TranscriptType& transcript)
303{
304 return OriginTag(transcript.transcript_index, transcript.round_index, /*is_submitted=*/true);
306
307} // namespace bb
308template <typename T>
309concept usesTag = requires(T x, const bb::OriginTag& tag) { x.set_origin_tag(tag); };
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:137
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:245
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
bool is_poisoned() const
~OriginTag()=default
void set_free_witness()
static constexpr size_t CONSTANT
OriginTag & operator=(const OriginTag &other)=default
static constexpr size_t FREE_WITNESS
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
bool operator==(const OriginTag &other) const