Skip to content

Commit

Permalink
signextend
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoine Cyr committed Nov 28, 2024
1 parent b06cb1a commit 2685a5b
Show file tree
Hide file tree
Showing 3 changed files with 257 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,18 +326,18 @@ namespace nil {
3); // rw_counter transition
std::vector<TYPE> tmp;

// tmp = {TYPE(rw_op_to_num(rw_operation_type::stack)),
// current_state.call_id(0),
// current_state.stack_size(0) - 1,
// TYPE(0), // storage_key_hi
// TYPE(0), // storage_key_lo
// TYPE(0), // field
// current_state.rw_counter(0),
// TYPE(0), // is_write
// A0,
// A1};
// lookup(tmp, "zkevm_rw");
/*
tmp = {TYPE(rw_op_to_num(rw_operation_type::stack)),
current_state.call_id(0),
current_state.stack_size(0) - 1,
TYPE(0), // storage_key_hi
TYPE(0), // storage_key_lo
TYPE(0), // field
current_state.rw_counter(0),
TYPE(0), // is_write
A0,
A1};
lookup(tmp, "zkevm_rw");

tmp = {TYPE(rw_op_to_num(rw_operation_type::stack)),
current_state.call_id(0),
current_state.stack_size(0) - 2,
Expand All @@ -360,7 +360,7 @@ namespace nil {
TYPE(1), // is_write
Res0,
Res1};
lookup(tmp, "zkevm_rw");*/
lookup(tmp, "zkevm_rw");
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2024 Alexey Yashunsky <[email protected]>
// Copyright (c) 2024 Antoine Cyr <[email protected]>
//
// MIT License
//
Expand All @@ -24,33 +25,250 @@

#pragma once

#include <numeric>
#include <algorithm>

#include <iostream>
#include <nil/blueprint/zkevm/zkevm_word.hpp>
#include <nil/blueprint/zkevm_bbf/types/opcode.hpp>
#include <numeric>

namespace nil {
namespace blueprint {
namespace bbf{
namespace bbf {
template<typename FieldType>
class opcode_abstract;

template<typename FieldType, GenerationStage stage>
class zkevm_signextend_bbf : public generic_component<FieldType, stage> {
using generic_component<FieldType, stage>::allocate;
using generic_component<FieldType, stage>::copy_constrain;
using generic_component<FieldType, stage>::constrain;
using generic_component<FieldType, stage>::lookup;
using generic_component<FieldType, stage>::lookup_table;

using value_type = typename FieldType::value_type;

constexpr static const std::size_t chunk_amount = 16;
constexpr static const value_type two_16 = 65536;
constexpr static const value_type two_32 = 4294967296;
constexpr static const value_type two_48 = 281474976710656;
constexpr static const value_type two_64 = 0x10000000000000000_cppui_modular254;
constexpr static const value_type two_128 =
0x100000000000000000000000000000000_cppui_modular254;
constexpr static const value_type two_192 =
0x1000000000000000000000000000000000000000000000000_cppui_modular254;

public:
using typename generic_component<FieldType, stage>::TYPE;
using typename generic_component<FieldType, stage>::context_type;

std::vector<TYPE> res;

public:
zkevm_signextend_bbf(context_type &context_object,
const opcode_input_type<FieldType, stage> &current_state)
: generic_component<FieldType, stage>(context_object, false),
res(chunk_amount) {
using integral_type = boost::multiprecision::number<
boost::multiprecision::backends::cpp_int_modular_backend<257>>;

std::vector<TYPE> b_chunks(chunk_amount);
std::vector<TYPE> x_chunks(chunk_amount);
std::vector<TYPE> r_chunks(chunk_amount);
std::vector<TYPE> indic(chunk_amount);
std::vector<TYPE> cur_i(chunk_amount);
std::vector<TYPE> val_n(chunk_amount);

TYPE sum_b;
TYPE x_sum;
TYPE sum_b_inverse;
TYPE b0p;
TYPE parity;
TYPE n;
TYPE xn;
TYPE xp;
TYPE xpp;
TYPE sb;
TYPE sgn;
TYPE saux;

if constexpr (stage == GenerationStage::ASSIGNMENT) {
zkevm_word_type b = current_state.stack_top();
zkevm_word_type x = current_state.stack_top(1);

int len = (integral_type(b) < 32) ? int(integral_type(b)) + 1 : 32;
integral_type sign = (integral_type(x) << (8 * (32 - len) + 1)) >> 256;
word_type result =
word_type((((integral_type(1) << 8 * (32 - len)) - 1) << 8 * len) *
sign) +
word_type((integral_type(x) << (8 * (32 - len) + 1)) >>
(8 * (32 - len) + 1));
// +1 because integral type is 257 bits long

unsigned int b0 = static_cast<unsigned int>(integral_type(b) % 65536);
b0p = (integral_type(b) > 65535) ? 32 : b0;
parity = b0p % 2;
n = (b0p - parity) / 2;
xn = static_cast<unsigned int>(
(integral_type(x) << (16 * (n > 15 ? 16 : 15 - n) + 1)) >>
(16 * 15 + 1));
// +1 because integral_type is 257 bits long
xpp = xn % 256;
xp = (xn - xpp) / 256;
sb = (parity == 0) ? xpp : xp;
sgn = (sb > 128);
saux = sb + 128 - sgn * 256;

b_chunks = zkevm_word_to_field_element<BlueprintFieldType>(b);
x_chunks = zkevm_word_to_field_element<BlueprintFieldType>(x);
r_chunks = zkevm_word_to_field_element<BlueprintFieldType>(result);
for (std::size_t i = 0; i < chunk_amount; i++) {
cur_i[i] = i;
val_n[i] = n;
indic[i] = (cur_j == val_n) ? 0 : (cur_j - val_n).inversed();
}

sum_b = 0;
for (std::size_t i = 1; j < chunk_amount; i++) {
sum_b += b_chunks[i];
}
sum_b_inverse = sum_b.is_zero() ? 0 : sum_b.inversed();

x_sum = 0;
for(std::size_t i = 0; i < chunk_amount; i++) {
x_sum += x_chunks[i] * (1 - (i - n)*indic[i]);
}
}

allocate(n);
for (std::size_t i = 0; i < chunk_amount; i++) {
allocate(b_chunks[i], i, 0);
allocate(x_chunks[i], i + chunk_amount, 0);
allocate(r_chunks[i], i + chunk_amount, 1);
allocate(indic);
res[i] = r_chunks[i];
constrain((i - n)*(1 - (i - n)*indic[i]));
}

allocate(b_sum);
allocate(b_sum_inverse);
allocate(x_sum);
allocate(b0p);
allocate(parity);
allocate(xn);
allocate(xp);
allocate(xpp);
allocate(sb);
allocate(sgn);
allocate(saux);

constrain(b_sum * (1 - b_sum_inverse * b_sum));
constrain((b0p - b_chunks[0]*(1 - b_sum*b_sum_inverse) - 32*b_sum*b_sum_inverse));
constrain(parity*(1-parity));
constrain(b0p - parity - 2*n);
//n < 32768 range check
allocate(2 * n);
//xp, xpp,saux < 256
allocate(256 * xp);
allocate(256 * xpp);
allocate(256 * saux);


constrain(xn - x_sum);
constrain(xn - xp*256 - xpp);

constrain(sb - (1-parity)*xpp - parity*xp);
constrain(sgn * (1-sgn));
constrain(sb + 128 - saux - 256*sgn);

// auto B_128 = chunks16_to_chunks128_reversed<TYPE>(b_chunks);
// auto X_128 = chunks16_to_chunks128_reversed<TYPE>(x_chunks);
// auto Res_128 = chunks16_to_chunks128_reversed<TYPE>(res);

// TYPE B0, B1, X0, X1, Res0, Res1;
// A0 = A_128.first;
// A1 = A_128.second;
// B0 = B_128.first;
// B1 = B_128.second;
// Res0 = Res_128.first;
// Res1 = Res_128.second;
// allocate(A0, 36, 0);
// allocate(A1, 37, 0);
// allocate(B0, 38, 0);
// allocate(B1, 39, 0);
// allocate(Res0, 40, 0);
// allocate(Res1, 41, 0);

if constexpr (stage == GenerationStage::CONSTRAINTS) {
/*
constrain(current_state.pc_next() - current_state.pc(2) -
1); // PC transition
constrain(current_state.gas(2) - current_state.gas_next() -
3); // GAS transition
constrain(current_state.stack_size(2) - current_state.stack_size_next() -
1); // stack_size transition
constrain(current_state.memory_size(2) -
current_state.memory_size_next()); // memory_size transition
constrain(current_state.rw_counter_next() - current_state.rw_counter(2) -
3); // rw_counter transition
std::vector<TYPE> tmp;
tmp = {TYPE(rw_op_to_num(rw_operation_type::stack)),
current_state.call_id(0),
current_state.stack_size(0) - 1,
TYPE(0), // storage_key_hi
TYPE(0), // storage_key_lo
TYPE(0), // field
current_state.rw_counter(0),
TYPE(0), // is_write
B0,
B1};
lookup(tmp, "zkevm_rw");
tmp = {TYPE(rw_op_to_num(rw_operation_type::stack)),
current_state.call_id(1),
current_state.stack_size(1) - 2,
TYPE(0), // storage_key_hi
TYPE(0), // storage_key_lo
TYPE(0), // field
current_state.rw_counter(1) + 1,
TYPE(0), // is_write
A0,
A1};
lookup(tmp, "zkevm_rw");
tmp = {TYPE(rw_op_to_num(rw_operation_type::stack)),
current_state.call_id(0),
current_state.stack_size(0) - 2,
TYPE(0), // storage_key_hi
TYPE(0), // storage_key_lo
TYPE(0), // field
current_state.rw_counter(0) + 2,
TYPE(1), // is_write
Res0,
Res1};
lookup(tmp, "zkevm_rw");*/
}
}
};

template<typename FieldType>
class zkevm_signextend_operation : public opcode_abstract<FieldType> {
public:
class zkevm_signextend_bbf : public opcode_abstract<FieldType> {
public:
virtual void fill_context(
typename generic_component<FieldType, GenerationStage::ASSIGNMENT>::context_type &context,
const opcode_input_type<FieldType, GenerationStage::ASSIGNMENT> &current_state
) {}
typename generic_component<FieldType, GenerationStage::ASSIGNMENT>::context_type
&context,
const opcode_input_type<FieldType, GenerationStage::ASSIGNMENT>
&current_state) {
zkevm_signextend_bbf<FieldType, GenerationStage::ASSIGNMENT> bbf_obj(
context, current_state);
}
virtual void fill_context(
typename generic_component<FieldType, GenerationStage::CONSTRAINTS>::context_type &context,
const opcode_input_type<FieldType, GenerationStage::CONSTRAINTS> &current_state
) {}
virtual std::size_t rows_amount() override {
return 2;
typename generic_component<FieldType,
GenerationStage::CONSTRAINTS>::context_type &context,
const opcode_input_type<FieldType, GenerationStage::CONSTRAINTS>
&current_state) {
zkevm_signextend_bbf<FieldType, GenerationStage::CONSTRAINTS> bbf_obj(
context, current_state);
}
virtual std::size_t rows_amount() override { return 2; }
};
} // namespace bbf
} // namespace blueprint
} // namespace nil
} // namespace bbf
} // namespace blueprint
} // namespace nil
Loading

0 comments on commit 2685a5b

Please sign in to comment.