diff --git a/include/nil/blueprint/transpiler/templates/modular_verifier.hpp b/include/nil/blueprint/transpiler/templates/modular_verifier.hpp index 089b685..b75cc6f 100644 --- a/include/nil/blueprint/transpiler/templates/modular_verifier.hpp +++ b/include/nil/blueprint/transpiler/templates/modular_verifier.hpp @@ -103,7 +103,6 @@ contract modular_verifier_$TEST_NAME$ is IModularVerifier{ uint256 Z_at_xi; uint256 l0; uint256[f_parts] F; - uint256 gas; bool b; } @@ -151,10 +150,9 @@ contract modular_verifier_$TEST_NAME$ is IModularVerifier{ function verify( bytes calldata blob, uint256[] calldata public_input - ) public view returns (bool result) { + ) public returns (bool result) { verifier_state memory state; state.b = true; - state.gas = gasleft(); state.xi = basic_marshalling.get_uint256_be(blob, $EVAL_PROOF_OFFSET$); state.Z_at_xi = addmod(field.pow_small(state.xi, rows_amount, modulus), modulus-1, modulus); state.l0 = mulmod( @@ -166,7 +164,7 @@ contract modular_verifier_$TEST_NAME$ is IModularVerifier{ //0. Direct public input check if(public_input.length > 0) { if (!public_input_direct(blob[$TABLE_Z_OFFSET$:$TABLE_Z_OFFSET$+$QUOTIENT_OFFSET$], public_input, state)) { - console.log("Wrong public input!"); + emit WrongPublicInput(); state.b = false; } } @@ -225,7 +223,6 @@ contract modular_verifier_$TEST_NAME$ is IModularVerifier{ F_consolidated = addmod(F_consolidated, mulmod(state.F[i],transcript.get_field_challenge(tr_state, modulus), modulus), modulus); unchecked{i++;} } - uint256 points_num = basic_marshalling.get_length(blob, $EVAL_PROOF_OFFSET$ + 0x20); transcript.update_transcript_b32_by_offset_calldata(tr_state, blob, 0x59); } @@ -241,7 +238,7 @@ contract modular_verifier_$TEST_NAME$ is IModularVerifier{ if(!modular_commitment_scheme_$TEST_NAME$.verify_eval( blob[z_offset - 0x8:], commitments, state.xi, tr_state.current_challenge )) { - console.log("Error from commitment scheme!"); + emit WrongCommitment(); state.b = false; } } @@ -260,13 +257,16 @@ contract modular_verifier_$TEST_NAME$ is IModularVerifier{ unchecked{i++;} } if( F_consolidated != mulmod(T_consolidated, state.Z_at_xi, modulus) ) { - console.log("Error. Table does't satisfy constraint system"); + emit ConstraintSystemNotSatisfied(); state.b = false; } - if(state.b) console.log("SUCCESS!"); else console.log("FAILURE!"); + if(state.b) { + emit ProofVerified(); + } else { + emit ProofVerificationFailed(); + } } - console.log("Gas for verification:", state.gas-gasleft()); result = state.b; } } diff --git a/test/detail/circuits.hpp b/test/detail/circuits.hpp index 1979546..91dd79b 100644 --- a/test/detail/circuits.hpp +++ b/test/detail/circuits.hpp @@ -246,7 +246,7 @@ namespace nil { 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() + boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; @@ -603,148 +603,165 @@ namespace nil { } - // 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; + //---------------------------------------------------------------------------// + // Test circuit 5 (with two public columns) + // + // rows_log = 4, k = 16-3 (total_rows), + // + // i | GATE | w_0 | w_1 | w_2 | public | public | q_add | q_mul | + // 0 | -- | x | y | z | p1 | 0 | 0 | 0 | + // 1 | ADD | x | y | z | 0 | p2 | 1 | 0 | + // 2 | ADD | x | y | z | 0 | 0 | 1 | 0 | + // ... | ADD | x | y | z | 0 | 0 | 1 | 0 | + // k-3 | ADD | x | y | z | 0 | 0 | 1 | 0 | + // k-2 | MUL | x | y | z | 0 | 0 | 0 | 1 | + // k-1 | MUL | x | y | z | 0 | 0 | 0 | 1 | + // + // ADD: x + y = z, copy(prev(z), y) + // MUL: x * y + prev(x) = z, copy(p1, y), copy(p2, z) + // + //---------------------------------------------------------------------------// + constexpr static const std::size_t witness_columns_5 = 3; + constexpr static const std::size_t public_columns_5 = 2; + constexpr static const std::size_t constant_columns_5 = 0; + constexpr static const std::size_t selector_columns_5 = 2; + constexpr static const std::size_t rows_log_5 = 4; + constexpr static const std::size_t permutation_5 = 4; using arithmetization_params_5 = plonk_arithmetization_params; template - circuit_description, 4, 3> circuit_test_5() { + circuit_description, rows_log_5, permutation_5> + circuit_test_t( + typename FieldType::value_type pi0 = 0, + typename FieldType::value_type pi1 = 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 = 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; + 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); for (std::size_t j = 0; j < table_columns; j++) { table[j].resize(test_circuit.table_rows); } - // lookup inputs + // init values typename FieldType::value_type one = FieldType::value_type::one(); typename FieldType::value_type zero = FieldType::value_type::zero(); + table[0][0] = algebra::random_element(); + table[1][0] = algebra::random_element(); + table[2][0] = algebra::random_element(); + table[3][0] = pi0; + table[4][1] = pi1; + q_add[0] = zero; + q_mul[0] = zero; + q_add[1] = zero; + q_mul[1] = 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(); + table[1][i] = table[2][i - 1]; + table[2][i] = table[0][i] + table[1][i]; + table[3][i] = zero; + q_add[i] = one; + q_mul[i] = 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)); + } + + // 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] = table[4][1]; + table[1][i] = table[3][0]; + table[2][i] = table[0][i] * table[1][i] + table[0][i - 1]; + table[3][i] = zero; + q_add[i] = zero; + q_mul[i] = one; + + plonk_variable x(0, i, false, + plonk_variable::column_type::witness); + plonk_variable p1(0, 0, false, + plonk_variable::column_type::public_input); + plonk_variable y(1, i, false, + plonk_variable::column_type::witness); + plonk_variable p2(1, 1, false, + plonk_variable::column_type::public_input); + + test_circuit.copy_constraints.push_back(plonk_copy_constraint(x, p2)); + test_circuit.copy_constraints.push_back(plonk_copy_constraint(y, p1)); + } + table[3][1] = zero; + table[3][2] = one; - // 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; + 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]; - } + selectors_assignment[0] = q_add; + selectors_assignment[1] = q_mul; - for (std::size_t i = 0; i < constant_columns; i++) { - constant_assignment[i] = table[witness_columns + selector_columns + i]; + for (std::size_t i = 0; i < public_columns; i++) { + public_input_assignment[i] = table[witness_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::column_type::witness); plonk_variable w1(1, 0, true, - plonk_variable::column_type::witness); + 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; + plonk_variable::column_type::witness); + plonk_variable w0_prev(0, -1, true, + plonk_variable::column_type::witness); + + plonk_constraint add_constraint; + add_constraint += w0; + add_constraint += w1; + add_constraint -= w2; + + std::vector> add_gate_costraints {add_constraint}; + plonk_gate> add_gate(0, add_gate_costraints); + test_circuit.gates.push_back(add_gate); + + plonk_constraint mul_constraint; + typename plonk_constraint::term_type w0_term(w0); + typename plonk_constraint::term_type w1_term(w1); + mul_constraint += w0_term * w1_term; + mul_constraint -= w2; + mul_constraint += w0_prev; + + std::vector> mul_gate_costraints {mul_constraint}; + plonk_gate> mul_gate(1, mul_gate_costraints); + test_circuit.gates.push_back(mul_gate); return test_circuit; } diff --git a/test/transpiler.cpp b/test/transpiler.cpp index b98d256..ebc3a20 100644 --- a/test/transpiler.cpp +++ b/test/transpiler.cpp @@ -497,6 +497,96 @@ BOOST_FIXTURE_TEST_CASE(transpiler_test, test_initializer) { } BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE(placeholder_circuit5) + using Endianness = nil::marshalling::option::big_endian; + using TTypeBase = nil::marshalling::field_type; + + 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 = rows_log_5; + constexpr static const std::size_t table_rows = 1 << table_rows_log; + constexpr static const std::size_t permutation_size = permutation_5; + constexpr static const std::size_t usable_rows = (1 << table_rows_log) - 3; + + struct placeholder_test_params { + using merkle_hash_type = hashes::keccak_1600<256>; + using transcript_hash_type = hashes::keccak_1600<256>; + + constexpr static const std::size_t witness_columns = witness_columns_5; + constexpr static const std::size_t public_input_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; + + using arithmetization_params = + plonk_arithmetization_params; + + constexpr static const std::size_t lambda = 1; + 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 pi1 = test_global_alg_rnd_engine(); + auto circuit = circuit_test_t(pi0, pi1, 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; + + std::vector columns_with_copy_constraints = {0, 1, 2, 3}; + + bool verifier_res; + + // 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 + lpc_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, + lpc_preprocessed_public_data.common_data, + lpc_scheme, + columns_with_copy_constraints.size(), + "circuit5", + 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(placeholder_circuit6) using Endianness = nil::marshalling::option::big_endian; using TTypeBase = nil::marshalling::field_type;