From 1b5f327c2581ff33d387691d73f32c7e7665065c Mon Sep 17 00:00:00 2001 From: Vasiliy Olekhov <145333445+vo-nil@users.noreply.github.com> Date: Thu, 7 Dec 2023 07:34:04 +0200 Subject: [PATCH] 46 check values in etha point (#55) * Commitents is in input file #39 * Placeholder verifier random values generation #39 * Recursive verifier template and basic generator added #39 * Basic placeholder verifier done #39 * U and V #39 * Lookups #39 * Pow operation optimized #39 * Merkle proofs #39 * Some changes for actor-zk-compatibility #39 * Pow operation optimized #39 * Pow function updated. Specialized pow functions for small degrees hardcoded #39 * Work with eta points updated and commented #39 * prepare_U_and_V optimized #39 * Optimize row count for combinedQ computation #39 * Bug in pow2 function #39 * remove utils.sol if no helper functions generated #45 NilFoundation/evm-placeholder-verification#81 * Added check values for eta points #46 * Reworked checking values to keccak of blob #46 * Correct keccak computation #46 * Code cleanup #46 * Removed recursive tests * Tests are now working #46 --------- Co-authored-by: e.tatuzova --- .../blueprint/transpiler/evm_verifier_gen.hpp | 104 +- .../blueprint/transpiler/lpc_scheme_gen.hpp | 16 +- .../recursive_verifier_generator.hpp | 929 ++++++++++++++++++ .../templates/commitment_scheme.hpp | 2 +- .../templates/recursive_verifier.hpp | 800 +++++++++++++++ include/nil/blueprint/transpiler/util.hpp | 18 +- test/detail/circuits.hpp | 476 ++++----- test/transpiler.cpp | 681 ++++++++++++- 8 files changed, 2650 insertions(+), 376 deletions(-) create mode 100644 include/nil/blueprint/transpiler/recursive_verifier_generator.hpp create mode 100644 include/nil/blueprint/transpiler/templates/recursive_verifier.hpp diff --git a/include/nil/blueprint/transpiler/evm_verifier_gen.hpp b/include/nil/blueprint/transpiler/evm_verifier_gen.hpp index b4c364d..4493be0 100644 --- a/include/nil/blueprint/transpiler/evm_verifier_gen.hpp +++ b/include/nil/blueprint/transpiler/evm_verifier_gen.hpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include @@ -44,12 +44,16 @@ #include #include +#include +#include +#include + namespace nil { namespace blueprint { template class evm_verifier_printer{ using common_data_type = typename nil::crypto3::zk::snark::placeholder_public_preprocessor< - typename PlaceholderParams::field_type, + typename PlaceholderParams::field_type, PlaceholderParams >::preprocessed_data_type::common_data_type; @@ -153,7 +157,7 @@ namespace nil { std::size_t term_is_power(crypto3::math::term const& term) { const auto &vars = term.get_vars(); auto var = std::cbegin(vars); - + if (var == std::cend(vars)) return 0; @@ -287,7 +291,7 @@ namespace nil { std::size_t lookups_library_size_threshold = 1000, std::size_t lookups_contract_size_threshold = 1000, bool deduce_horner = true, - bool optimize_powers = true + bool optimize_powers = true ) : _constraint_system(constraint_system), _common_data(common_data), @@ -447,7 +451,7 @@ namespace nil { } /** @brief Split items into buckets, each bucket is limited - * to max_bucket_size, minimizes number of buckets. + * to max_bucket_size, minimizes number of buckets. * items must be sorted * @param[in] items (item_id, item_size) * @param[in] max_bucket_size @@ -561,7 +565,7 @@ namespace nil { std::unordered_map gate_codes; std::vector> gate_costs(gates_count); std::vector gate_ids(gates_count); - + std::vector constraints; std::size_t total_cost = 0; @@ -584,8 +588,6 @@ namespace nil { std::size_t gate_modules_count = 0; - - std::size_t current_selector = 0; if (total_cost <= _gates_contract_size_threshold) { auto it = constraints.begin(); @@ -594,8 +596,10 @@ namespace nil { gate_argument_str << "\t\tuint256 gate;" << std::endl; gate_argument_str << print_constraint_series(it, constraints.end()); } else { + std::cout << "I am here!" << std::endl; auto it = constraints.begin(); while (it != constraints.end()) { + std::cout << "Gates modules count" << gate_modules_count << std::endl; std::string code = print_constraint_series(it, constraints.end()); std::string result = modular_external_gate_library_template; @@ -615,6 +619,7 @@ namespace nil { ++gate_modules_count; } } + std::cout << "Finished" << std::endl; if (_term_powers.size() > 0) { std::stringstream power_functions; @@ -752,23 +757,23 @@ namespace nil { lookup_str << "\t\t\tstate.shifted_selector_value = basic_marshalling.get_uint256_be(blob, " << _var_indices.at(shifted_sel_var) * 0x20 << ");" << std::endl; for( const auto &option: table.lookup_options ){ - lookup_str << + lookup_str << "\t\t\tl = mulmod( " << table_index << ", state.selector_value, modulus);" << std::endl; - lookup_str << + lookup_str << "\t\t\tstate.l_shifted = mulmod( " << table_index << ", state.shifted_selector_value, modulus);" << std::endl; lookup_str << "\t\t\tstate.theta_acc=state.theta;" << std::endl; for( const auto &var: option ){ - lookup_str << + lookup_str << "\t\t\tl = addmod( l, mulmod(state.selector_value, mulmod( state.theta_acc, basic_marshalling.get_uint256_be(blob, " << _var_indices.at(var) * 0x20 << "), modulus), modulus), modulus);" << std::endl; variable_type shifted_var = var; shifted_var.rotation = 1; - lookup_str << + lookup_str << "\t\t\tstate.l_shifted = addmod( state.l_shifted, mulmod(state.shifted_selector_value, mulmod( state.theta_acc, basic_marshalling.get_uint256_be(blob, " << _var_indices.at(shifted_var) * 0x20 << "), modulus), modulus), modulus);" << std::endl; lookup_str << "\t\t\tstate.theta_acc = mulmod(state.theta_acc, state.theta, modulus);" << std::endl; } - lookup_str << + lookup_str << "\t\t\tl = mulmod( l, state.mask, modulus);" << std::endl; - lookup_str << + lookup_str << "\t\t\tstate.l_shifted = mulmod( state.l_shifted, state.shifted_mask, modulus);" << std::endl; lookup_str << "\t\t\tstate.g = mulmod(state.g, addmod( state.factor, addmod(l, mulmod(state.beta, state.l_shifted, modulus), modulus), modulus), modulus);" << std::endl; j++; @@ -783,63 +788,98 @@ namespace nil { std::string eta_point_verification_code() { std::stringstream result; auto fixed_poly_values = _common_data.commitment_scheme_data; - - std::size_t poly_points = 2; - + using eta_hash = crypto3::hashes::keccak_1600<256>; + using field_element_type = nil::crypto3::marshalling::types::field_element< + nil::marshalling::field_type, + typename PlaceholderParams::field_type::value_type>; + if (fixed_poly_values.size() == 0) return ""; - + + std::vector eta_buf; + + std::size_t poly_points = 2*_permutation_size; + /* special_selectors */ + poly_points += 2; + poly_points += PlaceholderParams::arithmetization_params::constant_columns; + poly_points += PlaceholderParams::arithmetization_params::selector_columns; + eta_buf.resize( 32*poly_points ); + + std::array empty; + auto writer = eta_buf.begin(); + + result << "\t\t/* eta points check */" << std::endl; result << "\t\t{" << std::endl; - result << "\t\t\tuint256 poly_at_eta;" << std::endl; + result << "\t\t\tuint256[" << poly_points << "] memory points;" << std::endl; - result << "\t\t\t/* 1 - 2*permutation_size */" << std::endl; std::size_t i = 0, j = 0; std::size_t point_offset = 8; + + result << std::showbase << std::hex; + + result << "\t\t\t/* 1. 2*permutation_size */" << std::endl; + poly_points = 2; + while (j < 2*_permutation_size) { - result << "\t\t\tpoly_at_eta = basic_marshalling.get_uint256_be(blob, " << point_offset+(poly_points-1)*32 << ");" << "// " << i << std::endl; - result << "\t\t\tif(poly_at_eta != " << std::showbase<< std::hex << fixed_poly_values[0][i] << ") return false;" << std::endl; + result << "\t\t\tpoints[" << i << "] = basic_marshalling.get_uint256_be(blob,"; + result << point_offset + (poly_points-1)*32 << ");" << std::endl; + field_element_type value(fixed_poly_values[0][i]); + value.write(writer, 32); point_offset += 32*poly_points; ++i; ++j; } - result << "\t\t\t/* 2 - special selectors */" << std::endl; + result << "\t\t\t/* 2. special selectors */" << std::endl; poly_points = 3; + j = 0; while (j < 2) { - result << "\t\t\tpoly_at_eta = basic_marshalling.get_uint256_be(blob, " << point_offset+(poly_points-1)*32 << ");" << "// " << i << std::endl; - result << "\t\t\tif(poly_at_eta != " << std::showbase<< std::hex << fixed_poly_values[0][i] << ") return false;" << std::endl; + result << "\t\t\tpoints[" << i << "] = basic_marshalling.get_uint256_be(blob,"; + result << point_offset + (poly_points-1)*32 << ");" << std::endl; + field_element_type value(fixed_poly_values[0][i]); + value.write(writer, 32); point_offset += 32*poly_points; ++i; ++j; } + result << "\t\t\t/* 3. constant columns */" << std::endl; std::size_t column_rotation_offset = PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns; - result << "\t\t\t/* 3 - constant columns */" << std::endl; j = 0; while (j < PlaceholderParams::arithmetization_params::constant_columns) { poly_points = _common_data.columns_rotations[column_rotation_offset + j].size()+1; - result << "\t\t\tpoly_at_eta = basic_marshalling.get_uint256_be(blob, " << point_offset+(poly_points-1)*32 << ");" << "// " << i << std::endl; - result << "\t\t\tif(poly_at_eta != " << std::showbase<< std::hex << fixed_poly_values[0][i] << ") return false;" << std::endl; + result << "\t\t\tpoints[" << i << "] = basic_marshalling.get_uint256_be(blob,"; + result << point_offset + (poly_points-1)*32 << ");" << std::endl; + field_element_type value(fixed_poly_values[0][i]); + value.write(writer, 32); point_offset += 32*poly_points; ++i; ++j; } - result << "\t\t\t/* 4 - selector columns */" << std::endl; - column_rotation_offset = PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns + PlaceholderParams::constant_columns; + result << "\t\t\t/* 4. selector columns */" << std::endl; + column_rotation_offset += PlaceholderParams::constant_columns; j = 0; while (j < PlaceholderParams::arithmetization_params::selector_columns) { poly_points = _common_data.columns_rotations[column_rotation_offset + j].size()+1; - result << "\t\t\tpoly_at_eta = basic_marshalling.get_uint256_be(blob, " << point_offset+(poly_points-1)*32 << ");" << "// " << i << std::endl; - result << "\t\t\tif(poly_at_eta != " << std::showbase<< std::hex << fixed_poly_values[0][i] << ") return false;" << std::endl; + result << "\t\t\tpoints[" << i << "] = basic_marshalling.get_uint256_be(blob,"; + result << point_offset + (poly_points-1)*32 << ");" << std::endl; + field_element_type value(fixed_poly_values[0][i]); + value.write(writer, 32); point_offset += 32*(poly_points); ++i; ++j; } + eta_hash::digest_type hash_result = crypto3::hash(eta_buf); + result << "\t\t\t/* Check keccak(points) */" << std::endl; + result << "\t\t\tif ( bytes32(0x" << std::to_string(hash_result).data() << ") != keccak256(abi.encode(points))) {" << std::endl; + result << "\t\t\t\treturn false;" << std::endl; + result << "\t\t\t}" << std::endl; result << "\t\t}" << std::endl; + return result.str(); } diff --git a/include/nil/blueprint/transpiler/lpc_scheme_gen.hpp b/include/nil/blueprint/transpiler/lpc_scheme_gen.hpp index a13f1f6..ce60ecf 100644 --- a/include/nil/blueprint/transpiler/lpc_scheme_gen.hpp +++ b/include/nil/blueprint/transpiler/lpc_scheme_gen.hpp @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include @@ -40,21 +40,21 @@ namespace nil { namespace blueprint { template using common_data_type = typename nil::crypto3::zk::snark::placeholder_public_preprocessor< - typename PlaceholderParams::field_type, + typename PlaceholderParams::field_type, PlaceholderParams >::preprocessed_data_type::common_data_type; - + std::string rot_string (int j){ - if(j == 0) return "xi"; else - if(j == 1 ) return "mulmod(xi, omega, modulus)"; else - if(j == -1) return "mulmod(xi, inversed_omega, modulus)"; else + if(j == 0) return "xi"; else + if(j == 1 ) return "mulmod(xi, omega, modulus)"; else + if(j == -1) return "mulmod(xi, inversed_omega, modulus)"; else if(j > 0) return "mulmod(xi, field.pow_small(omega, " + to_string(j) + ", modulus), modulus)"; else if(j < 0) return "mulmod(xi, field.pow_small(inversed_omega, " + to_string(-j) + ", modulus), modulus)"; return ""; } - template + template void commitment_scheme_replaces( transpiler_replacements& replacements, const common_data_type &common_data, @@ -160,7 +160,7 @@ namespace nil { transcript(common_data.vk.constraint_system_hash); transcript(common_data.vk.fixed_values_commitment); auto etha = transcript.template challenge(); - + auto fri_params = lpc_scheme.get_fri_params(); replacements["$R$"] = to_string(fri_params.r); replacements["$LAMBDA$"] = to_string(PlaceholderParams::commitment_scheme_type::fri_type::lambda); diff --git a/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp b/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp new file mode 100644 index 0000000..dc7896d --- /dev/null +++ b/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp @@ -0,0 +1,929 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2023 Elena Tatuzova +// +// 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. +//---------------------------------------------------------------------------// +// @file Declaration of interfaces for PLONK unified addition component. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_RECURSIVE_VERIFIER_GENERATOR_HPP +#define CRYPTO3_RECURSIVE_VERIFIER_GENERATOR_HPP + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +namespace nil { + namespace blueprint { + template + struct recursive_verifier_generator{ + using field_type = typename PlaceholderParams::field_type; + using arithmetization_params = typename PlaceholderParams::arithmetization_params; + using proof_type = ProofType; + using common_data_type = CommonDataType; + using verification_key_type = typename common_data_type::verification_key_type; + using commitment_scheme_type = typename PlaceholderParams::commitment_scheme_type; + using constraint_system_type = typename PlaceholderParams::constraint_system_type; + using columns_rotations_type = std::array, PlaceholderParams::total_columns>; + using variable_type = typename constraint_system_type::variable_type; + using variable_indices_type = std::map; + using degree_visitor_type = typename constraint_system_type::degree_visitor_type; + using expression_type = typename constraint_system_type::expression_type; + using term_type = typename constraint_system_type::term_type; + using binary_operation_type = typename constraint_system_type::binary_operation_type; + using pow_operation_type = typename constraint_system_type::pow_operation_type; + + // TODO: Move logic to utils.hpp. It's similar to EVM verifier generator + static std::string zero_indices(columns_rotations_type col_rotations){ + std::vector zero_indices; + std::uint16_t fixed_values_points = 0; + std::stringstream result; + + for(std::size_t i= 0; i < PlaceholderParams::constant_columns + PlaceholderParams::selector_columns; i++){ + fixed_values_points += col_rotations[i + PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns].size() + 1; + } + + for(std::size_t i= 0; i < PlaceholderParams::total_columns; i++){ + std::size_t j = 0; + for(auto& rot: col_rotations[i]){ + if(rot == 0){ + zero_indices.push_back(j); + break; + } + j++; + } + } + + std::uint16_t sum = fixed_values_points; + std::size_t i = 0; + for(; i < PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns; i++){ + zero_indices[i] = sum + zero_indices[i]; + sum += col_rotations[i].size(); + if( i != 0) result << ", "; + result << zero_indices[i]; + } + + sum = 0; + for(; i < PlaceholderParams::total_columns; i++){ + zero_indices[i] = sum + zero_indices[i]; + sum += col_rotations[i].size() + 1; + if( i != 0) result << ", "; + result << zero_indices[i]; + } + return result.str(); + } + + static std::string generate_field_array2_from_64_hex_string(std::string str){ + BOOST_ASSERT_MSG(str.size() == 64, "input string must be 64 hex characters long"); + std::string first_half = str.substr(0, 32); + std::string second_half = str.substr(32, 32); + return "{\"vector\": [{\"field\": \"0x" + first_half + "\"},{\"field\": \"0x" + second_half + "\"}]}"; + } + + template + static inline std::string generate_hash(typename HashType::digest_type hashed_data){ + if constexpr(std::is_same>::value){ + std::stringstream out; + out << hashed_data; + return generate_field_array2_from_64_hex_string(out.str()); + } else if constexpr(nil::crypto3::hashes::is_poseidon::value){ + //std::cout << "Poseidon" << std::endl + std::stringstream out; + out << "{\"field\": \"" << hashed_data << "\"}"; + return out.str(); + } else if constexpr(std::is_same>::value){ + return "keccak\n"; + } + BOOST_ASSERT_MSG(false, "unsupported merkle hash type"); + return "unsupported merkle hash type"; + } + + template + static inline std::string generate_commitment(typename CommitmentSchemeType::commitment_type commitment) { + return generate_hash(commitment); + } + + static inline std::string generate_lookup_options_amount_list( + const constraint_system_type &constraint_system + ) { + std::string result; + for(std::size_t i = 0; i < constraint_system.lookup_tables().size(); i++){ + if( i != 0 ) result += ", "; + result += to_string(constraint_system.lookup_tables()[i].lookup_options.size()); + } + return result; + } + + static inline std::string generate_lookup_columns_amount_list( + const constraint_system_type &constraint_system + ) { + std::string result; + for(std::size_t i = 0; i < constraint_system.lookup_tables().size(); i++){ + if( i != 0 ) result += ", "; + result += to_string(constraint_system.lookup_tables()[i].lookup_options[0].size()); + } + return result; + } + + static inline std::string generate_lookup_constraints_amount_list( + const constraint_system_type &constraint_system + ) { + std::string result; + for(std::size_t i = 0; i < constraint_system.lookup_gates().size(); i++){ + if( i != 0 ) result += ", "; + result += to_string(constraint_system.lookup_gates()[i].constraints.size()); + } + return result; + } + + static inline std::string generate_lookup_constraint_table_ids_list( + const constraint_system_type &constraint_system + ){ + std::string result; + for(std::size_t i = 0; i < constraint_system.lookup_gates().size(); i++){ + for(std::size_t j = 0; j < constraint_system.lookup_gates()[i].constraints.size(); j++){ + if( i != 0 || j!=0 ) result += ", "; + result += to_string(constraint_system.lookup_gates()[i].constraints[j].table_id); + } + } + return result; + } + + static inline std::string generate_lookup_expressions_amount_list( + const constraint_system_type &constraint_system + ) { + std::string result; + for(std::size_t i = 0; i < constraint_system.lookup_gates().size(); i++){ + for(std::size_t j = 0; j < constraint_system.lookup_gates()[i].constraints.size(); j++){ + if( i != 0 || j != 0) result += ", "; + result += to_string(constraint_system.lookup_gates()[i].constraints[j].lookup_input.size()); + } + } + return result; + } + + static inline std::string generate_lookup_expressions_computation( + const constraint_system_type &constraint_system + ){ + return ""; + } + + template + static inline std::string generate_eval_proof(typename CommitmentSchemeType::proof_type eval_proof) { + if( CommitmentSchemeType::lpc::use_grinding ){ + BOOST_ASSERT_MSG(false, "grinding is not supported"); + std::cout << "Grinding is not supported" << std::endl; + return "Grinding is not supported"; + } + + std::stringstream out; + out << "\t\t{\"array\":[" << std::endl; + auto batch_info = eval_proof.z.get_batch_info(); + std::size_t sum = 0; + std::size_t poly_num = 0; + for(const auto& [k, v]: batch_info){ + std::cout << "Batch " << k << " polynomials num = " << v << std::endl; + for(std::size_t i = 0; i < v; i++){ + poly_num++; + BOOST_ASSERT(eval_proof.z.get_poly_points_number(k, i) != 0); + for(std::size_t j = 0; j < eval_proof.z.get_poly_points_number(k, i); j++){ + if( sum != 0 ) out << "," << std::endl; + out << "\t\t\t{\"field\":\"" << eval_proof.z.get(k, i, j) << "\"}"; + //std::cout << "batch " << k << " poly " << i << " value " << eval_proof.z.get(k, i, j) << std::endl; + sum++; + } + } + std::cout << "Sum = " << sum << std::endl; + } + std::cout << "Polynomials num = "<< poly_num << std::endl; + std::cout << "Evaluations num = "<< sum << std::endl; + out << std::endl << "\t\t]}," << std::endl; + out << "\t\t{\"array\": [" << std::endl; + for( std::size_t i = 0; i < eval_proof.fri_proof.fri_roots.size(); i++){ + if(i != 0) out << "," << std::endl; + out << "\t\t\t" << generate_commitment( + eval_proof.fri_proof.fri_roots[i] + ); + } + out << std::endl << "\t\t]}," << std::endl; + out << "\t\t{\"array\": [" << std::endl; + std::size_t cur = 0; + for( std::size_t i = 0; i < eval_proof.fri_proof.query_proofs.size(); i++){ + for( const auto &[j, initial_proof]: eval_proof.fri_proof.query_proofs[i].initial_proof){ + for( std::size_t k = 0; k < initial_proof.values.size(); k++){ + if(cur != 0) out << "," << std::endl; + BOOST_ASSERT_MSG(initial_proof.values[k].size() == 1, "Unsupported step_list[0] value"); + out << "\t\t\t{\"field\":\"" << initial_proof.values[k][0][0] << "\"}," << std::endl; + out << "\t\t\t{\"field\":\"" << initial_proof.values[k][0][1] << "\"}"; + cur++; + cur++; + } + } + } + std::cout << "Initial points values = " << cur++ << std::endl; + out << std::endl << "\t\t]}," << std::endl; + out << "\t\t{\"array\": [" << std::endl; + cur = 0; + for( std::size_t i = 0; i < eval_proof.fri_proof.query_proofs.size(); i++){ + for( std::size_t j = 0; j < eval_proof.fri_proof.query_proofs[i].round_proofs.size(); j++){ + const auto &round_proof = eval_proof.fri_proof.query_proofs[i].round_proofs[j]; + if(cur != 0) out << "," << std::endl; + BOOST_ASSERT_MSG(round_proof.y.size() == 1, "Unsupported step_lis value"); + out << "\t\t\t{\"field\":\"" << round_proof.y[0][0] << "\"}," << std::endl; + out << "\t\t\t{\"field\":\"" << round_proof.y[0][1] << "\"}"; + cur++; + cur++; + } + } + std::cout << "Round proofs values num = " << cur << std::endl; + out << std::endl << "\t\t]}," << std::endl; + + std::cout << "Print initial merkle proofs for FRI" << std::endl; + out << "\t\t{\"array\": [" << std::endl; + cur = 0; + std::cout << "Print merkle proof" << std::endl; + for( std::size_t i = 0; i < eval_proof.fri_proof.query_proofs.size(); i++){ + for( const auto &[j, initial_proof]: eval_proof.fri_proof.query_proofs[i].initial_proof){ + for( std::size_t k = 0; k < initial_proof.p.path().size(); k++){ + if(cur != 0) out << "," << std::endl; + out << "\t\t\t{\"int\":" << initial_proof.p.path()[k][0].position() << "}"; + cur ++; + } + break; + } + } + out << std::endl << "\t\t]}," << std::endl; + + out << "\t\t{\"array\": [" << std::endl; + cur = 0; + for( std::size_t i = 0; i < eval_proof.fri_proof.query_proofs.size(); i++){ + for( const auto &[j, initial_proof]: eval_proof.fri_proof.query_proofs[i].initial_proof){ + for( std::size_t k = 0; k < initial_proof.p.path().size(); k++){ + if(cur != 0) out << "," << std::endl; + out << "\t\t\t" << generate_hash( + initial_proof.p.path()[k][0].hash() + ); + cur ++; + } + } + } + out << std::endl << "\t\t]}," << std::endl; + + + std::cout << "Print round merkle proofs for FRI" << std::endl; + out << "\t\t{\"array\": [" << std::endl; + cur = 0; + for( std::size_t i = 0; i < eval_proof.fri_proof.query_proofs.size(); i++){ + for( std::size_t j = 0; j < eval_proof.fri_proof.query_proofs[i].round_proofs.size(); j++){ + const auto& p = eval_proof.fri_proof.query_proofs[i].round_proofs[j].p; + for( std::size_t k = 0; k < p.path().size(); k++){ + if(cur != 0) out << "," << std::endl; + out << "\t\t\t{\"int\": " << p.path()[k][0].position() << "}"; + cur++; + } + } + } + out << std::endl << "\t\t]}," << std::endl; + + out << "\t\t{\"array\": [" << std::endl; + cur = 0; + for( std::size_t i = 0; i < eval_proof.fri_proof.query_proofs.size(); i++){ + for( std::size_t j = 0; j < eval_proof.fri_proof.query_proofs[i].round_proofs.size(); j++){ + const auto& p = eval_proof.fri_proof.query_proofs[i].round_proofs[j].p; + for( std::size_t k = 0; k < p.path().size(); k++){ + if(cur != 0) out << "," << std::endl; + out << "\t\t\t" << generate_hash( + p.path()[k][0].hash() + ); + cur++; + } + } + } + out << std::endl << "\t\t]}," << std::endl; + + std::cout << "Print final polynomial" << std::endl; + cur = 0; + out << "\t\t{\"array\": [" << std::endl; + for( std::size_t i = 0; i < eval_proof.fri_proof.final_polynomial.size(); i++){ + if(cur != 0) out << "," << std::endl; + out << "\t\t\t{\"field\": \"" << eval_proof.fri_proof.final_polynomial[i] << "\"}"; + cur++; + } + out << std::endl << "\t\t]}"; + + return out.str(); + BOOST_ASSERT_MSG(false, "unsupported commitment scheme type"); + return "unsupported commitment scheme type"; + } + + static inline std::string generate_input( + std::vector public_input, + const verification_key_type &vk, + const proof_type &proof + ){ + std::stringstream out; + out << "[" << std::endl; + + out << "\t{\"array\":[" << std::endl; + out << "\t\t" << generate_hash( + vk.constraint_system_hash + ) << "," << std::endl; + out << "\t\t" << generate_hash( + vk.fixed_values_commitment + ) << std::endl; + out << "\t]}," << std::endl; + + out << "\t{\"struct\":[" << std::endl; + out << "\t\t{\"array\":[" << std::endl; + out << "\t\t\t" << generate_commitment(proof.commitments.at(1))//(nil::crypto3::zk::snark::VARIABLE_VALUES_BATCH) + << "," << std::endl; + out << "\t\t\t" << generate_commitment( + proof.commitments.at(2))//(nil::crypto3::zk::snark::PERMUTATION_BATCH) + << "," << std::endl; + out << "\t\t\t" << generate_commitment( + proof.commitments.at(3)) // (nil::crypto3::zk::snark::QUOTIENT_BATCH) + ; + + if( proof.commitments.find(4) != proof.commitments.end() ){ /*nil::crypto3::zk::snark::LOOKUP_BATCH*/ + out << "," << std::endl << "\t\t\t" << generate_commitment( + proof.commitments.at(4) //nil::crypto3::zk::snark::LOOKUP_BATCH) + ); + } + out << std::endl; + + out << "\t\t]}," << std::endl; + out << "\t\t{\"field\": \"" << proof.eval_proof.challenge << "\"}," << std::endl; + out << generate_eval_proof( + proof.eval_proof.eval_proof + ) << std::endl; + out << "\t]}" << std::endl; + + out << "]" << std::endl; + return out.str(); + } + + // TODO move logic to utils.hpp to prevent code duplication + static inline variable_indices_type get_plonk_variable_indices(const columns_rotations_type &col_rotations, std::size_t start_index){ + std::map result; + std::size_t j = 0; + for(std::size_t i = 0; i < PlaceholderParams::constant_columns; i++){ + for(auto& rot: col_rotations[i + PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns]){ + variable_type v(i, rot, true, variable_type::column_type::constant); + result[v] = j + start_index; + j++; + } + j++; + } + for(std::size_t i = 0; i < PlaceholderParams::selector_columns; i++){ + for(auto& rot: col_rotations[i + PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns + PlaceholderParams::constant_columns]){ + variable_type v(i, rot, true, variable_type::column_type::selector); + result[v] = j + start_index; + j++; + } + j++; + } + for(std::size_t i = 0; i < PlaceholderParams::witness_columns; i++){ + for(auto& rot: col_rotations[i]){ + variable_type v(i, rot, true, variable_type::column_type::witness); + result[v] = j + start_index; + j++; + } + } + for(std::size_t i = 0; i < PlaceholderParams::public_input_columns; i++){ + for(auto& rot: col_rotations[i + PlaceholderParams::witness_columns]){ + variable_type v(i, rot, true, variable_type::column_type::public_input); + result[v] = j + start_index; + j++; + } + } + return result; + } + + template + class expression_gen_code_visitor : public boost::static_visitor { + const variable_indices_type &_indices; + public: + expression_gen_code_visitor(const variable_indices_type &var_indices) :_indices(var_indices){} + + std::string generate_expression(const expression_type& expr) { + return boost::apply_visitor(*this, expr.get_expr()); + } + + std::string operator()(const term_type& term) { + std::string result; + std::vector v; + if( term.get_coeff() != field_type::value_type::one() || term.get_vars().size() == 0) + v.push_back("pallas::base_field_type::value_type(0x" + to_hex_string(term.get_coeff()) + "_cppui255)"); + for(auto& var: term.get_vars()){ + v.push_back("z[" + to_string(_indices.at(var)) + "]"); + } + for(std::size_t i = 0; i < v.size(); i++){ + if(i != 0) result += " * "; + result += v[i]; + } + return result; + } + + std::string operator()( + const pow_operation_type& pow) { + std::string result = boost::apply_visitor(*this, pow.get_expr().get_expr()); + return "pow" + to_string(pow.get_power()) + "(" + result +")"; + } + + std::string operator()( + const binary_operation_type& op) { + std::string left = boost::apply_visitor(*this, op.get_expr_left().get_expr()); + std::string right = boost::apply_visitor(*this, op.get_expr_right().get_expr()); + switch (op.get_op()) { + case binary_operation_type::ArithmeticOperatorType::ADD: + return "(" + left + " + " + right + ")"; + case binary_operation_type::ArithmeticOperatorType::SUB: + return "(" + left + " - " + right + ")"; + case binary_operation_type::ArithmeticOperatorType::MULT: + return "(" + left + " * " + right + ")"; + } + } + }; + + static inline std::string rot_string (int j){ + if(j == 0) return "xi"; else + if(j == 1 ) return "xi*omega"; else + if(j == -1) return "xi/omega"; else + if(j > 0) return "xi*pow(omega, " + to_string(j) + ")"; else + if(j < 0) return "xi/pow(omega, " + to_string(-j) + ")"; + return ""; + } + + static inline std::vector split_point_string(std::string point){ + std::vector result; + std::size_t found = point.find("& "); + std::size_t j = 0; + std::size_t prev = 0; + while (found!=std::string::npos){ + result.push_back(point.substr(prev, found-prev)); + prev = found + 2; + found = point.find("& ",prev); + j++; + } + return result; + } + + static inline std::tuple< + std::vector>, std::vector, std::map + > calculate_unique_points( + const common_data_type &common_data, + std::size_t permutation_size, + bool use_lookups, + std::size_t quotient_size, + std::size_t sorted_size + ){ + std::set unique_points; + std::vector points; + std::map singles; + std::vector> result; + std::vector points_ids; + + singles["etha"] = singles.size(); + singles[rot_string(0)] = singles.size(); + singles[rot_string(1)] = singles.size(); + + for(std::size_t i = 0; i < permutation_size*2; i++){ + points.push_back(rot_string(0) + "& etha& "); + } + unique_points.insert(rot_string(0) + "& etha& "); + points.push_back(rot_string(0) + "& "+ rot_string(1) + "& etha& "); + points.push_back(rot_string(0) + "& "+ rot_string(1) + "& etha& "); + unique_points.insert(rot_string(0) + "& "+ rot_string(1) + "& etha& "); + + for(std::size_t i = 0; i < PlaceholderParams::constant_columns; i++){ + std::stringstream str; + for(auto j:common_data.columns_rotations[i + PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns]){ + if(singles.find(rot_string(j)) == singles.end()) + singles[rot_string(j)] = singles.size(); + str << rot_string(j) << "& "; + } + str << "etha& "; + unique_points.insert(str.str()); + points.push_back(str.str()); + } + + for(std::size_t i = 0; i < PlaceholderParams::selector_columns; i++){ + std::stringstream str; + for(auto j:common_data.columns_rotations[i + PlaceholderParams::witness_columns + PlaceholderParams::public_input_columns + PlaceholderParams::constant_columns]){ + if(singles.find(rot_string(j)) == singles.end()) + singles[rot_string(j)] = singles.size(); + str << rot_string(j) << "& "; + } + str << "etha& "; + unique_points.insert(str.str()); + points.push_back(str.str()); + } + + for(std::size_t i = 0; i < PlaceholderParams::witness_columns; i++){ + std::stringstream str; + for(auto j:common_data.columns_rotations[i]){ + if(singles.find(rot_string(j)) == singles.end()) + singles[rot_string(j)] = singles.size(); + str << rot_string(j) << "& "; + } + unique_points.insert(str.str()); + points.push_back(str.str()); + } + + for(std::size_t i = 0; i < PlaceholderParams::public_input_columns; i++){ + std::stringstream str; + for(auto j:common_data.columns_rotations[i + PlaceholderParams::witness_columns]){ + if(singles.find(rot_string(j)) == singles.end()) + singles[rot_string(j)] = singles.size(); + str << rot_string(j) << "& "; + } + unique_points.insert(str.str()); + points.push_back(str.str()); + } + + unique_points.insert(rot_string(0) + "& " + rot_string(1) + "& ");//Permutation + points.push_back(rot_string(0) + "& " + rot_string(1) + "& "); + if(use_lookups){ + points.push_back(rot_string(0) + "& " + rot_string(1) + "& "); + } + unique_points.insert(rot_string(0) + "& ");// Quotient + for(std::size_t i = 0; i < quotient_size; i++){ + points.push_back(rot_string(0) + "& "); + } + if(use_lookups){ + unique_points.insert(rot_string(0) + "& " + rot_string(1) + "& " + rot_string(common_data.usable_rows_amount) + "& "); // Lookups + for( std::size_t i = 0; i < sorted_size; i++ ){ + points.push_back(rot_string(0) + "& " + rot_string(1) + "& " + rot_string(common_data.usable_rows_amount) + "& "); + } + singles[rot_string(common_data.usable_rows_amount)] = singles.size(); + } + + for(std::size_t i = 0; i < points.size(); i++){ + std::size_t j = 0; + bool found = false; + for(const auto &unique_point:unique_points){ + if(points[i] == unique_point){ + std::cout << "Point " << i << "=>" << unique_point << " => " << j << std::endl; + found = true; + points_ids.push_back(j); + break; + } + j++; + } + BOOST_ASSERT(found); + } + + for( const auto &p: unique_points){ + std::cout << "Point " << p << std::endl; + result.push_back(split_point_string(p)); + } + + std::cout << unique_points.size() << " unique points" << std::endl; + return std::make_tuple(result, points_ids, singles); + } + + static inline std::string generate_recursive_verifier( + const constraint_system_type &constraint_system, + const common_data_type &common_data, + const commitment_scheme_type &commitment_scheme, + std::size_t permutation_size + ){ + std::cout << "Permutation_size = " << permutation_size << std::endl; + std::string result = nil::blueprint::recursive_verifier_template; + bool use_lookups = constraint_system.lookup_gates().size() > 0; + std::cout << "Use lookups = " << use_lookups << std::endl; + transpiler_replacements reps; + + auto fri_params = commitment_scheme.get_fri_params(); + std::size_t batches_num = use_lookups?5:4; + auto lambda = PlaceholderParams::commitment_scheme_type::fri_type::lambda; + + std::size_t round_proof_layers_num = 0; + std::cout << "Log extended domain = " << log2(fri_params.D[0]->m) << std::endl; + for(std::size_t i = 0; i < fri_params.r; i++ ){ + round_proof_layers_num += log2(fri_params.D[i]->m) -1; + } + + + std::size_t lookup_degree = 0; + degree_visitor_type degree_visitor; + if(use_lookups){ + for(std::size_t i = 0; i < constraint_system.lookup_gates().size(); i++){ + for(std::size_t j = 0; j < constraint_system.lookup_gates()[i].constraints.size(); j++){ + std::size_t degree = 0; + for(std::size_t k = 0; k < constraint_system.lookup_gates()[i].constraints[j].lookup_input.size(); k++){ + degree = std::max(degree, std::size_t(degree_visitor.compute_max_degree(constraint_system.lookup_gates()[i].constraints[j].lookup_input[k]))); + } + std::cout << "Max_degree = " << degree << std::endl; + lookup_degree += (degree + 1); + } + } + for(std::size_t i = 0; i < constraint_system.lookup_tables().size(); i++){ + lookup_degree += 3 * constraint_system.lookup_tables()[i].lookup_options.size(); + } + } + std::cout << "Lookup degree = " << lookup_degree << std::endl; + + std::size_t rows_amount = common_data.rows_amount; + std::size_t quotient_degree = std::max( + (permutation_size + 1) * (common_data.rows_amount -1 ), + (lookup_degree + 1) * (common_data.rows_amount -1 ) + ); + + std::cout << "Permutation side = " << (permutation_size + 1) * (common_data.rows_amount -1 ) << std::endl; + std::cout << "Lookup side = " << (lookup_degree + 1) * (common_data.rows_amount -1 ) << std::endl; + std::cout << "Quotient degree = " << quotient_degree - 1 << std::endl; + std::size_t quotient_polys = (quotient_degree % rows_amount != 0)? (quotient_degree / rows_amount + 1): (quotient_degree / rows_amount); + std::cout << "Quotient polys = " << quotient_polys << std::endl; + + std::size_t poly_num = 2 * permutation_size + 2 + (use_lookups?2:1) + + arithmetization_params::total_columns + + constraint_system.sorted_lookup_columns_number() + quotient_polys; + std::cout << "FIXED_VALUES_BATCH poly num = " << 2 * permutation_size + 2 + arithmetization_params::constant_columns + arithmetization_params::selector_columns << std::endl; + std::cout << "VARIABLE_VALUES_BATCH poly num = " << arithmetization_params::witness_columns + arithmetization_params::public_input_columns << std::endl; + std::cout << "PERMUTATION_BATCH poly num = " << (use_lookups?2:1) << std::endl; + std::cout << "QUOTIENT_BATCH poly num = " << quotient_polys << std::endl; + std::cout << "LOOKUP_BATCH poly num = " << constraint_system.sorted_lookup_columns_number() << std::endl; + std::cout << "Poly num = " << poly_num << std::endl; + + std::size_t points_num = 4 * permutation_size + 6; + std::size_t table_values_num = 0; + for(std::size_t i = 0; i < arithmetization_params::constant_columns + arithmetization_params::selector_columns; i++){ + points_num += common_data.columns_rotations[i + arithmetization_params::witness_columns + arithmetization_params::public_input_columns].size() + 1; + table_values_num += common_data.columns_rotations[i + arithmetization_params::witness_columns + arithmetization_params::public_input_columns].size() + 1; + } + std::cout << "Fixed values points num = " << points_num << std::endl; + for(std::size_t i = 0; i < arithmetization_params::witness_columns + arithmetization_params::public_input_columns; i++){ + points_num += common_data.columns_rotations[i].size(); + table_values_num += common_data.columns_rotations[i].size(); + } + std::cout << "Variable values points num = " << points_num << std::endl; + points_num += use_lookups? 4 : 2; + std::cout << "Permutation polys points num = " << points_num << std::endl; + points_num += quotient_polys; + std::cout << "Quotient polys points num = " << points_num << std::endl; + + if( use_lookups ) { + points_num += constraint_system.sorted_lookup_columns_number() * 3; + std::cout << "Lookup polys points num = " << points_num << std::endl; + } + + + std::size_t constraints_amount = 0; + std::string gates_sizes = ""; + std::stringstream constraints_body; + std::size_t cur = 0; + auto verifier_indices = get_plonk_variable_indices(common_data.columns_rotations, 4*permutation_size + 6); + + expression_gen_code_visitor visitor(verifier_indices); + for(std::size_t i = 0; i < constraint_system.gates().size(); i++){ + constraints_amount += constraint_system.gates()[i].constraints.size(); + if( i != 0) gates_sizes += ", "; + gates_sizes += to_string(constraint_system.gates()[i].constraints.size()); + for(std::size_t j = 0; j < constraint_system.gates()[i].constraints.size(); j++, cur++){ + constraints_body << "\tconstraints[" << cur << "] = " << visitor.generate_expression(constraint_system.gates()[i].constraints[j]) << ";" << std::endl; + } + } + + std::stringstream lookup_expressions_body; + cur = 0; + for(const auto &lookup_gate: constraint_system.lookup_gates()){ + for(const auto &lookup_constraint: lookup_gate.constraints){ + for( const auto &expr: lookup_constraint.lookup_input){ + lookup_expressions_body << "\texpressions[" << cur << "] = " << visitor.generate_expression(expr) << ";" << std::endl; + cur++; + } + } + } + + std::stringstream lookup_gate_selectors_list; + cur = 0; + for(const auto &lookup_gate: constraint_system.lookup_gates()){ + variable_type var(lookup_gate.tag_index, 0, true, variable_type::column_type::selector); + lookup_gate_selectors_list << "\t\tlookup_gate_selectors[" << cur << "] = proof.z[" << verifier_indices[var] <<"];" << std::endl; + cur++; + } + + std::stringstream lookup_table_selectors_list; + cur = 0; + for(const auto &lookup_table: constraint_system.lookup_tables()){ + variable_type var(lookup_table.tag_index, 0, true, variable_type::column_type::selector); + lookup_table_selectors_list << "\t\tlookup_table_selectors[" << cur << "] = proof.z[" << verifier_indices[var] <<"];" << std::endl; + cur++; + } + + std::stringstream lookup_shifted_table_selectors_list; + cur = 0; + for(const auto &lookup_table: constraint_system.lookup_tables()){ + variable_type var(lookup_table.tag_index, 1, true, variable_type::column_type::selector); + lookup_shifted_table_selectors_list << "\t\tshifted_lookup_table_selectors[" << cur << "] = proof.z[" << verifier_indices[var] <<"];" << std::endl; + cur++; + } + + std::stringstream lookup_options_list; + cur = 0; + for(const auto &lookup_table: constraint_system.lookup_tables()){ + for(const auto &lookup_option: lookup_table.lookup_options){ + for( const auto &column: lookup_option){ + variable_type var(column.index, 0, true, variable_type::column_type::constant); + lookup_options_list << "\t\tlookup_table_lookup_options[" << cur << "] = proof.z[" << verifier_indices[var] <<"];" << std::endl; + cur++; + } + } + } + + std::stringstream lookup_shifted_options_list; + cur = 0; + for(const auto &lookup_table: constraint_system.lookup_tables()){ + for(const auto &lookup_option: lookup_table.lookup_options){ + for( const auto &column: lookup_option){ + variable_type var(column.index, 1, true, variable_type::column_type::constant); + lookup_shifted_options_list << "\t\tshifted_lookup_table_lookup_options[" << cur << "] = proof.z[" << verifier_indices[var] <<"];" << std::endl; + cur++; + } + } + } + + std::stringstream gates_selectors_indices; + cur = 0; + for(const auto &gate: constraint_system.gates()){ + if(cur != 0) gates_selectors_indices << ", "; + gates_selectors_indices << gate.selector_index; + cur++; + } + + std::vector> unique_points; + std::vector point_ids; + std::map singles; + std::tie(unique_points, point_ids, singles) = calculate_unique_points( + common_data, permutation_size, use_lookups, quotient_polys, use_lookups?constraint_system.sorted_lookup_columns_number():0 + ); + + std::string point_inds_str = ""; + for(std::size_t i = 0; i < point_ids.size(); i++){ + if( i != 0) point_inds_str += ", "; + point_inds_str += to_string(point_ids[i]); + } + + std::string singles_str = ""; + for(const auto &[k, v]: singles){ + singles_str+= "\tsingles[" + to_string(v) + "] = " + k + ";\n"; + } + + std::stringstream prepare_U_V_str; + for(std::size_t i = 0; i < unique_points.size(); i++){ + prepare_U_V_str << "\tV[" << i << "] = getV"<< unique_points[i].size() << "("; + for(std::size_t j = 0; j < unique_points[i].size(); j++ ){ + if(j != 0) prepare_U_V_str << ", "; + prepare_U_V_str << "singles[" << singles[unique_points[i][j]] << "]"; + } + prepare_U_V_str << ");" << std::endl << std::endl; + } + for(std::size_t ind = 0; ind < point_ids.size(); ind++){ + std::size_t i = point_ids.size() - 1 - ind; + prepare_U_V_str << "\ttmp = getU"<< unique_points[point_ids[i]].size() << "("; + for(std::size_t j = 0; j < unique_points[point_ids[i]].size(); j++ ){ + if(j != 0) prepare_U_V_str << ", "; + prepare_U_V_str << "singles[" << singles[unique_points[point_ids[i]][j]] << "]"; + } + for(std::size_t j = 0; j < unique_points[point_ids[i]].size(); j++ ){ + prepare_U_V_str << ", "; + if( j == unique_points[point_ids[i]].size() - 1 ) + prepare_U_V_str << "proof.z[z_ind]"; + else + prepare_U_V_str << "proof.z[z_ind - "<< unique_points[point_ids[i]].size() - j - 1 <<" ]"; + } + prepare_U_V_str << ");" << std::endl; + prepare_U_V_str << "\tz_ind = z_ind - " << unique_points[point_ids[i]].size() << ";" << std::endl; + for(std::size_t j = 0; j < unique_points[point_ids[i]].size(); j++ ){ + prepare_U_V_str << "\tcombined_U[" << point_ids[i] << "][" << j << "] = combined_U[" << point_ids[i] << "][" << j << "] + tmp[" << j << "] * theta_acc;" << std::endl; + } + prepare_U_V_str << "\ttheta_acc = theta_acc * challenges.lpc_theta;" << std::endl; + } + + std::stringstream compute_combined_y; + for(std::size_t i = 0; i < point_ids.size(); i++){ + /*y[0] = y[0] * challenges.lpc_theta; + y[0] = y[0] + proof.initial_proof_values[initial_proof_ind] * V_evals[point_ids[k]][0]; + y[1] = y[1] * challenges.lpc_theta; + y[1] = y[1] + proof.initial_proof_values[initial_proof_ind+1] * V_evals[point_ids[k]][1];*/ + +// compute_combined_y << "\t\ty[0] = y[0]*challenges.lpc_theta;" << std::endl; +// compute_combined_y << "\t\ty[0] = y[0] + proof.initial_proof_values[initial_proof_ind] * V_evals[" << point_ids[i]<< "][0];" << std::endl; +// compute_combined_y << "\t\tinitial_proof_ind++;" << std::endl; +// compute_combined_y << "\t\ty[1] = y[1]*challenges.lpc_theta;" << std::endl; +// compute_combined_y << "\t\ty[1] = y[1] + proof.initial_proof_values[initial_proof_ind] * V_evals[" << point_ids[i]<< "][1];" << std::endl; +// compute_combined_y << "\t\tinitial_proof_ind++;" << std::endl; + } + + std::size_t fixed_values_size = permutation_size * 2 + 2 + arithmetization_params::constant_columns + arithmetization_params::selector_columns; + std::size_t variable_values_size = arithmetization_params::witness_columns + arithmetization_params::public_input_columns; + std::string batches_size_list = to_string(fixed_values_size) + ", " + to_string(variable_values_size) + ", " + + to_string(use_lookups?2:1) + ", " + to_string(quotient_polys); + if(use_lookups) batches_size_list += ", " + to_string(constraint_system.sorted_lookup_columns_number()); + + + reps["$USE_LOOKUPS_DEFINE$"] = use_lookups?"#define __USE_LOOKUPS__ 1\n":""; + reps["$USE_LOOKUPS$"] = use_lookups? "true" : "false"; + reps["$BATCHES_NUM$"] = to_string(batches_num); + reps["$COMMITMENTS_NUM$"] = to_string(batches_num - 1); + reps["$POINTS_NUM$"] = to_string(points_num); + reps["$POLY_NUM$"] = to_string(poly_num); + reps["$INITIAL_PROOF_POINTS_NUM$"] = to_string(poly_num * lambda * 2); + reps["$ROUND_PROOF_POINTS_NUM$"] = to_string(fri_params.r * 2 * lambda); + reps["$FRI_ROOTS_NUM$"] = to_string(fri_params.r); + reps["$INITIAL_MERKLE_PROOFS_NUM$"] = to_string(batches_num * lambda); + reps["$INITIAL_MERKLE_PROOFS_POSITION_NUM$"] = to_string(lambda * (log2(fri_params.D[0]->m) - 1)); + reps["$INITIAL_MERKLE_PROOFS_HASH_NUM$"] = to_string(lambda * (log2(fri_params.D[0]->m) - 1) * batches_num); + reps["$ROUND_MERKLE_PROOFS_POSITION_NUM$"] = to_string(lambda * round_proof_layers_num); + reps["$ROUND_MERKLE_PROOFS_HASH_NUM$"] = to_string(lambda * round_proof_layers_num); + reps["$FINAL_POLYNOMIAL_SIZE$"] = to_string(std::pow(2, std::log2(fri_params.max_degree + 1) - fri_params.r + 1) - 2); + reps["$LAMBDA$"] = to_string(lambda); + reps["$PERMUTATION_SIZE$"] = to_string(permutation_size); + reps["$ZERO_INDICES$"] = zero_indices(common_data.columns_rotations); + reps["$TOTAL_COLUMNS$"] = to_string(arithmetization_params::total_columns); + reps["$ROWS_LOG$"] = to_string(log2(rows_amount)); + reps["$ROWS_AMOUNT$"] = to_string(rows_amount); + reps["$TABLE_VALUES_NUM$"] = to_string(table_values_num); + reps["$GATES_AMOUNT$"] = to_string(constraint_system.gates().size()); + reps["$CONSTRAINTS_AMOUNT$"] = to_string(constraints_amount); + reps["$GATES_SIZES$"] = gates_sizes; + reps["$GATES_SELECTOR_INDICES$"] = gates_selectors_indices.str(); + reps["$CONSTRAINTS_BODY$"] = constraints_body.str(); + reps["$WITNESS_COLUMNS_AMOUNT$"] = to_string(arithmetization_params::witness_columns); + reps["$PUBLIC_INPUT_COLUMNS_AMOUNT$"] = to_string(arithmetization_params::public_input_columns); + reps["$CONSTANT_COLUMNS_AMOUNT$"] = to_string(arithmetization_params::constant_columns); + reps["$SELECTOR_COLUMNS_AMOUNT$"] = to_string(arithmetization_params::selector_columns); + reps["$QUOTIENT_POLYS_START$"] = to_string(4*permutation_size + 6 + table_values_num + (use_lookups?4:2)); + reps["$QUOTIENT_POLYS_AMOUNT$"] = to_string(quotient_polys); + reps["$D0_SIZE$"] = to_string(fri_params.D[0]->m); + reps["$D0_LOG$"] = to_string(log2(fri_params.D[0]->m)); + reps["$D0_OMEGA$"] = "pallas::base_field_type::value_type(0x" + to_hex_string(fri_params.D[0]->get_domain_element(1)) + "_cppui255)"; + reps["$OMEGA$"] = "pallas::base_field_type::value_type(0x" + to_hex_string(common_data.basic_domain->get_domain_element(1)) + "_cppui255)"; + reps["$FRI_ROUNDS$"] = to_string(fri_params.r); + reps["$UNIQUE_POINTS$"] = to_string(unique_points.size()); + reps["$POINTS_IDS$"] = point_inds_str; + reps["$SINGLES_AMOUNT$"] = to_string(singles.size()); + reps["$SINGLES_COMPUTATION$"] = singles_str; + reps["$PREPARE_U_AND_V$"] = prepare_U_V_str.str(); + reps["$COMPUTE_COMBINED_Y$"] = compute_combined_y.str(); + reps["$SORTED_COLUMNS$"] = to_string(constraint_system.sorted_lookup_columns_number()); + reps["$SORTED_ALPHAS$"] = to_string(use_lookups? constraint_system.sorted_lookup_columns_number() - 1: 1); + reps["$LOOKUP_TABLE_AMOUNT$"] = to_string(constraint_system.lookup_tables().size()); + reps["$LOOKUP_GATE_AMOUNT$"] = to_string(constraint_system.lookup_gates().size()); + reps["$LOOKUP_OPTIONS_AMOUNT$"] = to_string(constraint_system.lookup_options_num()); + reps["$LOOKUP_OPTIONS_AMOUNT_LIST$"] = generate_lookup_options_amount_list(constraint_system); + reps["$LOOKUP_CONSTRAINTS_AMOUNT$"] = to_string(constraint_system.lookup_constraints_num()); + reps["$LOOKUP_CONSTRAINTS_AMOUNT_LIST$"] = generate_lookup_constraints_amount_list(constraint_system); + reps["$LOOKUP_EXPRESSIONS_AMOUNT$"] = to_string(constraint_system.lookup_expressions_num()); + reps["$LOOKUP_EXPRESSIONS_AMOUNT_LIST$"] = generate_lookup_expressions_amount_list(constraint_system); + reps["$LOOKUP_TABLES_COLUMNS_AMOUNT$"] = to_string(constraint_system.lookup_tables_columns_num()); + reps["$LOOKUP_TABLES_COLUMNS_AMOUNT_LIST$"] = generate_lookup_columns_amount_list(constraint_system); + reps["$LOOKUP_EXPRESSIONS_BODY$"] = lookup_expressions_body.str(); + reps["$LOOKUP_CONSTRAINT_TABLE_IDS_LIST$"] = generate_lookup_constraint_table_ids_list(constraint_system); + reps["$LOOKUP_GATE_SELECTORS_LIST$"] = lookup_gate_selectors_list.str(); + reps["$LOOKUP_TABLE_SELECTORS_LIST$"] = lookup_table_selectors_list.str(); + reps["$LOOKUP_SHIFTED_TABLE_SELECTORS_LIST$"] = lookup_shifted_table_selectors_list.str(); + reps["$LOOKUP_OPTIONS_LIST$"] = lookup_options_list.str(); + reps["$LOOKUP_SHIFTED_OPTIONS_LIST$"] = lookup_shifted_options_list.str(); + reps["$LOOKUP_SORTED_START$"] = to_string(4*permutation_size + 6 + table_values_num + (use_lookups?4:2) + quotient_polys); + reps["$BATCHES_AMOUNT_LIST$"] = batches_size_list; + + result = replace_all(result, reps); + return result; + } + }; + } +} + +#endif // CRYPTO3_RECURSIVE_VERIFIER_GENERATOR_HPP \ No newline at end of file diff --git a/include/nil/blueprint/transpiler/templates/commitment_scheme.hpp b/include/nil/blueprint/transpiler/templates/commitment_scheme.hpp index bbb47cf..954a3b4 100644 --- a/include/nil/blueprint/transpiler/templates/commitment_scheme.hpp +++ b/include/nil/blueprint/transpiler/templates/commitment_scheme.hpp @@ -437,7 +437,7 @@ unchecked { tr_state.current_challenge = transcript_state; commitment_state memory state; - $ETA_VALUES_VERIFICATION$ +$ETA_VALUES_VERIFICATION$ { uint256 offset; diff --git a/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp b/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp new file mode 100644 index 0000000..05ed1d5 --- /dev/null +++ b/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp @@ -0,0 +1,800 @@ +#ifndef __RECURSIVE_VERIFIER_TEMPLATE_HPP__ +#define __RECURSIVE_VERIFIER_TEMPLATE_HPP__ + +#include + +namespace nil { + namespace blueprint { + std::string recursive_verifier_template = R"( +#include +#include +#include + +$USE_LOOKUPS_DEFINE$ + +using namespace nil::crypto3; +using namespace nil::crypto3::algebra::curves; + +const bool use_lookups = $USE_LOOKUPS$; +const size_t batches_num = $BATCHES_NUM$; +const size_t commitments_num = $COMMITMENTS_NUM$; +const size_t points_num = $POINTS_NUM$; +const size_t poly_num = $POLY_NUM$; +const size_t initial_proof_points_num = $INITIAL_PROOF_POINTS_NUM$; +const size_t round_proof_points_num = $ROUND_PROOF_POINTS_NUM$; +const size_t fri_roots_num = $FRI_ROOTS_NUM$; +const size_t initial_merkle_proofs_num = $INITIAL_MERKLE_PROOFS_NUM$; +const size_t initial_merkle_proofs_position_num = $INITIAL_MERKLE_PROOFS_POSITION_NUM$; +const size_t initial_merkle_proofs_hash_num = $INITIAL_MERKLE_PROOFS_HASH_NUM$; +const size_t round_merkle_proofs_position_num = $ROUND_MERKLE_PROOFS_POSITION_NUM$; +const size_t round_merkle_proofs_hash_num = $ROUND_MERKLE_PROOFS_HASH_NUM$; +const size_t final_polynomial_size = $FINAL_POLYNOMIAL_SIZE$; +const size_t lambda = $LAMBDA$; +const size_t rows_amount = $ROWS_AMOUNT$; +const size_t rows_log = $ROWS_LOG$; +const size_t total_columns = $TOTAL_COLUMNS$; +const size_t sorted_columns = $SORTED_COLUMNS$; +const size_t permutation_size = $PERMUTATION_SIZE$; +const std::array zero_indices = {$ZERO_INDICES$}; +const size_t table_values_num = $TABLE_VALUES_NUM$; +const size_t gates_amount = $GATES_AMOUNT$; +constexpr std::array gates_selector_indices = {$GATES_SELECTOR_INDICES$}; +const size_t constraints_amount = $CONSTRAINTS_AMOUNT$; +const size_t witness_amount = $WITNESS_COLUMNS_AMOUNT$; +const size_t public_input_amount = $PUBLIC_INPUT_COLUMNS_AMOUNT$; +const size_t constant_amount = $CONSTANT_COLUMNS_AMOUNT$; +const size_t selector_amount = $SELECTOR_COLUMNS_AMOUNT$; +const size_t quotient_polys_start = $QUOTIENT_POLYS_START$; +const size_t quotient_polys_amount = $QUOTIENT_POLYS_AMOUNT$; +const size_t lookup_sorted_polys_start = $LOOKUP_SORTED_START$; +const size_t D0_size = $D0_SIZE$; +const size_t D0_log = $D0_LOG$; +const pallas::base_field_type::value_type D0_omega = $D0_OMEGA$; +const pallas::base_field_type::value_type omega = $OMEGA$; +const size_t fri_rounds = $FRI_ROUNDS$; +const std::array gates_sizes = {$GATES_SIZES$}; +const size_t unique_points = $UNIQUE_POINTS$; +const std::array point_ids = {$POINTS_IDS$}; +const size_t singles_amount = $SINGLES_AMOUNT$; +std::array batches_amount_list = {$BATCHES_AMOUNT_LIST$}; + +#ifdef __USE_LOOKUPS__ +const size_t lookup_table_amount = $LOOKUP_TABLE_AMOUNT$; +const size_t lookup_gate_amount = $LOOKUP_GATE_AMOUNT$; +constexpr std::array lookup_options_amount_list = {$LOOKUP_OPTIONS_AMOUNT_LIST$}; +constexpr std::array lookup_tables_columns_amount_list = {$LOOKUP_TABLES_COLUMNS_AMOUNT_LIST$}; +constexpr std::size_t lookup_options_amount = $LOOKUP_OPTIONS_AMOUNT$; +constexpr std::size_t lookup_table_columns_amount = $LOOKUP_TABLES_COLUMNS_AMOUNT$; + +constexpr std::array lookup_constraints_amount_list = {$LOOKUP_CONSTRAINTS_AMOUNT_LIST$}; +constexpr std::size_t lookup_constraints_amount = $LOOKUP_CONSTRAINTS_AMOUNT$; +constexpr std::array lookup_expressions_amount_list = {$LOOKUP_EXPRESSIONS_AMOUNT_LIST$}; +constexpr std::size_t lookup_expressions_amount = $LOOKUP_EXPRESSIONS_AMOUNT$; + + +constexpr std::size_t m_parameter = lookup_options_amount + lookup_constraints_amount; +constexpr std::size_t input_size_alphas = m_parameter - 1; + +constexpr std::size_t input_size_lookup_gate_selectors = lookup_gate_amount; +constexpr std::size_t input_size_lookup_gate_constraints_table_ids = lookup_constraints_amount; +constexpr std::size_t input_size_lookup_gate_constraints_lookup_inputs = lookup_expressions_amount; + +constexpr std::size_t input_size_lookup_table_selectors = lookup_table_amount; +constexpr std::size_t input_size_lookup_table_lookup_options = lookup_table_columns_amount; + +constexpr std::size_t input_size_shifted_lookup_table_selectors = lookup_table_amount; +constexpr std::size_t input_size_shifted_lookup_table_lookup_options = lookup_table_columns_amount; + +constexpr std::size_t input_size_sorted = m_parameter * 3 - 1; +#endif + +struct placeholder_proof_type{ + std::array commitments; + pallas::base_field_type::value_type challenge; + std::array z; + std::array fri_roots; + std::array initial_proof_values; + std::array round_proof_values; + std::array initial_proof_positions; + std::array initial_proof_hashes; + std::array round_merkle_proof_positions; + std::array round_proof_hashes; + std::array final_polynomial; +}; + +struct placeholder_challenges_type{ + pallas::base_field_type::value_type fri_etha; + pallas::base_field_type::value_type perm_beta; + pallas::base_field_type::value_type perm_gamma; + pallas::base_field_type::value_type lookup_theta; + pallas::base_field_type::value_type lookup_gamma; + pallas::base_field_type::value_type lookup_beta; + std::array lookup_alphas; + pallas::base_field_type::value_type gate_theta; + std::array alphas; + std::array fri_alphas; + std::array fri_x_indices; + pallas::base_field_type::value_type lpc_theta; + pallas::base_field_type::value_type xi; +}; + +typedef __attribute__((ext_vector_type(2))) typename pallas::base_field_type::value_type permutation_argument_thetas_type; +typedef __attribute__((ext_vector_type(3))) typename pallas::base_field_type::value_type permutation_argument_output_type; + +struct placeholder_permutation_argument_input_type{ + std::array xi_values; + std::array id_perm; + std::array sigma_perm; + permutation_argument_thetas_type thetas; +}; + +struct transcript_state_type{ + std::array state; + std::size_t cur; +}; + +void transcript(transcript_state_type &tr_state, pallas::base_field_type::value_type value) { + tr_state.state[tr_state.cur] = value; + if(tr_state.cur == 2){ + tr_state.state[0] = __builtin_assigner_poseidon_pallas_base({tr_state.state[0],tr_state.state[1],tr_state.state[2]})[2]; + tr_state.state[1] = pallas::base_field_type::value_type(0); + tr_state.state[2] = pallas::base_field_type::value_type(0); + tr_state.cur = 1; + } else{ + tr_state.state[tr_state.cur] = value; + tr_state.cur++; + } +} + +pallas::base_field_type::value_type transcript_challenge(transcript_state_type &tr_state) { + tr_state.state[0] = __builtin_assigner_poseidon_pallas_base({tr_state.state[0], tr_state.state[1], tr_state.state[2]})[2]; + tr_state.state[1] = pallas::base_field_type::value_type(0); + tr_state.state[2] = pallas::base_field_type::value_type(0); + tr_state.cur = 1; + return tr_state.state[0]; +} + +pallas::base_field_type::value_type pow2_p(pallas::base_field_type::value_type x, size_t plog){ + if(plog == 0) return pallas::base_field_type::value_type(1); + pallas::base_field_type::value_type result = x; + for(std::size_t i = 0; i < plog; i++){ + result = result * result; + } + return result; +} + +pallas::base_field_type::value_type pow2(pallas::base_field_type::value_type x){ + return x*x; +} + +pallas::base_field_type::value_type pow3(pallas::base_field_type::value_type x){ + return x*x*x; +} + +pallas::base_field_type::value_type pow4(pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result = x * x; + result = result * result; + return result; +} + +pallas::base_field_type::value_type pow5(pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result = x * x; + result = result * result; + return result * x; +} + +pallas::base_field_type::value_type pow6(pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result = x * x * x; + result = result * result; + return result; +} + +pallas::base_field_type::value_type pow7(pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result = x * x * x; + result = result * result; + return result * x; +} + +pallas::base_field_type::value_type pow8(pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result = x * x; + result = result * result; + return result * result; +} + +pallas::base_field_type::value_type pow9(pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result = x; + result = result * result; + result = result * result; + result = result * result; + result = result * x; + return result; +} + +pallas::base_field_type::value_type pow(pallas::base_field_type::value_type x, size_t p){ + pallas::base_field_type::value_type result = 1; + std::size_t mask = 1; + while(mask < p){mask = mask * 2;} // 8 + while(mask > 1){ + result = result * result; + mask = mask / 2; + if( p >= mask ){ + result = result * x; + p = p - mask; + } + } + return result; +} + +std::array fill_singles( + pallas::base_field_type::value_type xi, + pallas::base_field_type::value_type etha +){ + std::array singles; +$SINGLES_COMPUTATION$; + return singles; +} + +placeholder_challenges_type generate_challenges( + const std::array &vk, + const placeholder_proof_type &proof +){ + placeholder_challenges_type challenges; + + transcript_state_type tr_state; + tr_state.state[0] = pallas::base_field_type::value_type(0); + tr_state.state[1] = pallas::base_field_type::value_type(0); + tr_state.state[2] = pallas::base_field_type::value_type(0); + tr_state.cur = 1; + + transcript(tr_state, vk[0]); + transcript(tr_state, vk[1]); + + // LPC additional point + challenges.fri_etha = transcript_challenge(tr_state); + + transcript(tr_state, proof.commitments[0]); + + challenges.perm_beta = transcript_challenge(tr_state); + challenges.perm_gamma = transcript_challenge(tr_state); + + // Call lookup argument + if( use_lookups ){ + challenges.lookup_theta = transcript_challenge(tr_state); + transcript(tr_state, proof.commitments[3]); + challenges.lookup_beta = transcript_challenge(tr_state); + challenges.lookup_gamma = transcript_challenge(tr_state); + + for(std::size_t i = 0; i < sorted_columns-1; i++){ + challenges.lookup_alphas[i] = transcript_challenge(tr_state); + } + } + + // Call gate argument + transcript(tr_state, proof.commitments[1]); + challenges.gate_theta = transcript_challenge(tr_state); + + for(std::size_t i = 0; i < 8; i++){ + challenges.alphas[i] = transcript_challenge(tr_state); + } + transcript(tr_state, proof.commitments[2]); + + challenges.xi = transcript_challenge(tr_state); + + transcript(tr_state, vk[1]); + for(std::size_t i = 0; i < proof.commitments.size(); i++){ + transcript(tr_state, proof.commitments[i]); + } + + challenges.lpc_theta = transcript_challenge(tr_state); + + for(std::size_t i = 0; i < fri_roots_num; i++){ + transcript(tr_state, proof.fri_roots[i]); + challenges.fri_alphas[i] = transcript_challenge(tr_state); + } + + for(std::size_t i = 0; i < lambda; i++){ + challenges.fri_x_indices[i] = transcript_challenge(tr_state); + } + + return challenges; +} + +std::pair xi_polys( + pallas::base_field_type::value_type xi +){ + pallas::base_field_type::value_type xi_n = pow2_p(xi, rows_log) - pallas::base_field_type::value_type(1); + pallas::base_field_type::value_type l0 = (xi - pallas::base_field_type::value_type(1))*pallas::base_field_type::value_type(rows_amount); + l0 = xi_n / l0; + return std::make_pair(l0, xi_n); +} + +std::array calculate_constraints(std::array z){ + std::array constraints; +$CONSTRAINTS_BODY$ + + return constraints; +} + +#ifdef __USE_LOOKUPS__ +std::array calculate_lookup_expressions(std::array z){ + std::array expressions; +$LOOKUP_EXPRESSIONS_BODY$ + + return expressions; +} +#endif + +typename pallas::base_field_type::value_type + gate_argument_verifier( + std::array selectors, + std::array constraints, + typename pallas::base_field_type::value_type theta + ) { + + return __builtin_assigner_gate_arg_verifier( + selectors.data(), + (int*)gates_sizes.data(), + gates_amount, + constraints.data(), + constraints_amount, + theta + ); +} + +std::array getV3( + pallas::base_field_type::value_type xi0,pallas::base_field_type::value_type xi1,pallas::base_field_type::value_type xi2 +){ + std::array result; + result[0] = - xi0 * xi1 * xi2; + result[1] = xi0 * xi1 + xi1 * xi2 + xi0 * xi2; + result[2] = - xi0 - xi1 - xi2; + result[3] = pallas::base_field_type::value_type(1); +// __builtin_assigner_exit_check(result[0] + xi0 * result[1] + xi0 * xi0 * result[2] + xi0*xi0*xi0*result[3] == pallas::base_field_type::value_type(0)); + return result; +} + +std::array getV2( + pallas::base_field_type::value_type xi0,pallas::base_field_type::value_type xi1 +){ + std::array result; + result[0] = xi0 * xi1; + result[1] = - xi0 - xi1; + result[2] = pallas::base_field_type::value_type(1); + result[3] = pallas::base_field_type::value_type(0); +// __builtin_assigner_exit_check(result[0] + xi0 * result[1] + xi0 * xi0 * result[2] + xi0*xi0*xi0*result[3] == pallas::base_field_type::value_type(0)); + return result; +} + +std::array getV1( + pallas::base_field_type::value_type xi0 +){ + std::array result; + result[0] = - xi0; + result[1] = pallas::base_field_type::value_type(1); + result[2] = pallas::base_field_type::value_type(0); + result[3] = pallas::base_field_type::value_type(0); +// __builtin_assigner_exit_check(result[0] + xi0 * result[1] + xi0 * xi0 * result[2] + xi0*xi0*xi0*result[3] == pallas::base_field_type::value_type(0)); + return result; +} + +std::array getU3( + pallas::base_field_type::value_type x0,pallas::base_field_type::value_type x1,pallas::base_field_type::value_type x2, + pallas::base_field_type::value_type z0,pallas::base_field_type::value_type z1,pallas::base_field_type::value_type z2 +){ + std::array result; + pallas::base_field_type::value_type denom = (x0-x1)*(x1-x2)*(x2-x0); + + z0 = z0 * (x2-x1); + z1 = z1 * (x0-x2); + z2 = z2 * (x1-x0); + + result[0] = (z0*x1*x2 + z1*x0*x2 + z2*x0*x1)/denom; + result[1] = (-z0*(x1 + x2) - z1*(x0 + x2) - z2 * (x0 + x1))/denom; + result[2] = (z0 + z1 + z2)/denom; + +// __builtin_assigner_exit_check(result[0] + x0 * result[1] + x0 * x0 * result[2] == z0/(x2-x1)); +// __builtin_assigner_exit_check(result[0] + x1 * result[1] + x1 * x1 * result[2] == z1/(x0-x2)); +// __builtin_assigner_exit_check(result[0] + x2 * result[1] + x2 * x2 * result[2] == z2/(x1-x0)); + + return result; +} + +std::array getU2( + pallas::base_field_type::value_type x0,pallas::base_field_type::value_type x1, + pallas::base_field_type::value_type z0,pallas::base_field_type::value_type z1 +){ + std::array result; + pallas::base_field_type::value_type denom = (x0-x1); + result[0] = (-z0*x1 + z1*x0)/denom; + result[1] = (z0 - z1)/denom; + result[2] = pallas::base_field_type::value_type(0); + +// __builtin_assigner_exit_check(result[0] + x0 * result[1] + x0 * x0 * result[2] == z0); +// __builtin_assigner_exit_check(result[0] + x1 * result[1] + x1 * x1 * result[2] == z1); + + return result; +} + +std::array getU1( + pallas::base_field_type::value_type x0, + pallas::base_field_type::value_type z0 +){ + std::array result; + result[0] = z0; + result[1] = pallas::base_field_type::value_type(0); + result[2] = pallas::base_field_type::value_type(0); + +// __builtin_assigner_exit_check(result[0] + x0 * result[1] + x0 * x0 * result[2] == z0); + + return result; +} + +pallas::base_field_type::value_type eval4(std::array poly, pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result; + result = poly[3]; + result = result *x + poly[2]; + result = result *x + poly[1]; + result = result *x + poly[0]; +// __builtin_assigner_exit_check(poly[0] + x * poly[1] + x * x * poly[2] + x*x*x*poly[3] == result); + return result; +} + +pallas::base_field_type::value_type eval3(std::array poly, pallas::base_field_type::value_type x){ + pallas::base_field_type::value_type result; + result = poly[2]; + result = result *x + poly[1]; + result = result *x + poly[0]; +// __builtin_assigner_exit_check(poly[0] + x * poly[1] + x * x * poly[2] == result); + return result; +} + +pallas::base_field_type::value_type calculate_leaf_hash( + std::array val, + std::size_t start_index, + std::size_t leaf_size +){ + pallas::base_field_type::value_type hash_state = pallas::base_field_type::value_type(0); + for(std::size_t pos = 0; pos < leaf_size; pos+=2){ + hash_state = __builtin_assigner_poseidon_pallas_base( + {hash_state, val[start_index + pos], val[start_index + pos+1]} + )[2]; + } + return hash_state; +} + +pallas::base_field_type::value_type calculate_reversed_leaf_hash( + std::array &val, + std::size_t start_index, + std::size_t leaf_size +){ + pallas::base_field_type::value_type hash_state = pallas::base_field_type::value_type(0); + for(std::size_t pos = 0; pos < leaf_size; pos+=2){ + hash_state = __builtin_assigner_poseidon_pallas_base( + {hash_state, val[start_index + pos + 1], val[start_index + pos]} + )[2]; + } + return hash_state; +} + +constexpr std::size_t L0_IND = 0; +constexpr std::size_t Z_AT_XI_IND = 1; +constexpr std::size_t F_CONSOLIDATED_IND = 2; +constexpr std::size_t T_CONSOLIDATED_IND = 3; + +typedef __attribute__((ext_vector_type(2))) + typename pallas::base_field_type::value_type pair_type; + +typedef __attribute__((ext_vector_type(4))) + typename pallas::base_field_type::value_type lookup_output_type; + +typedef __attribute__((ext_vector_type(2))) + typename pallas::base_field_type::value_type pair_type; + + +[[circuit]] bool placeholder_verifier( + std::array vk, + placeholder_proof_type proof +) { + placeholder_challenges_type challenges = generate_challenges(vk, proof); + __builtin_assigner_exit_check(challenges.xi == proof.challenge); + + std::array different_values; + std::tie(different_values[L0_IND], different_values[Z_AT_XI_IND]) = xi_polys(challenges.xi); + + std::array F = {0,0,0,0,0,0,0,0}; + + // Call permutation argument + placeholder_permutation_argument_input_type perm_arg_input; + perm_arg_input.thetas[0] = challenges.perm_beta; + perm_arg_input.thetas[1] = challenges.perm_gamma; + + for( std::size_t i = 0; i < permutation_size; i++ ){ + perm_arg_input.xi_values[i] = proof.z[4*permutation_size + 6 + zero_indices[i]]; + perm_arg_input.id_perm[i] = proof.z[2*i]; + perm_arg_input.sigma_perm[i] = proof.z[2*permutation_size + 2*i]; + } + + permutation_argument_output_type permutation_argument = __builtin_assigner_permutation_arg_verifier( + perm_arg_input.xi_values.data(), + perm_arg_input.id_perm.data(), + perm_arg_input.sigma_perm.data(), + permutation_size, + different_values[L0_IND], + proof.z[4*permutation_size + 6 + table_values_num], // V + proof.z[4*permutation_size + 6 + table_values_num + 1], // V_shifted + proof.z[4*permutation_size], // q_last + proof.z[4*permutation_size + 3], // q_blind + perm_arg_input.thetas + ); + + F[0] = permutation_argument[0]; + F[1] = permutation_argument[1]; + F[2] = permutation_argument[2]; + +// __builtin_assigner_exit_check(F[0] == pallas::base_field_type::value_type(0x2e55b062d92d4a6c8dc3e2db4f1e7e5f17605c7c45172c614cde1f97f69b2fc4_cppui255)); +// __builtin_assigner_exit_check(F[1] == pallas::base_field_type::value_type(0x18b0640a55f9108406cd93ee729c37150b635e94911bd0d6b99876e36dc47c6e_cppui255)); +// __builtin_assigner_exit_check(F[2] == pallas::base_field_type::value_type(0x1e713451797d9acbc945c8761b1e16d9f155a13f8ddfcab1e0322f2864d277e7_cppui255)); +#ifdef __USE_LOOKUPS__ + { + std::array alphas = challenges.lookup_alphas; + std::array lookup_gate_selectors; +$LOOKUP_GATE_SELECTORS_LIST$ + std::array lookup_gate_constraints_table_ids = {$LOOKUP_CONSTRAINT_TABLE_IDS_LIST$}; + std::array lookup_gate_constraints_lookup_inputs = calculate_lookup_expressions(proof.z); + std::array lookup_table_selectors; +$LOOKUP_TABLE_SELECTORS_LIST$ + std::array shifted_lookup_table_selectors; +$LOOKUP_SHIFTED_TABLE_SELECTORS_LIST$ + std::array lookup_table_lookup_options; +$LOOKUP_OPTIONS_LIST$ + std::array shifted_lookup_table_lookup_options; +$LOOKUP_SHIFTED_OPTIONS_LIST$ + + std::array sorted; + for(std::size_t i = 0; i < input_size_sorted; i++){ + sorted[i] = proof.z[lookup_sorted_polys_start + i]; + } + + typename pallas::base_field_type::value_type theta = challenges.lookup_theta; + typename pallas::base_field_type::value_type beta = challenges.lookup_beta; + typename pallas::base_field_type::value_type gamma = challenges.lookup_gamma; + typename pallas::base_field_type::value_type L0 = different_values[L0_IND]; + pair_type V_L_values = { + proof.z[4*permutation_size + 6 + table_values_num + 2], // V + proof.z[4*permutation_size + 6 + table_values_num + 3], // V_shifted + }; + pair_type q_last = {proof.z[4*permutation_size], proof.z[4*permutation_size + 1]}; + pair_type q_blind = {proof.z[4*permutation_size + 3], proof.z[4*permutation_size + 4]}; + + lookup_output_type lookup_argument; + + std::array lookup_input; + std::size_t cur = 0; + std::size_t cur_e = 0; + for(std::size_t g = 0; g < lookup_gate_amount; g++){ + for( std::size_t i = 0; i < lookup_constraints_amount_list[g]; i++ ){ + lookup_input[cur] = lookup_gate_selectors[g] * lookup_gate_constraints_table_ids[cur]; + pallas::base_field_type::value_type theta_acc = theta; + for(std::size_t e = 0; e < lookup_expressions_amount_list[cur]; e++){ + lookup_input[cur] = lookup_input[cur] + lookup_gate_selectors[g] * lookup_gate_constraints_lookup_inputs[cur_e] * theta_acc; + theta_acc = theta_acc * theta; + cur_e++; + } + cur++; + } + } + + std::array lookup_value; + std::array lookup_shifted_value; + cur = 0; + std::size_t cur_o = 0; + pallas::base_field_type::value_type tab_id = 1; + for( std::size_t t = 0; t < lookup_table_amount; t++ ){ + for( std::size_t o = 0; o < lookup_options_amount_list[t]; o++ ){ + pallas::base_field_type::value_type theta_acc = theta; + lookup_value[cur] = lookup_table_selectors[t] * tab_id; + lookup_shifted_value[cur] = shifted_lookup_table_selectors[t] * tab_id; + for( std::size_t c = 0; c < lookup_tables_columns_amount_list[t]; c++){ + lookup_value[cur] = lookup_value[cur] + lookup_table_selectors[t] * lookup_table_lookup_options[cur_o] * theta_acc; + lookup_shifted_value[cur] = lookup_shifted_value[cur] + shifted_lookup_table_selectors[t] * shifted_lookup_table_lookup_options[cur_o] * theta_acc; + theta_acc = theta_acc * theta; + cur_o++; + } + lookup_value[cur] = lookup_value[cur] * (pallas::base_field_type::value_type(1) - q_last[0] - q_blind[0]); + lookup_shifted_value[cur] = lookup_shifted_value[cur] * (pallas::base_field_type::value_type(1) - q_last[1] - q_blind[1]); + cur++; + } + tab_id = tab_id + 1; + } + + pallas::base_field_type::value_type g = pallas::base_field_type::value_type(1); + pallas::base_field_type::value_type h = pallas::base_field_type::value_type(1); + + for( std::size_t i = 0; i < lookup_constraints_amount; i++ ){ + g = g *(pallas::base_field_type::value_type(1)+beta)*(gamma + lookup_input[i]); + } + for( std::size_t i = 0; i < lookup_options_amount; i++ ){ + g = g * ((pallas::base_field_type::value_type(1)+beta) * gamma + lookup_value[i] + beta * lookup_shifted_value[i]); + } + for( std::size_t i = 0; i < m_parameter; i++ ){ + h = h * ((pallas::base_field_type::value_type(1)+beta) * gamma + sorted[3*i] + beta * sorted[3*i+1]); + } + + lookup_argument[0] = (pallas::base_field_type::value_type(1) - V_L_values[0]) * L0; + lookup_argument[1] = q_last[0]*(V_L_values[0] * V_L_values[0] - V_L_values[0]); + lookup_argument[2] = (pallas::base_field_type::value_type(1) - q_last[0] - q_blind[0]) * (V_L_values[1] * h - V_L_values[0] * g); + lookup_argument[3] = pallas::base_field_type::value_type(0); + for(std::size_t i = 0; i < input_size_alphas; i++){ + lookup_argument[3] = lookup_argument[3] + alphas[i] * (sorted[3*i + 3] - sorted[3*i + 2]); + } + lookup_argument[3] = lookup_argument[3] * L0; + F[3] = lookup_argument[0]; + F[4] = lookup_argument[1]; + F[5] = lookup_argument[2]; + F[6] = lookup_argument[3]; + } +#endif + + if constexpr( gates_amount > 0) { + std::array constraints; + std::array selectors; + constraints = calculate_constraints(proof.z); + + for( std::size_t i = 0; i < gates_amount; i++ ){ + selectors[i] = proof.z[4 * permutation_size + 6 + zero_indices[witness_amount + public_input_amount + constant_amount + gates_selector_indices[i]]]; + } + + F[7] = gate_argument_verifier( + selectors, + constraints, + challenges.gate_theta + ); + F[7] *= (pallas::base_field_type::value_type(1) - proof.z[4*permutation_size] - proof.z[4*permutation_size + 3]); + } + + different_values[F_CONSOLIDATED_IND] = pallas::base_field_type::value_type(0); + for(std::size_t i = 0; i < 8; i++){ + F[i] *= challenges.alphas[i]; + different_values[F_CONSOLIDATED_IND] += F[i]; + } + + different_values[T_CONSOLIDATED_IND] = pallas::base_field_type::value_type(0); + pallas::base_field_type::value_type factor = pallas::base_field_type::value_type(1); + for(std::size_t i = 0; i < quotient_polys_amount; i++){ + different_values[T_CONSOLIDATED_IND] += proof.z[quotient_polys_start + i] * factor; + factor *= (different_values[Z_AT_XI_IND] + pallas::base_field_type::value_type(1)); + } + __builtin_assigner_exit_check(different_values[F_CONSOLIDATED_IND] == different_values[T_CONSOLIDATED_IND] * (different_values[Z_AT_XI_IND])); + + // Commitment scheme + std::array singles = fill_singles(challenges.xi, challenges.fri_etha); + std::array, unique_points> V; + std::array, poly_num> U; + std::array, unique_points> combined_U; + std::size_t z_ind = points_num - 1; + pallas::base_field_type::value_type theta_acc(1); + std::array tmp; + + for(std::size_t u = 0; u < unique_points; u++){ + combined_U[u][0] = pallas::base_field_type::value_type(0); + combined_U[u][1] = pallas::base_field_type::value_type(0); + combined_U[u][2] = pallas::base_field_type::value_type(0); + } + +$PREPARE_U_AND_V$ + + std::array, D0_log> res; + std::size_t round_proof_ind = 0; + std::size_t initial_proof_ind = 0; + std::size_t initial_proof_hash_ind = 0; + pallas::base_field_type::value_type interpolant; + std::size_t cur_val = 0; + std::size_t round_proof_hash_ind = 0; + + for(std::size_t i = 0; i < lambda; i++){ + __builtin_assigner_fri_cosets(res.data(), D0_log, D0_omega, 256, challenges.fri_x_indices[i]); + + pallas::base_field_type::value_type hash_state; + for(std::size_t b = 0; b < batches_num; b++){ + pallas::base_field_type::value_type hash_state(0); + if(res[0][2] == pallas::base_field_type::value_type(0)){ + hash_state = calculate_leaf_hash(proof.initial_proof_values, cur_val, batches_amount_list[b] *2); + } else if(res[0][2] == pallas::base_field_type::value_type(1)){ + hash_state = calculate_reversed_leaf_hash(proof.initial_proof_values, cur_val, batches_amount_list[b] *2); + } + cur_val += batches_amount_list[b] *2; + for(std::size_t r = i * initial_merkle_proofs_position_num/lambda; r < (i + 1)* initial_merkle_proofs_position_num/lambda ; r++){ + if(proof.initial_proof_positions[r] == 1){ + hash_state = __builtin_assigner_poseidon_pallas_base({0, hash_state, proof.initial_proof_hashes[initial_proof_hash_ind]})[2]; + } else{ + hash_state = __builtin_assigner_poseidon_pallas_base({0, proof.initial_proof_hashes[initial_proof_hash_ind], hash_state})[2]; + } + initial_proof_hash_ind ++; + } + if(b == 0) + __builtin_assigner_exit_check(hash_state == vk[1]); + else + __builtin_assigner_exit_check(hash_state == proof.commitments[b-1]); + } + + std::array y = {0,0}; + std::array, unique_points> V_evals; + std::size_t ind = 0; + pallas::base_field_type::value_type theta_acc(1); + + for(std::size_t u = 0; u < unique_points; u++){ + V_evals[u][0] = pallas::base_field_type::value_type(1) / eval4(V[u], res[0][0]); + V_evals[u][1] = pallas::base_field_type::value_type(1) / eval4(V[u], res[0][1]); + y[0] = y[0] - eval3(combined_U[u], res[0][0]) * V_evals[u][0]; + y[1] = y[1] - eval3(combined_U[u], res[0][1]) * V_evals[u][1]; + } + + initial_proof_ind = initial_proof_ind + poly_num * 2; + std::size_t in = initial_proof_ind - 1; + for(int k = poly_num; k > 0;){ + k--; + y[0] = y[0] + theta_acc * proof.initial_proof_values[in-1] * V_evals[point_ids[k]][0]; + y[1] = y[1] + theta_acc * proof.initial_proof_values[in] * V_evals[point_ids[k]][1]; + in -= 2; + theta_acc = theta_acc * challenges.lpc_theta; + } + + std::size_t D = D0_log - 1; + pallas::base_field_type::value_type rhash; + for(std::size_t j = 0; j < fri_rounds; j++){ + if(res[j][2] == pallas::base_field_type::value_type(0)){ + rhash = __builtin_assigner_poseidon_pallas_base({0, y[0], y[1]})[2]; + } else { + rhash = __builtin_assigner_poseidon_pallas_base({0, y[1], y[0]})[2]; + } + for( std::size_t d = 0; d < D; d++){ + if(proof.round_merkle_proof_positions[round_proof_hash_ind] == 1){ + rhash = __builtin_assigner_poseidon_pallas_base({0, rhash, proof.round_proof_hashes[round_proof_hash_ind]})[2]; + } else { + rhash = __builtin_assigner_poseidon_pallas_base({0, proof.round_proof_hashes[round_proof_hash_ind], rhash})[2]; + } + round_proof_hash_ind++; + } + __builtin_assigner_exit_check(rhash == proof.fri_roots[j]); + D--; + + interpolant = __builtin_assigner_fri_lin_inter( + res[j][0], + y[0], + y[1], + challenges.fri_alphas[j] + ); + __builtin_assigner_exit_check(interpolant == proof.round_proof_values[round_proof_ind]); + y[0] = proof.round_proof_values[round_proof_ind]; + y[1] = proof.round_proof_values[round_proof_ind + 1]; + + pallas::base_field_type::value_type rhash; + round_proof_ind += 2; + } + + interpolant = pallas::base_field_type::value_type(0); + pallas::base_field_type::value_type x = res[fri_rounds][0]; + pallas::base_field_type::value_type factor = pallas::base_field_type::value_type(1); + for(std::size_t j = 0; j < final_polynomial_size; j++){ + interpolant = interpolant + proof.final_polynomial[j] * factor; + factor = factor * x; + } + __builtin_assigner_exit_check(interpolant == y[0]); + + interpolant = pallas::base_field_type::value_type(0); + x = res[fri_rounds][1]; + factor = pallas::base_field_type::value_type(1); + for(std::size_t j = 0; j < final_polynomial_size; j++){ + interpolant = interpolant + proof.final_polynomial[j] * factor; + factor = factor * x; + } + __builtin_assigner_exit_check(interpolant == y[1]); + } + + return true; +} + )"; + } +} + +#endif //__RECURSIVE_VERIFIER_TEMPLATE_HPP__ \ No newline at end of file diff --git a/include/nil/blueprint/transpiler/util.hpp b/include/nil/blueprint/transpiler/util.hpp index 825f5d8..48271b6 100644 --- a/include/nil/blueprint/transpiler/util.hpp +++ b/include/nil/blueprint/transpiler/util.hpp @@ -31,7 +31,7 @@ #include #include -#include +#include namespace nil { namespace blueprint { @@ -43,6 +43,12 @@ namespace nil { return strstr.str(); } + template std::string to_hex_string(T val) { + std::stringstream strstr; + strstr << std::hex << val << std::dec; + return strstr.str(); + } + void replace_and_print(std::string input, transpiler_replacements reps, std::string output_file_name){ std::string code = input; @@ -54,6 +60,16 @@ namespace nil { out << code; out.close(); } + + std::string replace_all(std::string input, transpiler_replacements reps){ + std::string code = input; + + for(const auto&[k,v]: reps){ + boost::replace_all(code, k, v); + } + + return code; + } } } diff --git a/test/detail/circuits.hpp b/test/detail/circuits.hpp index 1979546..9d09ac7 100644 --- a/test/detail/circuits.hpp +++ b/test/detail/circuits.hpp @@ -53,7 +53,7 @@ namespace nil { namespace crypto3 { namespace zk { namespace snark { - template + template class circuit_description { typedef zk::snark::detail::placeholder_policy policy_type; @@ -61,12 +61,8 @@ namespace nil { constexpr static const std::size_t public_columns = ParamsType::public_input_columns; public: - const std::size_t table_rows = 1 << rows_log; - - std::shared_ptr> domain; - - typename FieldType::value_type omega; - typename FieldType::value_type delta; + std::size_t table_rows; + std::size_t usable_rows = usable_rows_amount; typename policy_type::variable_assignment_type table; @@ -76,10 +72,7 @@ namespace nil { std::vector> lookup_tables; - circuit_description() - : domain(math::make_evaluation_domain(table_rows)) - , omega(domain->get_domain_element(1)) - , delta(algebra::fields::arithmetic_params::multiplicative_generator) { + circuit_description() : table_rows(0){ } }; @@ -95,41 +88,40 @@ namespace nil { // ADD: x + y = z // MUL: x * y = z //---------------------------------------------------------------------------// - constexpr static const std::size_t witness_columns_1 = 3; - constexpr static const std::size_t public_columns_1 = 1; - constexpr static const std::size_t constant_columns_1 = 0; - constexpr static const std::size_t selector_columns_1 = 2; + const std::size_t witness_columns_1 = 3; + const std::size_t public_columns_1 = 1; + const std::size_t constant_columns_1 = 0; + const std::size_t selector_columns_1 = 2; + const std::size_t rows_amount_1 = 13; using arithmetization_params_1 = plonk_arithmetization_params; template - circuit_description, 4, 4> circuit_test_1( + circuit_description, rows_amount_1, 4> circuit_test_1( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t rows_log = 4; + constexpr static const std::size_t usable_rows = 13; constexpr static const std::size_t permutation = 4; constexpr static const std::size_t witness_columns = witness_columns_1; constexpr static const std::size_t public_columns = public_columns_1; constexpr static const std::size_t constant_columns = constant_columns_1; constexpr static const std::size_t selector_columns = selector_columns_1; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + constant_columns; typedef placeholder_circuit_params circuit_params; - - circuit_description test_circuit; - + circuit_description test_circuit; std::array, table_columns> table; - std::vector q_add(test_circuit.table_rows); - std::vector q_mul(test_circuit.table_rows); + std::vector q_add(test_circuit.usable_rows); + std::vector q_mul(test_circuit.usable_rows); for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); + table[j].resize(test_circuit.usable_rows); } // init values @@ -137,40 +129,45 @@ namespace nil { table[0][0] = alg_rnd(); table[1][0] = alg_rnd(); table[2][0] = alg_rnd(); -// table[3][0] = algebra::random_element(); + table[3][0] = table[2][0]; + plonk_variable x(2, 0, false, + plonk_variable::column_type::witness); + plonk_variable y(0, 0, false, + plonk_variable::column_type::public_input); + test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); + q_add[0] = FieldType::value_type::zero(); q_mul[0] = FieldType::value_type::zero(); // fill rows with ADD gate - for (std::size_t i = 1; i < test_circuit.table_rows - 5; i++) { + for (std::size_t i = 1; i < test_circuit.usable_rows - 5; i++) { table[0][i] = alg_rnd(); table[1][i] = alg_rnd(); table[2][i] = table[0][i] + table[1][i]; -// table[3][i] = FieldType::value_type::zero(); + table[3][i] = table[3][0]; q_add[i] = one; q_mul[i] = FieldType::value_type::zero(); - - plonk_variable x(1, i, false, - plonk_variable::column_type::witness); - plonk_variable y(2, i - 1, false, - plonk_variable::column_type::witness); - //test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); + plonk_variable x(0, i, false, + plonk_variable::column_type::public_input); + plonk_variable y(0, 0, false, + plonk_variable::column_type::public_input); + test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); } // fill rows with MUL gate - for (std::size_t i = test_circuit.table_rows - 5; i < test_circuit.table_rows - 3; i++) { + for (std::size_t i = test_circuit.table_rows - 5; i < test_circuit.table_rows; i++) { table[0][i] = alg_rnd(); table[1][i] = alg_rnd(); table[2][i] = table[0][i] * table[1][i]; -// table[3][i] = FieldType::value_type::zero(); + table[3][i] = table[2][i]; q_add[i] = FieldType::value_type::zero(); q_mul[i] = one; - plonk_variable x(1, i, false, + plonk_variable x(2, i, false, plonk_variable::column_type::witness); - plonk_variable y(0, 0, false, + plonk_variable y(0, i, false, plonk_variable::column_type::public_input); - //test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); + test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); } std::array, witness_columns> private_assignment; @@ -185,15 +182,13 @@ namespace nil { selectors_assignment[0] = q_add; selectors_assignment[1] = q_mul; - for (std::size_t i = 0; i < public_columns; i++) { - public_input_assignment[i] = table[witness_columns + i]; - } + public_input_assignment[0] = table[3]; test_circuit.table = plonk_assignment_table( plonk_private_assignment_table(private_assignment), plonk_public_assignment_table( public_input_assignment, constant_assignment, selectors_assignment)); -// test_circuit.init(); + test_circuit.table_rows = zk_padding>(test_circuit.table, alg_rnd); plonk_variable w0(0, 0, true, plonk_variable::column_type::witness); plonk_variable w1(1, 0, true, plonk_variable::column_type::witness); @@ -210,7 +205,7 @@ namespace nil { plonk_constraint mul_constraint; typename plonk_constraint::term_type w0_term(w0); - typename plonk_constraint::term_type w1_term(w1); + typename plonk_constraint::term_type w1_term(w1); mul_constraint += w0_term * w1_term; mul_constraint -= w2; @@ -237,78 +232,77 @@ namespace nil { constexpr static const std::size_t public_columns_t = 1; constexpr static const std::size_t constant_columns_t = 0; constexpr static const std::size_t selector_columns_t = 2; + constexpr static const std::size_t usable_rows_t = 5; using arithmetization_params_t = plonk_arithmetization_params; template - circuit_description, 4, 4> + circuit_description, 5, 4> circuit_test_t( - typename FieldType::value_type pi0 = 0, - typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), - boost::random::mt11213b rnd = boost::random::mt11213b() + typename FieldType::value_type pi0,// = 0, + typename nil::crypto3::random::algebraic_engine alg_rnd, //= nil::crypto3::random::algebraic_engine(), + boost::random::mt11213b rnd// = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t rows_log = 4; constexpr static const std::size_t permutation = 4; - constexpr static const std::size_t witness_columns = witness_columns_t; constexpr static const std::size_t public_columns = public_columns_t; constexpr static const std::size_t constant_columns = constant_columns_t; constexpr static const std::size_t selector_columns = selector_columns_t; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + constant_columns; typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::array, table_columns> table; - std::vector q_add(test_circuit.table_rows); - std::vector q_mul(test_circuit.table_rows); + std::vector q_add(test_circuit.usable_rows); + std::vector q_mul(test_circuit.usable_rows); for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); + table[j].resize(test_circuit.usable_rows); } // init values typename FieldType::value_type one = FieldType::value_type::one(); - table[0][0] = algebra::random_element(); - table[1][0] = algebra::random_element(); - table[2][0] = algebra::random_element(); + table[0][0] = alg_rnd(); + table[1][0] = alg_rnd(); + table[2][0] = alg_rnd(); table[3][0] = pi0; q_add[0] = FieldType::value_type::zero(); q_mul[0] = FieldType::value_type::zero(); // fill rows with ADD gate - for (std::size_t i = 1; i < test_circuit.table_rows - 5; i++) { - table[0][i] = algebra::random_element(); + for (std::size_t i = 1; i < 3; i++) { + table[0][i] = alg_rnd(); table[1][i] = table[2][i - 1]; table[2][i] = table[0][i] + table[1][i]; table[3][i] = FieldType::value_type::zero(); q_add[i] = one; q_mul[i] = FieldType::value_type::zero(); - plonk_variable x(1, i, false, + plonk_variable x(1, i, false, plonk_variable::column_type::witness); - plonk_variable y(2, i - 1, false, + plonk_variable y(2, i - 1, false, plonk_variable::column_type::witness); test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); } // fill rows with MUL gate - for (std::size_t i = test_circuit.table_rows - 5; i < test_circuit.table_rows - 3; i++) { - table[0][i] = algebra::random_element(); + for (std::size_t i = 3; i < 5; i++) { + table[0][i] = alg_rnd(); table[1][i] = table[3][0]; table[2][i] = table[0][i] * table[1][i] + table[0][i - 1]; table[3][i] = FieldType::value_type::zero(); q_add[i] = FieldType::value_type::zero(); q_mul[i] = one; - plonk_variable x(1, i, false, + plonk_variable x(1, i, false, plonk_variable::column_type::witness); - plonk_variable y(0, 0, false, + plonk_variable y(0, 0, false, plonk_variable::column_type::public_input); test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); } @@ -334,6 +328,7 @@ namespace nil { plonk_private_assignment_table(private_assignment), plonk_public_assignment_table( public_input_assignment, constant_assignment, selectors_assignment)); + test_circuit.table_rows = zk_padding>(test_circuit.table, alg_rnd); plonk_variable w0(0, 0, true, plonk_variable::column_type::witness); @@ -355,7 +350,7 @@ namespace nil { plonk_constraint mul_constraint; typename plonk_constraint::term_type w0_term(w0); - typename plonk_constraint::term_type w1_term(w1); + typename plonk_constraint::term_type w1_term(w1); mul_constraint += w0_term * w1_term; mul_constraint -= w2; mul_constraint += w0_prev; @@ -372,47 +367,55 @@ namespace nil { constexpr static const std::size_t public_columns_3 = 0; constexpr static const std::size_t constant_columns_3 = 3; constexpr static const std::size_t selector_columns_3 = 2; + constexpr static const std::size_t usable_rows_3 = 4; + constexpr static const std::size_t permutation_size_3 = 3; using arithmetization_params_3 = plonk_arithmetization_params; template - circuit_description, 3, 3> circuit_test_3( + circuit_description, usable_rows_3, permutation_size_3> circuit_test_3( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; using field_type = typename FieldType::value_type; - constexpr static const std::size_t rows_log = 3; - constexpr static const std::size_t permutation = 3; - + constexpr static const std::size_t permutation = permutation_size_3; constexpr static const std::size_t witness_columns = witness_columns_3; constexpr static const std::size_t public_columns = public_columns_3; constexpr static const std::size_t constant_columns = constant_columns_3; constexpr static const std::size_t selector_columns = selector_columns_3; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + constant_columns; + constexpr static const std::size_t usable_rows = usable_rows_3; typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::array, table_columns> table; for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); + table[j].resize(test_circuit.usable_rows); } // lookup inputs typename FieldType::value_type one = FieldType::value_type::one(); typename FieldType::value_type zero = FieldType::value_type::zero(); - table[0] = {1, 0, 0, 0, 0, 0, 0, 0}; // Witness 1 - table[1] = {0, 0, 0, 0, 0, 0, 0, 0}; - table[2] = {0, 0, 0, 0, 0, 0, 0, 0}; + table[0] = {1, 3, 0, 0}; // Witness 1 + table[1] = {0, 0, 0, 0}; + table[2] = {0, 0, 0, 3}; - table[3] = {0, 1, 0, 1, 0, 0, 0, 0}; //Lookup values - table[4] = {0, 0, 1, 0, 0, 0, 0, 0}; //Lookup values - table[5] = {0, 1, 0, 0, 0, 0, 0, 0}; //Lookup values + plonk_variable x(0, 1, false, + plonk_variable::column_type::witness); + plonk_variable y(2, 3, false, + plonk_variable::column_type::witness); + test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, y)); + + + table[3] = {0, 1, 0, 1}; //Lookup values + table[4] = {0, 0, 1, 0}; //Lookup values + table[5] = {0, 1, 0, 0}; //Lookup values std::array, witness_columns> private_assignment; for (std::size_t i = 0; i < witness_columns; i++) { @@ -425,17 +428,11 @@ namespace nil { std::array, constant_columns> constant_assignment; std::vector sel_lookup(test_circuit.table_rows); - sel_lookup[0] = one; - sel_lookup[1] = zero; - sel_lookup[2] = zero; - sel_lookup[3] = zero; + sel_lookup = {1, 0, 0, 0}; selectors_assignment[0] = sel_lookup; std::vector sel_lookup_table(test_circuit.table_rows); - sel_lookup_table[0] = zero; - sel_lookup_table[1] = one; - sel_lookup_table[2] = one; - sel_lookup_table[3] = one; + sel_lookup_table = {0, 1, 1, 1}; selectors_assignment[1] = sel_lookup_table; for (std::size_t i = 0; i < constant_columns; i++) { @@ -445,6 +442,7 @@ namespace nil { plonk_private_assignment_table(private_assignment), plonk_public_assignment_table( public_input_assignment, constant_assignment, selectors_assignment)); + test_circuit.table_rows = zk_padding(test_circuit.table, alg_rnd); plonk_variable w0(0, 0, true, plonk_variable::column_type::witness); plonk_variable w1(1, 0, true, plonk_variable::column_type::witness); @@ -473,8 +471,8 @@ namespace nil { return test_circuit; } - // Binary multiplication. - // b_i -- random binaries, + // Binary multiplication. + // b_i -- random binaries, // r_i ordinary random numbers. // One gate: w1*w2 - w3 = 0 // ---------------------------------------------------------------------------------- @@ -499,7 +497,7 @@ namespace nil { circuit_description, 3, 3> circuit_test_4( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), - boost::random::mt11213b rnd = boost::random::mt11213b() + boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; @@ -510,7 +508,7 @@ namespace nil { constexpr static const std::size_t public_columns = public_columns_4; constexpr static const std::size_t constant_columns = constant_columns_4; constexpr static const std::size_t selector_columns = selector_columns_4; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + constant_columns; typedef placeholder_circuit_params circuit_params; @@ -529,9 +527,9 @@ namespace nil { table[1] = {rnd() % 2, rnd() % 2, rnd(), rnd() % 2, rnd() % 2, 0, 0, 0};; table[2] = {table[0][0] * table[1][0], table[0][1] * table[1][1], table[0][2] * table[1][2], table[0][3] * table[1][3], table[0][4] * table[1][4], 0, 0, 0}; - + //lookup values - // Reserved zero row for unselected lookup input rows + // Reserved zero row for unselected lookup input rows table[3] = {0, 0, 0, 1, 1, 0, 0, 0}; table[4] = {0, 0, 1, 0, 1, 0, 0, 0}; table[5] = {0, 0, 0, 0, 1, 0, 0, 0}; @@ -576,7 +574,7 @@ namespace nil { plonk_constraint mul_constraint; typename plonk_constraint::term_type w0_term(w0); - typename plonk_constraint::term_type w1_term(w1); + typename plonk_constraint::term_type w1_term(w1); mul_constraint += w0_term * w1_term; mul_constraint -= w2; @@ -602,161 +600,14 @@ namespace nil { return test_circuit; } - - // Lookup complex test - // 1. Lookup gate with 4 constraints - // 1.1 w1 \in table 1 - // 1.2 w3 \in table1 - // 1.3 w1 \in table 2 - // 1.4 w1, w2, w3 \in table 3 - // 2. Lookup gate with 2 constraints - // 2.1 w2 \in table 1 - // 2.2 w2 \in table 2 - // --------------------------------------------------------------------------- - // | Table tag 0 | Table tag 1 | W1 | W2 | W3 | Lookup tag | L1 | L2 | L3 | - // --------------------------------------------------------------------------- - // | 1 | 1 | 1 | 2 | 123 | 0 | 0 | 0 | 0 | - // | 2 | 1 | 124| 2 | 3 | 1 | 1 | 0 | 0 | - // | 1 | 1 | 3 | 4 | 125 | 1 | 2 | 0 | 0 | - // | 2 | 1 | 127| 4 | 5 | 1 | 3 | 0 | 0 | - // | 1 | 2 | 5 | 6 | 128 | 1 | 4 | 0 | 0 | - // | 3 | 2 | 6 | 7 | 129 | 1 | 5 | 0 | 0 | - // | 3 | 2 | 7 | 8 | 130 | 2 | 6 | 0 | 0 | - // | 3 | 2 | 8 | 9 | 131 | 2 | 7 | 0 | 0 | - // | 3 | 2 | 9 | 10 | 132 | 2 | 8 | 0 | 0 | - // | 4 | 0 | 0 | 0 | 1 | 2 | 9 | 0 | 0 | - // | 4 | 0 | 0 | 1 | 0 | 2 | 10| 0 | 0 | - // | 4 | 0 | 1 | 0 | 0 | 3 | 0 | 0 | 1 | - // | 4 | 0 | 1 | 1 | 1 | 3 | 1 | 0 | 0 | - // | 0 | 0 | 0 | 0 | 128| 3 | 0 | 1 | 0 | - // | 0 | 0 | 0 | 0 | 129| 3 | 1 | 1 | 1 | - // | 0 | 0 | 0 | 0 | 130| 0 | 0 | 0 | 0 | - ///--------------------------------------------------------------------------- - constexpr static const std::size_t witness_columns_5= 3; - constexpr static const std::size_t public_columns_5 = 0; - constexpr static const std::size_t constant_columns_5 = 3; - constexpr static const std::size_t selector_columns_5 = 3; - - using arithmetization_params_5 = plonk_arithmetization_params; - - template - circuit_description, 4, 3> circuit_test_5() { - using assignment_type = typename FieldType::value_type; - - constexpr static const std::size_t rows_log = 4; - constexpr static const std::size_t permutation = 3; - - constexpr static const std::size_t witness_columns = witness_columns_5; - constexpr static const std::size_t public_columns = public_columns_5; - constexpr static const std::size_t constant_columns = constant_columns_5; - constexpr static const std::size_t selector_columns = selector_columns_5; - constexpr static const std::size_t table_columns = - witness_columns + public_columns + constant_columns + selector_columns; - - typedef placeholder_circuit_params circuit_params; - - circuit_description test_circuit; - - std::array, table_columns> table; - for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); - } - - // lookup inputs - typename FieldType::value_type one = FieldType::value_type::one(); - typename FieldType::value_type zero = FieldType::value_type::zero(); - - // Witness - table[0] = { 1, 124, 3, 127, 5, 6, 7, 8, 9, 0, 0, 1, 1, 131, 133, 135}; // W0 - table[1] = { 2, 2, 4, 4, 6, 7, 8, 9, 10, 0, 1, 0, 1, 132, 134, 136}; // W1 - table[2] = {123, 3, 125, 5, 129, 130, 131, 132, 10, 1, 0, 0, 0, 128, 129, 130}; // W2 - - // Tags - table[3] = { 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0}; // Lookup table tag - table[4] = { 1, 2, 1, 2, 1, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 136}; // Lookup tag1 - table[5] = { 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 130}; // Lookup tag2 - - // Lookups - table[6] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 1, 1, 0}; // L1 - table[7] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 136}; // L2 - table[8] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 130}; // L3 - - std::array, witness_columns> private_assignment; - for (std::size_t i = 0; i < witness_columns; i++) { - private_assignment[i] = table[i]; - } - - - std::array, selector_columns> selectors_assignment; - std::array, public_columns> public_input_assignment = {}; - std::array, constant_columns> constant_assignment; - - for (std::size_t i = 0; i < selector_columns; i++) { - selectors_assignment[i] = table[witness_columns + i]; - } - - for (std::size_t i = 0; i < constant_columns; i++) { - constant_assignment[i] = table[witness_columns + selector_columns + i]; - } - - test_circuit.table = plonk_assignment_table( - plonk_private_assignment_table(private_assignment), - plonk_public_assignment_table( - public_input_assignment, constant_assignment, selectors_assignment)); - - plonk_variable w0(0, 0, true, - plonk_variable::column_type::witness); - plonk_variable w1(1, 0, true, - plonk_variable::column_type::witness); - plonk_variable w2(2, 0, true, - plonk_variable::column_type::witness); - - plonk_variable l0(0, 0, true, - plonk_variable::column_type::constant); - plonk_variable l1(1, 0, true, - plonk_variable::column_type::constant); - plonk_variable l2(2, 0, true, - plonk_variable::column_type::constant); - - std::vector> lookup_constraints0(4); - lookup_constraints0[0].lookup_input.push_back(typename plonk_constraint::term_type(w0)); - lookup_constraints0[0].table_id = 1; - lookup_constraints0[1].lookup_input.push_back(typename plonk_constraint::term_type(w2)); - lookup_constraints0[1].table_id = 1; - lookup_constraints0[2].lookup_input.push_back(typename plonk_constraint::term_type(w1)); - lookup_constraints0[2].table_id = 2; - lookup_constraints0[3].lookup_input.push_back(typename plonk_constraint::term_type(w0)); - lookup_constraints0[3].lookup_input.push_back(typename plonk_constraint::term_type(w1)); - lookup_constraints0[3].lookup_input.push_back(typename plonk_constraint::term_type(w2)); - lookup_constraints0[3].table_id = 3; - plonk_lookup_gate> lookup_gate0(1, lookup_constraints0); - - std::vector> lookup_constraints1(2); - lookup_constraints1[0].lookup_input.push_back(typename plonk_constraint::term_type(w1)); - lookup_constraints1[0].table_id = 1; - lookup_constraints1[1].lookup_input.push_back(typename plonk_constraint::term_type(w1)); - lookup_constraints1[1].table_id = 2; - plonk_lookup_gate> lookup_gate1(2, lookup_constraints1); - - test_circuit.lookup_gates.push_back(lookup_gate0); - test_circuit.lookup_gates.push_back(lookup_gate1); - - plonk_lookup_table lookup_table({l0, l1, l2}, 0); - test_circuit.lookup_table = lookup_table; - - return test_circuit; - } - //---------------------------------------------------------------------------// // Test fibonacci circuit - // i | GATE | w_0 | public | q_add | - // 0 | -- | f(0) | a | 0 | - // 1 | FIB | f(1) | b | 1 | - // ... | FIB | | 0 | 1 | - // k-2 | FIB | f(k-2) | 0 | 0 | - // k-1 | -- | f(k-1) | 0 | 0 | + // i | GATE | w_0 | public | q_add | + // 0 | -- | f(0) | a | 0 | + // 1 | FIB | f(1) | b | 1 | + // ... | FIB | | 0 | 1 | + // k-2 | FIB | f(k-2) | 0 | 0 | + // k-1 | -- | f(k-1) | 0 | 0 | // // public input is copy constrainted to f(0) and f(1) // FIB: w_0(i-1) + w_0(i) == w_0(i+1) @@ -769,9 +620,11 @@ namespace nil { using arithmetization_params_fib = plonk_arithmetization_params; - template - circuit_description, rows_log, 2> - circuit_test_fib() { + template + circuit_description, usable_rows, 2> + circuit_test_fib( + typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine() + ) { using assignment_type = typename FieldType::value_type; constexpr static const std::size_t permutation = 2; @@ -780,20 +633,19 @@ namespace nil { constexpr static const std::size_t public_columns = public_columns_fib; constexpr static const std::size_t constant_columns = constant_columns_fib; constexpr static const std::size_t selector_columns = selector_columns_fib; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + selector_columns; typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::array, table_columns> table; - std::vector q_add(test_circuit.table_rows); - std::vector q_mul(test_circuit.table_rows); + std::vector q_add(test_circuit.usable_rows); + std::vector q_mul(test_circuit.usable_rows); for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); + table[j].resize(test_circuit.usable_rows); } - // init values typename FieldType::value_type zero = FieldType::value_type::zero(); typename FieldType::value_type one = FieldType::value_type::one(); @@ -807,7 +659,7 @@ namespace nil { // selector table[2][0] = zero; - table[2][0] = one; + table[2][1] = one; plonk_variable x0(0, 0, false, plonk_variable::column_type::witness); plonk_variable x1(0, 1, false, plonk_variable::column_type::witness); @@ -817,15 +669,11 @@ namespace nil { // test_circuit.copy_constraints.push_back(plonk_copy_constraint(x0, p0)); // test_circuit.copy_constraints.push_back(plonk_copy_constraint(x1, p1)); - for (std::size_t i = 2; i < test_circuit.table_rows - 1; i++) { + for (std::size_t i = 2; i < test_circuit.usable_rows - 1; i++) { table[0][i] = table[0][i-2] + table[0][i-1]; table[1][i] = zero; - table[2][i] = one; + table[2][i-1] = one; } - table[2][test_circuit.table_rows - 4] = zero; - table[2][test_circuit.table_rows - 3] = zero; - table[2][test_circuit.table_rows - 2] = zero; - table[2][test_circuit.table_rows - 1] = zero; std::array, witness_columns> private_assignment; private_assignment[0] = table[0]; @@ -839,18 +687,20 @@ namespace nil { public_input_assignment[0] = table[1]; selectors_assignment[0] = table[2]; + test_circuit.table = plonk_assignment_table( plonk_private_assignment_table(private_assignment), plonk_public_assignment_table( public_input_assignment, constant_assignment, selectors_assignment)); + test_circuit.table_rows = zk_padding>(test_circuit.table, alg_rnd); plonk_variable w0(0, -1, true, plonk_variable::column_type::witness); plonk_variable w1(0, 0, true, plonk_variable::column_type::witness); plonk_variable w2(0, 1, true, plonk_variable::column_type::witness); typename plonk_constraint::term_type w0_term(w0); - typename plonk_constraint::term_type w1_term(w1); - typename plonk_constraint::term_type w2_term(w2); + typename plonk_constraint::term_type w1_term(w1); + typename plonk_constraint::term_type w2_term(w2); plonk_constraint fib_constraint; fib_constraint += w0_term; @@ -860,7 +710,7 @@ namespace nil { std::vector> fib_costraints {fib_constraint}; plonk_gate> fib_gate(0, fib_costraints); test_circuit.gates.push_back(fib_gate); - + return test_circuit; } @@ -873,7 +723,7 @@ namespace nil { // Lookup gate2: // w1{-1} + w1 \in Table 2 // --------------------------------------------------------------------------------- - // | s1 | s2 | W1 | W2 | LT1 | L1 | L2 | L3 | + // | s1 | s2 | W1 | W2 | LT1 | L1 | L2 | L3 | // --------------------------------------------------------------------------------- // | 1 | 0 | r1 | 7 | 0 | 0 | 0 | 0 | -- reserved for unselected rows // | 1 | 1 | r2 | r1+r2 | 1 | 2 | 7 | 12 | -- reserved for unselected rows @@ -887,54 +737,55 @@ namespace nil { constexpr static const std::size_t public_columns_6 = 0; constexpr static const std::size_t constant_columns_6 = 3; constexpr static const std::size_t selector_columns_6 = 3; + constexpr static const std::size_t usable_rows_6 = 6; using arithmetization_params_6 = plonk_arithmetization_params; template circuit_description, 3, 3> circuit_test_6( + arithmetization_params_6>, usable_rows_6, 3> circuit_test_6( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t rows_log = 3; constexpr static const std::size_t permutation = 3; constexpr static const std::size_t witness_columns = witness_columns_6; constexpr static const std::size_t public_columns = public_columns_6; constexpr static const std::size_t constant_columns = constant_columns_6; constexpr static const std::size_t selector_columns = selector_columns_6; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + constant_columns + selector_columns; + constexpr static const std::size_t usable_rows = usable_rows_6; typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::array, table_columns> table; for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); + table[j].resize(test_circuit.usable_rows); } // lookup inputs typename FieldType::value_type one = FieldType::value_type::one(); typename FieldType::value_type zero = FieldType::value_type::zero(); - table[0] = {rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, 0, 0}; - table[1] = {7, table[0][0] + table[0][1], table[0][1] + table[0][2], table[0][2] + table[0][3], table[0][3] + table[0][4], table[0][4] + table[0][5], 0, 0};; + table[0] = {rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2, rnd() % 5 + 2}; + table[1] = {7, table[0][0] + table[0][1], table[0][1] + table[0][2], table[0][2] + table[0][3], table[0][3] + table[0][4], table[0][4] + table[0][5]}; + - // selectors - // Reserved zero row for unselected lookup input rows - table[2] = {0, 1, 1, 1, 1, 1, 0, 0}; // LT1 - table[3] = {1, 1, 1, 1, 1, 1, 0, 0}; // For the first lookup gate - table[4] = {0, 1, 1, 1, 1, 1, 0, 0}; // For the second lookup gate + // Reserved zero row for unselected lookup input rows + table[2] = {0, 1, 1, 1, 1, 1}; // LT1 + table[3] = {1, 1, 1, 1, 1, 1}; // For the first lookup gate + table[4] = {0, 1, 1, 1, 1, 1}; // For the second lookup gate // Lookup values - table[5] = {0, 2, 3, 4, 5, 6, 0, 0}; // L1 - table[6] = {0, 7, 8, 9, 10, 11, 0, 0}; // L2 - table[7] = {0, 12, 12, 12, 12, 12, 0, 0}; // L3 + table[5] = {0, 2, 3, 4, 5, 6}; // L1 + table[6] = {0, 7, 8, 9, 10, 11}; // L2 + table[7] = {0, 12, 12, 12, 12, 12}; // L3 std::array, witness_columns> private_assignment; for (std::size_t i = 0; i < witness_columns; i++) { @@ -956,6 +807,7 @@ namespace nil { plonk_private_assignment_table(private_assignment), plonk_public_assignment_table( public_input_assignment, constant_assignment, selectors_assignment)); + test_circuit.table_rows = zk_padding(test_circuit.table, alg_rnd); plonk_variable w0( 0, 0, true, plonk_variable::column_type::witness); plonk_variable w0_1(0,-1, true, plonk_variable::column_type::witness); @@ -1017,54 +869,54 @@ namespace nil { // | s0 | s1 | s2 | s3 | W1 | W2 | LT1 | LT2 | L1 | L2 | L3 | L4 | L5 | L6 | L7 // ---------------------------------------------------------------------------------------- // | 1 | 1 | 0 | 0 | 1 | 2^w1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 -- reserved for unselected rows - // | 1 | 1 | 0 | 1 | 2 | 2^w1 | 1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 + // | 1 | 1 | 0 | 1 | 2 | 2^w1 | 1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 // | 1 | 1 | 0 | 1 | 3 | 2^w1 | 1 | 0 | 0 | 2 | 3 | 4 | 5 | 6 | 7 // | 1 | 1 | 1 | 1 | 4 | 2^w1 | 1 | 0 | 0 | 1 | 3 | 4 | 5 | 6 | 7 -- unselected for lookups // | 1 | 1 | 1 | 1 | 5 | 2^w1 | 1 | 0 | 0 | 1 | 2 | 4 | 5 | 6 | 7 // | 1 | 1 | 1 | 1 | 6 | 2^w1 | 1 | 0 | 0 | 1 | 2 | 3 | 4 | 6 | 7 // | 1 | 0 | 1 | 1 | 7 | 2^w1 | 1 | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 7 // | 1 | 0 | 1 | 1 | 0 | 2^w1 | 1 | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 - // | 1 | 0 | 1 | 1 | 1 | 2^w1 | 0 | 1 | 0 | 1 | 6 | 64| 1 | 64 |4096 - // | 1 | 0 | 1 | 1 | 2 | 2^w1 | 0 | 1 | 1 | 2 | 7 | 128| 2 |128 |8192 - // | 1 | 0 | 1 | 1 | 3 | 2^w1 | 0 | 1 | 2 | 4 | 7 | 128| 4 |256 |16384 - // | 1 | 0 | 0 | 1 | 4 | 2^w1 | 0 | 1 | 3 | 8 | 7 | 128| 8 |512 |16384 - // | 1 | 0 | 0 | 1 | 5 | 2^w1 | 0 | 1 | 4 | 16 | 7 | 128| 16 |1024|16384 - // | 1 | 0 | 0 | 1 | 6 | 2^w1 | 0 | 1 | 5 | 32 | 7 | 128| 32 |2048|16384 + // | 1 | 0 | 1 | 1 | 1 | 2^w1 | 0 | 1 | 0 | 1 | 6 | 64| 1 | 64 |4096 + // | 1 | 0 | 1 | 1 | 2 | 2^w1 | 0 | 1 | 1 | 2 | 7 | 128| 2 |128 |8192 + // | 1 | 0 | 1 | 1 | 3 | 2^w1 | 0 | 1 | 2 | 4 | 7 | 128| 4 |256 |16384 + // | 1 | 0 | 0 | 1 | 4 | 2^w1 | 0 | 1 | 3 | 8 | 7 | 128| 8 |512 |16384 + // | 1 | 0 | 0 | 1 | 5 | 2^w1 | 0 | 1 | 4 | 16 | 7 | 128| 16 |1024|16384 + // | 1 | 0 | 0 | 1 | 6 | 2^w1 | 0 | 1 | 5 | 32 | 7 | 128| 32 |2048|16384 // --------------------------------------------------------------------------------- - constexpr static const std::size_t witness_columns_7= 2; constexpr static const std::size_t public_columns_7 = 0; constexpr static const std::size_t constant_columns_7 = 7; constexpr static const std::size_t selector_columns_7 = 6; + constexpr static const std::size_t usable_rows_7 = 14; using arithmetization_params_7 = plonk_arithmetization_params; template circuit_description, 4, 3> circuit_test_7( + arithmetization_params_7>, usable_rows_7, 4> circuit_test_7( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t rows_log = 4; - constexpr static const std::size_t permutation = 3; + constexpr static const std::size_t permutation = 4; constexpr static const std::size_t witness_columns = witness_columns_7; constexpr static const std::size_t public_columns = public_columns_7; constexpr static const std::size_t constant_columns = constant_columns_7; constexpr static const std::size_t selector_columns = selector_columns_7; - constexpr static const std::size_t table_columns = + constexpr static const std::size_t table_columns = witness_columns + public_columns + constant_columns + selector_columns; + constexpr static const std::size_t usable_rows = usable_rows_7; typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::array, table_columns> table; for (std::size_t j = 0; j < table_columns; j++) { - table[j].resize(test_circuit.table_rows); + table[j].resize(test_circuit.usable_rows); } // lookup inputs @@ -1086,24 +938,24 @@ namespace nil { } // selectors - // Reserved zero row for unselected lookup input rows + // Reserved zero row for unselected lookup input rows std::array, selector_columns> selectors_assignment; - selectors_assignment[0] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 }; // Selector for single gate - selectors_assignment[1] = {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }; // Selector lookup gate with multiple rotations - selectors_assignment[2] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }; // Selector for gate w1 = 2^w0 - selectors_assignment[3] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }; // Selector for gate w1_{-1} * w1 \in Table 3 - selectors_assignment[4] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 }; // Selector for lookup tables 2, 3 - selectors_assignment[5] = {0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // Selector for lookup table with 7 columns + selectors_assignment[0] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }; // Selector for single gate + selectors_assignment[1] = {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }; // Selector lookup gate with multiple rotations + selectors_assignment[2] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; // Selector for gate w1 = 2^w0 + selectors_assignment[3] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; // Selector for gate w1_{-1} * w1 \in Table 3 + selectors_assignment[4] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; // Selector for lookup tables 2, 3 + selectors_assignment[5] = {0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; // Selector for lookup table with 7 columns // Lookup values std::array, constant_columns> constant_assignment; - constant_assignment[0] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0 }; // Lookup tables - constant_assignment[1] = {0, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 0, 0 }; // Lookup tables - constant_assignment[2] = {0, 3, 3, 3, 2, 2, 2, 2, 6, 7, 7, 7, 7, 7, 0, 0 }; // Lookup tables - constant_assignment[3] = {0, 4, 4, 4, 4, 3, 3, 3, 64, 128, 128, 128, 128, 128, 0, 0 }; // Lookup tables - constant_assignment[4] = {0, 5, 5, 5, 5, 5, 4, 4, 1, 2, 4, 8, 16, 32, 0, 0 }; // Lookup tables - constant_assignment[5] = {0, 6, 6, 6, 6, 6, 6, 5, 64, 128, 256, 512, 1024, 2048, 0, 0 }; // Lookup tables - constant_assignment[6] = {0, 7, 7, 7, 7, 7, 7, 7,4096,8192,16384,16384,16384,16384, 0, 0 }; // Lookup tables + constant_assignment[0] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5 }; // Lookup tables + constant_assignment[1] = {0, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32 }; // Lookup tables + constant_assignment[2] = {0, 3, 3, 3, 2, 2, 2, 2, 6, 7, 7, 7, 7, 7 }; // Lookup tables + constant_assignment[3] = {0, 4, 4, 4, 4, 3, 3, 3, 64, 128, 128, 128, 128, 128 }; // Lookup tables + constant_assignment[4] = {0, 5, 5, 5, 5, 5, 4, 4, 1, 2, 4, 8, 16, 32 }; // Lookup tables + constant_assignment[5] = {0, 6, 6, 6, 6, 6, 6, 5, 64, 128, 256, 512, 1024, 2048 }; // Lookup tables + constant_assignment[6] = {0, 7, 7, 7, 7, 7, 7, 7,4096,8192,16384,16384,16384,16384 }; // Lookup tables std::array, witness_columns> private_assignment; for (std::size_t i = 0; i < witness_columns; i++) { @@ -1112,11 +964,11 @@ namespace nil { std::array, public_columns> public_input_assignment = {}; - test_circuit.table = plonk_assignment_table( plonk_private_assignment_table(private_assignment), plonk_public_assignment_table( public_input_assignment, constant_assignment, selectors_assignment)); + test_circuit.table_rows = zk_padding(test_circuit.table, alg_rnd); plonk_variable w0( 0, 0, true, plonk_variable::column_type::witness); plonk_variable w0__7(0,-7, true, plonk_variable::column_type::witness); @@ -1165,7 +1017,7 @@ namespace nil { plonk_variable w1__1( 1, -1, true, plonk_variable::column_type::witness); plonk_lookup_constraint lookup_constraint3; typename plonk_constraint::term_type w1__1_term(w1__1); - typename plonk_constraint::term_type w1_term(w1); + typename plonk_constraint::term_type w1_term(w1); lookup_constraint3.lookup_input = {w1__1_term* w1_term}; lookup_constraint3.table_id = 3; diff --git a/test/transpiler.cpp b/test/transpiler.cpp index b98d256..5d7d177 100644 --- a/test/transpiler.cpp +++ b/test/transpiler.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,7 @@ #include #include +// #include #include "./detail/circuits.hpp" @@ -118,6 +120,7 @@ typename fri_type::params_type create_fri_params(std::size_t degree_log, const i return params; } + // ******************************************************************************* // * Randomness setup // *******************************************************************************/ @@ -130,7 +133,7 @@ nil::crypto3::random::algebraic_engine test_global_alg_rnd_engine; struct test_initializer { // Enumerate all fields used in tests; using field1_type = algebra::curves::pallas::base_field_type; - + using field2_type = algebra::curves::bls12<381>::scalar_field_type; test_initializer() { test_global_seed = 0; @@ -153,6 +156,7 @@ struct test_initializer { BOOST_TEST_MESSAGE("test_global_seed = " << test_global_seed); test_global_rnd_engine = boost::random::mt11213b(test_global_seed); test_global_alg_rnd_engine = nil::crypto3::random::algebraic_engine(test_global_seed); + test_global_alg_rnd_engine = nil::crypto3::random::algebraic_engine(test_global_seed); } void setup() { @@ -174,7 +178,6 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit1) using merkle_hash_type = hashes::keccak_1600<256>; using transcript_hash_type = hashes::keccak_1600<256>; constexpr static const std::size_t table_rows_log = 4; - constexpr static const std::size_t table_rows = 1 << table_rows_log; struct placeholder_test_params { constexpr static const std::size_t table_rows = 1 << table_rows_log; @@ -205,16 +208,17 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit1) crypto3::zk::commitments::proof_of_work >; - using lpc_type = commitments::list_polynomial_commitment; using lpc_scheme_type = typename commitments::lpc_commitment_scheme; using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; + BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { auto circuit = circuit_test_1(test_global_alg_rnd_engine); + plonk_table_description desc; - desc.rows_amount = table_rows; + desc.rows_amount = placeholder_test_params::table_rows; desc.usable_rows_amount = placeholder_test_params::usable_rows; typename policy_type::constraint_system_type constraint_system( @@ -225,7 +229,6 @@ BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { ); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; @@ -259,7 +262,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2) using curve_type = algebra::curves::bls12<381>; using field_type = typename curve_type::scalar_field_type; - constexpr static const std::size_t table_rows_log = 4; + constexpr static const std::size_t table_rows_log = 3; constexpr static const std::size_t table_rows = 1 << table_rows_log; constexpr static const std::size_t permutation_size = 4; constexpr static const std::size_t usable_rows = (1 << table_rows_log) - 3; @@ -286,7 +289,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2) using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; - using lpc_params_type = commitments::list_polynomial_commitment_params< + using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, placeholder_test_params::lambda, @@ -298,6 +301,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2) using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; + BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { auto pi0 = test_global_alg_rnd_engine(); auto circuit = circuit_test_t(pi0, test_global_alg_rnd_engine, test_global_rnd_engine); @@ -314,7 +318,7 @@ BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { ); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; bool verifier_res; @@ -370,7 +374,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit3) using circuit_params = placeholder_circuit_params; using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; - using lpc_params_type = commitments::list_polynomial_commitment_params< + using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, placeholder_test_params::lambda, @@ -382,8 +386,10 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit3) using lpc_scheme_type = typename commitments::lpc_commitment_scheme; using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; + BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { - auto circuit = circuit_test_3(); + auto circuit = circuit_test_3(test_global_alg_rnd_engine, test_global_rnd_engine); + plonk_table_description desc; desc.rows_amount = table_rows; @@ -447,7 +453,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit4) using circuit_params = placeholder_circuit_params; using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; - using lpc_params_type = commitments::list_polynomial_commitment_params< + using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, placeholder_test_params::lambda, @@ -459,10 +465,12 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit4) using lpc_scheme_type = typename commitments::lpc_commitment_scheme; using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; + BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { - auto circuit = circuit_test_4(test_global_alg_rnd_engine, test_global_rnd_engine); + auto circuit = circuit_test_4(test_global_alg_rnd_engine); plonk_table_description desc; + desc.rows_amount = table_rows; desc.usable_rows_amount = usable_rows; @@ -505,7 +513,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit6) constexpr static const std::size_t table_rows_log = 3; constexpr static const std::size_t table_rows = 1 << table_rows_log; - constexpr static const std::size_t permutation_size = 3; + constexpr static const std::size_t permutation_size = 4; constexpr static const std::size_t usable_rows = 6; struct placeholder_test_params { @@ -526,7 +534,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit6) using circuit_params = placeholder_circuit_params; using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; - using lpc_params_type = commitments::list_polynomial_commitment_params< + using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, placeholder_test_params::lambda, @@ -538,10 +546,12 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit6) using lpc_scheme_type = typename commitments::lpc_commitment_scheme; using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; + BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { auto circuit = circuit_test_6(test_global_alg_rnd_engine, test_global_rnd_engine); plonk_table_description desc; + desc.rows_amount = table_rows; desc.usable_rows_amount = usable_rows; @@ -561,6 +571,7 @@ BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + auto printer = nil::blueprint::evm_verifier_printer( constraint_system, preprocessed_public_data.common_data, @@ -605,7 +616,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit7) using circuit_params = placeholder_circuit_params; using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; - using lpc_params_type = commitments::list_polynomial_commitment_params< + using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, placeholder_test_params::lambda, @@ -617,12 +628,14 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit7) using lpc_scheme_type = typename commitments::lpc_commitment_scheme; using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; + BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { auto circuit = circuit_test_7(test_global_alg_rnd_engine, test_global_rnd_engine); - plonk_table_description desc; - desc.rows_amount = table_rows; - desc.usable_rows_amount = usable_rows; + + desc.rows_amount = circuit.table_rows; + desc.usable_rows_amount = circuit.usable_rows; + std::size_t table_rows_log = std::log2(circuit.table_rows); typename policy_type::constraint_system_type constraint_system( circuit.gates, @@ -637,20 +650,644 @@ BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + transcript_type transcript; + typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + + auto printer = nil::blueprint::evm_verifier_printer( constraint_system, preprocessed_public_data.common_data, lpc_scheme, columns_with_copy_constraints.size(), "circuit7", - 26, /* gates library size threshold */ - 60, /* lookups library size threshold */ - 13, /* gates inline size threshold */ - 15 /* lookups inline size threshold */ + 26, // gates library size threshold + 60, // lookups library size threshold + 13, // gates inline size threshold + 15 // lookups inline size threshold ); printer.print(); } BOOST_AUTO_TEST_SUITE_END() + +#if 0 +BOOST_AUTO_TEST_SUITE(recursive_circuit1) + using Endianness = nil::marshalling::option::big_endian; + using TTypeBase = nil::marshalling::field_type; + + using curve_type = algebra::curves::pallas; + using field_type = typename curve_type::base_field_type; + using policy = hashes::detail::mina_poseidon_policy; + using merkle_hash_type = hashes::poseidon; + using transcript_hash_type = hashes::poseidon; + + constexpr static const std::size_t table_rows_log = 4; + constexpr static const std::size_t table_rows = 1 << table_rows_log; + + struct placeholder_test_params { + constexpr static const std::size_t table_rows = 1 << table_rows_log; + constexpr static const std::size_t permutation_size = 4; + constexpr static const std::size_t usable_rows = (1 << table_rows_log) - 3; + + constexpr static const std::size_t witness_columns = witness_columns_1; + constexpr static const std::size_t public_input_columns = public_columns_1; + constexpr static const std::size_t constant_columns = constant_columns_1; + constexpr static const std::size_t selector_columns = selector_columns_1; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 2; + constexpr static const std::size_t m = 2; + }; + typedef placeholder_circuit_params circuit_params; + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + + using lpc_params_type = commitments::list_polynomial_commitment_params< + merkle_hash_type, + transcript_hash_type, + placeholder_test_params::lambda, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; +BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { + auto circuit = circuit_test_1(test_global_alg_rnd_engine); + plonk_table_description desc; + + desc.rows_amount = table_rows; + desc.usable_rows_amount = placeholder_test_params::usable_rows; + + typename policy_type::constraint_system_type constraint_system( + circuit.gates, + circuit.copy_constraints, + circuit.lookup_gates, + circuit.lookup_tables + ); + typename policy_type::variable_assignment_type assignments = circuit.table; + + + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + + + typename lpc_type::fri_type::params_type fri_params = create_fri_params(table_rows_log); + lpc_scheme_type lpc_scheme(fri_params); + + typename placeholder_public_preprocessor::preprocessed_data_type + preprocessed_public_data = placeholder_public_preprocessor::process( + constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size() + ); + { + std::string cpp_path = "./circuit1/placeholder_verifier.cpp"; + std::ofstream output_file; + output_file.open(cpp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_recursive_verifier( + constraint_system, preprocessed_public_data.common_data, lpc_scheme, columns_with_copy_constraints.size() + ); + output_file.close(); + } + + typename placeholder_private_preprocessor::preprocessed_data_type + preprocessed_private_data = placeholder_private_preprocessor::process( + constraint_system, assignments.private_table(), desc); + + auto proof = placeholder_prover::process( + preprocessed_public_data, preprocessed_private_data, desc, constraint_system, assignments, lpc_scheme); + + bool verifier_res = placeholder_verifier::process( + preprocessed_public_data, proof, constraint_system, lpc_scheme); + BOOST_CHECK(verifier_res); + + { + std::string inp_path = "./circuit1/placeholder_verifier.inp"; + std::ofstream output_file; + output_file.open(inp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_input( + {}, preprocessed_public_data.common_data.vk, proof + ); + output_file.close(); + } + +/* auto printer = nil::blueprint::evm_verifier_printer( + constraint_system, + lpc_preprocessed_public_data.common_data, + lpc_scheme, + columns_with_copy_constraints.size(), + "circuit1", + 26, // gates library size threshold + 60, // lookups library size threshold + 13, // gates inline size threshold + 15 // lookups inline size threshold + ); + printer.print();*/ +} +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(recursive_circuit2) + using Endianness = nil::marshalling::option::big_endian; + using TTypeBase = nil::marshalling::field_type; + + using curve_type = algebra::curves::pallas; + using field_type = typename curve_type::base_field_type; + + struct placeholder_test_params { + using policy = hashes::detail::mina_poseidon_policy; + using merkle_hash_type = hashes::poseidon; + using transcript_hash_type = hashes::poseidon; + + constexpr static const std::size_t witness_columns = 3; + constexpr static const std::size_t public_input_columns = 1; + constexpr static const std::size_t constant_columns = 0; + constexpr static const std::size_t selector_columns = 2; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 10; + constexpr static const std::size_t m = 2; + }; + using circuit_t_params = placeholder_circuit_params< + field_type, + typename placeholder_test_params::arithmetization_params + >; + + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + + using lpc_params_type = commitments::list_polynomial_commitment_params< + typename placeholder_test_params::merkle_hash_type, + typename placeholder_test_params::transcript_hash_type, + placeholder_test_params::lambda, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; + +BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { + auto pi0 = test_global_alg_rnd_engine(); + auto circuit = circuit_test_t(pi0, test_global_alg_rnd_engine, test_global_rnd_engine); + + plonk_table_description desc; + desc.rows_amount = circuit.table_rows; + desc.usable_rows_amount = circuit.usable_rows; + auto table_rows_log = log2(circuit.table_rows); + + typename policy_type::constraint_system_type constraint_system( + circuit.gates, + circuit.copy_constraints, + circuit.lookup_gates, + circuit.lookup_tables + ); + typename policy_type::variable_assignment_type assignments = circuit.table; + + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + + // LPC commitment scheme + typename lpc_type::fri_type::params_type fri_params = create_fri_params(table_rows_log); + lpc_scheme_type lpc_scheme(fri_params); + + typename placeholder_public_preprocessor::preprocessed_data_type + preprocessed_public_data = placeholder_public_preprocessor::process( + constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size() + ); + { + std::string cpp_path = "./circuit2/placeholder_verifier.cpp"; + std::ofstream output_file; + output_file.open(cpp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_recursive_verifier( + constraint_system, preprocessed_public_data.common_data, lpc_scheme, columns_with_copy_constraints.size() + ); + output_file.close(); + } + + typename placeholder_private_preprocessor::preprocessed_data_type + preprocessed_private_data = placeholder_private_preprocessor::process( + constraint_system, assignments.private_table(), desc); + + auto proof = placeholder_prover::process( + preprocessed_public_data, preprocessed_private_data, desc, constraint_system, assignments, lpc_scheme); + + bool verifier_res = placeholder_verifier::process( + preprocessed_public_data, proof, constraint_system, lpc_scheme); + BOOST_CHECK(verifier_res); + + std::string inp_path = "./circuit2/placeholder_verifier.inp"; + std::ofstream output_file; + output_file.open(inp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_input( + {}, preprocessed_public_data.common_data.vk, proof + ); + output_file.close(); + +/* auto printer = nil::blueprint::evm_verifier_printer( + constraint_system, + lpc_preprocessed_public_data.common_data, + lpc_scheme, + columns_with_copy_constraints.size(), + "circuit2", + 26, // gates library size threshold + 60, // lookups library size threshold + 13, // gates inline size threshold + 15 // lookups inline size threshold + ); + printer.print();*/ +} +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(recursive_circuit3) + using Endianness = nil::marshalling::option::big_endian; + using TTypeBase = nil::marshalling::field_type; + using curve_type = algebra::curves::pallas; + using field_type = typename curve_type::base_field_type; + + constexpr static const std::size_t table_rows_log = 3; + constexpr static const std::size_t table_rows = 1 << table_rows_log; + constexpr static const std::size_t permutation_size = 4; + constexpr static const std::size_t usable_rows = 4; + + struct placeholder_test_params { + using policy = hashes::detail::mina_poseidon_policy; + using merkle_hash_type = hashes::poseidon; + using transcript_hash_type = hashes::poseidon; + + constexpr static const std::size_t witness_columns = witness_columns_3; + constexpr static const std::size_t public_input_columns = public_columns_3; + constexpr static const std::size_t constant_columns = constant_columns_3; + constexpr static const std::size_t selector_columns = selector_columns_3; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 10; + constexpr static const std::size_t m = 2; + }; + + using circuit_params = placeholder_circuit_params; + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + using lpc_params_type = commitments::list_polynomial_commitment_params< + typename placeholder_test_params::merkle_hash_type, + typename placeholder_test_params::transcript_hash_type, + placeholder_test_params::lambda, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; +BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { + auto circuit = circuit_test_3(); + plonk_table_description desc; + + desc.rows_amount = table_rows; + desc.usable_rows_amount = usable_rows; + + typename policy_type::constraint_system_type constraint_system( + circuit.gates, + circuit.copy_constraints, + circuit.lookup_gates, + circuit.lookup_tables + ); + typename policy_type::variable_assignment_type assignments = circuit.table; + + auto fri_params = create_fri_params(table_rows_log); + lpc_scheme_type lpc_scheme(fri_params); + + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + + typename placeholder_public_preprocessor::preprocessed_data_type + preprocessed_public_data = placeholder_public_preprocessor::process( + constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + { + std::string cpp_path = "./circuit3/placeholder_verifier.cpp"; + std::ofstream output_file; + output_file.open(cpp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_recursive_verifier( + constraint_system, preprocessed_public_data.common_data, lpc_scheme, permutation_size + ); + output_file.close(); + } + + typename placeholder_private_preprocessor::preprocessed_data_type + preprocessed_private_data = placeholder_private_preprocessor::process( + constraint_system, assignments.private_table(), desc); + + auto proof = placeholder_prover::process( + preprocessed_public_data, preprocessed_private_data, desc, constraint_system, assignments, lpc_scheme); + + bool verifier_res = placeholder_verifier::process( + preprocessed_public_data, proof, constraint_system, lpc_scheme); + BOOST_CHECK(verifier_res); + + { + std::string inp_path = "./circuit3/placeholder_verifier.inp"; + std::ofstream output_file; + output_file.open(inp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_input( + {}, preprocessed_public_data.common_data.vk, proof + ); + output_file.close(); + } +} +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(recursive_circuit4) + using curve_type = algebra::curves::pallas; + using field_type = typename curve_type::base_field_type; + + constexpr static const std::size_t table_rows_log = 3; + constexpr static const std::size_t table_rows = 1 << table_rows_log; + constexpr static const std::size_t permutation_size = 4; + constexpr static const std::size_t usable_rows = 5; + + struct placeholder_test_params { + using policy = hashes::detail::mina_poseidon_policy; + using merkle_hash_type = hashes::poseidon; + using transcript_hash_type = hashes::poseidon; + + constexpr static const std::size_t witness_columns = witness_columns_4; + constexpr static const std::size_t public_input_columns = public_columns_4; + constexpr static const std::size_t constant_columns = constant_columns_4; + constexpr static const std::size_t selector_columns = selector_columns_4; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 40; + constexpr static const std::size_t m = 2; + }; + + using circuit_params = placeholder_circuit_params; + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + using lpc_params_type = commitments::list_polynomial_commitment_params< + typename placeholder_test_params::merkle_hash_type, + typename placeholder_test_params::transcript_hash_type, + placeholder_test_params::lambda, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; +BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { + auto circuit = circuit_test_4(test_global_alg_rnd_engine, test_global_rnd_engine); + + plonk_table_description desc; + desc.rows_amount = table_rows; + desc.usable_rows_amount = usable_rows; + + typename policy_type::constraint_system_type constraint_system( + circuit.gates, + circuit.copy_constraints, + circuit.lookup_gates, + circuit.lookup_tables + ); + typename policy_type::variable_assignment_type assignments = circuit.table; + + auto fri_params = create_fri_params(table_rows_log); + lpc_scheme_type lpc_scheme(fri_params); + + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + + typename placeholder_public_preprocessor::preprocessed_data_type + preprocessed_public_data = placeholder_public_preprocessor::process( + constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + { + std::string cpp_path = "./circuit4/placeholder_verifier.cpp"; + std::ofstream output_file; + output_file.open(cpp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_recursive_verifier( + constraint_system, preprocessed_public_data.common_data, lpc_scheme, permutation_size + ); + output_file.close(); + } + + typename placeholder_private_preprocessor::preprocessed_data_type + preprocessed_private_data = placeholder_private_preprocessor::process( + constraint_system, assignments.private_table(), desc); + + auto proof = placeholder_prover::process( + preprocessed_public_data, preprocessed_private_data, desc, constraint_system, assignments, lpc_scheme); + + bool verifier_res = placeholder_verifier::process( + preprocessed_public_data, proof, constraint_system, lpc_scheme); + BOOST_CHECK(verifier_res); + + { + std::string inp_path = "./circuit4/placeholder_verifier.inp"; + std::ofstream output_file; + output_file.open(inp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_input( + {}, preprocessed_public_data.common_data.vk, proof + ); + output_file.close(); + } +} +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(recursive_circuit6) + using Endianness = nil::marshalling::option::big_endian; + using TTypeBase = nil::marshalling::field_type; + using curve_type = algebra::curves::pallas; + using field_type = typename curve_type::base_field_type; + + constexpr static const std::size_t table_rows_log = 3; + constexpr static const std::size_t table_rows = 1 << table_rows_log; + constexpr static const std::size_t permutation_size = 3; + constexpr static const std::size_t usable_rows = 6; + + struct placeholder_test_params { + using policy = hashes::detail::mina_poseidon_policy; + using merkle_hash_type = hashes::poseidon; + using transcript_hash_type = hashes::poseidon; + + constexpr static const std::size_t witness_columns = witness_columns_6; + constexpr static const std::size_t public_input_columns = public_columns_6; + constexpr static const std::size_t constant_columns = constant_columns_6; + constexpr static const std::size_t selector_columns = selector_columns_6; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 10; + constexpr static const std::size_t m = 2; + }; + + using circuit_params = placeholder_circuit_params; + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + using lpc_params_type = commitments::list_polynomial_commitment_params< + typename placeholder_test_params::merkle_hash_type, + typename placeholder_test_params::transcript_hash_type, + placeholder_test_params::lambda, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; +BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { + auto circuit = circuit_test_6(test_global_alg_rnd_engine, test_global_rnd_engine); + + plonk_table_description desc; + desc.rows_amount = table_rows; + desc.usable_rows_amount = usable_rows; + + typename policy_type::constraint_system_type constraint_system( + circuit.gates, + circuit.copy_constraints, + circuit.lookup_gates, + circuit.lookup_tables + ); + typename policy_type::variable_assignment_type assignments = circuit.table; + + auto fri_params = create_fri_params(table_rows_log); + lpc_scheme_type lpc_scheme(fri_params); + + std::vector columns_with_copy_constraints = {0, 1, 2}; + + typename placeholder_public_preprocessor::preprocessed_data_type + preprocessed_public_data = placeholder_public_preprocessor::process( + constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + { + std::string cpp_path = "./circuit6/placeholder_verifier.cpp"; + std::ofstream output_file; + output_file.open(cpp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_recursive_verifier( + constraint_system, preprocessed_public_data.common_data, lpc_scheme, permutation_size + ); + output_file.close(); + } + + std::cout << std::endl << std::endl; + + typename placeholder_private_preprocessor::preprocessed_data_type + preprocessed_private_data = placeholder_private_preprocessor::process( + constraint_system, assignments.private_table(), desc); + + auto proof = placeholder_prover::process( + preprocessed_public_data, preprocessed_private_data, desc, constraint_system, assignments, lpc_scheme); + + bool verifier_res = placeholder_verifier::process( + preprocessed_public_data, proof, constraint_system, lpc_scheme); + BOOST_CHECK(verifier_res); + + { + std::string inp_path = "./circuit6/placeholder_verifier.inp"; + std::ofstream output_file; + output_file.open(inp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_input( + {}, preprocessed_public_data.common_data.vk, proof + ); + output_file.close(); + } +} +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(recursive_circuit7) + using Endianness = nil::marshalling::option::big_endian; + using TTypeBase = nil::marshalling::field_type; + using curve_type = algebra::curves::pallas; + using field_type = typename curve_type::base_field_type; + + constexpr static const std::size_t table_rows_log = 4; + constexpr static const std::size_t table_rows = 1 << table_rows_log; + constexpr static const std::size_t permutation_size = 4; + constexpr static const std::size_t usable_rows = 14; + + struct placeholder_test_params { + using policy = hashes::detail::mina_poseidon_policy; + using merkle_hash_type = hashes::poseidon; + using transcript_hash_type = hashes::poseidon; + + constexpr static const std::size_t witness_columns = witness_columns_7; + constexpr static const std::size_t public_input_columns = public_columns_7; + constexpr static const std::size_t constant_columns = constant_columns_7; + constexpr static const std::size_t selector_columns = selector_columns_7; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 10; + constexpr static const std::size_t m = 2; + }; + + using circuit_params = placeholder_circuit_params; + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + using lpc_params_type = commitments::list_polynomial_commitment_params< + typename placeholder_test_params::merkle_hash_type, + typename placeholder_test_params::transcript_hash_type, + placeholder_test_params::lambda, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; +BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { + auto circuit = circuit_test_7(test_global_alg_rnd_engine, test_global_rnd_engine); + plonk_table_description desc; + + desc.rows_amount = circuit.table_rows; + desc.usable_rows_amount = circuit.usable_rows; + std::size_t table_rows_log = std::log2(circuit.table_rows); + + typename policy_type::constraint_system_type constraint_system( + circuit.gates, + circuit.copy_constraints, + circuit.lookup_gates, + circuit.lookup_tables + ); + typename policy_type::variable_assignment_type assignments = circuit.table; + + auto fri_params = create_fri_params(table_rows_log); + lpc_scheme_type lpc_scheme(fri_params); + + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + transcript_type transcript; + + typename placeholder_public_preprocessor::preprocessed_data_type + preprocessed_public_data = placeholder_public_preprocessor::process( + constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + { + std::string cpp_path = "./circuit7/placeholder_verifier.cpp"; + std::ofstream output_file; + output_file.open(cpp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_recursive_verifier( + constraint_system, preprocessed_public_data.common_data, lpc_scheme, permutation_size + ); + output_file.close(); + } + + typename placeholder_private_preprocessor::preprocessed_data_type + preprocessed_private_data = placeholder_private_preprocessor::process( + constraint_system, assignments.private_table(), desc); + + auto proof = placeholder_prover::process( + preprocessed_public_data, preprocessed_private_data, desc, constraint_system, assignments, lpc_scheme); + + bool verifier_res = placeholder_verifier::process( + preprocessed_public_data, proof, constraint_system, lpc_scheme); + BOOST_CHECK(verifier_res); + + { + std::string inp_path = "./circuit7/placeholder_verifier.inp"; + std::ofstream output_file; + output_file.open(inp_path); + output_file << nil::blueprint::recursive_verifier_generator::generate_input( + {}, preprocessed_public_data.common_data.vk, proof + ); + output_file.close(); + } +} +BOOST_AUTO_TEST_SUITE_END() +#endif