Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
smt_util.cpp
Go to the documentation of this file.
1#include "smt_util.hpp"
2
13bb::fr string_to_fr(const std::string& number, int base, bool is_signed, size_t step)
14{
15 if (base == 2) {
16 step = 64;
17 } else if (base == 16) {
18 step = 4;
19 } else if (base == 10) {
20 step = 19;
21 } else if (step == 0) {
22 info("Step should be non zero");
23 return 0;
24 }
25
26 char* ptr = nullptr;
27
28 bb::fr res = 0;
29 size_t i = number[0] == '-' ? 1 : 0;
30 bb::fr step_power = bb::fr(base).pow(step);
31 for (; i < number.size(); i += step) {
32 std::string slice = number.substr(i, step);
33 bb::fr cur_power = i + step > number.size() ? bb::fr(base).pow(number.size() - i) : step_power;
34 res *= cur_power;
35 res += std::strtoull(slice.data(), &ptr, base);
36 }
37 res = number[0] == '-' ? -res : res;
38
39 if (base == 2 && number[0] == '1' && is_signed) {
40 auto max = bb::fr(uint256_t(1) << number.length());
41 res -= max;
42 }
43
44 return res;
45}
46
62std::vector<std::vector<bb::fr>> default_model(const std::vector<std::string>& special,
65 const std::string& fname,
66 bool pack)
67{
70 vterms1.reserve(c1.get_num_vars());
71 vterms2.reserve(c1.get_num_vars());
72
73 for (uint32_t i = 0; i < c1.get_num_vars(); i++) {
74 vterms1.push_back(c1.symbolic_vars[c1.real_variable_index[i]]);
75 vterms2.push_back(c2.symbolic_vars[c2.real_variable_index[i]]);
76 }
77
80
81 std::fstream myfile;
82 myfile.open(fname, std::ios::out | std::ios::trunc | std::ios::binary);
83 myfile << "w12 = {" << std::endl;
84
85 std::vector<std::vector<bb::fr>> packed_witness;
86 packed_witness.reserve(c1.get_num_vars());
87 int base = c1.type == smt_terms::TermType::BVTerm ? 2 : 10;
88
89 for (uint32_t i = 0; i < c1.get_num_vars(); i++) {
90 std::string vname1 = vterms1[i].toString();
91 std::string vname2 = vterms2[i].toString();
92 std::string new_line = "{" + mmap1[vname1] + ", " + mmap2[vname2] + "}, // " + vname1 + ", " + vname2;
93
94 if (c1.real_variable_index[i] != i) {
95 new_line += " -> " + std::to_string(c1.real_variable_index[i]);
96 }
97
98 if (mmap1[vname1] != mmap2[vname2]) {
99 info(RED, new_line, RESET);
100 }
101 myfile << new_line << std::endl;
102 packed_witness.push_back({ string_to_fr(mmap1[vname1], base), string_to_fr(mmap2[vname2], base) });
103 }
104 myfile << "};";
105 myfile.close();
106
107 // Accessing post processing functionality of the symbolic circuit
108 // Once we obtained the witness, compatible with current configuration(e.g. BVTerm)
109 // We can further compute the remaining witness entries, which were optimized and hence
110 // are not provided by the solver
111 for (const auto& post : c1.post_process) {
112 uint32_t res_idx = post.first;
113 auto left_idx = static_cast<uint32_t>(post.second[0]);
114 auto right_idx = static_cast<uint32_t>(post.second[1]);
115 bb::fr q_m = post.second[2];
116 bb::fr q_l = post.second[3];
117 bb::fr q_r = post.second[4];
118 bb::fr q_c = post.second[5];
119 packed_witness[res_idx][0] = q_m * packed_witness[left_idx][0] * packed_witness[right_idx][0] +
120 q_l * packed_witness[left_idx][0] + q_r * packed_witness[right_idx][0] + q_c;
121 packed_witness[res_idx][1] = q_m * packed_witness[left_idx][1] * packed_witness[right_idx][1] +
122 q_l * packed_witness[left_idx][1] + q_r * packed_witness[right_idx][1] + q_c;
123 }
124 if (pack) {
125 msgpack::sbuffer buffer;
126 msgpack::pack(buffer, packed_witness);
127
128 std::fstream myfile;
129 myfile.open(fname + ".pack", std::ios::out | std::ios::trunc | std::ios::binary);
130
131 myfile.write(buffer.data(), static_cast<int64_t>(buffer.size()));
132 myfile.close();
133 }
134
136 for (const auto& vname : special) {
137 vterms.insert({ vname + "_1", c1[vname] });
138 vterms.insert({ vname + "_2", c2[vname] });
139 }
140
142 for (const auto& vname : special) {
143 info(vname, "_1, ", vname, "_2 = ", mmap[vname + "_1"], ", ", mmap[vname + "_2"]);
144 }
145 return packed_witness;
146}
147
162std::vector<bb::fr> default_model_single(const std::vector<std::string>& special,
164 const std::string& fname,
165 bool pack)
166{
168 vterms.reserve(c.get_num_vars());
169
170 for (uint32_t i = 0; i < c.get_num_vars(); i++) {
171 vterms.push_back(c.symbolic_vars[c.real_variable_index[i]]);
172 }
173
175
176 std::fstream myfile;
177 myfile.open(fname, std::ios::out | std::ios::trunc | std::ios::binary);
178 myfile << "w = {" << std::endl;
179
180 std::vector<bb::fr> packed_witness;
181 packed_witness.reserve(c.get_num_vars());
182 int base = c.type == smt_terms::TermType::BVTerm ? 2 : 10;
183
184 for (uint32_t i = 0; i < c.get_num_vars(); i++) {
185 std::string vname = vterms[i].toString();
186 std::string new_line = mmap[vname] + ", // " + vname;
187 if (c.real_variable_index[i] != i) {
188 new_line += " -> " + std::to_string(c.real_variable_index[i]);
189 }
190 myfile << new_line << std::endl;
191 packed_witness.push_back(string_to_fr(mmap[vname], base));
192 }
193 myfile << "};";
194 myfile.close();
195
196 // Accessing post processing functionality of the symbolic circuit
197 // Once we obtained the witness, compatible with current configuration(e.g. BVTerm)
198 // We can further compute the remaining witness entries, which were optimized and hence
199 // are not provided by the solver
200 for (const auto& post : c.post_process) {
201 uint32_t res_idx = post.first;
202 auto left_idx = static_cast<uint32_t>(post.second[0]);
203 auto right_idx = static_cast<uint32_t>(post.second[1]);
204 bb::fr q_m = post.second[2];
205 bb::fr q_l = post.second[3];
206 bb::fr q_r = post.second[4];
207 bb::fr q_c = post.second[5];
208 packed_witness[res_idx] = q_m * packed_witness[left_idx] * packed_witness[right_idx] +
209 q_l * packed_witness[left_idx] + q_r * packed_witness[right_idx] + q_c;
210 }
211 if (pack) {
212 msgpack::sbuffer buffer;
213 msgpack::pack(buffer, packed_witness);
214
215 std::fstream myfile;
216 myfile.open(fname + ".pack", std::ios::out | std::ios::trunc | std::ios::binary);
217
218 myfile.write(buffer.data(), static_cast<int64_t>(buffer.size()));
219 myfile.close();
220 }
221
223 for (const auto& vname : special) {
224 vterms1.insert({ vname, c[vname] });
225 }
226
228 for (const auto& vname : special) {
229 info(vname, " = ", mmap1[vname]);
230 }
231 return packed_witness;
232}
233
242{
243 std::ifstream fin;
244 fin.open(fname, std::ios::ate | std::ios::binary);
245 if (!fin.is_open()) {
246 throw std::invalid_argument("file not found");
247 }
248 if (fin.tellg() == -1) {
249 throw std::invalid_argument("something went wrong");
250 }
251
252 uint64_t fsize = static_cast<uint64_t>(fin.tellg());
253 fin.seekg(0, std::ios_base::beg);
254
256 char* encoded_data = new char[fsize];
257 fin.read(encoded_data, static_cast<std::streamsize>(fsize));
258 msgpack::unpack(encoded_data, fsize).get().convert(res);
259 return res;
260}
261
270{
271 std::ifstream fin;
272 fin.open(fname, std::ios::ate | std::ios::binary);
273 if (!fin.is_open()) {
274 throw std::invalid_argument("file not found");
275 }
276 if (fin.tellg() == -1) {
277 throw std::invalid_argument("something went wrong");
278 }
279
280 uint64_t fsize = static_cast<uint64_t>(fin.tellg());
281 fin.seekg(0, std::ios_base::beg);
282
284 char* encoded_data = new char[fsize];
285 fin.read(encoded_data, static_cast<std::streamsize>(fsize));
286 msgpack::unpack(encoded_data, fsize).get().convert(res);
287 return res;
288}
289
298{
299 auto start = std::chrono::high_resolution_clock::now();
300 bool res = s->check();
301 auto stop = std::chrono::high_resolution_clock::now();
302 uint32_t duration_secs = static_cast<uint32_t>(duration_cast<std::chrono::seconds>(stop - start).count());
303 info("Time elapsed: ", duration_secs / 60, " min ", duration_secs % 60, " sec");
304
305 info(s->cvc_result);
306 return res;
307}
308
316{
318 limbs.reserve(16);
319 for (size_t i = 0; i < 16; i++) {
320 limbs.emplace_back(el % 4);
321 el /= 4;
322 }
323 std::reverse(limbs.begin(), limbs.end());
324 std::vector<bb::fr> accumulators;
325 accumulators.reserve(16);
326 bb::fr accumulator = 0;
327 for (size_t i = 0; i < 16; i++) {
328 accumulator = accumulator * 4 + limbs[i];
329 accumulators.emplace_back(accumulator);
330 }
331 std::reverse(limbs.begin(), limbs.end());
332 std::reverse(accumulators.begin(), accumulators.end());
333 return { limbs, accumulators };
334}
335
345{
346 for (auto list : builder.range_lists) {
347 uint64_t num_multiples_of_three = (list.first / bb::UltraCircuitBuilder::DEFAULT_PLOOKUP_RANGE_STEP_SIZE);
348 for (uint64_t i = 0; i <= num_multiples_of_three; i++) {
349 builder.set_variable(list.second.variable_indices[i],
351 }
352 builder.set_variable(list.second.variable_indices[num_multiples_of_three + 1], list.first);
353 }
354}
static constexpr size_t DEFAULT_PLOOKUP_RANGE_STEP_SIZE
static constexpr size_t length()
Definition uint256.hpp:140
Base class for symbolic circuits.
std::vector< uint32_t > real_variable_index
size_t get_num_vars() const
std::unordered_map< uint32_t, std::vector< bb::fr > > post_process
std::unordered_map< uint32_t, STerm > symbolic_vars
Class for the solver.
Definition solver.hpp:80
std::unordered_map< std::string, std::string > model(std::unordered_map< std::string, cvc5::Term > &terms) const
Definition solver.cpp:80
cvc5::Result cvc_result
Definition solver.hpp:88
void info(Args... args)
Definition log.hpp:70
AluTraceBuilder builder
Definition alu.test.cpp:123
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
std::vector< bb::fr > default_model_single(const std::vector< std::string > &special, smt_circuit::CircuitBase &c, const std::string &fname, bool pack)
Get pretty formatted result of the solver work.
Definition smt_util.cpp:162
bool smt_timer(smt_solver::Solver *s)
Get the solver result and amount of time that it took to solve.
Definition smt_util.cpp:297
std::vector< bb::fr > import_witness_single(const std::string &fname)
Import witness, obtained by solver, from file.
Definition smt_util.cpp:269
void fix_range_lists(bb::UltraCircuitBuilder &builder)
Fix the triples from range_lists in the witness.
Definition smt_util.cpp:344
std::pair< std::vector< bb::fr >, std::vector< bb::fr > > base4(uint32_t el)
base4 decomposition with accumulators
Definition smt_util.cpp:315
std::vector< std::vector< bb::fr > > default_model(const std::vector< std::string > &special, smt_circuit::CircuitBase &c1, smt_circuit::CircuitBase &c2, const std::string &fname, bool pack)
Get pretty formatted result of the solver work.
Definition smt_util.cpp:62
bb::fr string_to_fr(const std::string &number, int base, bool is_signed, size_t step)
Converts a string of an arbitrary base to fr. Note: there should be no prefix.
Definition smt_util.cpp:13
std::vector< std::vector< bb::fr > > import_witness(const std::string &fname)
Import witness, obtained by solver, from file.
Definition smt_util.cpp:241
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
#define RED
#define RESET