Skip to content

Commit

Permalink
Moved large function from lookup_argument to constraint_system, fixed…
Browse files Browse the repository at this point in the history
… bug in evaluation points#320
  • Loading branch information
ETatuzova committed Apr 23, 2024
1 parent dc5a738 commit 3f607e0
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,58 @@ namespace nil {
}


std::vector<std::size_t> lookup_parts(
std::size_t max_quotient_chunks
) const {
if( max_quotient_chunks == 0 ){
return {this->sorted_lookup_columns_number()};
}

using VariableType = plonk_variable<typename FieldType::value_type>;
typedef math::expression_max_degree_visitor<VariableType> degree_visitor_type;
std::vector<std::size_t> lookup_parts;
degree_visitor_type lookup_visitor;

std::size_t lookup_chunk = 0;
std::size_t lookup_part = 0;
std::size_t max_constraint_degree;
for (const auto& gate :_lookup_gates) {
for (const auto& constr : gate.constraints) {
max_constraint_degree = 0;
for (const auto& li : constr.lookup_input) {
std::size_t deg = lookup_visitor.compute_max_degree(li);
max_constraint_degree = std::max(
max_constraint_degree,
deg
);
}
if( lookup_chunk + max_constraint_degree + 1>= max_quotient_chunks ){
lookup_parts.push_back(lookup_part);
lookup_chunk = 0;
lookup_part = 0;
}
// +1 because lookup input is multiplied by selector
lookup_chunk += max_constraint_degree + 1;
lookup_part++;
}
}
for (const auto& table : _lookup_tables) {
for( const auto &lookup_options: table.lookup_options ){
// +3 because now any lookup option is lookup_column * lookup_selector * (1-q_last-q_blind) -- three polynomials degree rows_amount-1
if( lookup_chunk + 3 >= max_quotient_chunks ){
lookup_parts.push_back(lookup_part);
lookup_chunk = 0;
lookup_part = 0;
}
lookup_chunk += 3;
lookup_part++;
}
}

lookup_parts.push_back(lookup_part);
return lookup_parts;
}

bool operator==(const plonk_constraint_system<FieldType> &other) const {
return (this->_gates == other._gates) && (this->_copy_constraints == other._copy_constraints) &&
(this->_lookup_gates == other._lookup_gates) && (this->_lookup_tables == other._lookup_tables) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,61 +50,41 @@ namespace nil {
}
plonk_variable<typename FieldType::value_type> first;
plonk_variable<typename FieldType::value_type> second;
bool operator==(const plonk_copy_constraint<FieldType> &other){
return ((first == other.first ) && (second == other.second));
}
protected:
void initialize(
const plonk_variable<typename FieldType::value_type> &_first,
const plonk_variable<typename FieldType::value_type> &_second
){
BOOST_ASSERT(_first.relative == false);
BOOST_ASSERT(_second.relative == false);
if(_first.type == _second.type){
if(_first.index < _second.index){
first = plonk_variable<typename FieldType::value_type>(_first);
second = plonk_variable<typename FieldType::value_type>(_second);
} else if (_first.index > _second.index){
first = plonk_variable<typename FieldType::value_type>(_second);
second = plonk_variable<typename FieldType::value_type>(_first);
} else if (_first.rotation < _second.rotation){
first = plonk_variable<typename FieldType::value_type>(_first);
second = plonk_variable<typename FieldType::value_type>(_second);
} else if (_first.rotation > _second.rotation){
first = plonk_variable<typename FieldType::value_type>(_second);
second = plonk_variable<typename FieldType::value_type>(_first);
} else {
BOOST_ASSERT_MSG(false, "Copy constraint with equal variables");
}
return;
}
if( _first.type == plonk_variable<typename FieldType::value_type>::column_type::witness){
first = plonk_variable<typename FieldType::value_type>(_first);
second = plonk_variable<typename FieldType::value_type>(_second);
} else if (
_first.type == plonk_variable<typename FieldType::value_type>::column_type::public_input &&
_second.type != plonk_variable<typename FieldType::value_type>::column_type::witness
){
first = plonk_variable<typename FieldType::value_type>(_first);
second = plonk_variable<typename FieldType::value_type>(_second);
} else if(
_first.type == plonk_variable<typename FieldType::value_type>::column_type::constant &&
_second.type == plonk_variable<typename FieldType::value_type>::column_type::selector
){
first = plonk_variable<typename FieldType::value_type>(_first);
second = plonk_variable<typename FieldType::value_type>(_second);
if( _first.relative || _second.relative ) std::cout << "Relative variable " << _first << " " << _second << std::endl;
if( _first == _second ) std::cout << "First == second " << _first << " " << _second << std::endl;
BOOST_ASSERT_MSG( _first != _second, "First and second variables are equal" );
BOOST_ASSERT_MSG( _first.relative == false, "First variable in copy constraint is relative" );
BOOST_ASSERT_MSG( _second.relative == false, "Second variable in copy constraint is relative" );

if(_first < _second ){
first = _first;
second = _second;
} else {
first = plonk_variable<typename FieldType::value_type>(_second);
second = plonk_variable<typename FieldType::value_type>(_first);
first = _second;
second = _first;
}
return;
}
};

template <typename FieldType>
bool operator==(const plonk_copy_constraint<FieldType> &a, const plonk_copy_constraint<FieldType> &b) {
return a.first == b.first && a.second == b.second;
}

template <typename FieldType>
bool operator!=(const plonk_copy_constraint<FieldType> &a, const plonk_copy_constraint<FieldType> &b) {
return !(a == b);
}

template <typename FieldType>
bool operator<(const plonk_copy_constraint<FieldType> &a, const plonk_copy_constraint<FieldType> &b) {
return a.first < b.first || (a.first == b.first && a.second < b.second);
}
} // namespace snark
} // namespace zk
} // namespace crypto3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

#include <nil/crypto3/math/algorithms/make_evaluation_domain.hpp>
#include <nil/crypto3/zk/snark/systems/plonk/placeholder/params.hpp>
#include <nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp>
#include <nil/crypto3/zk/commitments/type_traits.hpp>

namespace nil {
Expand All @@ -46,59 +45,148 @@ namespace nil {
// but it is not convenient to place it inside any of these classes.
//
// This piece of code is used in different projects with verifiers, and it's not good ot repeat it.
template <typename PlaceholderParams>
struct placeholder_info{
using variable_indices_type = std::map<nil::crypto3::zk::snark::plonk_variable<typename PlaceholderParams::field_type::value_type>, std::size_t>;

std::size_t batches_num;
std::vector<std::size_t> batches_sizes;
std::size_t poly_num;
std::size_t quotient_size;
std::size_t permutation_batch_size;
bool use_lookups;
bool use_permutations;

// Commitments order in placeholder proof
int variable_value_batch_order;
int permutation_batch_order;
int quotient_batch_order;
int lookup_batch_order;

// Polynomial_amount
std::size_t permutation_poly_amount;
std::size_t lookup_poly_amount;

std::size_t permutation_size;
std::size_t round_proof_layers_num;

variable_indices_type var_indices;
std::vector<std::size_t> permuted_zero_indices;
};


template<typename PlaceholderParams, typename enable = void>
placeholder_info prepare_placeholder_info();
placeholder_info<PlaceholderParams> prepare_placeholder_info();

// TODO remove permutation size
template<typename PlaceholderParams, std::enable_if_t<nil::crypto3::zk::is_lpc<typename PlaceholderParams::commitment_scheme_type>, bool> = true>
placeholder_info prepare_placeholder_info(
placeholder_info<PlaceholderParams> prepare_placeholder_info(
const typename PlaceholderParams::constraint_system_type &constraint_system,
const typename nil::crypto3::zk::snark::placeholder_public_preprocessor<typename PlaceholderParams::field_type, PlaceholderParams>::preprocessed_data_type::common_data_type &common_data,
const typename PlaceholderParams::commitment_scheme_type::params_type &fri_params,
std::size_t perm_size
const typename nil::crypto3::zk::snark::placeholder_public_preprocessor<typename PlaceholderParams::field_type, PlaceholderParams>::preprocessed_data_type::common_data_type &common_data
) {
placeholder_info<PlaceholderParams> res;
auto &desc = common_data.desc;
placeholder_info res;
auto &fri_params = common_data.commitment_params;

res.permutation_size = perm_size;
res.permutation_size = common_data.permuted_columns.size();
res.use_lookups = constraint_system.num_lookup_gates() != 0;
res.batches_num = res.use_lookups ? 5 : 4;
res.use_permutations = common_data.permuted_columns.size() != 0;

res.variable_value_batch_order = 0;
res.permutation_batch_order = res.use_lookups || res.use_permutations ? 1 : -1;
res.quotient_batch_order = res.use_lookups || res.use_permutations ? 2: 1;
res.lookup_batch_order = res.use_lookups? 3: -1;
std::cout << "Quotient batch order " << res.quotient_batch_order << std::endl;

res.batches_num = 3;
if( res.use_lookups || res.use_permutations ) res.batches_num++;
if( res.use_lookups ) res.batches_num++;

std::size_t cur = 0;
res.batches_sizes.resize(res.batches_num);
res.batches_sizes[0] = res.permutation_size * 2 + 2 + desc.constant_columns + desc.selector_columns;
res.batches_sizes[1] = desc.witness_columns + desc.public_input_columns;
res.batches_sizes[2] = res.use_lookups ? 2 : 1;
// TODO: place it to one single place to prevent code duplication
std::size_t split_polynomial_size = std::max(
(res.permutation_size + 2) * (desc.rows_amount -1 ),
(constraint_system.lookup_poly_degree_bound() + 1) * (desc.rows_amount -1 )//,
);
split_polynomial_size = std::max(
split_polynomial_size,
(common_data.max_gates_degree + 1) * (desc.rows_amount -1)
);
split_polynomial_size = (split_polynomial_size % desc.rows_amount != 0)?
(split_polynomial_size / desc.rows_amount + 1):
(split_polynomial_size / desc.rows_amount);
res.quotient_size = res.batches_sizes[3] = split_polynomial_size;
if(res.use_lookups) res.batches_sizes[4] = constraint_system.sorted_lookup_columns_number();
res.batches_sizes[cur++] = res.permutation_size * 2 + 2 + desc.constant_columns + desc.selector_columns;
res.batches_sizes[cur++] = desc.witness_columns + desc.public_input_columns;

std::size_t full_permutation_polynomial_size = res.use_permutations? (res.permutation_size + 2) : 0;
std::size_t full_lookup_polynomial_size = res.use_lookups? (constraint_system.lookup_poly_degree_bound() + 1) : 0;
std::size_t full_gate_polynomial_size = (common_data.max_gates_degree + 1);
std::size_t max_quotient_size = std::max(full_permutation_polynomial_size, full_lookup_polynomial_size);
max_quotient_size = std::max(max_quotient_size, full_gate_polynomial_size);
res.permutation_batch_size = 0;
res.permutation_poly_amount = res.use_permutations? 1: 0;
res.lookup_poly_amount = res.use_lookups? 1: 0;
if( res.use_lookups || res.use_permutations ){
res.permutation_batch_size = res.use_lookups ? 2 : 1;
if( common_data.max_quotient_chunks > 0 ){
res.permutation_batch_size += full_permutation_polynomial_size/common_data.max_quotient_chunks;
res.permutation_batch_size += full_lookup_polynomial_size/common_data.max_quotient_chunks;
res.permutation_poly_amount += full_permutation_polynomial_size/common_data.max_quotient_chunks;
res.lookup_poly_amount += full_lookup_polynomial_size/common_data.max_quotient_chunks;
}
res.batches_sizes[cur++] = res.permutation_batch_size;
}

max_quotient_size *= (desc.rows_amount - 1);
max_quotient_size = max_quotient_size % desc.rows_amount == 0 ? max_quotient_size / desc.rows_amount : max_quotient_size / desc.rows_amount + 1 ;
if( common_data.max_quotient_chunks == 0 ){
res.quotient_size = res.batches_sizes[cur++] = max_quotient_size;
} else {
res.quotient_size = res.batches_sizes[cur++] = max_quotient_size < common_data.max_quotient_chunks? max_quotient_size: common_data.max_quotient_chunks;
}

if(res.use_lookups) res.batches_sizes[cur++] = constraint_system.sorted_lookup_columns_number();
res.poly_num = std::accumulate(res.batches_sizes.begin(), res.batches_sizes.end(), 0);

res.round_proof_layers_num = 0;
for(std::size_t i = 0; i < fri_params.r; i++ ){
res.round_proof_layers_num += log2(fri_params.D[i]->m) -1;
}

// variable indices
using variable_type = nil::crypto3::zk::snark::plonk_variable<typename PlaceholderParams::field_type::value_type>;
auto &col_rotations = common_data.columns_rotations;
std::size_t j = 0;

std::map<std::size_t, std::size_t> zero_indices;

for(std::size_t i = 0; i < common_data.desc.constant_columns; i++){
for(auto& rot: col_rotations[i + common_data.desc.witness_columns + common_data.desc.public_input_columns]){
variable_type v(i, rot, true, variable_type::column_type::constant);
res.var_indices[v] = j;
if( rot == 0 ) zero_indices[i + common_data.desc.witness_columns + common_data.desc.public_input_columns] = j;
j++;
}
}
for(std::size_t i = 0; i < common_data.desc.selector_columns; i++){
for(auto& rot: col_rotations[i + common_data.desc.witness_columns + common_data.desc.public_input_columns + common_data.desc.constant_columns]){
variable_type v(i, rot, true, variable_type::column_type::selector);
res.var_indices[v] = j;
if( rot == 0) zero_indices[i + common_data.desc.witness_columns + common_data.desc.public_input_columns + common_data.desc.constant_columns] = j;
j++;
}
}
for(std::size_t i = 0; i < common_data.desc.witness_columns; i++){
for(auto& rot: col_rotations[i]){
variable_type v(i, rot, true, variable_type::column_type::witness);
res.var_indices[v] = j;
if(rot == 0) zero_indices[i] = j;
j++;
}
}
for(std::size_t i = 0; i < common_data.desc.public_input_columns; i++){
for(auto& rot: col_rotations[i + common_data.desc.witness_columns]){
variable_type v(i, rot, true, variable_type::column_type::public_input);
res.var_indices[v] = j;
if(rot == 0) zero_indices[i + common_data.desc.witness_columns] = j;
j++;
}
}

for( std::size_t i = 0; i < common_data.permuted_columns.size(); i++ ){
std::size_t ind = common_data.permuted_columns[i];
res.permuted_zero_indices.push_back(zero_indices[ind]);
}

return res;
}

Expand Down
Loading

0 comments on commit 3f607e0

Please sign in to comment.