Skip to content

Commit

Permalink
zkevm_state_selector rewritten, stack size, gas, pc computation updat…
Browse files Browse the repository at this point in the history
…ed, JUMP and JUMPI implemented #325
  • Loading branch information
ETatuzova committed Sep 18, 2024
1 parent d3d1949 commit 3d3e45d
Show file tree
Hide file tree
Showing 37 changed files with 905 additions and 923 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ namespace nil {
if (!constraint_result.is_zero()) {
std::cout << "Constraint " << j << " from gate " << i << " on row " << selector_row
<< " is not satisfied." << std::endl;
for(std::size_t k = 0; k < assignments.rows_amount(); k++){
std::cout << gates[i].constraints[j].evaluate(k, assignments) << " ";
}
std::cout << std::endl;
std::cout << "Constraint: " << gates[i].constraints[j] << std::endl;
std::cout << "Constraint result: " << constraint_result << std::endl;
std::cout << "Offending gate:" << std::endl;
Expand Down
255 changes: 255 additions & 0 deletions libs/blueprint/include/nil/blueprint/zkevm/index_selector.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2024 Dmitrii Tabalin <d.tabalin@nil.foundation>
// Copyright (c) 2024 Alexey Yashunsky <a.yashunsky@nil.foundation>
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//---------------------------------------------------------------------------//

#pragma once

#include <nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp>
#include <nil/blueprint/blueprint/plonk/circuit.hpp>
#include <nil/blueprint/blueprint/plonk/assignment.hpp>
#include <nil/blueprint/component.hpp>
#include <nil/blueprint/manifest.hpp>
#include <nil/blueprint/zkevm/state.hpp>

namespace nil {
namespace blueprint {
namespace components {
// activates a witness column based on an input value
// is used to achieve dynamic selector behavior
// actual implementation
template<typename ArithmetizationType, typename FieldType>
class index_selector;

template<typename BlueprintFieldType>
class index_selector<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>,
BlueprintFieldType>
: public plonk_component<BlueprintFieldType> {

public:
using component_type = plonk_component<BlueprintFieldType>;

using var = typename component_type::var;
using manifest_type = plonk_component_manifest;
using constraint_type = crypto3::zk::snark::plonk_constraint<BlueprintFieldType>;
using state_var = state_var<BlueprintFieldType>;

std::size_t options_amount;

class gate_manifest_type : public component_gate_manifest {
private:
std::size_t options_amount;

public:
gate_manifest_type(std::size_t options_amount_) :
options_amount(options_amount_) {};

bool operator<(gate_manifest_type const& other) const {
return (options_amount < other.options_amount);
}

std::uint32_t gates_amount() const override {
return index_selector::gates_amount;
}
};

static gate_manifest get_gate_manifest(
std::size_t options_amount
) {
gate_manifest manifest = gate_manifest(gate_manifest_type(options_amount));
return manifest;
}

static manifest_type get_manifest(std::size_t options_amount) {
manifest_type manifest = manifest_type(
// TODO: make the manifest depend on options_amount
// this requires the manifest rework
std::shared_ptr<manifest_param>(new manifest_single_value_param(
options_amount
)),
false
);
return manifest;
}

constexpr static std::size_t get_rows_amount(
std::size_t options_amount
) {
return 1;
}

constexpr static const std::size_t gates_amount = 1;
const std::size_t rows_amount = get_rows_amount(options_amount);
const std::string component_name = "index selector component";

struct input_type {
std::size_t index;
std::vector<std::reference_wrapper<var>> all_vars() {
return {};
}
};

struct result_type {
result_type(const index_selector &component, std::size_t start_row_index) {}
std::vector<std::reference_wrapper<var>> all_vars() {
return {};
}
};

template<typename ContainerType>
explicit index_selector(ContainerType witness, std::size_t options_amount_) :
component_type(witness, {}, {}, get_manifest(options_amount_)),
options_amount(options_amount_){
BOOST_ASSERT(this->witness_amount() >= options_amount);
};

template<typename WitnessContainerType, typename ConstantContainerType,
typename PublicInputContainerType>
index_selector(
WitnessContainerType witness, ConstantContainerType constant,
PublicInputContainerType public_input, std::size_t options_amount_) :
component_type(witness, constant, public_input, get_manifest(options_amount_)),
options_amount(options_amount_){
BOOST_ASSERT(this->witness_amount() >= options_amount);
};

index_selector(
std::initializer_list<typename component_type::witness_container_type::value_type> witnesses,
std::initializer_list<typename component_type::constant_container_type::value_type>
constants,
std::initializer_list<typename component_type::public_input_container_type::value_type>
public_inputs,
std::size_t options_amount_, bool is_compressed_ = false) :
component_type(witnesses, constants, public_inputs, get_manifest(options_amount_)),
options_amount(options_amount_){
BOOST_ASSERT(this->witness_amount() >= this->options_amount);
};


// Here we only check that all variables are zeroes and ones, and their sum is 1
std::vector<constraint_type> generate_constraints() const {
std::cout << "Index selector generate_constraints options_amount = " << this->options_amount << std::endl;
std::vector<constraint_type> constraints;

std::size_t option_cells_amount = (this->options_amount + 1)/2,
option_WA = this->witness_amount() - 1;
for (std::size_t i = 0; i < options_amount; i++) {
var curr_var = var(this->W(i),0);
constraints.push_back(curr_var * (curr_var - 1));
}
return constraints;
}

// Allows conveniently connect sum_constraints from different areas;
constraint_type sum_constraint(std::size_t rotation = 0){
constraint_type sum_to_one;
for (std::size_t i = 0; i < options_amount; i++) {
var curr_var = var(this->W(i), rotation);
sum_to_one += curr_var;
}
return sum_to_one;
}

constraint_type index_constraint(std::size_t rotation = 0){
constraint_type compose_constraint;
for (std::size_t i = 0; i < options_amount; i++){
var curr_var = var(this->W(i),rotation);
compose_constraint += i * curr_var;
}
return compose_constraint;
}

state_var index(std::size_t i){
return state_var(this->W(i));
}
};

template<typename BlueprintFieldType>
using plonk_index_selector =
index_selector<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>,
BlueprintFieldType>;

template<typename BlueprintFieldType>
typename plonk_index_selector<BlueprintFieldType>::result_type generate_assignments(
const plonk_index_selector<BlueprintFieldType> &component,
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>>
&assignment,
const typename plonk_index_selector<BlueprintFieldType>::input_type
&instance_input,
const std::uint32_t start_row_index) {

using component_type = plonk_index_selector<BlueprintFieldType>;
using value_type = typename BlueprintFieldType::value_type;
using integral_type = typename BlueprintFieldType::integral_type;

std::size_t index = instance_input.index;
//if( index >= component.options_amount ) std::cout << index << ">=" << component.options_amount << std::endl;
BOOST_ASSERT(index < component.options_amount);

// calculating this is somehow very unintuitive
std::size_t option_WA = component.witness_amount() - 1;

const integral_type parity = index & 1; // index%2

for (std::size_t i = 1; i < component.witness_amount() - 1; i++) { // zerofy all
assignment.witness(component.W(i), start_row_index) = 0;
}
assignment.witness(component.W(index), start_row_index) = 1;

return typename component_type::result_type(component, start_row_index);
}

template<typename BlueprintFieldType>
std::size_t generate_gates(
const plonk_index_selector<BlueprintFieldType> &component,
circuit<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>> &bp,
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>>
&assignment,
const typename plonk_index_selector<BlueprintFieldType>::input_type
&instance_input) {

return bp.add_gate(component.generate_constraints());
}

template<typename BlueprintFieldType>
typename plonk_index_selector<BlueprintFieldType>::result_type generate_circuit(
const plonk_index_selector<BlueprintFieldType> &component,
circuit<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>> &bp,
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>>
&assignment,
const typename plonk_index_selector<BlueprintFieldType>::input_type
&instance_input,
const std::size_t start_row_index) {

using component_type = plonk_index_selector<BlueprintFieldType>;
using state_var = state_var<BlueprintFieldType>;

std::size_t selector_index = generate_gates(component, bp, assignment, instance_input);
assignment.enable_selector(selector_index, start_row_index, start_row_index);

return typename component_type::result_type(component, start_row_index);
}

} // namespace components
} // namespace blueprint
} // namespace nil
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ namespace nil {
using value_type = typename BlueprintFieldType::value_type;
using var = typename op_type::var;

zkevm_add_sub_operation(bool _is_add) : is_add(_is_add) {}
zkevm_add_sub_operation(bool _is_add) : is_add(_is_add) {
this->stack_input = 2;
this->stack_output = 1;
}

bool is_add;

Expand Down Expand Up @@ -126,8 +129,8 @@ namespace nil {
return {{gate_class::MIDDLE_OP, {constraints, {}}}};
}

void generate_assignments(zkevm_table_type &zkevm_table, zkevm_machine_interface &machine) override {
zkevm_stack &stack = machine.stack;
void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
zkevm_stack stack = machine.stack;
using word_type = typename zkevm_stack::word_type;
word_type a = stack.pop();
word_type b = stack.pop();
Expand Down
10 changes: 8 additions & 2 deletions libs/blueprint/include/nil/blueprint/zkevm/operations/addmod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ namespace nil {
constexpr static const value_type two128 = 0x100000000000000000000000000000000_cppui_modular254;
constexpr static const value_type two192 = 0x1000000000000000000000000000000000000000000000000_cppui_modular254;

zkevm_addmod_operation(){
this->stack_input = 3;
this->stack_output = 1;
this->gas_cost = 8;
}

template<typename T, typename V = T>
T chunk_sum_64(const std::vector<V> &chunks, const unsigned char chunk_idx) const {
BOOST_ASSERT(chunk_idx < 4);
Expand Down Expand Up @@ -318,12 +324,12 @@ namespace nil {
return { {gate_class::MIDDLE_OP, {constraints, {} }} };
}

void generate_assignments(zkevm_table_type &zkevm_table, zkevm_machine_interface &machine) override {
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 = boost::multiprecision::number<
boost::multiprecision::backends::cpp_int_modular_backend<257>>;

zkevm_stack &stack = machine.stack;
zkevm_stack stack = machine.stack;

word_type a = stack.pop();
word_type b = stack.pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ namespace nil {
using value_type = typename BlueprintFieldType::value_type;
using var = typename op_type::var;

zkevm_bitwise_operation(bitwise_type _bit_operation) : bit_operation(_bit_operation) {}
zkevm_bitwise_operation(bitwise_type _bit_operation) : bit_operation(_bit_operation) {
this->stack_input = 2;
this->stack_output = 1;
}

bitwise_type bit_operation;

Expand Down Expand Up @@ -100,8 +103,8 @@ namespace nil {
return { {gate_class::MIDDLE_OP, {constraints, lookup_constraints}} };
}

void generate_assignments(zkevm_table_type &zkevm_table, zkevm_machine_interface &machine) override {
zkevm_stack &stack = machine.stack;
void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
zkevm_stack stack = machine.stack;
using word_type = typename zkevm_stack::word_type;
using integral_type = typename BlueprintFieldType::integral_type;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ namespace nil {
using value_type = typename BlueprintFieldType::value_type;
using var = typename op_type::var;

zkevm_byte_operation(){
this->stack_input = 2;
this->stack_output = 1;
}

std::map<gate_class, std::pair<
std::vector<std::pair<std::size_t, constraint_type>>,
std::vector<std::pair<std::size_t, lookup_constraint_type>>
Expand Down Expand Up @@ -124,8 +129,8 @@ namespace nil {
return {{gate_class::MIDDLE_OP, {constraints, lookup_constraints}}};
}

void generate_assignments(zkevm_table_type &zkevm_table, zkevm_machine_interface &machine) override {
zkevm_stack &stack = machine.stack;
void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
zkevm_stack stack = machine.stack;
using word_type = typename zkevm_stack::word_type;
using integral_type = boost::multiprecision::number<
boost::multiprecision::backends::cpp_int_modular_backend<257>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ namespace nil {
using value_type = typename BlueprintFieldType::value_type;
using var = typename op_type::var;

zkevm_calldataload_operation() {}
zkevm_calldataload_operation() {
this->stack_input = 1;
this->stack_output = 1;
}

constexpr static const value_type two_16 = 65536;
constexpr static const value_type two_32 = 4294967296;
Expand All @@ -66,8 +69,8 @@ namespace nil {
return {{gate_class::MIDDLE_OP, {{}, {}}}};
}

void generate_assignments(zkevm_table_type &zkevm_table, zkevm_machine_interface &machine) override {
zkevm_stack &stack = machine.stack;
void generate_assignments(zkevm_table_type &zkevm_table, const zkevm_machine_interface &machine) override {
zkevm_stack stack = machine.stack;
std::cout << "Generate assignments and gates for CALLDATALOAD" << std::endl;
stack.push(0);
}
Expand Down
Loading

0 comments on commit 3d3e45d

Please sign in to comment.