@@ -143,41 +143,57 @@ namespace nil {
143
143
// copy_constrain(input.rlc_challenge, rlc_challenge[0]);
144
144
// }
145
145
static const auto zerohash = zkevm_keccak_hash ({});
146
- for (std::size_t i = 0 ; i < max_bytecode_size; i++) {
147
- constrain (tag[i] * (tag[i] - 1 )); // 0. TAG is zeroes or ones -- maybe there will be third value for non-used rows
148
- constrain ((tag[i] - 1 ) * index[i]); // 1. INDEX for HEADER and unused bytes is zero
149
- constrain ((tag[i] - 1 ) * (length_left[i] - value[i])); // 4. In contract header length_left == contract length
150
- constrain (is_opcode[i] * (is_opcode[i] - 1 )); // 7. is_opcode is zeroes or ones
151
- constrain ((tag[i] - 1 ) * is_opcode[i]); // 8. is_opcode on HEADER are zeroes
152
- constrain ((tag[i] - 1 ) * (value_rlc[i] - length_left[i])); // 14. value_rlc for HEADERS == 0;
153
-
154
- if (i > 0 ) {
155
- constrain ((tag[i-1 ] - 1 ) * index[i]); // 2. INDEX for first contract byte is zero
156
- constrain (tag[i-1 ] * tag[i] * (index[i] - index[i-1 ] - 1 )); // 3. INDEX is incremented for all bytes
157
- constrain (tag[i] * (length_left[i-1 ] - length_left[i] - 1 )); // 5. In contract bytes each row decrement length_left
158
- constrain (tag[i-1 ] * (tag[i] - 1 ) * length_left[i-1 ]); // 6. Length_left is zero for last byte in the contract
159
- constrain ((tag[i-1 ] - 1 ) * tag[i] * (is_opcode[i] - 1 )); // 9. Fist is_opcode on BYTE after HEADER is 1
160
- constrain (tag[i] * (is_opcode[i] - 1 ) * (push_size[i-1 ] - push_size[i] - 1 )); // 10. PUSH_SIZE decreases for non-opcodes
161
- constrain (is_opcode[i] * push_size[i-1 ]); // 11. before opcode push_size is always zero
162
- constrain (tag[i] * (hash_hi[i-1 ] - hash_hi[i])); // 12. for all bytes hash is similar to previous
163
- constrain (tag[i] * (hash_lo[i-1 ] - hash_lo[i])); // 13. for all bytes hash is similar to previous
164
- constrain (tag[i] * (value_rlc[i] - value_rlc[i-1 ] * rlc_challenge[i] - value[i])); // 15. for all bytes RLC is correct
165
- constrain (tag[i] * (rlc_challenge[i] - rlc_challenge[i-1 ])); // 16. for each BYTEs rlc_challenge are similar
146
+ if constexpr (stage == GenerationStage::CONSTRAINTS) {
147
+ std::vector<TYPE> every;
148
+ std::vector<TYPE> non_first;
149
+ std::vector<TYPE> bytes;
150
+
151
+ // Every constraints
152
+ every.push_back (context_object.relativize (tag[0 ] * (tag[0 ] - 1 ), -1 )); // 0. TAG is zeroes or ones -- maybe there will be third value for non-used rows
153
+ every.push_back (context_object.relativize ((tag[0 ] - 1 ) * index[0 ], -1 )); // 1. INDEX for HEADER and unused bytes is zero
154
+ every.push_back (context_object.relativize ((tag[0 ] - 1 ) * (length_left[0 ] - value[0 ]), -1 )); // 4. In contract header length_left == contract length
155
+ every.push_back (context_object.relativize (is_opcode[0 ] * (is_opcode[0 ] - 1 ), -1 )); // 7. is_opcode is zeroes or ones
156
+ every.push_back (context_object.relativize ((tag[0 ] - 1 ) * is_opcode[0 ], -1 )); // 8. is_opcode on HEADER are zeroes
157
+ every.push_back (context_object.relativize ((tag[0 ] - 1 ) * (value_rlc[0 ] - length_left[0 ]), -1 )); // 14. value_rlc for HEADERS == 0;
158
+
159
+ // Non-first row constraints
160
+ non_first.push_back (context_object.relativize ((tag[0 ] - 1 ) * index[1 ], -1 )); // 2. INDEX for first contract byte is zero
161
+ non_first.push_back (context_object.relativize (tag[0 ] * tag[1 ] * (index[1 ] - index[0 ] - 1 ), -1 )); // 3. INDEX is incremented for all bytes
162
+ non_first.push_back (context_object.relativize (tag[1 ] * (length_left[0 ] - length_left[1 ] - 1 ), -1 )); // 5. In contract bytes each row decrement length_left
163
+ non_first.push_back (context_object.relativize (tag[0 ] * (tag[1 ] - 1 ) * length_left[0 ], -1 )); // 6. Length_left is zero for last byte in the contract
164
+ non_first.push_back (context_object.relativize ((tag[0 ] - 1 ) * tag[1 ] * (is_opcode[1 ] - 1 ), -1 )); // 9. Fist is_opcode on BYTE after HEADER is 1
165
+ non_first.push_back (context_object.relativize (tag[1 ] * (is_opcode[1 ] - 1 ) * (push_size[0 ] - push_size[1 ] - 1 ), -1 )); // 10. PUSH_SIZE decreases for non-opcodes
166
+ non_first.push_back (context_object.relativize (is_opcode[1 ] * push_size[0 ], -1 )); // 11. before opcode push_size is always zero
167
+ non_first.push_back (context_object.relativize (tag[1 ] * (hash_hi[0 ] - hash_hi[1 ]), -1 )); // 12. for all bytes hash is similar to previous
168
+ non_first.push_back (context_object.relativize (tag[1 ] * (hash_lo[0 ] - hash_lo[1 ]), -1 )); // 13. for all bytes hash is similar to previous
169
+ non_first.push_back (context_object.relativize (tag[1 ] * (value_rlc[1 ] - value_rlc[0 ] * rlc_challenge[1 ] - value[1 ]), -1 )); // 15. for all bytes RLC is correct
170
+ non_first.push_back (context_object.relativize (tag[1 ] * (rlc_challenge[1 ] - rlc_challenge[0 ]), -1 )); // 16. for each BYTEs rlc_challenge are similar
171
+
172
+ // Bytes constraint
173
+ bytes.push_back (context_object.relativize (tag[2 ] * (rlc_challenge[1 ] - rlc_challenge[0 ]), -1 )); // 17. rlc_challenge is similar for different contracts
174
+
175
+ // Apply constraints
176
+ for (std::size_t i = 0 ; i < every.size (); i++) {
177
+ context_object.relative_constrain (every[i], 0 , max_bytecode_size - 1 );
166
178
}
167
- if (i> 0 && i < max_bytecode_size- 1 ) {
168
- constrain (tag[i+ 1 ] * (rlc_challenge[i] - rlc_challenge[i- 1 ])); // 17. rlc_challenge is similar for different contracts
179
+ for (std:: size_t i = 0 ; i < non_first. size (); i++ ) {
180
+ context_object. relative_constrain (non_first[i], 1 , max_bytecode_size - 1 );
169
181
}
170
- lookup (tag[i]*value[i]," byte_range_table/full" );
171
- lookup (std::vector<TYPE>({value[i]*is_opcode[i], push_size[i]*is_opcode[i], is_opcode[i]})," zkevm_opcodes/full" );
172
-
173
- if ( i > 0 ){
174
- lookup (std::vector<TYPE>({
175
- tag[i] + 1 - tag[i], // TODO: update math::expression constructor with constant parameter
176
- tag[i-1 ] * (1 - tag[i]) * value_rlc[i-1 ],
177
- tag[i-1 ] * (1 - tag[i]) * hash_hi[i-1 ] + (1 - tag[i-1 ] * (1 - tag[i])) * w_hi<FieldType>(zerohash),
178
- tag[i-1 ] * (1 - tag[i]) * hash_lo[i-1 ] + (1 - tag[i-1 ] * (1 - tag[i])) * w_lo<FieldType>(zerohash)
179
- }), " keccak_table" );
182
+ for (std::size_t i = 0 ; i < bytes.size (); i++) {
183
+ context_object.relative_constrain (bytes[i], 1 , max_bytecode_size - 2 );
180
184
}
185
+
186
+ std::vector<TYPE> tmp = {context_object.relativize (tag[0 ] * value[0 ], -1 )};
187
+ context_object.relative_lookup (tmp, " byte_range_table/full" , 0 , max_bytecode_size - 1 );
188
+ tmp = {context_object.relativize (std::vector<TYPE>({value[0 ] * is_opcode[0 ],
189
+ push_size[0 ] * is_opcode[0 ],
190
+ is_opcode[0 ]}), -1 )};
191
+ context_object.relative_lookup (tmp, " zkevm_opcodes/full" , 0 , max_bytecode_size - 1 );
192
+ tmp = {context_object.relativize (std::vector<TYPE>({tag[1 ] + 1 - tag[1 ], // TODO: update math::expression constructor with constant parameter
193
+ tag[0 ] * (1 - tag[1 ]) * value_rlc[0 ],
194
+ tag[0 ] * (1 - tag[1 ]) * hash_hi[0 ] + (1 - tag[0 ] * (1 - tag[1 ])) * w_hi<FieldType>(zerohash),
195
+ tag[0 ] * (1 - tag[1 ]) * hash_lo[0 ] + (1 - tag[0 ] * (1 - tag[1 ])) * w_lo<FieldType>(zerohash)}), -1 )};
196
+ context_object.relative_lookup (tmp, " keccak_table" , 1 , max_bytecode_size - 1 );
181
197
}
182
198
};
183
199
};
0 commit comments