Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
origin_tag.cpp
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
10#include <cstring>
11#include <string>
12
13namespace bb {
14using namespace numeric;
15#ifndef AZTEC_NO_ORIGIN_TAGS
16
17namespace {
22inline int highest_set_bit_128(uint128_t value)
23{
24 if (value == 0) {
25 return -1;
26 }
27 // Check high 64 bits first
28 auto high = static_cast<uint64_t>(value >> 64);
29 if (high != 0) {
30 return 127 - __builtin_clzll(high);
31 }
32 // Check low 64 bits
33 auto low = static_cast<uint64_t>(value);
34 return 63 - __builtin_clzll(low);
35}
36
40inline uint128_t extract_uint128(const uint64_t* data)
41{
42 uint128_t result = 0;
43 std::memcpy(&result, data, sizeof(uint128_t));
44 return result;
45}
46} // namespace
47
63void check_round_provenance(const uint256_t& provenance_a, const uint256_t& provenance_b)
64{
65 // Lower 128 bits = submitted rounds, Upper 128 bits = challenge rounds
66 const auto submitted_a = extract_uint128(&provenance_a.data[0]);
67 const auto submitted_b = extract_uint128(&provenance_b.data[0]);
68
69 // Nothing to check if either has no submitted data or both are from the same round(s)
70 if (submitted_a == 0 || submitted_b == 0 || submitted_a == submitted_b) {
71 return;
72 }
73
74 // Ensure that values from different rounds are not mixing without max challenge round >= max submitted round
75 const auto challenges_a = extract_uint128(&provenance_a.data[2]);
76 const auto challenges_b = extract_uint128(&provenance_b.data[2]);
77 const int max_challenge_round = highest_set_bit_128(challenges_a | challenges_b);
78 const int max_submitted_round = highest_set_bit_128(submitted_a | submitted_b);
79
80 if (max_challenge_round < max_submitted_round) {
81 throw_or_abort("Round provenance check failed: max challenge round (" + std::to_string(max_challenge_round) +
82 ") < max submitted round (" + std::to_string(max_submitted_round) + ")");
83 }
84}
85
86bool OriginTag::operator==(const OriginTag& other) const
87{
88 return this->transcript_index == other.transcript_index && this->round_provenance == other.round_provenance &&
89 this->instant_death == other.instant_death;
90}
91OriginTag::OriginTag(const OriginTag& tag_a, const OriginTag& tag_b)
92{
93 // Elements with instant death should not be touched
94 if (tag_a.instant_death || tag_b.instant_death) {
95 throw_or_abort("Touched an element that should not have been touched");
96 }
97 // If one of the tags is a constant, just use the other tag
98 if (tag_a.transcript_index == CONSTANT) {
99 *this = tag_b;
100 return;
101 }
102 if (tag_b.transcript_index == CONSTANT) {
103 *this = tag_a;
104 return;
105 }
106
107 // A free witness element should not interact with an element that has an origin
108 if (tag_a.is_free_witness()) {
109 if (!tag_b.is_free_witness() && !tag_b.is_empty()) {
110 throw_or_abort("A free witness element should not interact with an element that has an origin");
111 } else {
112 // If both are free witnesses or one of them is empty, just use tag_a
113 *this = tag_a;
114 return;
115 }
116 }
117 if (tag_b.is_free_witness()) {
118 if (!tag_a.is_free_witness() && !tag_a.is_empty()) {
119 throw_or_abort("A free witness element should not interact with an element that has an origin");
120 } else {
121 // If both are free witnesses or one of them is empty, just use tag_b
122 *this = tag_b;
123 return;
124 }
125 }
126 // Elements from different transcripts shouldn't interact
127 if (tag_a.transcript_index != tag_b.transcript_index) {
128 throw_or_abort("Tags from different transcripts were involved in the same computation");
129 }
130 // Check that submitted values from different rounds don't mix without challenges
132
135}
136
137#else
138bool OriginTag::operator==(const OriginTag&) const
139{
140 return true;
141}
142
143#endif
144} // namespace bb
const std::vector< MemoryValue > data
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
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.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
unsigned __int128 uint128_t
Definition serialize.hpp:45
size_t transcript_index
OriginTag()=default
static constexpr size_t CONSTANT
bool is_empty() const
bool is_free_witness() const
numeric::uint256_t round_provenance
bool operator==(const OriginTag &other) const
void throw_or_abort(std::string const &err)