@@ -160,97 +160,117 @@ namespace nil {
160
160
}
161
161
162
162
static const auto zerohash = zkevm_keccak_hash ({});
163
- for (std::size_t i = 0 ; i < max_bytecode_size; i++) {
163
+ if constexpr (stage == GenerationStage::CONSTRAINTS) {
164
+ std::vector<TYPE> every;
165
+ std::vector<TYPE> non_first;
166
+ std::vector<TYPE> bytes;
167
+
168
+ // Every constraints
164
169
// 0. TAG is zeroes, one or two
165
- constrain (tag[i] * (tag[i] - 1 ) * (tag[i] - 2 ));
170
+ every.push_back (context_object.relativize (
171
+ tag[0 ] * (tag[0 ] - 1 ) * (tag[0 ] - 2 ), -1 ));
166
172
// 1. INDEX for HEADER and unused bytes is zero
167
- constrain ((tag[i] - 2 ) * (tag[i] - 1 ) * index[i]);
173
+ every.push_back (context_object.relativize (
174
+ (tag[0 ] - 2 ) * (tag[0 ] - 1 ) * index[0 ], -1 ));
168
175
// 4. In contract header length_left == contract length
169
- constrain ((tag[i] - 2 ) * (tag[i] - 1 ) *
170
- (length_left[i] - value[i]));
176
+ every.push_back (context_object.relativize (
177
+ (tag[0 ] - 2 ) * (tag[0 ] - 1 ) * (length_left[0 ] - value[0 ]),
178
+ -1 ));
171
179
// 7. is_opcode is zeroes or ones
172
- constrain (is_opcode[i] * (is_opcode[i] - 1 ));
180
+ every.push_back (context_object.relativize (
181
+ is_opcode[0 ] * (is_opcode[0 ] - 1 ), -1 ));
173
182
// 8. is_opcode on HEADER are zeroes
174
- constrain ((tag[i] - 2 ) * (tag[i] - 1 ) * is_opcode[i]);
183
+ every.push_back (context_object.relativize (
184
+ (tag[0 ] - 2 ) * (tag[0 ] - 1 ) * is_opcode[0 ], -1 ));
175
185
// 14. value_rlc for HEADERS == length_left
176
- constrain ((tag[i] - 2 ) * (tag[i] - 1 ) *
177
- (value_rlc[i] - length_left[i]));
186
+ every.push_back (context_object.relativize (
187
+ (tag[0 ] - 2 ) * (tag[0 ] - 1 ) * (value_rlc[0 ] - length_left[0 ]),
188
+ -1 ));
178
189
179
- if (i > 0 ) {
180
- // 2. INDEX for first contract byte is zero
181
- constrain ((tag[i - 1 ] - 2 ) * (tag[i - 1 ] - 1 ) * index[i]);
182
- // 3. INDEX is incremented for all bytes
183
- constrain (tag[i - 1 ] * tag[i] *
184
- (index[i] - index[i - 1 ] - 1 ));
185
- // 5. In contract bytes each row decrement length_left
186
- constrain (tag[i] * (length_left[i - 1 ] - length_left[i] - 1 ));
187
- // 6. Length_left is zero for last byte in the contract
188
- constrain (tag[i - 1 ] * (tag[i] - 2 ) * (tag[i] - 1 ) *
189
- length_left[i - 1 ]);
190
- // 9. First is_opcode on BYTE after HEADER is 1
191
- constrain ((tag[i] - 2 ) * (tag[i - 1 ] - 1 ) * tag[i] *
192
- (is_opcode[i] - 1 ));
193
- // 10. PUSH_SIZE decreases for non-opcodes except metadata
194
- constrain ((tag[i] - 2 ) * tag[i] * (is_opcode[i] - 1 ) *
195
- (push_size[i - 1 ] - push_size[i] - 1 ));
196
- // 11. before opcode push_size is always zero
197
- constrain (is_opcode[i] * push_size[i - 1 ]);
198
- // 12. for all bytes hash is similar to previous
199
- constrain (tag[i] * (hash_hi[i - 1 ] - hash_hi[i]));
200
- // 13. for all bytes hash is similar to previous
201
- constrain (tag[i] * (hash_lo[i - 1 ] - hash_lo[i]));
202
- // 15. for all bytes RLC is correct
203
- constrain (tag[i] *
204
- (value_rlc[i] -
205
- value_rlc[i - 1 ] * rlc_challenge[i] - value[i]));
206
- // 16. for each BYTEs rlc_challenge are similar
207
- constrain (tag[i] * (rlc_challenge[i] - rlc_challenge[i - 1 ]));
208
- }
209
- if (i > 0 && i < max_bytecode_size - 1 ) {
210
- // 17. rlc_challenge is similar for different contracts
211
- constrain (tag[i + 1 ] *
212
- (rlc_challenge[i] - rlc_challenge[i - 1 ]));
213
- }
214
- lookup (tag[i] * value[i] * (2 - tag[i]), " byte_range_table/full" );
215
- lookup (std::vector<TYPE>({value[i] * is_opcode[i],
216
- push_size[i] * is_opcode[i],
217
- is_opcode[i]}),
218
- " zkevm_opcodes/full" );
190
+ // Non-first row constraints
191
+ // 2. INDEX for first contract byte is zero
192
+ non_first.push_back (context_object.relativize (
193
+ (tag[0 ] - 2 ) * (tag[0 ] - 1 ) * index[1 ], -1 ));
194
+ // 3. INDEX is incremented for all bytes
195
+ non_first.push_back (context_object.relativize (
196
+ tag[0 ] * tag[1 ] * (index[1 ] - index[0 ] - 1 ), -1 ));
197
+ // 5. In contract bytes each row decrement length_left
198
+ non_first.push_back (context_object.relativize (
199
+ tag[1 ] * (length_left[0 ] - length_left[1 ] - 1 ), -1 ));
200
+ // 6. Length_left is zero for last byte in the contract
201
+ non_first.push_back (context_object.relativize (
202
+ tag[0 ] * (tag[1 ] - 2 ) * (tag[1 ] - 1 ) * length_left[0 ], -1 ));
203
+ // 9. First is_opcode on BYTE after HEADER is 1
204
+ non_first.push_back (context_object.relativize (
205
+ (tag[1 ] - 2 ) * (tag[0 ] - 1 ) * tag[1 ] * (is_opcode[1 ] - 1 ),
206
+ -1 ));
207
+ // 10. PUSH_SIZE decreases for non-opcodes except metadata
208
+ non_first.push_back (context_object.relativize (
209
+ (tag[1 ] - 2 ) * tag[1 ] * (is_opcode[1 ] - 1 ) *
210
+ (push_size[0 ] - push_size[1 ] - 1 ),
211
+ -1 ));
212
+ // 11. before opcode push_size is always zero
213
+ non_first.push_back (
214
+ context_object.relativize (is_opcode[1 ] * push_size[0 ], -1 ));
215
+ // 12. for all bytes hash is similar to previous
216
+ non_first.push_back (context_object.relativize (
217
+ tag[1 ] * (hash_hi[0 ] - hash_hi[1 ]), -1 ));
218
+ // 13. for all bytes hash is similar to previous
219
+ non_first.push_back (context_object.relativize (
220
+ tag[1 ] * (hash_lo[0 ] - hash_lo[1 ]), -1 ));
221
+ // 15. for all bytes RLC is correct
222
+ non_first.push_back (context_object.relativize (
223
+ tag[1 ] * (value_rlc[1 ] - value_rlc[0 ] * rlc_challenge[1 ] -
224
+ value[1 ]),
225
+ -1 ));
226
+ // 16. for each BYTEs rlc_challenge are similar
227
+ non_first.push_back (context_object.relativize (
228
+ tag[1 ] * (rlc_challenge[1 ] - rlc_challenge[0 ]), -1 ));
229
+
230
+ // Bytes constraint
231
+ // 17. rlc_challenge is similar for different contracts
232
+ bytes.push_back (context_object.relativize (
233
+ tag[2 ] * (rlc_challenge[1 ] - rlc_challenge[0 ]), -1 ));
219
234
220
- if (i > 0 ) {
221
- // Lookup for last byte
222
- lookup (
223
- std::vector<TYPE>(
224
- {// TODO: update math::expression constructor with
225
- // constant parameter
226
- tag[i] + 1 - tag[i],
227
- is_byte[i - 1 ] * (1 - is_byte[i]) * value_rlc[i - 1 ],
228
- is_byte[i - 1 ] * (1 - is_byte[i]) * hash_hi[i - 1 ] +
229
- (1 - is_byte[i - 1 ] * (1 - is_byte[i])) *
230
- w_hi<FieldType>(zerohash),
231
- is_byte[i - 1 ] * (1 - is_byte[i]) * hash_lo[i - 1 ] +
232
- (1 - is_byte[i - 1 ] * (1 - is_byte[i])) *
233
- w_lo<FieldType>(zerohash)}),
234
- " keccak_table" );
235
+ // Apply constraints
236
+ for (std::size_t i = 0 ; i < every.size (); i++) {
237
+ context_object.relative_constrain (every[i], 0 ,
238
+ max_bytecode_size - 1 );
235
239
}
236
240
for (std::size_t i = 0 ; i < non_first.size (); i++) {
237
- context_object.relative_constrain (non_first[i], 1 , max_bytecode_size - 1 );
241
+ context_object.relative_constrain (non_first[i], 1 ,
242
+ max_bytecode_size - 1 );
238
243
}
239
244
for (std::size_t i = 0 ; i < bytes.size (); i++) {
240
- context_object.relative_constrain (bytes[i], 1 , max_bytecode_size - 2 );
245
+ context_object.relative_constrain (bytes[i], 1 ,
246
+ max_bytecode_size - 2 );
241
247
}
242
248
243
- std::vector<TYPE> tmp = {context_object.relativize (tag[0 ] * value[0 ], -1 )};
244
- context_object.relative_lookup (tmp, " byte_range_table/full" , 0 , max_bytecode_size - 1 );
245
- tmp = {context_object.relativize (std::vector<TYPE>({value[0 ] * is_opcode[0 ],
246
- push_size[0 ] * is_opcode[0 ],
247
- is_opcode[0 ]}), -1 )};
248
- context_object.relative_lookup (tmp, " zkevm_opcodes/full" , 0 , max_bytecode_size - 1 );
249
- tmp = {context_object.relativize (std::vector<TYPE>({tag[1 ] + 1 - tag[1 ], // TODO: update math::expression constructor with constant parameter
250
- tag[0 ] * (1 - tag[1 ]) * value_rlc[0 ],
251
- tag[0 ] * (1 - tag[1 ]) * hash_hi[0 ] + (1 - tag[0 ] * (1 - tag[1 ])) * w_hi<FieldType>(zerohash),
252
- tag[0 ] * (1 - tag[1 ]) * hash_lo[0 ] + (1 - tag[0 ] * (1 - tag[1 ])) * w_lo<FieldType>(zerohash)}), -1 )};
253
- context_object.relative_lookup (tmp, " keccak_table" , 1 , max_bytecode_size - 1 );
249
+ // Lookups
250
+ std::vector<TYPE> tmp = {context_object.relativize (
251
+ tag[0 ] * value[0 ] * (2 - tag[0 ]), -1 )};
252
+ context_object.relative_lookup (tmp, " byte_range_table/full" , 0 ,
253
+ max_bytecode_size - 1 );
254
+ tmp = {context_object.relativize (
255
+ std::vector<TYPE>({value[0 ] * is_opcode[0 ],
256
+ push_size[0 ] * is_opcode[0 ],
257
+ is_opcode[0 ]}),
258
+ -1 )};
259
+ context_object.relative_lookup (tmp, " zkevm_opcodes/full" , 0 ,
260
+ max_bytecode_size - 1 );
261
+ tmp = {context_object.relativize (
262
+ std::vector<TYPE>(
263
+ {tag[1 ] + 1 - tag[1 ],
264
+ is_byte[0 ] * (1 - is_byte[1 ]) * value_rlc[0 ],
265
+ is_byte[0 ] * (1 - is_byte[1 ]) * hash_hi[0 ] +
266
+ (1 - is_byte[0 ] * (1 - is_byte[1 ])) *
267
+ w_hi<FieldType>(zerohash),
268
+ is_byte[0 ] * (1 - is_byte[1 ]) * hash_lo[0 ] +
269
+ (1 - is_byte[0 ] * (1 - is_byte[1 ])) *
270
+ w_lo<FieldType>(zerohash)}),
271
+ -1 )};
272
+ context_object.relative_lookup (tmp, " keccak_table" , 1 ,
273
+ max_bytecode_size - 1 );
254
274
}
255
275
};
256
276
};
0 commit comments