diff --git a/include/nil/blueprint/transpiler/evm_verifier_gen.hpp b/include/nil/blueprint/transpiler/evm_verifier_gen.hpp index a4241e0..f144b22 100644 --- a/include/nil/blueprint/transpiler/evm_verifier_gen.hpp +++ b/include/nil/blueprint/transpiler/evm_verifier_gen.hpp @@ -598,6 +598,7 @@ namespace nil { } else { 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; @@ -794,6 +795,7 @@ namespace nil { if (fixed_poly_values.size() == 0) return ""; + result << "\t\t\t///* 1 - 2*permutation_size */" << std::endl; std::vector eta_buf; std::size_t poly_points = 2*_permutation_size; @@ -806,7 +808,7 @@ namespace nil { std::array empty; auto writer = eta_buf.begin(); - result << "\t\t/* eta points check */" << std::endl; + result << "\t\t///* eta points check */" << std::endl; result << "\t\t{" << std::endl; result << "\t\t\tuint256[" << poly_points << "] memory points;" << std::endl; @@ -883,8 +885,6 @@ namespace nil { void print(){ std::filesystem::create_directory(_folder_name); - std::cout << "Generating verifier " << _test_name << std::endl; - std::string gate_argument = print_gate_argument(); std::string lookup_argument = print_lookup_argument(); diff --git a/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp b/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp index fbd0df2..178c515 100644 --- a/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp +++ b/include/nil/blueprint/transpiler/recursive_verifier_generator.hpp @@ -45,18 +45,24 @@ namespace nil { namespace blueprint { - template + template struct recursive_verifier_generator{ using field_type = typename PlaceholderParams::field_type; using arithmetization_params = typename PlaceholderParams::arithmetization_params; - using proof_type = nil::crypto3::zk::snark::placeholder_proof; - using common_data_type = typename nil::crypto3::zk::snark::placeholder_public_preprocessor::preprocessed_data_type::common_data_type; + 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 = nil::crypto3::zk::snark::plonk_variable; + 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; + using assignment_table_type = typename PlaceholderParams::assignment_table_type; // TODO: Move logic to utils.hpp. It's similar to EVM verifier generator static std::string zero_indices(columns_rotations_type col_rotations){ @@ -111,13 +117,12 @@ namespace nil { 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 + } else if constexpr(std::is_same>::value){ + return "{\"field\": \"" << hashed_data << "\"}"; + } else { 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"; @@ -125,182 +130,244 @@ namespace nil { template static inline std::string generate_commitment(typename CommitmentSchemeType::commitment_type commitment) { - if constexpr(std::is_same< - CommitmentSchemeType, - nil::crypto3::zk::commitments::lpc_commitment_scheme - >::value - ){ - return generate_hash(commitment); - } else if constexpr(nil::crypto3::hashes::is_poseidon::value){ - std::cout << "Poseidon" << std::endl; - return generate_hash(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()); } - BOOST_ASSERT_MSG(false, "unsupported commitment scheme type"); - return "unsupported commitment scheme type"; + 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 constexpr(std::is_same< - CommitmentSchemeType, - nil::crypto3::zk::commitments::lpc_commitment_scheme - >::value - ){ - 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"; - } + 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::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){ + 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 << "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]; + } + 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(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] << "\"}"; + 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 << "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{\"field\":" << 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( 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++; } - 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; + + 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{\"int\":" << initial_proof.p.path()[k][0].position() << "}"; + cur ++; } + break; } - out << std::endl << "\t\t]}," << std::endl; - + } + 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{\"field\": " << p.path()[k][0].position() << "}"; - cur++; - } + 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; - - 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; + + 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; - - 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]}," << 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]}"; - - return out.str(); } + out << std::endl << "\t\t]}," << 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 + const typename assignment_table_type::public_input_container_type &public_inputs, + const proof_type &proof, + const std::array public_input_sizes ){ std::stringstream out; out << "[" << std::endl; + out << "\t{\"array\":[" << std::endl; + std::size_t cur = 0; + for(std::size_t i = 0; i < arithmetization_params::public_input_columns; i++){ + std::size_t max_non_zero = 0; + for(std::size_t j = 0; j < public_inputs[i].size(); j++){ + if( public_inputs[i][j] != 0 ) max_non_zero = j; + } + if( max_non_zero + 1 > public_input_sizes[i] ) { + std::cout << "Public input size is larger than reserved. Real size = " << max_non_zero + 1 << " reserved = " << public_input_sizes[i] << std::endl; + exit(1); + } + BOOST_ASSERT(max_non_zero <= public_input_sizes[i]); + for(std::size_t j = 0; j < public_input_sizes[i]; j++){ + if(cur != 0) out << "," << std::endl; + if( j >= public_inputs[i].size() ) + out << "\t\t{\"field\": \"" << typename field_type::value_type(0) << "\"}"; + else + out << "\t\t{\"field\": \"" << public_inputs[i][j] << "\"}"; + cur++; + } + } + out << std::endl << "\t]}," << std::endl; + std::cout << "Public input: " << out.str() << std::endl; + out << "\t{\"array\":[" << std::endl; out << "\t\t" << generate_hash( vk.constraint_system_with_params_hash @@ -312,15 +379,22 @@ namespace nil { 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(nil::crypto3::zk::snark::VARIABLE_VALUES_BATCH) - ) << "," << std::endl; - out << "\t\t\t" << generate_commitment( - proof.commitments.at(nil::crypto3::zk::snark::PERMUTATION_BATCH) - ) << "," << std::endl; + proof.commitments.at(2))//(nil::crypto3::zk::snark::PERMUTATION_BATCH) + << "," << std::endl; out << "\t\t\t" << generate_commitment( - proof.commitments.at(nil::crypto3::zk::snark::QUOTIENT_BATCH) - ) << std::endl; + 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( @@ -334,7 +408,6 @@ namespace nil { // 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){ - using variable_type = nil::crypto3::zk::snark::plonk_variable; std::map result; std::size_t j = 0; for(std::size_t i = 0; i < PlaceholderParams::constant_columns; i++){ @@ -376,11 +449,11 @@ namespace nil { public: expression_gen_code_visitor(const variable_indices_type &var_indices) :_indices(var_indices){} - std::string generate_expression(const nil::crypto3::math::expression& expr) { + std::string generate_expression(const expression_type& expr) { return boost::apply_visitor(*this, expr.get_expr()); } - std::string operator()(const nil::crypto3::math::term& term) { + 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) @@ -396,133 +469,465 @@ namespace nil { } std::string operator()( - const nil::crypto3::math::pow_operation& pow) { + const pow_operation_type& pow) { std::string result = boost::apply_visitor(*this, pow.get_expr().get_expr()); - return "pow(" + result + ", " + to_string(pow.get_power()) + ")"; + return "pow" + to_string(pow.get_power()) + "(" + result +")"; } std::string operator()( - const nil::crypto3::math::binary_arithmetic_operation& op) { + 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 nil::crypto3::math::ArithmeticOperator::ADD: + case binary_operation_type::ArithmeticOperatorType::ADD: return "(" + left + " + " + right + ")"; - case nil::crypto3::math::ArithmeticOperator::SUB: + case binary_operation_type::ArithmeticOperatorType::SUB: return "(" + left + " - " + right + ")"; - case nil::crypto3::math::ArithmeticOperator::MULT: + 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){ + found = true; + points_ids.push_back(j); + break; + } + j++; + } + BOOST_ASSERT(found); + } + + for( const auto &p: unique_points){ + result.push_back(split_point_string(p)); + } + + 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::size_t permutation_size, + const std::array public_input_sizes ){ - if constexpr(std::is_same< - commitment_scheme_type, - nil::crypto3::zk::commitments::lpc_commitment_scheme - >::value - ){ - 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; - 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 rows_amount = common_data.rows_amount; - std::size_t quotient_degree = (permutation_size + 1)* (common_data.rows_amount -1 ); - 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::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::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::cout << visitor.generate_expression(constraint_system.gates()[i].constraints[j]) << std::endl; - std::cout << constraint_system.gates()[i].constraints[j] << std::endl; + std::string result = nil::blueprint::recursive_verifier_template; + bool use_lookups = constraint_system.lookup_gates().size() > 0; + transpiler_replacements lookup_reps; + transpiler_replacements reps; + + auto fri_params = commitment_scheme.get_commitment_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; + 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]))); + } + 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(); + } + } - 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(log2(fri_params.D[0]->m) - fri_params.r); - 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_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["$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); - - result = replace_all(result, reps); - return result; + std::size_t rows_amount = common_data.rows_amount; + std::size_t quotient_degree = std::max( + (permutation_size + 2) * (common_data.rows_amount -1 ), + (lookup_degree + 1) * (common_data.rows_amount -1 ) + ); + + std::size_t quotient_polys = (quotient_degree % rows_amount != 0)? (quotient_degree / rows_amount + 1): (quotient_degree / rows_amount); + + 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::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; } - BOOST_ASSERT_MSG(false, "unsupported commitment scheme type"); - return "unsupported commitment scheme type"; + 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(); + } + points_num += use_lookups? 4 : 2; + points_num += quotient_polys; + + if( use_lookups ) { + points_num += constraint_system.sorted_lookup_columns_number() * 3; + } + + + 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::cout << "Printing" << std::endl; + + 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::string public_input_sizes_str = ""; + std::size_t full_public_input_size = 0; + for(std::size_t i = 0; i < public_input_sizes.size(); i++){ + if(i != 0) public_input_sizes_str += ", "; + public_input_sizes_str += to_string(public_input_sizes[i]); + full_public_input_size += public_input_sizes[i]; + } + + 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()); + + lookup_reps["$LOOKUP_VARS$"] = use_lookups?lookup_vars:""; + lookup_reps["$LOOKUP_EXPRESSIONS$"] = use_lookups?lookup_expressions:""; + lookup_reps["$LOOKUP_CODE$"] = use_lookups?lookup_code:""; + result = replace_all(result, lookup_reps); + + 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; + reps["$PUBLIC_INPUT_SIZES$"] = public_input_sizes_str; + reps["$FULL_PUBLIC_INPUT_SIZE$"] = to_string(full_public_input_size); + + result = replace_all(result, reps); + return result; } }; } diff --git a/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp b/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp index 7ad346c..9462faa 100644 --- a/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp +++ b/include/nil/blueprint/transpiler/templates/recursive_verifier.hpp @@ -5,6 +5,152 @@ namespace nil { namespace blueprint { + std::string lookup_vars = R"( +#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 + )"; + + std::string lookup_expressions = R"( +#ifdef __USE_LOOKUPS__ +std::array calculate_lookup_expressions(std::array z){ + std::array expressions; +$LOOKUP_EXPRESSIONS_BODY$ + + return expressions; +} +#endif + )"; + + std::string lookup_code = R"( +#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 = precomputed_values.l0; + 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 + )"; + std::string recursive_verifier_template = R"( #include #include @@ -13,7 +159,16 @@ namespace nil { using namespace nil::crypto3; using namespace nil::crypto3::algebra::curves; -const bool use_lookups = false; +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 std::array public_input_sizes = {$PUBLIC_INPUT_SIZES$}; +const std::size_t full_public_input_size = $FULL_PUBLIC_INPUT_SIZE$; + +namespace placeholder_verifier{ + +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$; @@ -29,19 +184,30 @@ 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$; -std::array gates_sizes = {$GATES_SIZES$}; +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$; +const std::array batches_amount_list = {$BATCHES_AMOUNT_LIST$}; + +$LOOKUP_VARS$ struct placeholder_proof_type{ std::array commitments; @@ -50,9 +216,9 @@ struct placeholder_proof_type{ std::array fri_roots; std::array initial_proof_values; std::array round_proof_values; - std::array initial_proof_positions; + std::array initial_proof_positions; std::array initial_proof_hashes; - std::array round_merkle_proof_positions; + std::array round_merkle_proof_positions; std::array round_proof_hashes; std::array final_polynomial; }; @@ -64,11 +230,12 @@ struct placeholder_challenges_type{ 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; + 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; }; @@ -82,12 +249,108 @@ struct placeholder_permutation_argument_input_type{ permutation_argument_thetas_type thetas; }; -pallas::base_field_type::value_type transcript(pallas::base_field_type::value_type tr_state, pallas::base_field_type::value_type value) { - return hash(value, hash(tr_state, tr_state)); +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) { + if(tr_state.cur == 3){ + 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; + } + 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; } -std::pair transcript_challenge(pallas::base_field_type::value_type tr_state) { - return std::make_pair(hash(tr_state, tr_state), hash(tr_state, tr_state)); +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( @@ -96,59 +359,69 @@ placeholder_challenges_type generate_challenges( ){ placeholder_challenges_type challenges; - pallas::base_field_type::value_type tr_state(0x2fadbe2852044d028597455bc2abbd1bc873af205dfabb8a304600f3e09eeba8_cppui255); + 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; - tr_state = transcript(tr_state, vk[0]); - tr_state = transcript(tr_state, vk[1]); + transcript(tr_state, vk[0]); + transcript(tr_state, vk[1]); // LPC additional point - std::tie(tr_state, challenges.fri_etha) = transcript_challenge(tr_state); + challenges.fri_etha = transcript_challenge(tr_state); - tr_state = transcript(tr_state, proof.commitments[0]); + transcript(tr_state, proof.commitments[0]); - std::tie(tr_state, challenges.perm_beta) = transcript_challenge(tr_state); - std::tie(tr_state, challenges.perm_gamma) = transcript_challenge(tr_state); + challenges.perm_beta = transcript_challenge(tr_state); + challenges.perm_gamma = transcript_challenge(tr_state); // Call lookup argument if( use_lookups ){ - __builtin_assigner_exit_check(false); + 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 - tr_state = transcript(tr_state, proof.commitments[1]); - std::tie(tr_state, challenges.gate_theta) = transcript_challenge(tr_state); + transcript(tr_state, proof.commitments[1]); + challenges.gate_theta = transcript_challenge(tr_state); for(std::size_t i = 0; i < 8; i++){ - std::tie(tr_state, challenges.alphas[i]) = transcript_challenge(tr_state); + 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]); } - tr_state = transcript(tr_state, proof.commitments[2]); - std::tie(tr_state, challenges.xi) = transcript_challenge(tr_state); + challenges.lpc_theta = transcript_challenge(tr_state); for(std::size_t i = 0; i < fri_roots_num; i++){ - tr_state = transcript(tr_state, proof.fri_roots[i]); - std::tie(tr_state, challenges.fri_alphas[i]) = transcript_challenge(tr_state); + transcript(tr_state, proof.fri_roots[i]); + challenges.fri_alphas[i] = transcript_challenge(tr_state); } for(std::size_t i = 0; i < lambda; i++){ - std::tie(tr_state, challenges.fri_x_indices[i]) = transcript_challenge(tr_state); + challenges.fri_x_indices[i] = transcript_challenge(tr_state); } return challenges; } -pallas::base_field_type::value_type pow(pallas::base_field_type::value_type x, size_t p){ - pallas::base_field_type::value_type result = x; - for(std::size_t i = 1; i < p; i++){ - result = result * x; - } - return result; -} - std::pair xi_polys( pallas::base_field_type::value_type xi ){ - pallas::base_field_type::value_type xi_n = pow(xi, rows_amount) - pallas::base_field_type::value_type(1); + 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); @@ -161,6 +434,8 @@ std::array calculate_co return constraints; } +$LOOKUP_EXPRESSIONS$ + typename pallas::base_field_type::value_type gate_argument_verifier( std::array selectors, @@ -170,7 +445,7 @@ typename pallas::base_field_type::value_type return __builtin_assigner_gate_arg_verifier( selectors.data(), - (int*)gates_sizes.data(), + (int*)&gates_sizes, gates_amount, constraints.data(), constraints_amount, @@ -178,22 +453,182 @@ typename pallas::base_field_type::value_type ); } +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; +} +struct precomputed_values_type{ + pallas::base_field_type::value_type l0; + pallas::base_field_type::value_type Z_at_xi; + pallas::base_field_type::value_type F_consolidated; + pallas::base_field_type::value_type T_consolidated; +}; + 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 public_input, 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); + precomputed_values_type precomputed_values; + std::tie(precomputed_values.l0, precomputed_values.Z_at_xi) = xi_polys(challenges.xi); - std::array F = {0,0,0,0,0,0,0,0}; + std::array F;// = {0,0,0,0,0,0,0,0}; + F[0] = pallas::base_field_type::value_type(0); + F[1] = pallas::base_field_type::value_type(0); + F[2] = pallas::base_field_type::value_type(0); + F[3] = pallas::base_field_type::value_type(0); + F[4] = pallas::base_field_type::value_type(0); + F[5] = pallas::base_field_type::value_type(0); + F[6] = pallas::base_field_type::value_type(0); + F[7] = pallas::base_field_type::value_type(0); // Call permutation argument placeholder_permutation_argument_input_type perm_arg_input; @@ -211,7 +646,7 @@ constexpr std::size_t T_CONSOLIDATED_IND = 3; perm_arg_input.id_perm.data(), perm_arg_input.sigma_perm.data(), permutation_size, - different_values[L0_IND], + precomputed_values.l0, 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 @@ -222,16 +657,18 @@ constexpr std::size_t T_CONSOLIDATED_IND = 3; F[0] = permutation_argument[0]; F[1] = permutation_argument[1]; F[2] = permutation_argument[2]; - { + + $LOOKUP_CODE$ + + 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[i + witness_amount+public_input_amount + constant_amount]]; + 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, @@ -240,24 +677,152 @@ constexpr std::size_t T_CONSOLIDATED_IND = 3; 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); + precomputed_values.F_consolidated = 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]; + precomputed_values.F_consolidated += F[i]; } - different_values[T_CONSOLIDATED_IND] = pallas::base_field_type::value_type(0); + precomputed_values.T_consolidated = 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)); + precomputed_values.T_consolidated += proof.z[quotient_polys_start + i] * factor; + factor *= (precomputed_values.Z_at_xi + 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])); + __builtin_assigner_exit_check(precomputed_values.F_consolidated == precomputed_values.T_consolidated * precomputed_values.Z_at_xi); + + // 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, 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; + y[0] = pallas::base_field_type::value_type(0); + y[1] = pallas::base_field_type::value_type(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 +#endif //__RECURSIVE_VERIFIER_TEMPLATE_HPP__ 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