Skip to content

Commit

Permalink
blueprint: use big_uint as zkevm_word_type
Browse files Browse the repository at this point in the history
  • Loading branch information
ioxid committed Dec 20, 2024
1 parent 6368029 commit 28f71fd
Show file tree
Hide file tree
Showing 62 changed files with 1,412 additions and 981 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ namespace nil {
nil::crypto3::algebra::fields::field<256>::integral_type n(d);
std::pair<value_type, value_type> hash_value;

hash_value.first = (n & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000_big_uint257) >> 128;
hash_value.second = n & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_big_uint257;
hash_value.first =
(n &
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000_big_uint256) >>
128;
hash_value.second = n & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_big_uint256;
return hash_value;
}

Expand Down
15 changes: 5 additions & 10 deletions crypto3/libs/blueprint/include/nil/blueprint/zkevm/copy_event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,16 +199,11 @@ namespace nil {
// CALLOP, RETURN, REVERT, RETURNDATACOPY

// This function is just for testing. It'll be fully rewritten in evm-assigner.
std::size_t copy_events_from_trace(
std::vector<copy_event> &result,
boost::property_tree::ptree const &pt,
std::size_t rows_amount,
std::size_t call_id = 0,
std::size_t transaction_id = 0,
std::size_t initial_rw_counter = 0
){
using integral_type = nil::crypto3::multiprecision::big_uint<257>;

std::size_t copy_events_from_trace(std::vector<copy_event> &result,
boost::property_tree::ptree const &pt,
std::size_t rows_amount, std::size_t call_id = 0,
std::size_t transaction_id = 0,
std::size_t initial_rw_counter = 0) {
boost::property_tree::ptree ptrace = pt.get_child("result.structLogs");
boost::property_tree::ptree pstack;
boost::property_tree::ptree pmemory;
Expand Down
29 changes: 17 additions & 12 deletions crypto3/libs/blueprint/include/nil/blueprint/zkevm/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,19 @@ namespace nil {

void append_opcode(
std::string opcode,
const std::vector<zkevm_word_type> &stack, // Stack state before operation
const std::vector<zkevm_word_type> &stack_next, // stack state after operation. We need it for correct PUSH and correct SLOAD
const std::vector<uint8_t> &memory , // Memory state before operation in bytes format
const std::vector<uint8_t> &memory_next , // Memory state before operation in bytes format
const std::map<zkevm_word_type, zkevm_word_type> &storage,// Storage state before operation
const std::map<zkevm_word_type, zkevm_word_type> &storage_next// Storage state before operation
){
using integral_type = nil::crypto3::multiprecision::big_uint<257>;

const std::vector<zkevm_word_type> &stack, // Stack state before operation
const std::vector<zkevm_word_type>
&stack_next, // stack state after operation. We need it for correct PUSH and
// correct SLOAD
const std::vector<uint8_t>
&memory, // Memory state before operation in bytes format
const std::vector<uint8_t>
&memory_next, // Memory state before operation in bytes format
const std::map<zkevm_word_type, zkevm_word_type>
&storage, // Storage state before operation
const std::map<zkevm_word_type, zkevm_word_type>
&storage_next // Storage state before operation
) {
// Opcode is not presented in RW lookup table. We just take it from json
// // std::cout << opcode << std::endl;
if(opcode == "STOP") {
Expand Down Expand Up @@ -420,8 +424,8 @@ namespace nil {
// std::cout << "\t" << rw_ops[rw_ops.size()-1] << std::endl;
rw_ops.push_back(stack_operation(call_id, stack.size()-1, rw_ops.size(), false, stack[stack.size()-1]));
// std::cout << "\t" << rw_ops[rw_ops.size()-1] << std::endl;
std::size_t length = std::size_t(integral_type(stack[stack.size()-3]));
std::size_t dest = std::size_t(integral_type(stack[stack.size()-1]));
std::size_t length = std::size_t(stack[stack.size()-3]);
std::size_t dest = std::size_t(stack[stack.size()-1]);
// std::cout << "Length = " << length << std::endl;
// std::cout << "Memory_size " << memory.size() << "=>" << memory_next.size() << std::endl;
for( std::size_t i = 0; i < length; i++){
Expand Down Expand Up @@ -584,7 +588,7 @@ namespace nil {
BOOST_ASSERT_MSG(addr < std::numeric_limits<std::size_t>::max(), "Cannot process so large memory address");
// std::cout << "\t\t Address = 0x" << std::hex << addr << std::dec << " memory size " << memory.size() << std::endl;
for( std::size_t i = 0; i < 32; i++){
rw_ops.push_back(memory_operation(call_id, addr+i, rw_ops.size(), false, addr+i < memory.size() ? memory[std::size_t(integral_type(addr+i))]: 0));
rw_ops.push_back(memory_operation(call_id, addr+i, rw_ops.size(), false, addr+i < memory.size() ? memory[std::size_t(addr+i)]: 0));
// std::cout << "\t" << rw_ops[rw_ops.size()-1] << std::endl;
}
rw_ops.push_back(stack_operation(call_id, stack_next.size()-1, rw_ops.size(), true, stack_next[stack_next.size()-1]));
Expand Down Expand Up @@ -1256,6 +1260,7 @@ namespace nil {
BOOST_ASSERT(false);
}
}

public:
rw_trace(boost::property_tree::ptree const &pt, std::size_t rows_amount, std::size_t _call_id = 0){
call_id = _call_id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,26 +326,24 @@ namespace nil {

void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
using word_type = typename zkevm_stack::word_type;
using integral_type = nil::crypto3::multiprecision::big_uint<257>;

word_type a = machine.stack_top();
word_type b = machine.stack_top(1);
word_type N = machine.stack_top(2);

integral_type s_integral = integral_type(a) + integral_type(b);
int is_overflow = (s_integral >= zkevm_modulus);
word_type s = word_type(s_integral);
auto s_full = nil::crypto3::multiprecision::big_uint<257>(a) + b;
int is_overflow = s_full.bit_test(256);
word_type s = s_full.truncate<256>();

integral_type r_integral = N != 0u ? s_integral / integral_type(N) : 0u;
bool r_overflow = (r_integral >= zkevm_modulus);
word_type r = r_integral;
auto r_full = N != 0u ? s_full / N : 0u;
bool r_overflow = r_full.bit_test(256);
word_type r = r_full.truncate<256>();

// word_type q = N != 0u ? s % N : s;
word_type q = word_type(s_integral - r_integral*integral_type(N));
word_type q_out = N != 0u ? q : 0; // according to EVM spec s % 0 = 0
word_type q = word_type(s_full - r_full * N);
word_type q_out = N != 0u ? q : 0u; // according to EVM spec s % 0 = 0

bool t_last = integral_type(q) < integral_type(N);
word_type v = word_type(integral_type(q) + integral_type(t_last)*zkevm_modulus - integral_type(N));
word_type v = subtract_wrapping(q, N);

word_type result = q_out;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,15 @@ namespace nil {

word_type result;
switch(bit_operation) {
case B_AND: result = a.base() & b.base(); break;
case B_OR: result = a.base() | b.base(); break;
case B_XOR: result = a.base() ^ b.base(); break;
case B_AND:
result = a & b;
break;
case B_OR:
result = a | b;
break;
case B_XOR:
result = a ^ b;
break;
}

const std::vector<value_type> a_chunks = zkevm_word_to_field_element<BlueprintFieldType>(a);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,22 +131,17 @@ namespace nil {

void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
using word_type = typename zkevm_stack::word_type;
using integral_type = nil::crypto3::multiprecision::big_uint<257>;

word_type i = machine.stack_top();
word_type x = machine.stack_top(1);
int shift = (integral_type(i) < 32) ? int(integral_type(i)) : 32;
word_type result = word_type((integral_type(x) << ((8*shift) + 1)) >> (31*8 + 1));
// +1 because integral type is 257 bits long
int shift = (i < 32) ? int(i) : 32;
word_type result = (x << (8 * shift)) >> (31 * 8);

unsigned int i0 = static_cast<unsigned int>(integral_type(i) % 65536),
i0p = (integral_type(i) > 65535) ? 32 : i0;
unsigned int i0 = static_cast<unsigned int>(i % 65536), i0p = (i > 65535) ? 32 : i0;
int parity = i0p % 2,
n = (i0p - parity) / 2;
unsigned int xn = static_cast<unsigned int>((integral_type(x) << (16*n + 1)) >> (16*15 + 1)),
// +1 because integral_type is 257 bits long
xpp = xn % 256,
xp = (xn - xpp) / 256;
unsigned int xn = static_cast<unsigned int>((x << (16 * n)) >> (16 * 15)),
xpp = xn % 256, xp = (xn - xpp) / 256;

const std::vector<value_type> i_chunks = zkevm_word_to_field_element<BlueprintFieldType>(i);
const std::vector<value_type> x_chunks = zkevm_word_to_field_element<BlueprintFieldType>(x);
Expand Down Expand Up @@ -179,7 +174,8 @@ namespace nil {
assignment.witness(witness_cols[chunk_amount + 4], curr_row) = xn; // n is the offset from MSW
assignment.witness(witness_cols[chunk_amount + 5], curr_row) = xp;
assignment.witness(witness_cols[chunk_amount + 6], curr_row) = xpp;
assignment.witness(witness_cols[chunk_amount + 7], curr_row) = static_cast<value_type>(integral_type(result));
assignment.witness(witness_cols[chunk_amount + 7], curr_row) =
static_cast<value_type>(result);
}

std::size_t rows_amount() override {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,20 +175,15 @@ namespace nil {

void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
using word_type = typename zkevm_stack::word_type;
using integral_type = nil::crypto3::multiprecision::big_uint<257>;

auto is_negative = [](word_type x) {
return (integral_type(x) > zkevm_modulus/2 - 1);
};

word_type x = machine.stack_top();
word_type y = machine.stack_top(1);
word_type r;

if ((cmp_operation == C_LT) || (cmp_operation == C_SLT)) {
r = (integral_type(x) < integral_type(y));
r = x < y;
} else {
r = (integral_type(x) > integral_type(y));
r = x > y;
}

word_type result;
Expand All @@ -212,7 +207,7 @@ namespace nil {
a = x;
c = y;
}
b = word_type(integral_type(c) + integral_type(r)*zkevm_modulus - integral_type(a));
b = subtract_wrapping(c, a);

const std::vector<value_type> a_chunks = zkevm_word_to_field_element<BlueprintFieldType>(a);
const std::vector<value_type> b_chunks = zkevm_word_to_field_element<BlueprintFieldType>(b);
Expand All @@ -236,17 +231,16 @@ namespace nil {
if (cmp_operation == C_EQ) {
assignment.witness(witness_cols[2*chunk_amount], curr_row + 1) =
b_sum.is_zero() ? value_type::zero() : value_type::one() * b_sum.inversed();
assignment.witness(witness_cols[chunk_amount + 1], curr_row + 1) = integral_type(result);
assignment.witness(witness_cols[chunk_amount + 1], curr_row + 1) = result;
}

for (std::size_t i = 0; i < chunk_amount; i++) {
assignment.witness(witness_cols[i], curr_row + 2) = r_chunks[i];
}

if ((cmp_operation == C_SLT) || (cmp_operation == C_SGT)) {
integral_type two_15 = 32768,
biggest_a_chunk = integral_type(a) >> (256 - 16),
biggest_r_chunk = integral_type(c) >> (256 - 16);
word_type two_15 = 32768, biggest_a_chunk = a >> (256 - 16),
biggest_r_chunk = c >> (256 - 16);

// find the sign bit by adding 2^16/2 to the biggest chunk. The carry-on bit is 1 iff the sign bit is 1
assignment.witness(witness_cols[chunk_amount], curr_row + 1) =
Expand All @@ -257,7 +251,7 @@ namespace nil {
(biggest_r_chunk > two_15 - 1) ? (biggest_r_chunk - two_15) : biggest_r_chunk + two_15;
assignment.witness(witness_cols[chunk_amount + 3], curr_row + 1) = (biggest_r_chunk > two_15 - 1);

assignment.witness(witness_cols[chunk_amount + 4], curr_row + 1) = integral_type(result);
assignment.witness(witness_cols[chunk_amount + 4], curr_row + 1) = result;
}

// we might want to pack carries more efficiently?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ namespace nil {
zkevm_stack &stack = machine.stack;
word_type a = stack.pop();
word_type b = stack.pop();
word_type result = b.base() != 0u ? a.base() / b.base() : 0u;
word_type q = b.base() != 0u ? a.base() % b.base() : a;
word_type result = b != 0u ? a / b : 0u;
word_type q = b != 0u ? a % b : a;

const std::vector<value_type> a_chunks = zkevm_word_to_field_element<BlueprintFieldType>(a);
const std::vector<value_type> b_chunks = zkevm_word_to_field_element<BlueprintFieldType>(b);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,14 +278,11 @@ namespace nil {
using word_type = typename zkevm_stack::word_type;
word_type a = machine.stack_top();
word_type b = machine.stack_top(1);
using integral_type = nil::crypto3::multiprecision::big_uint<257>;
integral_type r_integral = b != 0u ? integral_type(a) / integral_type(b) : 0u;
word_type r = r_integral;
word_type q = b != 0u ? integral_type(a) % integral_type(b) : a;
word_type q_out = b != 0u ? q : 0; // according to EVM spec a % 0 = 0

bool t_last = integral_type(q) < integral_type(b);
word_type v = word_type(integral_type(q) + integral_type(t_last)*zkevm_modulus - integral_type(b));
word_type r = b != 0u ? a / b : 0u;
word_type q = b != 0u ? a % b : a;
word_type q_out = b != 0u ? q : 0u; // according to EVM spec a % 0 = 0

word_type v = subtract_wrapping(q, b);

word_type result = is_div ? r : q_out;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ namespace nil {
void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine,
zkevm_word_type additional_input) {
using word_type = typename zkevm_stack::word_type;
using integral_type = nil::crypto3::multiprecision::big_uint<257>;
using circuit_integral_type = typename BlueprintFieldType::integral_type;
zkevm_opcode opcode_mnemo = machine.error_opcode();
std::size_t opcode_num = zkevm_table.get_opcodes_info().get_opcode_number(opcode_mnemo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ namespace nil {
void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine,
zkevm_word_type additional_input) {
using word_type = typename zkevm_stack::word_type;
using integral_type = nil::crypto3::multiprecision::big_uint<257>;
using circuit_integral_type = typename BlueprintFieldType::integral_type;

assignment_type &assignment = zkevm_table.get_assignment();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ namespace nil {
for (std::size_t i = 0; i < chunk_amount; i++) {
assignment.witness(witness_cols[i], curr_row) = chunks[i];
}
assignment.witness(witness_cols[chunk_amount], curr_row) = (a.base() == 0u);
assignment.witness(witness_cols[chunk_amount], curr_row) = (a == 0u);
const value_type chunk_sum = std::accumulate(chunks.begin(), chunks.end(), value_type::zero());
assignment.witness(witness_cols[2*chunk_amount], curr_row) =
chunk_sum == 0 ? value_type::zero() : value_type::one() * chunk_sum.inversed();
Expand Down
Loading

0 comments on commit 28f71fd

Please sign in to comment.