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#pragma once
13#include <cstddef>
14#include <iterator>
15#include <ostream>
16#include <type_traits>
17#include <vector>
18
19// Trait to detect if a type is iterable
20template <typename T, typename = void> struct is_iterable : std::false_type {};
21
22// this gets used only when we can call std::begin() and std::end() on that type
23template <typename T>
24struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T&>())), decltype(std::end(std::declval<T&>()))>>
25 : std::true_type {};
26
27template <typename T> constexpr bool is_iterable_v = is_iterable<T>::value;
28
29#define STANDARD_TESTING_TAGS /*Tags reused in tests*/ \
30 const size_t parent_id = 0; \
31 [[maybe_unused]] const auto clear_tag = OriginTag(); \
32 const auto submitted_value_origin_tag = OriginTag( \
33 parent_id, /*round_id=*/0, /*is_submitted=*/true); /*A tag describing a value submitted in the 0th round*/ \
34 const auto next_submitted_value_origin_tag = OriginTag( \
35 parent_id, /*round_id=*/1, /*is_submitted=*/true); /*A tag describing a value submitted in the 1st round*/ \
36 const auto challenge_origin_tag = OriginTag( \
37 parent_id, /*round_id=*/0, /*is_submitted=*/false); /*A tag describing a challenge derived in the 0th round*/ \
38 const auto next_challenge_tag = OriginTag( \
39 parent_id, /*round_id=*/1, /*is_submitted=*/false); /*A tag describing a challenge derived in the 1st round*/ \
40 const auto first_two_merged_tag = \
41 OriginTag(submitted_value_origin_tag, \
42 challenge_origin_tag); /*A tag describing a value constructed from values submitted by the prover in \
43 the 0th round and challenges from the same round */ \
44 const auto first_and_third_merged_tag = \
45 OriginTag(submitted_value_origin_tag, \
46 next_challenge_tag); /* A tag describing a value constructed from values submitted in the 0th round \
47 and challenges computed in the 1st round*/ \
48 const auto first_second_third_merged_tag = OriginTag( \
49 first_two_merged_tag, next_challenge_tag); /* A tag describing a value computed from values submitted in the \
50 0th round and challenges generated in the 0th and 1st round*/ \
51 const auto first_to_fourth_merged_tag = \
52 OriginTag(first_second_third_merged_tag, \
53 next_submitted_value_origin_tag); /* A tag describing a value computed from values submitted in the \
54 0th and 1st round and challenges generated in the 0th and 1st round*/ \
55 const auto instant_death_tag = []() { \
56 auto some_tag = OriginTag(); \
57 some_tag.poison(); \
58 return some_tag; \
59 }(); /* A tag that causes and abort on any arithmetic*/
60
61namespace bb {
62
63void check_round_provenance(const uint256_t& provenance_a, const uint256_t& provenance_b);
64#ifndef AZTEC_NO_ORIGIN_TAGS
65struct OriginTag {
66
67 static constexpr size_t CONSTANT = static_cast<size_t>(-1);
68 static constexpr size_t FREE_WITNESS = static_cast<size_t>(-2);
69 // transcript_index represents the index of a unique transcript object that generated the value. It uses
70 // a concrete index, not bits for now, since we never expect two different indices to be used in the same
71 // computation apart from equality assertion
72 // transcript_index is set to CONSTANT if the value is just a constant
73 // transcript_index is set to FREE_WITNESS if the value is a free witness (not a constant and not from the
74 // transcript)
76
77 // round_provenance specifies which submitted values and challenges have been used to generate this element
78 // The lower 128 bits represent using a submitted value from a corresponding round (the shift represents the
79 // round) The higher 128 bits represent using a challenge value from an corresponding round (the shift
80 // represents the round)
82
83 // Instant death is used for poisoning values we should never use in arithmetic
84 bool instant_death = false;
86 // Default Origin Tag has everything set to zero and can't cause any issues
87 OriginTag() = default;
88 OriginTag(const OriginTag& other) = default;
89 OriginTag(OriginTag&& other) = default;
90 OriginTag& operator=(const OriginTag& other) = default;
91 OriginTag& operator=(OriginTag&& other) noexcept
92 {
93
95 round_provenance = other.round_provenance;
96 instant_death = other.instant_death;
97 return *this;
98 }
106 OriginTag(size_t transcript_idx, size_t round_number, bool is_submitted = true)
107 : transcript_index(transcript_idx)
108 , round_provenance((static_cast<uint256_t>(1) << (round_number + (is_submitted ? 0 : 128))))
109 {
110 BB_ASSERT_LT(round_number, 128U);
111 }
112
122 OriginTag(const OriginTag& tag_a, const OriginTag& tag_b);
123
133 template <class... T>
134 OriginTag(const OriginTag& tag, const T&... rest)
138 {
139
140 OriginTag merged_tag = *this;
141 for (const auto& next_tag : { rest... }) {
142 merged_tag = OriginTag(merged_tag, next_tag);
143 }
144 *this = merged_tag;
146 ~OriginTag() = default;
147 bool operator==(const OriginTag& other) const;
148 void poison() { instant_death = true; }
149 void unpoison() { instant_death = false; }
150 bool is_poisoned() const { return instant_death; }
151 bool is_empty() const { return !instant_death && transcript_index == CONSTANT; };
152
153 bool is_free_witness() const { return transcript_index == FREE_WITNESS; }
154 void set_free_witness()
160 {
163 }
169};
170inline std::ostream& operator<<(std::ostream& os, OriginTag const& v)
171{
172 return os << "{ transcript_idx: " << v.transcript_index << ", round_prov: " << v.round_provenance
173 << ", instadeath: " << v.instant_death << " }";
174}
175
176#else
177
178struct OriginTag {
179 OriginTag() = default;
180 OriginTag(const OriginTag& other) = default;
181 OriginTag(OriginTag&& other) = default;
182 OriginTag& operator=(const OriginTag& other) = default;
183 OriginTag& operator=(OriginTag&& other) = default;
184 ~OriginTag() = default;
185
186 OriginTag(size_t transcript_idx [[maybe_unused]],
187 size_t round_number [[maybe_unused]],
188 bool is_submitted [[maybe_unused]] = true)
189 {}
190
191 OriginTag(const OriginTag&, const OriginTag&) {}
192 template <class... T> OriginTag(const OriginTag&, const T&...) {}
193 bool operator==(const OriginTag& other) const;
194 void poison() {}
195 void unpoison() {}
196 static bool is_poisoned() { return false; }
197 static bool is_empty() { return true; };
198 bool is_free_witness() const { return false; }
199 void set_free_witness() {}
200 void unset_free_witness() {}
201 void clear_round_provenance() {}
202};
203inline std::ostream& operator<<(std::ostream& os, OriginTag const&)
204{
205 return os << "{ Origin Tag tracking is disabled in release builds }";
206}
207#endif
208
209// Helper functions for working with origin tags
218template <bool in_circuit, typename T> inline void assign_origin_tag(T& elem, const OriginTag& tag)
219{
220 if constexpr (in_circuit) {
221 if constexpr (is_iterable_v<T>) {
222 for (auto& e : elem) {
223 e.set_origin_tag(tag);
224 }
225 } else {
226 elem.set_origin_tag(tag);
227 }
228 }
229}
230
239template <bool in_circuit, typename T> inline void check_origin_tag(T& elem, const OriginTag& tag)
240{
241 if constexpr (in_circuit) {
242 if constexpr (is_iterable_v<T>) {
243 for (auto& e : elem) {
244 BB_ASSERT(e.get_origin_tag() == tag);
245 };
246 } else {
247 BB_ASSERT(elem.get_origin_tag() == tag);
248 }
249 }
250}
251
259template <bool in_circuit, typename DataType> inline void unset_free_witness_tags(std::vector<DataType>& input)
260{
261 if constexpr (in_circuit) {
262 for (auto& entry : input) {
263 entry.unset_free_witness_tag();
264 }
265 }
266}
267
278template <bool in_circuit, typename Codec, typename T>
279inline std::vector<typename Codec::DataType> tag_and_serialize(const T& component, const OriginTag& tag)
280{
281 if constexpr (in_circuit) {
282 assign_origin_tag<in_circuit>(const_cast<T&>(component), tag);
283 }
284 // Serialize to field elements
285 return Codec::serialize_to_fields(component);
286}
287
296template <typename TranscriptType> inline OriginTag extract_transcript_tag(const TranscriptType& transcript)
297{
298 return OriginTag(transcript.transcript_index, transcript.round_index, /*is_submitted=*/true);
300
301} // namespace bb
302template <typename T>
303concept usesTag = requires(T x, const bb::OriginTag& tag) { x.set_origin_tag(tag); };
#define BB_ASSERT(expression,...)
Definition assert.hpp:80
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:153
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