Skip to content

Commit 498c270

Browse files
AntoineCyrayashunsky
authored andcommitted
relative constraints bytecode
1 parent 95589ac commit 498c270

File tree

1 file changed

+48
-32
lines changed
  • crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf

1 file changed

+48
-32
lines changed

crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/bytecode.hpp

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -143,41 +143,57 @@ namespace nil {
143143
// copy_constrain(input.rlc_challenge, rlc_challenge[0]);
144144
// }
145145
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);
166178
}
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);
169181
}
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);
180184
}
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);
181197
}
182198
};
183199
};

0 commit comments

Comments
 (0)