diff --git a/flake.nix b/flake.nix index 18d12df041..5586dc8798 100644 --- a/flake.nix +++ b/flake.nix @@ -77,18 +77,27 @@ enableDebug = false; crypto3 = crypto3; evm-assigner = evm-assigner; + transpiler = transpiler; + proof-producer = proof-producer; + parallel-crypto3 = parallel-crypto3; }); zkevm-framework-tests = (pkgs.callPackage ./zkevm-framework/zkevm-framework.nix { runTests = true; enableDebug = false; crypto3 = crypto3; evm-assigner = evm-assigner; + transpiler = transpiler; + proof-producer = proof-producer; + parallel-crypto3 = parallel-crypto3; }); zkevm-framework-debug-tests = (pkgs.callPackage ./zkevm-framework/zkevm-framework.nix { enableDebug = true; runTests = true; crypto3 = crypto3; evm-assigner = evm-assigner; + transpiler = transpiler; + proof-producer = proof-producer; + parallel-crypto3 = parallel-crypto3; }); transpiler = (pkgs.callPackage ./transpiler/transpiler.nix { @@ -186,6 +195,9 @@ enableDebug = false; crypto3 = packages.crypto3; evm-assigner = evm-assigner-gcc; + transpiler = packages.transpiler; + proof-producer = proof-producer-gcc; + parallel-crypto3 = packages.parallel-crypto3; }); transpiler-gcc = (pkgs.callPackage ./transpiler/transpiler.nix { diff --git a/proof-producer/CMakeLists.txt b/proof-producer/CMakeLists.txt index 8814ebf72a..acb67eafa0 100644 --- a/proof-producer/CMakeLists.txt +++ b/proof-producer/CMakeLists.txt @@ -96,3 +96,22 @@ set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/bin/proof-producer") include(CPack) + +# INSTALL + +set(CONFIG_PATH ${CMAKE_INSTALL_LIBDIR}/cmake/proof-producer) +set(TARGET_NAMESPACE crypto3::) +install(EXPORT proof-producerTargets NAMESPACE ${TARGET_NAMESPACE} DESTINATION ${CONFIG_PATH}) + +include(CMakePackageConfigHelpers) +configure_package_config_file( + cmake/Config.cmake.in + proof-producer-config.cmake + INSTALL_DESTINATION ${CONFIG_PATH} +) + +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/proof-producer-config.cmake + DESTINATION ${CONFIG_PATH} +) diff --git a/proof-producer/bin/proof-producer/CMakeLists.txt b/proof-producer/bin/proof-producer/CMakeLists.txt index ec905b2d8c..4aa4f555b1 100644 --- a/proof-producer/bin/proof-producer/CMakeLists.txt +++ b/proof-producer/bin/proof-producer/CMakeLists.txt @@ -40,11 +40,14 @@ function(setup_proof_generator_target) src/main.cpp ) + add_library(${ARG_TARGET_NAME}-lib INTERFACE) + # Make sure to add these dependencies before the others, since for multi-threaded version dependency on # actor-zk must come first. if(ARG_ADDITIONAL_DEPENDENCIES) foreach(lib IN LISTS ARG_ADDITIONAL_DEPENDENCIES) target_link_libraries(${ARG_TARGET_NAME} ${lib}) + target_link_libraries(${ARG_TARGET_NAME}-lib INTERFACE ${lib}) endforeach() endif() @@ -65,6 +68,11 @@ function(setup_proof_generator_target) $ ) + target_include_directories(${ARG_TARGET_NAME}-lib INTERFACE + $ + $ + ) + target_link_libraries(${ARG_TARGET_NAME} crypto3::all @@ -75,14 +83,32 @@ function(setup_proof_generator_target) Boost::program_options Boost::thread ) + + target_link_libraries(${ARG_TARGET_NAME}-lib INTERFACE + crypto3::all + + crypto3::transpiler + + Boost::filesystem + Boost::log + Boost::program_options + Boost::thread + ) endfunction() # Declare single-threaded target set(SINGLE_THREADED_TARGET "${CURRENT_PROJECT_NAME}-single-threaded") setup_proof_generator_target(TARGET_NAME ${SINGLE_THREADED_TARGET}) + # Declare multi-threaded target set(MULTI_THREADED_TARGET "${CURRENT_PROJECT_NAME}-multi-threaded") setup_proof_generator_target(TARGET_NAME ${MULTI_THREADED_TARGET} ADDITIONAL_DEPENDENCIES actor::zk) install(TARGETS ${SINGLE_THREADED_TARGET} ${MULTI_THREADED_TARGET} RUNTIME DESTINATION bin) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Install library +install(TARGETS ${SINGLE_THREADED_TARGET}-lib ${MULTI_THREADED_TARGET}-lib EXPORT proof-producerTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp index dec4e7ec0d..252a7d3eec 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp @@ -314,7 +314,8 @@ namespace nil { commitment_scheme.state_commited(crypto3::zk::snark::LOOKUP_BATCH); commitment_scheme.mark_batch_as_fixed(crypto3::zk::snark::FIXED_VALUES_BATCH); - commitment_scheme.set_fixed_polys_values(common_data_->commitment_scheme_data); + commitment_scheme.set_fixed_polys_values(common_data_.has_value() ? common_data_->commitment_scheme_data : + public_preprocessed_data_->common_data.commitment_scheme_data); std::size_t theta_power = commitment_scheme.compute_theta_power_for_combined_Q(); @@ -492,6 +493,13 @@ namespace nil { return true; } + bool set_circuit(const ConstraintSystem& circuit) { + BOOST_LOG_TRIVIAL(info) << "Set circuit" << std::endl; + + constraint_system_.emplace(std::move(circuit)); + return true; + } + bool read_assignment_table(const boost::filesystem::path& assignment_table_file_) { BOOST_LOG_TRIVIAL(info) << "Read assignment table from " << assignment_table_file_; @@ -512,6 +520,20 @@ namespace nil { return true; } + bool set_assignment_table(const AssignmentTable& assignment_table, std::size_t used_rows_amount) { + BOOST_LOG_TRIVIAL(info) << "Set external assignment table" << std::endl; + + table_description_->witness_columns = assignment_table.witnesses_amount(); + table_description_->public_input_columns = assignment_table.public_inputs_amount(); + table_description_->constant_columns = assignment_table.constants_amount(); + table_description_->selector_columns = assignment_table.selectors_amount(); + table_description_->usable_rows_amount = used_rows_amount; + table_description_->rows_amount = assignment_table.rows_amount(); + assignment_table_.emplace(std::move(assignment_table)); + public_inputs_.emplace(assignment_table_->public_inputs()); + return true; + } + bool save_assignment_description(const boost::filesystem::path& assignment_description_file) { BOOST_LOG_TRIVIAL(info) << "Writing assignment description to " << assignment_description_file; diff --git a/proof-producer/cmake/Config.cmake.in b/proof-producer/cmake/Config.cmake.in new file mode 100644 index 0000000000..560a39a6a5 --- /dev/null +++ b/proof-producer/cmake/Config.cmake.in @@ -0,0 +1,7 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(crypto3 REQUIRED) +find_dependency(crypto3_transpiler) + +include("${CMAKE_CURRENT_LIST_DIR}/proof-producerTargets.cmake") diff --git a/run.sh b/run.sh new file mode 100644 index 0000000000..7c283bcfe4 --- /dev/null +++ b/run.sh @@ -0,0 +1,24 @@ +echo "1th circuit partial proof" +./result/bin/assigner --shard-id 1 --block-hash 0x001 --path /root/tmp/out/ --target-circuits add.0 -e pallas --input 326522724692461750427768532537390503835 --input 89059515727727869117346995944635890507 --input 291547819587797372485177713898460727720 --input 194782098816759892662980765881849306481 --log-level debug +echo "2th circuit partial proof" +./result/bin/assigner --shard-id 1 --block-hash 0x001 --path /root/tmp/out/ --target-circuits add.1 -e pallas --input 326522724692461750427768532537390503835 --input 89059515727727869117346995944635890507 --input 291547819587797372485177713898460727720 --input 194782098816759892662980765881849306481 --log-level debug + +echo "aggregate challenges" +./result/bin/proof-producer-multi-threaded --stage="generate-aggregated-challenge" --input-challenge-files "/root/tmp/out/challenge.0.1.0x001" "/root/tmp/out/challenge.1.1.0x001" --aggregated-challenge-file="/root/tmp/out/aggregated_challenges.1.0x001" + +echo "compute Q 1th circuit" +./result/bin/proof-producer-multi-threaded --stage="compute-combined-Q" --aggregated-challenge-file="/root/tmp/out/aggregated_challenges.1.0x001" --combined-Q-starting-power=0 --commitment-state-file="/root/tmp/out/commitment_state.0.1.0x001" --combined-Q-polynomial-file="/root/tmp/out/combined_Q.0.1.0x001" +echo "compute Q 2th circuit" +./result/bin/proof-producer-multi-threaded --stage="compute-combined-Q" --aggregated-challenge-file="/root/tmp/out/aggregated_challenges.1.0x001" --combined-Q-starting-power=0 --commitment-state-file="/root/tmp/out/commitment_state.1.1.0x001" --combined-Q-polynomial-file="/root/tmp/out/combined_Q.1.1.0x001" + +echo "aggregate FRY" +./result/bin/proof-producer-multi-threaded --stage="aggregated-FRI" --assignment-description-file="/root/tmp/out/assignment_table_description.0.1.0x001" --aggregated-challenge-file="/root/tmp/out/aggregated_challenges.1.0x001" --input-combined-Q-polynomial-files "/root/tmp/out/combined_Q.0.1.0x001" "/root/tmp/out/combined_Q.1.1.0x001" --proof="/root/tmp/out/aggregated_FRI_proof.1.0x001" --proof-of-work-file="/root/tmp/out/POW.1.0x001" --consistency-checks-challenges-file="/root/tmp/out/challenges.1.0x001" + +echo "consistency check 1th circuit" +./result/bin/proof-producer-multi-threaded --stage="consistency-checks" --commitment-state-file="/root/tmp/out/commitment_state.0.1.0x001" --combined-Q-polynomial-file="/root/tmp/out/combined_Q.0.1.0x001" --consistency-checks-challenges-file="/root/tmp/out/challenges.1.0x001" --proof="/root/tmp/out/LPC_consistency_check_proof.0.1.0x001" +echo "consistency check 2th circuit" +./result/bin/proof-producer-multi-threaded --stage="consistency-checks" --commitment-state-file="/root/tmp/out/commitment_state.1.1.0x001" --combined-Q-polynomial-file="/root/tmp/out/combined_Q.1.1.0x001" --consistency-checks-challenges-file="/root/tmp/out/challenges.1.0x001" --proof="/root/tmp/out/LPC_consistency_check_proof.1.1.0x001" + + +echo "merge final proof" +./result/bin/proof-producer-multi-threaded --stage merge-proofs --partial-proof "/root/tmp/out/proof.0.1.0x001" "/root/tmp/out/proof.1.1.0x001" --initial-proof "/root/tmp/out/LPC_consistency_check_proof.0.1.0x001" "/root/tmp/out/LPC_consistency_check_proof.1.1.0x001" --aggregated-FRI-proof "/root/tmp/out/aggregated_FRI_proof.1.0x001" --proof "/root/tmp/out/final-proof.1.0x001" diff --git a/zkevm-framework/bin/assigner/CMakeLists.txt b/zkevm-framework/bin/assigner/CMakeLists.txt index 86c4423b78..76bb52b969 100644 --- a/zkevm-framework/bin/assigner/CMakeLists.txt +++ b/zkevm-framework/bin/assigner/CMakeLists.txt @@ -13,12 +13,17 @@ target_include_directories(${TARGET_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/include ) +find_package(actor_zk REQUIRED) + +find_package(proof-producer REQUIRED) + target_link_libraries(${TARGET_NAME} PRIVATE zkEVMPreset zkEVMAssignerRunner zkEVMJsonHelpers zkEVMOutputArtifacts + crypto3::proof-producer-multi-threaded-lib Boost::program_options Boost::log Boost::random diff --git a/zkevm-framework/bin/assigner/src/main.cpp b/zkevm-framework/bin/assigner/src/main.cpp index 485ca25d81..5d846ddce8 100644 --- a/zkevm-framework/bin/assigner/src/main.cpp +++ b/zkevm-framework/bin/assigner/src/main.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "checks.hpp" @@ -49,74 +50,232 @@ std::optional write_circuit(nil::evm_assigner::zkevm_circuit idx, } template -int setup_prover(const std::string& assignment_table_file_name, - const std::string& circuit_file_name, - zkevm_circuits& circuits) { +std::optional setup_prover(const std::optional& circuit_file_name, + const std::optional& assignment_table_file_name, + std::unordered_map>& assignments, + zkevm_circuits& circuits) { auto start = std::chrono::high_resolution_clock::now(); using Endianness = nil::marshalling::option::big_endian; - std::unordered_map> - assignments; - auto init_start = std::chrono::high_resolution_clock::now(); auto err = initialize_circuits(circuits, assignments); if (err) { - std::cerr << "Preset step failed: " << err.value() << std::endl; - return 1; + return "Preset step failed: " + err.value(); } auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - init_start); std::cout << "INITIALIZE: " << duration.count() << " ms\n"; - auto write_assignments_start = std::chrono::high_resolution_clock::now(); - err = write_binary_assignments( - assignments, assignment_table_file_name); - if (err) { - std::cerr << "Write assignments failed: " << err.value() << std::endl; - return 1; + if (circuit_file_name) { + auto write_circuits_start = std::chrono::high_resolution_clock::now(); + const auto& circuit_names = circuits.get_circuit_names(); + for (const auto& circuit_name : circuit_names) { + std::string concrete_circuit_file_name = circuit_file_name.value() + "." + std::to_string(circuits.get_index(circuit_name)); + if (circuit_name == "bytecode") { + err = write_circuit(circuits.get_index(circuit_name), + assignments, + circuits.m_bytecode_circuit, + concrete_circuit_file_name); + } else if (circuit_name == "sha256") { + err = write_circuit(circuits.get_index(circuit_name), + assignments, + circuits.m_sha256_circuit, + concrete_circuit_file_name); + } else if (circuit_name == "add") { + err = write_circuit(circuits.get_index(circuit_name), + assignments, + circuits.m_add_circuit, + concrete_circuit_file_name); + } + if (err) { + return "Write circuits failed: " + err.value(); + } + } + duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - write_circuits_start); + std::cout << "WRITE CIRCUITS: " << duration.count() << " ms\n"; } - duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - write_assignments_start); - std::cout << "WRITE ASSIGNMENT TABLES: " << duration.count() << " ms\n"; - auto write_circuits_start = std::chrono::high_resolution_clock::now(); - const auto& circuit_names = circuits.get_circuit_names(); - for (const auto& circuit_name : circuit_names) { - std::string concrete_circuit_file_name = circuit_file_name + "_" + circuit_name; - if (circuit_name == "bytecode") { - err = write_circuit(nil::evm_assigner::zkevm_circuit::BYTECODE, - assignments, - circuits.m_bytecode_circuit, - concrete_circuit_file_name); - } else if (circuit_name == "sha256") { - err = write_circuit(nil::evm_assigner::zkevm_circuit::BYTECODE, - assignments, - circuits.m_sha256_circuit, - concrete_circuit_file_name); - } + if (assignment_table_file_name) { + auto write_assignments_start = std::chrono::high_resolution_clock::now(); + auto err = write_binary_assignments( + assignments, assignment_table_file_name.value()); if (err) { - std::cerr << "Write circuits failed: " << err.value() << std::endl; - return 1; + return "Write assignments failed: " + err.value(); } + duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - write_assignments_start); + std::cout << "WRITE ASSIGNMENT TABLES: " << duration.count() << " ms\n"; } - duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - write_circuits_start); - std::cout << "WRITE CIRCUITS: " << duration.count() << " ms\n"; duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); std::cout << "SETUP: " << duration.count() << " ms\n"; - return 0; + return {}; +} + +template +void set_paddnig(nil::blueprint::assignment& assignments) { + std::uint32_t used_rows_amount = assignments.rows_amount(); + + std::uint32_t padded_rows_amount = std::pow(2, std::ceil(std::log2(used_rows_amount))); + if (padded_rows_amount == used_rows_amount) { + padded_rows_amount *= 2; + } + if (padded_rows_amount < 8) { + padded_rows_amount = 8; + } + + for (std::uint32_t i = 0; i < assignments.witnesses_amount(); i++) { + for (std::uint32_t j = assignments.witness_column_size(i); j < padded_rows_amount; j++) { + assignments.witness(i, j) = 0; + } + } + for (std::uint32_t i = 0; i < assignments.public_inputs_amount(); i++) { + for (std::uint32_t j = assignments.public_input_column_size(i); j < padded_rows_amount; j++) { + assignments.public_input(i, j) = 0; + } + } + for (std::uint32_t i = 0; i < assignments.constants_amount(); i++) { + for (std::uint32_t j = assignments.constant_column_size(i); j < padded_rows_amount; j++) { + assignments.constant(i, j) = 0; + } + } + for (std::uint32_t i = 0; i < assignments.selectors_amount(); i++) { + for (std::uint32_t j = assignments.selector_column_size(i); j < padded_rows_amount; j++) { + assignments.selector(i, j) = 0; + } + } +} + +template +std::optional fill_sha256_table(nil::blueprint::assignment& sha256_table, + const std::vector& input) { + using component_type = + nil::blueprint::components::sha256>; + + // Prepare witness container to make an instance of the component + typename component_type::manifest_type m = component_type::get_manifest(); + size_t witness_amount = *(m.witness_amount->begin()); + std::vector witnesses(witness_amount); + std::iota(witnesses.begin(), witnesses.end(), 0); // fill 0, 1, ... + + component_type component_instance = component_type( + witnesses, std::array{0}, std::array{0}); + + constexpr const std::int32_t block_size = 2; + constexpr const std::int32_t input_blocks_amount = 2; + + const auto& row_idx = sha256_table.public_input_column_size(0); + std::array input_block_vars = { + typename component_type::var(0, row_idx, false, component_type::var::column_type::public_input), + typename component_type::var(0, row_idx + 1, false, component_type::var::column_type::public_input), + typename component_type::var(0, row_idx + 2, false, component_type::var::column_type::public_input), + typename component_type::var(0, row_idx + 3, false, component_type::var::column_type::public_input) + }; + typename component_type::input_type component_input = {input_block_vars}; + //set input values + sha256_table.public_input(0, row_idx) = typename BlueprintFieldType::extended_integral_type(input[0].c_str()); + sha256_table.public_input(0, row_idx + 1) = typename BlueprintFieldType::extended_integral_type(input[1].c_str()); + sha256_table.public_input(0, row_idx + 2) = typename BlueprintFieldType::extended_integral_type(input[2].c_str()); + sha256_table.public_input(0, row_idx + 3) = typename BlueprintFieldType::extended_integral_type(input[3].c_str()); + + nil::blueprint::components::generate_assignments(component_instance, sha256_table, component_input, 0); + + return {}; +} + +template +std::optional fill_add_table(nil::blueprint::assignment& add_table, + const std::vector& input) { + using component_type = + nil::blueprint::components::addition, + BlueprintFieldType, nil::blueprint::basic_non_native_policy>; + + // Prepare witness container to make an instance of the component + typename component_type::manifest_type m = component_type::get_manifest(); + size_t witness_amount = *(m.witness_amount->begin()); + std::vector witnesses(witness_amount); + std::iota(witnesses.begin(), witnesses.end(), 0); // fill 0, 1, ... + + component_type component_instance = component_type( + witnesses, std::array{0}, std::array{0}); + + const auto& row_idx = add_table.public_input_column_size(0); + auto v0 = typename component_type::var(0, row_idx, false, component_type::var::column_type::public_input); + auto v1 = typename component_type::var(0, row_idx + 1, false, component_type::var::column_type::public_input); + typename component_type::input_type component_input = {v0, v1}; + //set input values + add_table.public_input(0, row_idx) = typename BlueprintFieldType::extended_integral_type(input[0].c_str()); + add_table.public_input(0, row_idx + 1) = typename BlueprintFieldType::extended_integral_type(input[1].c_str()); + + nil::blueprint::components::generate_assignments(component_instance, add_table, component_input, 0); + + return {}; +} + +template +std::optional fill_assignment_tables(std::unordered_map>& assignments, + const std::optional& shardId, + const std::optional& blockHash, + const std::optional& block_file_name, + const std::optional& account_storage_file_name, + const std::vector& input, + const zkevm_circuits& circuits, + const std::optional& artifacts, + boost::log::trivial::severity_level log_level) { + using Endianness = nil::marshalling::option::big_endian; + + auto start = std::chrono::high_resolution_clock::now(); + + // generate assignments for sha256 + auto find_it = assignments.find(circuits.get_index("sha256")); + if (find_it != assignments.end()) { + auto& sha256_table = find_it->second; + return fill_sha256_table(sha256_table, input); + } + find_it = assignments.find(circuits.get_index("add")); + if (find_it != assignments.end()) { + auto& add_table = find_it->second; + return fill_add_table(add_table, input); + } + return "Can't find assignment table for sha256"; + + + /*single_thread_runner runner(assignments, shardId, + circuit_names, log_level); + + auto err = runner.extract_block_with_messages(blockHash, block_file_name); + if (err) { + return "Extract input block failed: " + err.value(); + } + + err = runner.extract_accounts_with_storage(account_storage_file_name); + if (err) { + return "Extract account storage failed: " + err.value(); + } + + err = runner.run(assignment_table_file_name, artifacts); + if (err) { + return "Assigner run failed: " + err.value(); + }*/ + + auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); + std::cout << "FILL ASSIGNMENT TABLES: " << duration.count() << " ms\n"; + + return {}; } template -int curve_dependent_main(uint64_t shardId, const std::string& blockHash, - const std::string& block_file_name, - const std::string& account_storage_file_name, - const std::string& assignment_table_file_name, - const std::string& circuit_file_name, +int curve_dependent_main(const std::optional& shardId, + const std::optional& blockHash, + const std::optional& block_file_name, + const std::optional& account_storage_file_name, + const std::optional& assignment_table_file_name, + const std::optional& circuit_file_name, const std::optional& artifacts, const std::vector& target_circuits, - bool is_setup, + const std::vector& input, + const std::optional& path, boost::log::trivial::severity_level log_level) { using ArithmetizationType = nil::crypto3::zk::snark::plonk_constraint_system; @@ -124,46 +283,131 @@ int curve_dependent_main(uint64_t shardId, const std::string& blockHash, boost::log::core::get()->set_filter(boost::log::trivial::severity >= log_level); zkevm_circuits circuits; - circuits.m_names = target_circuits; - - - if (is_setup) { - BOOST_LOG_TRIVIAL(debug) << "SetUp prover\n"; - return setup_prover(assignment_table_file_name, circuit_file_name, circuits); + // TODO just for check sha256, should be removed ater add regular zk EVM circuits + std::optional circuit_file_index; + if (target_circuits.size() == 1 && target_circuits[0].find("sha256") != std::string::npos) { + circuit_file_index = target_circuits[0].substr(7); + circuits.m_names = {"sha256"}; + } else if (target_circuits.size() == 1 && target_circuits[0].find("add") != std::string::npos) { + circuit_file_index = target_circuits[0].substr(4); + circuits.m_names = {"add"}; + }else { + circuits.m_names = target_circuits; } + std::unordered_map> assignments; - auto err = initialize_circuits(circuits, assignments); + BOOST_LOG_TRIVIAL(debug) << "SetUp prover\n"; + auto err = setup_prover(circuit_file_name, assignment_table_file_name, assignments, circuits); if (err) { - std::cerr << "Preset step failed: " << err.value() << std::endl; + std::cerr << "Failed set up prover " << err.value() << std::endl; return 1; } - single_thread_runner runner(assignments, shardId, - circuits.get_circuit_names(), log_level); - - err = runner.extract_block_with_messages(blockHash, block_file_name); + BOOST_LOG_TRIVIAL(debug) << "Fill assignment tables\n"; + err = fill_assignment_tables( + assignments, shardId, blockHash, block_file_name, + account_storage_file_name, input, circuits, artifacts, log_level); if (err) { - std::cerr << "Extract input block failed: " << err.value() << std::endl; + std::cerr << "Failed fill assignment tables " << err.value() << std::endl; return 1; } - err = runner.extract_accounts_with_storage(account_storage_file_name); - if (err) { - std::cerr << "Extract account storage failed: " << err.value() << std::endl; - return 1; - } + using CurveType = nil::crypto3::algebra::curves::pallas; + using HashType = nil::crypto3::hashes::keccak_1600<256>; - err = runner.run(assignment_table_file_name, artifacts); - if (err.has_value()) { - std::cerr << "Assigner run failed: " << err.value() << std::endl; - return 1; + auto prover = nil::proof_generator::Prover( + 9, //lambda + 2, //expand_factor + 0, //max_quotient_chunks + 69 //grind + ); + + // for each circuit + const auto& circuit_names = circuits.get_circuit_names(); + for(const auto& circuit_name : circuit_names) { + const auto circuit_index = circuits.get_index(circuit_name); + auto start = std::chrono::high_resolution_clock::now(); + if (circuit_name == "sha256") { + prover.set_circuit(circuits.m_sha256_circuit); + auto find_it = assignments.find(circuits.get_index("sha256")); + if (find_it == assignments.end()) { + std::cerr << "Can't find assignment table for sha256" << std::endl; + return 1; + } + auto& sha256_table = find_it->second; + std::size_t used_rows_amount = sha256_table.rows_amount(); + set_paddnig(sha256_table); + prover.set_assignment_table(sha256_table, used_rows_amount); + } else if (circuit_name == "add") { + prover.set_circuit(circuits.m_add_circuit); + auto find_it = assignments.find(circuits.get_index("add")); + if (find_it == assignments.end()) { + std::cerr << "Can't find assignment table for add" << std::endl; + return 1; + } + auto& add_table = find_it->second; + std::size_t used_rows_amount = add_table.rows_amount(); + set_paddnig(add_table); + prover.set_assignment_table(add_table, used_rows_amount); + } + auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); + std::cout << "SET PROOF PRODUCER INPUTS: " << duration.count() << " ms\n"; + + auto process_public_data_start = std::chrono::high_resolution_clock::now(); + if (!prover.preprocess_public_data()) { + std::cerr << "Failed preprocess public data" << std::endl; + return 1; + } + duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - process_public_data_start); + std::cout << "PROCESS PUBLIC DATA: " << duration.count() << " ms\n"; + + auto process_private_data_start = std::chrono::high_resolution_clock::now(); + if (!prover.preprocess_private_data()) { + std::cerr << "Failed preproces private data" << std::endl; + return 1; + } + duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - process_private_data_start); + std::cout << "PREPROCESS PRIVATE DATA: " << duration.count() << " ms\n"; + + std::string file_name_suffix = circuit_file_index.has_value() ? circuit_file_index.value() : std::to_string(circuit_index); + if (shardId) { + file_name_suffix += "." + std::to_string(shardId.value()); + } + if (blockHash) { + file_name_suffix += "." + blockHash.value(); + } + std::string file_root_path = path.has_value() ? path.value() : ""; + auto partial_proof_start = std::chrono::high_resolution_clock::now(); + if (!prover.generate_partial_proof_to_file(file_root_path + "proof." + file_name_suffix, + file_root_path + "challenge." + file_name_suffix, + file_root_path + "theta_power." + file_name_suffix)) { + std::cerr << "Failed generation partial proof" << std::endl; + return 1; + } + duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - partial_proof_start); + std::cout << "PARTIAL PROOF: " << duration.count() << " ms\n"; + + auto write_commitment_state_start = std::chrono::high_resolution_clock::now(); + if (!prover.save_commitment_state_to_file(file_root_path + "commitment_state." + file_name_suffix)) { + std::cerr << "Failed write commitment state" << std::endl; + return 1; + } + duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - write_commitment_state_start); + std::cout << "WRITE COMMITMENT STATE: " << duration.count() << " ms\n"; + + if (!prover.save_assignment_description(file_root_path + "assignment_table_description." + file_name_suffix)) { + std::cerr << "Failed write assignment table description" << std::endl; + return 1; + } } + + // Check if bytecode table is satisfied to the bytecode constraints - auto it = assignments.find(nil::evm_assigner::zkevm_circuit::BYTECODE); + /*auto it = assignments.find(nil::evm_assigner::zkevm_circuit::BYTECODE); if (it == assignments.end()) { std::cerr << "Can;t find bytecode assignment table\n"; return 1; @@ -172,17 +416,16 @@ int curve_dependent_main(uint64_t shardId, const std::string& blockHash, if (!::is_satisfied(circuits.m_bytecode_circuit, bytecode_table)) { std::cerr << "Bytecode table is not satisfied!" << std::endl; return 0; // Do not produce failure for now - } + }*/ return 0; } int main(int argc, char* argv[]) { - boost::program_options::options_description options_desc("zkEVM1 assigner"); + boost::program_options::options_description options_desc("zkEVM assigner"); // clang-format off options_desc.add_options()("help,h", "Display help message") ("version,v", "Display version") - ("setup", "Run prover setup") ("assignment-tables,t", boost::program_options::value(), "Assignment tables output files") ("circuits,c", boost::program_options::value(), "Circuits output files") ("output-text", boost::program_options::value(), "Output assignment table in readable format. " @@ -204,6 +447,8 @@ int main(int argc, char* argv[]) { ("account-storage,s", boost::program_options::value(), "Account storage config file") ("elliptic-curve-type,e", boost::program_options::value(), "Native elliptic curve type (pallas, vesta, ed25519, bls12381)") ("target-circuits", boost::program_options::value>(), "Fill assignment table only for certain circuits. If not set - fill assignments for all") + ("input", boost::program_options::value>(), "sha256 input val00 val01, val10, val11") + ("path", boost::program_options::value(), "Path to the output folder") ("log-level,l", boost::program_options::value(), "Log level (trace, debug, info, warning, error, fatal)"); // clang-format on @@ -235,62 +480,40 @@ int main(int argc, char* argv[]) { return 0; } - uint64_t shardId = 0; - std::string assignment_table_file_name; - std::string circuit_file_name; - std::string blockHash; - std::string block_file_name; - std::string account_storage_file_name; + std::optional shardId = std::nullopt; + std::optional assignment_table_file_name = std::nullopt; + std::optional circuit_file_name = std::nullopt; + std::optional blockHash = std::nullopt; + std::optional block_file_name = std::nullopt; + std::optional account_storage_file_name = std::nullopt; + std::optional path = std::nullopt; std::string elliptic_curve; std::string log_level; std::vector target_circuits; + std::vector input; if (vm.count("assignment-tables")) { assignment_table_file_name = vm["assignment-tables"].as(); - } else { - std::cerr << "Invalid command line argument - assignment table file name is not specified" - << std::endl; - std::cout << options_desc << std::endl; - return 1; } if (vm.count("circuits")) { circuit_file_name = vm["circuits"].as(); - } else { - std::cerr << "Invalid command line argument - circuits file name is not specified" - << std::endl; - std::cout << options_desc << std::endl; - return 1; } if (vm.count("block-file")) { block_file_name = vm["block-file"].as(); - } else { - block_file_name = ""; - if (vm.count("shard-id")) { - shardId = vm["shard-id"].as(); - } else { - std::cerr << "Invalid command line argument - shard-id or block-file must be specified" - << std::endl; - std::cout << options_desc << std::endl; - return 1; - } + } - if (vm.count("block-hash")) { - blockHash = vm["block-hash"].as(); - } else { - std::cerr - << "Invalid command line argument - block-hash or block-file must be specified" - << std::endl; - std::cout << options_desc << std::endl; - return 1; - } + if (vm.count("shard-id")) { + shardId = vm["shard-id"].as(); + } + + if (vm.count("block-hash")) { + blockHash = vm["block-hash"].as(); } if (vm.count("account-storage")) { account_storage_file_name = vm["account-storage"].as(); - } else { - account_storage_file_name = ""; } std::optional artifacts = std::nullopt; @@ -314,9 +537,19 @@ int main(int argc, char* argv[]) { target_circuits = vm["target-circuits"].as>(); } - bool is_setup = false; - if (vm.count("setup")) { - is_setup = true; + if (vm.count("input")) { + input = vm["input"].as>(); + if (input.size() != 4) { + std::cerr << "wrong input, should has 4 values" << std::endl; + return 1; + } + } else { + std::cerr << "input is required" << std::endl; + return 1; + } + + if (vm.count("path")) { + path = vm["path"].as(); } if (vm.count("log-level")) { @@ -355,7 +588,7 @@ int main(int argc, char* argv[]) { return curve_dependent_main< typename nil::crypto3::algebra::curves::pallas::base_field_type>( shardId, blockHash, block_file_name, account_storage_file_name, - assignment_table_file_name, circuit_file_name, artifacts, target_circuits, is_setup, log_options[log_level]); + assignment_table_file_name, circuit_file_name, artifacts, target_circuits, input, path, log_options[log_level]); break; } case 1: { @@ -367,10 +600,7 @@ int main(int argc, char* argv[]) { break; } case 3: { - return curve_dependent_main< - typename nil::crypto3::algebra::fields::bls12_base_field<381>>( - shardId, blockHash, block_file_name, account_storage_file_name, - assignment_table_file_name, circuit_file_name, artifacts, target_circuits, is_setup, log_options[log_level]); + std::cerr << "bls12 curve based circuits are not supported yet\n"; break; } }; diff --git a/zkevm-framework/libs/preset/include/zkevm_framework/preset/add.hpp b/zkevm-framework/libs/preset/include/zkevm_framework/preset/add.hpp new file mode 100644 index 0000000000..a4378e6622 --- /dev/null +++ b/zkevm-framework/libs/preset/include/zkevm_framework/preset/add.hpp @@ -0,0 +1,67 @@ +#ifndef ZKEMV_FRAMEWORK_LIBS_PRESET_ADD_HPP_ +#define ZKEMV_FRAMEWORK_LIBS_PRESET_ADD_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +std::optional initialize_add_circuit( + nil::blueprint::circuit>& + add_circuit, + std::unordered_map>>& + assignments) { + // initialize assignment table + nil::crypto3::zk::snark::plonk_table_description desc(65, // witness + 1, // public + 35, // constants + 56 // selectors + ); + BOOST_LOG_TRIVIAL(debug) << "add table:\n" + << "witnesses = " << desc.witness_columns + << " public inputs = " << desc.public_input_columns + << " constants = " << desc.constant_columns + << " selectors = " << desc.selector_columns << "\n"; + using ArithmetizationType = + nil::crypto3::zk::snark::plonk_constraint_system; + + auto insert_it = assignments.insert(std::pair>( + nil::evm_assigner::zkevm_circuit::RW,// index = 0, just for experiment with add + nil::blueprint::assignment(desc))); + auto& add_table = insert_it.first->second; + + using component_type = + nil::blueprint::components::addition, + BlueprintFieldType, nil::blueprint::basic_non_native_policy>; + + // Prepare witness container to make an instance of the component + typename component_type::manifest_type m = component_type::get_manifest(); + size_t witness_amount = *(m.witness_amount->begin()); + std::vector witnesses(witness_amount); + std::iota(witnesses.begin(), witnesses.end(), 0); // fill 0, 1, ... + + component_type component_instance = component_type( + witnesses, std::array{0}, std::array{0}); + + const auto& row_idx = add_table.public_input_column_size(0); + auto v0 = typename component_type::var(0, row_idx, false, component_type::var::column_type::public_input); + auto v1 = typename component_type::var(0, row_idx + 1, false, component_type::var::column_type::public_input); + typename component_type::input_type input = {v0, v1}; + + nil::blueprint::components::generate_circuit(component_instance, add_circuit, + add_table, input, 0); + + BOOST_LOG_TRIVIAL(debug) << "rows amount = " << add_table.rows_amount() << "\n"; + return {}; +} + +#endif // ZKEMV_FRAMEWORK_LIBS_PRESET_ADD_HPP_ diff --git a/zkevm-framework/libs/preset/include/zkevm_framework/preset/preset.hpp b/zkevm-framework/libs/preset/include/zkevm_framework/preset/preset.hpp index 10937ab38e..6b2b60168c 100644 --- a/zkevm-framework/libs/preset/include/zkevm_framework/preset/preset.hpp +++ b/zkevm-framework/libs/preset/include/zkevm_framework/preset/preset.hpp @@ -12,6 +12,7 @@ #include "zkevm_framework/preset/bytecode.hpp" #include "zkevm_framework/preset/sha256.hpp" +#include "zkevm_framework/preset/add.hpp" template struct zkevm_circuits { @@ -19,9 +20,19 @@ struct zkevm_circuits { std::vector m_names; nil::blueprint::circuit m_bytecode_circuit; nil::blueprint::circuit m_sha256_circuit; - const std::vector& get_circuit_names() { + nil::blueprint::circuit m_add_circuit; + const std::vector& get_circuit_names() const { return m_names.size() > 0 ? m_names : m_default_names; } + nil::evm_assigner::zkevm_circuit get_index(const std::string& name) const { + if (name == "bytecode" || name == "sha256") { + return nil::evm_assigner::zkevm_circuit::BYTECODE; + } else if (name == "add") { + return nil::evm_assigner::zkevm_circuit::RW; + }else { + return nil::evm_assigner::zkevm_circuit::BYTECODE;// TODO invalid index + } + } }; template @@ -45,6 +56,11 @@ std::optional initialize_circuits( if (err) { return err; } + } else if (circuit_name == "add") { + auto err = initialize_add_circuit(circuits.m_add_circuit, assignments); + if (err) { + return err; + } } } return {}; diff --git a/zkevm-framework/libs/preset/include/zkevm_framework/preset/sha256.hpp b/zkevm-framework/libs/preset/include/zkevm_framework/preset/sha256.hpp index 0c9d0f161e..f848b63e97 100644 --- a/zkevm-framework/libs/preset/include/zkevm_framework/preset/sha256.hpp +++ b/zkevm-framework/libs/preset/include/zkevm_framework/preset/sha256.hpp @@ -69,6 +69,7 @@ std::optional initialize_sha256_circuit( nil::blueprint::components::generate_circuit(component_instance, sha256_circuit, sha256_table, input, 0); + std::vector lookup_columns_indices; for (std::size_t i = 1; i < sha256_table.constants_amount(); i++) { lookup_columns_indices.push_back(i); diff --git a/zkevm-framework/tests/bin/CMakeLists.txt b/zkevm-framework/tests/bin/CMakeLists.txt index ab57599507..e8af7f5af8 100644 --- a/zkevm-framework/tests/bin/CMakeLists.txt +++ b/zkevm-framework/tests/bin/CMakeLists.txt @@ -9,6 +9,7 @@ if(ENABLE_EXECUTABLES_TESTS) -t assignment -e pallas -s ${CMAKE_SOURCE_DIR}/bin/assigner/example_data/state.json + --input "" --log-level debug DEPENDS $ diff --git a/zkevm-framework/zkevm-framework.nix b/zkevm-framework/zkevm-framework.nix index 91b3a5cf54..7427d840af 100644 --- a/zkevm-framework/zkevm-framework.nix +++ b/zkevm-framework/zkevm-framework.nix @@ -12,6 +12,9 @@ valijson, gtest, evm-assigner, + transpiler, + parallel-crypto3, + proof-producer, enableDebugging, enableDebug ? false, runTests ? false, @@ -28,7 +31,7 @@ in stdenv.mkDerivation rec { # enableDebugging will keep debug symbols in boost propagatedBuildInputs = [ (if enableDebug then (enableDebugging boost) else boost) ]; - buildInputs = [crypto3 evm-assigner intx ethash sszpp valijson gtest]; + buildInputs = [crypto3 evm-assigner proof-producer transpiler parallel-crypto3 intx ethash sszpp valijson gtest]; cmakeFlags = [