Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
to_radix_trace.cpp
Go to the documentation of this file.
2
3#include <cassert>
4#include <memory>
5
15
16namespace bb::avm2::tracegen {
17
20{
21 using C = Column;
22
23 const auto& p_limbs_per_radix = get_p_limbs_per_radix();
24
25 uint32_t row = 1; // We start from row 1 because this trace contains shifted columns.
26 for (const auto& event : events) {
27 FF value = event.value;
28 uint32_t radix = event.radix;
29 size_t radix_index = static_cast<size_t>(radix);
30 uint32_t safe_limbs = static_cast<uint32_t>(p_limbs_per_radix[radix_index].size()) - 1;
31
32 FF acc = 0;
33 FF exponent = 1;
34 bool found = false;
35 bool acc_under_p = false;
36
37 for (uint32_t i = 0; i < event.limbs.size(); ++i) {
38 bool is_padding = i > safe_limbs;
39 uint8_t limb = event.limbs[i];
40 uint8_t p_limb = is_padding ? 0 : p_limbs_per_radix[radix_index][static_cast<size_t>(i)];
41
42 if (limb != p_limb) {
43 acc_under_p = limb < p_limb;
44 }
45 FF limb_p_diff = limb == p_limb ? 0 : limb > p_limb ? limb - p_limb - 1 : p_limb - limb - 1;
46
47 bool is_unsafe_limb = i == safe_limbs;
48 FF safety_diff_inverse = is_unsafe_limb ? FF(0) : (FF(i) - FF(safe_limbs)).invert();
49
50 acc += exponent * limb;
51
52 FF rem = value - acc;
53 found = rem == 0;
54 FF rem_inverse = found ? 0 : rem.invert();
55
56 bool end = i == (event.limbs.size() - 1);
57
58 trace.set(row,
59 { {
60 { C::to_radix_sel, 1 },
61 { C::to_radix_value, value },
62 { C::to_radix_radix, radix },
63 { C::to_radix_limb_index, i },
64 { C::to_radix_limb, limb },
65 { C::to_radix_start, i == 0 },
66 { C::to_radix_end, end },
67 { C::to_radix_not_end, !end },
68 { C::to_radix_exponent, exponent },
69 { C::to_radix_not_padding_limb, !is_padding },
70 { C::to_radix_acc, acc },
71 { C::to_radix_found, found },
72 { C::to_radix_limb_radix_diff, radix - 1 - limb },
73 { C::to_radix_rem_inverse, rem_inverse },
74 { C::to_radix_safe_limbs, safe_limbs },
75 { C::to_radix_is_unsafe_limb, is_unsafe_limb },
76 { C::to_radix_safety_diff_inverse, safety_diff_inverse },
77 { C::to_radix_p_limb, p_limb },
78 { C::to_radix_acc_under_p, acc_under_p },
79 { C::to_radix_limb_lt_p, limb < p_limb },
80 { C::to_radix_limb_eq_p, limb == p_limb },
81 { C::to_radix_limb_p_diff, limb_p_diff },
82 } });
83
84 row++;
85 if (is_unsafe_limb) {
86 exponent = 0;
87 }
88 exponent *= radix;
89 }
90 }
91}
92
95{
96 using C = Column;
97
98 uint32_t row = 1; // We start from row 1 because this trace contains shifted columns.
99 for (const auto& event : events) {
100
101 // Helpers
102 uint8_t num_limbs_is_zero = event.limbs.empty() ? 1 : 0;
103 FF num_limbs_inv = event.limbs.empty() ? FF(0) : FF(event.limbs.size()).invert();
104 uint8_t value_is_zero = event.value == FF(0) ? 1 : 0;
105 FF value_inv = event.value == FF(0) ? FF(0) : event.value.invert();
106
107 // Error Handling - Out of Memory Access
108 uint64_t dst_addr = static_cast<uint64_t>(event.dst_addr);
109 uint64_t max_write_addr = dst_addr + event.limbs.size() - 1;
110 bool write_out_of_range = max_write_addr > AVM_HIGHEST_MEM_ADDRESS;
111
112 // Error Handling - Radix Range
113 bool invalid_radix = (event.radix < 2 || event.radix > 256);
114 bool invalid_bitwise_radix = event.is_output_bits && event.radix != 2;
115
116 // Error Handling - Num Limbs and Value
117 bool invalid_num_limbs = event.limbs.empty() && !(event.value == FF(0));
118
119 if (write_out_of_range || invalid_radix) {
120 trace.set(row,
121 { {
122 { C::to_radix_mem_sel, 1 },
123 { C::to_radix_mem_start, 1 },
124 { C::to_radix_mem_last, 1 },
125 // Unconditional Inputs
126 { C::to_radix_mem_execution_clk, event.execution_clk },
127 { C::to_radix_mem_space_id, event.space_id },
128 { C::to_radix_mem_dst_addr, dst_addr },
129 { C::to_radix_mem_value_to_decompose, event.value },
130 { C::to_radix_mem_radix, event.radix },
131 { C::to_radix_mem_num_limbs, static_cast<uint32_t>(event.limbs.size()) },
132 { C::to_radix_mem_is_output_bits, event.is_output_bits ? 1 : 0 },
133 // Helpers
134 { C::to_radix_mem_max_mem_addr, AVM_HIGHEST_MEM_ADDRESS },
135 { C::to_radix_mem_max_write_addr, max_write_addr },
136 { C::to_radix_mem_two, 2 },
137 { C::to_radix_mem_two_five_six, 256 },
138 { C::to_radix_mem_sel_num_limbs_is_zero, num_limbs_is_zero },
139 { C::to_radix_mem_num_limbs_inv, num_limbs_inv },
140 { C::to_radix_mem_sel_value_is_zero, value_is_zero },
141 { C::to_radix_mem_value_inv, value_inv },
142 // Error Handling
143 { C::to_radix_mem_sel_dst_out_of_range_err, write_out_of_range },
144 { C::to_radix_mem_sel_radix_lt_2_err, event.radix < 2 },
145 { C::to_radix_mem_sel_radix_gt_256_err, event.radix > 256 },
146 { C::to_radix_mem_sel_invalid_bitwise_radix, invalid_bitwise_radix ? 1 : 0 },
147 { C::to_radix_mem_sel_invalid_num_limbs_err, invalid_num_limbs ? 1 : 0 },
148 { C::to_radix_mem_err, 1 },
149 } });
150 row++;
151 continue;
152 }
153
154 // At this point there are no errors, so we process the limbs
155 uint32_t num_limbs = static_cast<uint32_t>(event.limbs.size());
156 for (uint32_t i = 0; i < event.limbs.size(); ++i) {
157 MemoryValue limb_value = event.limbs[i];
158 bool start = i == 0;
159 bool last = i == (event.limbs.size() - 1);
160
161 trace.set(
162 row,
163 { {
164 { C::to_radix_mem_sel, 1 },
165 { C::to_radix_mem_start, start ? 1 : 0 },
166 { C::to_radix_mem_num_limbs_minus_one_inv, num_limbs - 1 == 0 ? 0 : FF(num_limbs - 1).invert() },
167 { C::to_radix_mem_last, last ? 1 : 0 },
168 // Unconditional Inputs
169 { C::to_radix_mem_execution_clk, event.execution_clk },
170 { C::to_radix_mem_space_id, event.space_id },
171 { C::to_radix_mem_dst_addr, dst_addr },
172 { C::to_radix_mem_value_to_decompose, event.value },
173 { C::to_radix_mem_radix, event.radix },
174 { C::to_radix_mem_num_limbs, num_limbs },
175 { C::to_radix_mem_is_output_bits, event.is_output_bits ? 1 : 0 },
176 // Helpers
177 { C::to_radix_mem_max_mem_addr, AVM_HIGHEST_MEM_ADDRESS },
178 { C::to_radix_mem_max_write_addr, max_write_addr },
179 { C::to_radix_mem_two, start ? 2 : 0 },
180 { C::to_radix_mem_two_five_six, start ? 256 : 0 },
181 { C::to_radix_mem_sel_num_limbs_is_zero, start ? num_limbs_is_zero : 0 },
182 { C::to_radix_mem_num_limbs_inv, num_limbs_inv },
183 { C::to_radix_mem_sel_value_is_zero, start ? value_is_zero : 0 },
184 { C::to_radix_mem_value_inv, value_inv },
185 // Output
186 { C::to_radix_mem_sel_should_exec, !event.limbs.empty() ? 1 : 0 },
187 { C::to_radix_mem_limb_index_to_lookup, num_limbs - 1 },
188 { C::to_radix_mem_output_limb_value, limb_value.as_ff() },
189 { C::to_radix_mem_output_tag, static_cast<uint8_t>(limb_value.get_tag()) },
190 } });
191
192 num_limbs--; // Decrement the number of limbs
193 dst_addr++; // Increment the destination address for the next limb
194 row++;
195 }
196 }
197}
198
202 .add<lookup_to_radix_limb_less_than_radix_range_settings, InteractionType::LookupIntoIndexedByClk>()
204 .add<lookup_to_radix_fetch_p_limb_settings, InteractionType::LookupIntoPDecomposition>()
206 // Mem Aware To Radix
207 // GT checks
208 .add<lookup_to_radix_mem_check_dst_addr_in_range_settings, InteractionType::LookupGeneric>()
210 .add<lookup_to_radix_mem_check_radix_gt_256_settings, InteractionType::LookupGeneric>()
211 // Dispatch to To Radix
213 // Write to Memory (this should be a permutation)
214 .add<lookup_to_radix_mem_write_mem_settings, InteractionType::LookupGeneric>()
215 // Permutation to execution (should be moved later)
217
218} // namespace bb::avm2::tracegen
#define AVM_HIGHEST_MEM_ADDRESS
ValueTag get_tag() const
InteractionDefinition & add(auto &&... args)
void process(const simulation::EventEmitterInterface< simulation::ToRadixEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_with_memory(const simulation::EventEmitterInterface< simulation::ToRadixMemoryEvent >::Container &events, TraceContainer &trace)
uint32_t dst_addr
TestTraceContainer trace
lookup_settings< lookup_to_radix_limb_p_diff_range_settings_ > lookup_to_radix_limb_p_diff_range_settings
const std::array< std::vector< uint8_t >, 257 > & get_p_limbs_per_radix()
Definition to_radix.cpp:33
permutation_settings< perm_to_radix_mem_dispatch_exec_to_radix_settings_ > perm_to_radix_mem_dispatch_exec_to_radix_settings
lookup_settings< lookup_to_radix_mem_check_radix_lt_2_settings_ > lookup_to_radix_mem_check_radix_lt_2_settings
lookup_settings< lookup_to_radix_limb_range_settings_ > lookup_to_radix_limb_range_settings
lookup_settings< lookup_to_radix_fetch_safe_limbs_settings_ > lookup_to_radix_fetch_safe_limbs_settings
lookup_settings< lookup_to_radix_mem_input_output_to_radix_settings_ > lookup_to_radix_mem_input_output_to_radix_settings
AvmFlavorSettings::FF FF
Definition field.hpp:10
simulation::PublicDataTreeReadWriteEvent event
constexpr field invert() const noexcept