-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Antoine Cyr
committed
Nov 28, 2024
1 parent
b06cb1a
commit 2685a5b
Showing
3 changed files
with
257 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
// | ||
|
@@ -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> ¤t_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> ¤t_state | ||
) {} | ||
typename generic_component<FieldType, GenerationStage::ASSIGNMENT>::context_type | ||
&context, | ||
const opcode_input_type<FieldType, GenerationStage::ASSIGNMENT> | ||
¤t_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> ¤t_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> | ||
¤t_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 |
Oops, something went wrong.