Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
tinyram_aux.cpp
Go to the documentation of this file.
1 
14 #include <cassert>
15 #include <fstream>
16 #include <libff/common/profiling.hpp>
17 #include <libff/common/utils.hpp>
19 #include <string>
20 
21 namespace libsnark
22 {
23 
26 
27 std::map<tinyram_opcode, std::string> tinyram_opcode_names = {
28  {tinyram_opcode_AND, "and"},
29  {tinyram_opcode_OR, "or"},
30  {tinyram_opcode_XOR, "xor"},
31  {tinyram_opcode_NOT, "not"},
32  {tinyram_opcode_ADD, "add"},
33  {tinyram_opcode_SUB, "sub"},
34  {tinyram_opcode_MULL, "mull"},
35  {tinyram_opcode_UMULH, "umulh"},
36  {tinyram_opcode_SMULH, "smulh"},
37  {tinyram_opcode_UDIV, "udiv"},
38  {tinyram_opcode_UMOD, "umod"},
39  {tinyram_opcode_SHL, "shl"},
40  {tinyram_opcode_SHR, "shr"},
41 
42  {tinyram_opcode_CMPE, "cmpe"},
43  {tinyram_opcode_CMPA, "cmpa"},
44  {tinyram_opcode_CMPAE, "cmpae"},
45  {tinyram_opcode_CMPG, "cmpg"},
46  {tinyram_opcode_CMPGE, "cmpge"},
47 
48  {tinyram_opcode_MOV, "mov"},
49  {tinyram_opcode_CMOV, "cmov"},
50  {tinyram_opcode_JMP, "jmp"},
51 
52  {tinyram_opcode_CJMP, "cjmp"},
53  {tinyram_opcode_CNJMP, "cnjmp"},
54 
55  {tinyram_opcode_10111, "opcode_10111"},
56  {tinyram_opcode_11000, "opcode_11000"},
57  {tinyram_opcode_11001, "opcode_11001"},
58  {tinyram_opcode_STOREB, "store.b"},
59  {tinyram_opcode_LOADB, "load.b"},
60 
61  {tinyram_opcode_STOREW, "store.w"},
62  {tinyram_opcode_LOADW, "load.w"},
63  {tinyram_opcode_READ, "read"},
64  {tinyram_opcode_ANSWER, "answer"}};
65 
66 std::map<tinyram_opcode, tinyram_opcode_args> opcode_args = {
99 
100 std::map<std::string, tinyram_opcode> opcode_values;
101 
103 {
104  if (opcode_values.empty()) {
105  for (auto it : tinyram_opcode_names) {
106  opcode_values[it.second] = it.first;
107  }
108  }
109 }
110 
111 std::vector<tinyram_instruction> generate_tinyram_prelude(
112  const tinyram_architecture_params &ap)
113 {
114  std::vector<tinyram_instruction> result;
115  const size_t increment = libff::log2(ap.w) / 8;
116  const size_t mem_start = 1ul << (ap.w - 1);
117  // 0: store.w 0, r0
118  result.emplace_back(
120  // 1: mov r0, 2^{W-1}
121  result.emplace_back(
122  tinyram_instruction(tinyram_opcode_MOV, true, 0, 0, mem_start));
123  // 2: read r1, 0
124  result.emplace_back(
125  tinyram_instruction(tinyram_opcode_READ, true, 1, 0, 0));
126  // 3: cjmp 7
127  result.emplace_back(
128  tinyram_instruction(tinyram_opcode_CJMP, true, 0, 0, 7));
129  // 4: add r0, r0, INCREMENT
130  result.emplace_back(
131  tinyram_instruction(tinyram_opcode_ADD, true, 0, 0, increment));
132  // 5: store.w r0, r1
133  result.emplace_back(
134  tinyram_instruction(tinyram_opcode_STOREW, false, 1, 0, 0));
135  // 6: jmp 2
136  result.emplace_back(tinyram_instruction(tinyram_opcode_JMP, true, 0, 0, 2));
137  // 7: store.w 2^{W-1}, r0
138  result.emplace_back(
139  tinyram_instruction(tinyram_opcode_STOREW, true, 0, 0, mem_start));
140  return result;
141 }
142 
144 {
145  return dwaddr_len();
146 }
147 
148 size_t tinyram_architecture_params::value_size() const { return 2 * w; }
149 
151 {
152  // + flag + tape1_exhausted
153  return k * w + 2;
154 }
155 
157 {
158  // the initial PC address is memory units for the RAM reduction
159  const size_t initial_pc_addr = generate_tinyram_prelude(*this).size();
160  return initial_pc_addr;
161 }
162 
164 {
165  libff::bit_vector result(this->cpu_state_size(), false);
166  return result;
167 }
168 
170  const tinyram_program &program,
171  const tinyram_input_tape &primary_input) const
172 {
173  // remember that memory consists of 1ul<<dwaddr_len() double words (!)
174  memory_contents m;
175 
176  for (size_t i = 0; i < program.instructions.size(); ++i) {
177  m[i] = program.instructions[i].as_dword(*this);
178  }
179 
180  const size_t input_addr = 1ul << (dwaddr_len() - 1);
181  // the first word will contain 2^{w-1} + input_size (the
182  // location where the last input word was stored)
183 
184  size_t latest_double_word = (1ull << (w - 1)) + primary_input.size();
185  for (size_t i = 0; i < primary_input.size() / 2 + 1; ++i) {
186  if (2 * i < primary_input.size()) {
187  latest_double_word += (primary_input[2 * i] << w);
188  }
189 
190  m[input_addr + i] = latest_double_word;
191 
192  if (2 * i + 1 < primary_input.size()) {
193  latest_double_word = primary_input[2 * i + 1];
194  }
195  }
196 
197  return m;
198 }
199 
201 {
202  // assumption: answer is the last
203  return libff::log2(static_cast<size_t>(tinyram_opcode_ANSWER));
204 }
205 
207 {
208  return libff::log2(k);
209 }
210 
212 {
213  return 2 * w -
214  (opcode_width() + 1 + 2 * reg_arg_width() + reg_arg_or_imm_width());
215 }
216 
218 {
219  return std::max(w, reg_arg_width());
220 }
221 
223 {
224  return w - (libff::log2(w) - 2);
225 }
226 
228 {
229  return libff::log2(w) - 2;
230 }
231 
232 size_t tinyram_architecture_params::bytes_in_word() const { return w / 8; }
233 
234 size_t tinyram_architecture_params::instr_size() const { return 2 * w; }
235 
237  const tinyram_architecture_params &other) const
238 {
239  return (this->w == other.w && this->k == other.k);
240 }
241 
242 std::ostream &operator<<(
243  std::ostream &out, const tinyram_architecture_params &ap)
244 {
245  out << ap.w << "\n";
246  out << ap.k << "\n";
247  return out;
248 }
249 
250 std::istream &operator>>(std::istream &in, tinyram_architecture_params &ap)
251 {
252  in >> ap.w;
253  libff::consume_newline(in);
254  in >> ap.k;
255  libff::consume_newline(in);
256  return in;
257 }
258 
260  const tinyram_opcode &opcode,
261  const bool arg2_is_imm,
262  const size_t &desidx,
263  const size_t &arg1idx,
264  const size_t &arg2idx_or_imm)
265  : opcode(opcode)
266  , arg2_is_imm(arg2_is_imm)
267  , desidx(desidx)
268  , arg1idx(arg1idx)
269  , arg2idx_or_imm(arg2idx_or_imm)
270 {
271 }
272 
274  const tinyram_architecture_params &ap) const
275 {
276  size_t result = static_cast<size_t>(opcode);
277  result = (result << 1) | (arg2_is_imm ? 1 : 0);
278  result = (result << libff::log2(ap.k)) | desidx;
279  result = (result << libff::log2(ap.k)) | arg1idx;
280  result =
281  (result << (2 * ap.w - ap.opcode_width() - 1 - 2 * libff::log2(ap.k))) |
283 
284  return result;
285 }
286 
288 {
289  printf("* Number of registers (k): %zu\n", k);
290  printf("* Word size (w): %zu\n", w);
291 }
292 
294  const tinyram_architecture_params &ap)
295 {
296  const tinyram_opcode opcode =
297  (tinyram_opcode)(std::rand() % (1ul << ap.opcode_width()));
298  const bool arg2_is_imm = std::rand() & 1;
299  const size_t desidx = std::rand() % (1ul << ap.reg_arg_width());
300  const size_t arg1idx = std::rand() % (1ul << ap.reg_arg_width());
301  const size_t arg2idx_or_imm =
302  std::rand() % (1ul << ap.reg_arg_or_imm_width());
303  return tinyram_instruction(
304  opcode, arg2_is_imm, desidx, arg1idx, arg2idx_or_imm);
305 }
306 
308 {
309  instructions.emplace_back(instr);
310 }
311 
313  const tinyram_architecture_params &ap, std::istream &preprocessed)
314 {
316 
317  tinyram_program program;
318 
319  libff::enter_block("Loading program");
320  std::string instr, line;
321 
322  while (preprocessed >> instr) {
323  libff::print_indent();
324  size_t immflag, des, a1;
325  long long int a2;
326  if (preprocessed.good()) {
327  preprocessed >> immflag >> des >> a1 >> a2;
328  a2 = ((1ul << ap.w) + (a2 % (1ul << ap.w))) % (1ul << ap.w);
330  opcode_values[instr], immflag, des, a1, a2));
331  }
332  }
333  libff::leave_block("Loading program");
334 
335  return program;
336 }
337 
339  const tinyram_architecture_params &ap,
340  const size_t boot_trace_size_bound,
341  const tinyram_program &program,
342  const tinyram_input_tape &primary_input)
343 {
344  // TODO: document the reverse order here
345 
346  memory_store_trace result;
347 
348  size_t boot_pos = boot_trace_size_bound - 1;
349  for (size_t i = 0; i < program.instructions.size(); ++i) {
350  result.set_trace_entry(
351  boot_pos--,
352  std::make_pair(i, program.instructions[i].as_dword(ap)));
353  }
354 
355  const size_t primary_input_base_addr = (1ul << (ap.dwaddr_len() - 1));
356 
357  for (size_t j = 0; j < primary_input.size(); j += 2) {
358  const size_t memory_dword =
359  primary_input[j] +
360  ((j + 1 < primary_input.size() ? primary_input[j + 1] : 0) << ap.w);
361  result.set_trace_entry(
362  boot_pos--,
363  std::make_pair(primary_input_base_addr + j, memory_dword));
364  }
365 
366  return result;
367 }
368 
369 tinyram_input_tape load_tape(std::istream &tape)
370 {
371  libff::enter_block("Loading tape");
372  tinyram_input_tape result;
373 
374  libff::print_indent();
375  printf("Tape contents:");
376  size_t cell;
377  while (tape >> cell) {
378  printf("\t%zu", cell);
379  result.emplace_back(cell);
380  }
381  printf("\n");
382 
383  libff::leave_block("Loading tape");
384  return result;
385 }
386 
387 } // namespace libsnark
libsnark::tinyram_opcode_SHL
@ tinyram_opcode_SHL
Definition: tinyram_aux.hpp:38
libsnark::tinyram_opcode_ANSWER
@ tinyram_opcode_ANSWER
Definition: tinyram_aux.hpp:63
libsnark::tinyram_opcode_args_des_arg2
@ tinyram_opcode_args_des_arg2
Definition: tinyram_aux.hpp:68
libsnark::tinyram_architecture_params::dwaddr_len
size_t dwaddr_len() const
Definition: tinyram_aux.cpp:222
libsnark::tinyram_architecture_params::value_size
size_t value_size() const
Definition: tinyram_aux.cpp:148
libsnark::tinyram_opcode_JMP
@ tinyram_opcode_JMP
Definition: tinyram_aux.hpp:50
libsnark::tinyram_opcode_names
std::map< tinyram_opcode, std::string > tinyram_opcode_names
Definition: tinyram_aux.cpp:27
libsnark::generate_tinyram_prelude
std::vector< tinyram_instruction > generate_tinyram_prelude(const tinyram_architecture_params &ap)
Definition: tinyram_aux.cpp:111
libsnark::tinyram_instruction::arg2_is_imm
bool arg2_is_imm
Definition: tinyram_aux.hpp:178
libsnark::tinyram_instruction::opcode
tinyram_opcode opcode
Definition: tinyram_aux.hpp:177
libsnark::tinyram_instruction::arg2idx_or_imm
size_t arg2idx_or_imm
Definition: tinyram_aux.hpp:181
libsnark
Definition: accumulation_vector.hpp:18
libsnark::tinyram_opcode_CMPA
@ tinyram_opcode_CMPA
Definition: tinyram_aux.hpp:42
libsnark::tinyram_architecture_params::instruction_padding_width
size_t instruction_padding_width() const
Definition: tinyram_aux.cpp:211
libsnark::tinyram_architecture_params::subaddr_len
size_t subaddr_len() const
Definition: tinyram_aux.cpp:227
libsnark::operator<<
std::ostream & operator<<(std::ostream &out, const accumulation_vector< T > &v)
libsnark::tinyram_opcode_args_arg2_des
@ tinyram_opcode_args_arg2_des
Definition: tinyram_aux.hpp:72
libsnark::tinyram_opcode_UMOD
@ tinyram_opcode_UMOD
Definition: tinyram_aux.hpp:37
libsnark::tinyram_opcode_CMPE
@ tinyram_opcode_CMPE
Definition: tinyram_aux.hpp:41
libsnark::tinyram_architecture_params::print
void print() const
Definition: tinyram_aux.cpp:287
libsnark::tinyram_opcode_11000
@ tinyram_opcode_11000
Definition: tinyram_aux.hpp:55
libsnark::tinyram_opcode_CMPGE
@ tinyram_opcode_CMPGE
Definition: tinyram_aux.hpp:45
libsnark::load_preprocessed_program
tinyram_program load_preprocessed_program(const tinyram_architecture_params &ap, std::istream &preprocessed)
Definition: tinyram_aux.cpp:312
libsnark::tinyram_opcode_MOV
@ tinyram_opcode_MOV
Definition: tinyram_aux.hpp:47
libsnark::tinyram_architecture_params
Definition: tinyram_aux.hpp:126
libsnark::tinyram_opcode_STOREW
@ tinyram_opcode_STOREW
Definition: tinyram_aux.hpp:60
libsnark::tinyram_opcode_CMOV
@ tinyram_opcode_CMOV
Definition: tinyram_aux.hpp:48
libsnark::memory_contents
std::map< size_t, size_t > memory_contents
Definition: memory_interface.hpp:25
libsnark::tinyram_architecture_params::reg_arg_or_imm_width
size_t reg_arg_or_imm_width() const
Definition: tinyram_aux.cpp:217
libsnark::tinyram_instruction
Definition: tinyram_aux.hpp:174
libsnark::tinyram_opcode_SUB
@ tinyram_opcode_SUB
Definition: tinyram_aux.hpp:32
libsnark::tinyram_opcode_UMULH
@ tinyram_opcode_UMULH
Definition: tinyram_aux.hpp:34
libsnark::tinyram_opcode_SMULH
@ tinyram_opcode_SMULH
Definition: tinyram_aux.hpp:35
libsnark::tinyram_opcode_AND
@ tinyram_opcode_AND
Definition: tinyram_aux.hpp:27
libsnark::tinyram_opcode_MULL
@ tinyram_opcode_MULL
Definition: tinyram_aux.hpp:33
libsnark::tinyram_input_tape
std::vector< size_t > tinyram_input_tape
Definition: tinyram_aux.hpp:122
libsnark::tinyram_opcode_args_none
@ tinyram_opcode_args_none
Definition: tinyram_aux.hpp:71
libsnark::random_tinyram_instruction
tinyram_instruction random_tinyram_instruction(const tinyram_architecture_params &ap)
Definition: tinyram_aux.cpp:293
libsnark::ensure_tinyram_opcode_value_map
void ensure_tinyram_opcode_value_map()
Definition: tinyram_aux.cpp:102
libsnark::tinyram_architecture_params::bytes_in_word
size_t bytes_in_word() const
Definition: tinyram_aux.cpp:232
libsnark::tinyram_opcode_SHR
@ tinyram_opcode_SHR
Definition: tinyram_aux.hpp:39
libsnark::memory_store_trace::set_trace_entry
void set_trace_entry(const size_t timestamp, const address_and_value &av)
Definition: memory_store_trace.cpp:36
libsnark::tinyram_opcode_args_des_arg1_arg2
@ tinyram_opcode_args_des_arg1_arg2
Definition: tinyram_aux.hpp:67
libsnark::tinyram_architecture_params::operator==
bool operator==(const tinyram_architecture_params &other) const
Definition: tinyram_aux.cpp:236
libsnark::opcode_args
std::map< tinyram_opcode, tinyram_opcode_args > opcode_args
Definition: tinyram_aux.cpp:66
libsnark::tinyram_architecture_params::w
reg_width_t w
Definition: tinyram_aux.hpp:129
libsnark::tinyram_opcode_args_arg2
@ tinyram_opcode_args_arg2
Definition: tinyram_aux.hpp:70
libsnark::tinyram_architecture_params::cpu_state_size
size_t cpu_state_size() const
Definition: tinyram_aux.cpp:150
libsnark::tinyram_instruction::desidx
size_t desidx
Definition: tinyram_aux.hpp:179
libsnark::tinyram_instruction::arg1idx
size_t arg1idx
Definition: tinyram_aux.hpp:180
libsnark::tinyram_opcode_READ
@ tinyram_opcode_READ
Definition: tinyram_aux.hpp:62
libsnark::tinyram_opcode
tinyram_opcode
Definition: tinyram_aux.hpp:26
libsnark::tinyram_opcode_11001
@ tinyram_opcode_11001
Definition: tinyram_aux.hpp:56
libsnark::tinyram_opcode_XOR
@ tinyram_opcode_XOR
Definition: tinyram_aux.hpp:29
libsnark::tinyram_opcode_CMPAE
@ tinyram_opcode_CMPAE
Definition: tinyram_aux.hpp:43
libsnark::tinyram_opcode_CNJMP
@ tinyram_opcode_CNJMP
Definition: tinyram_aux.hpp:52
libsnark::tinyram_architecture_params::k
reg_count_t k
Definition: tinyram_aux.hpp:130
libsnark::tinyram_opcode_NOT
@ tinyram_opcode_NOT
Definition: tinyram_aux.hpp:30
libsnark::memory_store_trace
Definition: memory_store_trace.hpp:29
libsnark::tinyram_opcode_CMPG
@ tinyram_opcode_CMPG
Definition: tinyram_aux.hpp:44
libsnark::operator>>
std::istream & operator>>(std::istream &in, accumulation_vector< T > &v)
libsnark::tinyram_default_instruction
tinyram_instruction tinyram_default_instruction
Definition: tinyram_aux.cpp:24
libsnark::tinyram_architecture_params::reg_arg_width
size_t reg_arg_width() const
Definition: tinyram_aux.cpp:206
tinyram_aux.hpp
libsnark::tinyram_architecture_params::initial_cpu_state
libff::bit_vector initial_cpu_state() const
Definition: tinyram_aux.cpp:163
libsnark::tinyram_architecture_params::address_size
size_t address_size() const
Definition: tinyram_aux.cpp:143
libsnark::tinyram_instruction::as_dword
size_t as_dword(const tinyram_architecture_params &ap) const
Definition: tinyram_aux.cpp:273
libsnark::load_tape
tinyram_input_tape load_tape(std::istream &tape)
Definition: tinyram_aux.cpp:369
libsnark::tinyram_opcode_CJMP
@ tinyram_opcode_CJMP
Definition: tinyram_aux.hpp:51
libsnark::tinyram_boot_trace_from_program_and_input
memory_store_trace tinyram_boot_trace_from_program_and_input(const tinyram_architecture_params &ap, const size_t boot_trace_size_bound, const tinyram_program &program, const tinyram_input_tape &primary_input)
Definition: tinyram_aux.cpp:338
libsnark::tinyram_opcode_LOADW
@ tinyram_opcode_LOADW
Definition: tinyram_aux.hpp:61
libsnark::tinyram_instruction::tinyram_instruction
tinyram_instruction(const tinyram_opcode &opcode, const bool arg2_is_imm, const size_t &desidx, const size_t &arg1idx, const size_t &arg2idx_or_imm)
Definition: tinyram_aux.cpp:259
libsnark::opcode_values
std::map< std::string, tinyram_opcode > opcode_values
Definition: tinyram_aux.cpp:100
libsnark::tinyram_architecture_params::instr_size
size_t instr_size() const
Definition: tinyram_aux.cpp:234
libsnark::tinyram_program::add_instruction
void add_instruction(const tinyram_instruction &instr)
Definition: tinyram_aux.cpp:307
libsnark::tinyram_architecture_params::initial_pc_addr
size_t initial_pc_addr() const
Definition: tinyram_aux.cpp:156
libsnark::tinyram_architecture_params::opcode_width
size_t opcode_width() const
Definition: tinyram_aux.cpp:200
libsnark::tinyram_architecture_params::initial_memory_contents
memory_contents initial_memory_contents(const tinyram_program &program, const tinyram_input_tape &primary_input) const
Definition: tinyram_aux.cpp:169
libsnark::tinyram_opcode_args_arg1_arg2
@ tinyram_opcode_args_arg1_arg2
Definition: tinyram_aux.hpp:69
libsnark::tinyram_program
Definition: tinyram_aux.hpp:200
libsnark::tinyram_opcode_STOREB
@ tinyram_opcode_STOREB
Definition: tinyram_aux.hpp:58
libsnark::tinyram_program::instructions
std::vector< tinyram_instruction > instructions
Definition: tinyram_aux.hpp:203
libsnark::tinyram_opcode_10111
@ tinyram_opcode_10111
Definition: tinyram_aux.hpp:54
libsnark::tinyram_opcode_UDIV
@ tinyram_opcode_UDIV
Definition: tinyram_aux.hpp:36
libsnark::tinyram_opcode_ADD
@ tinyram_opcode_ADD
Definition: tinyram_aux.hpp:31
libsnark::tinyram_opcode_LOADB
@ tinyram_opcode_LOADB
Definition: tinyram_aux.hpp:59
libsnark::tinyram_opcode_OR
@ tinyram_opcode_OR
Definition: tinyram_aux.hpp:28