diff --git a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/input_generators/hardhat_input_generator.hpp b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/input_generators/hardhat_input_generator.hpp index 1c47b4ae3e..7e332082a8 100644 --- a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/input_generators/hardhat_input_generator.hpp +++ b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/input_generators/hardhat_input_generator.hpp @@ -52,8 +52,8 @@ namespace nil { _bytecodes.new_buffer(bytecode); } - std::size_t call_id = 0; std::size_t rw_counter = 0; + std::size_t call_id = 0; for( auto &pt: pts){ boost::property_tree::ptree ptrace = pt.get_child("result.structLogs"); std::cout << "PT = " << ptrace.size() << std::endl; @@ -83,7 +83,7 @@ namespace nil { state.gas = atoi(it->second.get_child("gas").data().c_str()); state.pc = atoi(it->second.get_child("pc").data().c_str()); state.rw_counter = rw_counter; - state.bytecode_hash = _bytecodes.get_data()[0].second; // TODO: fix it if possible + state.bytecode_hash = _bytecodes.get_data()[call_id].second; // TODO: fix it if possible state.additional_input = opcode.substr(0,4) == "PUSH"? stack_next[stack_next.size() - 1]: 0; state.tx_finish = (std::distance(it, ptrace.end()) != 1); state.stack_size = stack.size(); diff --git a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/rw.hpp b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/rw.hpp index d01fa2b947..6cb04ed611 100644 --- a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/rw.hpp +++ b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/rw.hpp @@ -377,7 +377,7 @@ namespace nil { special_constraints[STACK_OP].push_back(context_object.relativize(stack_selector * is_first[1] * (1 - is_write[1]), -1)); // 4. First stack operation is obviously write //if(i!=0) { non_first_row_constraints.push_back(context_object.relativize(stack_selector * (address[1] - address[0]) * (is_write[1] - 1), -1)); // 5. First operation is always write - non_first_row_constraints.push_back(context_object.relativize(stack_selector * (address[1] - address[0]) * (address[1] - address[0] - 1), -1)); // 6. Stack pointer always grows and only by one + non_first_row_constraints.push_back(context_object.relativize(stack_selector * (1 - is_first[1]) * (address[1] - address[0]) * (address[1] - address[0] - 1), -1)); // 6. Stack pointer always grows and only by one non_first_row_constraints.push_back(context_object.relativize(stack_selector * (1 - is_first[1]) * (state_root_hi[1] - state_root_before_hi[0]), -1)); non_first_row_constraints.push_back(context_object.relativize(stack_selector * (1 - is_first[1]) * (state_root_lo[1] - state_root_before_lo[0]), -1)); //} diff --git a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/subcomponents/rw_table.hpp b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/subcomponents/rw_table.hpp index 676af32d01..a0aacd48b6 100644 --- a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/subcomponents/rw_table.hpp +++ b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/subcomponents/rw_table.hpp @@ -67,7 +67,8 @@ namespace nil { //std::cout << "RW assign size = " << rw_trace.size() << std::endl; BOOST_ASSERT(rw_trace.size() < max_rw_size); for( std::size_t i = 0; i < rw_trace.size(); i++ ){ - //if( rw_trace[i].op != nil::blueprint::PADDING_OP ) std::cout << "\t" << i << "." << rw_trace[i] << std::endl; + //if( rw_trace[i].op != rw_operation_type::padding ) + // std::cout << "\t" << i << "." << rw_trace[i] << std::endl; op[i] = rw_op_to_num(rw_trace[i].op); id[i] = rw_trace[i].call_id; address[i] = integral_type(rw_trace[i].address); diff --git a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/types/rw_operation.hpp b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/types/rw_operation.hpp index 6ec50d1729..c049c720b1 100644 --- a/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/types/rw_operation.hpp +++ b/crypto3/libs/blueprint/include/nil/blueprint/zkevm_bbf/types/rw_operation.hpp @@ -87,6 +87,30 @@ namespace nil { } }; + // For testing purposes + std::ostream& operator<<(std::ostream& os, const rw_operation& obj){ + if(obj.op == rw_operation_type::start ) os << "START : "; + if(obj.op == rw_operation_type::stack ) os << "STACK : "; + if(obj.op == rw_operation_type::memory ) os << "MEMORY : "; + if(obj.op == rw_operation_type::storage ) os << "STORAGE : "; + if(obj.op == rw_operation_type::transient_storage ) os << "TRANSIENT_STORAGE : "; + if(obj.op == rw_operation_type::call_context ) os << "CALL_CONTEXT_OP : "; + if(obj.op == rw_operation_type::account ) os << "ACCOUNT_OP : "; + if(obj.op == rw_operation_type::tx_refund_op ) os << "TX_REFUND_OP : "; + if(obj.op == rw_operation_type::tx_access_list_account ) os << "TX_ACCESS_LIST_ACCOUNT_OP : "; + if(obj.op == rw_operation_type::tx_access_list_account_storage ) os << "TX_ACCESS_LIST_ACCOUNT_STORAGE_OP : "; + if(obj.op == rw_operation_type::tx_log ) os << "TX_LOG_OP : "; + if(obj.op == rw_operation_type::tx_receipt ) os << "TX_RECEIPT_OP : "; + if(obj.op == rw_operation_type::padding ) os << "PADDING_OP : "; + os << obj.rw_counter << " call_id = " << obj.call_id << ", addr =" << std::hex << obj.address << std::dec; + if(obj.op == rw_operation_type::storage || obj.op == rw_operation_type::transient_storage) + os << " storage_key = " << obj.storage_key; + if(obj.is_write) os << " W "; else os << " R "; + os << "[" << std::hex << obj.initial_value << std::dec <<"] => "; + os << "[" << std::hex << obj.value << std::dec <<"]"; + return os; + } + rw_operation start_rw_operation(){ return rw_operation({rw_operation_type::start, 0, 0, 0, 0, 0, 0, 0}); } diff --git a/crypto3/libs/blueprint/test/zkevm_bbf/rw.cpp b/crypto3/libs/blueprint/test/zkevm_bbf/rw.cpp index 48bb187236..2a95695d74 100644 --- a/crypto3/libs/blueprint/test/zkevm_bbf/rw.cpp +++ b/crypto3/libs/blueprint/test/zkevm_bbf/rw.cpp @@ -60,10 +60,15 @@ class zkEVMRWTestFixture: public BBFTestFixture { template void test_zkevm_rw( - std::string path, + std::vector paths, std::size_t max_rw_size ){ - auto [bytecodes, traces] = load_hardhat_input(path); + auto [bytecodes, traces] = load_hardhat_input(paths[0]); + for( std::size_t i = 1; i < paths.size(); i++ ){ + auto [bytecodes_next, traces_next] = load_hardhat_input(paths[i]); + bytecodes.insert(bytecodes.end(), bytecodes_next.begin(), bytecodes_next.end()); + traces.insert(traces.end(), traces_next.begin(), traces_next.end()); + } nil::blueprint::bbf::zkevm_hardhat_input_generator circuit_inputs(bytecodes, traces); @@ -83,22 +88,26 @@ BOOST_FIXTURE_TEST_SUITE(blueprint_bbf_rw, zkEVMRWTestFixture) using integral_type = typename field_type::integral_type; using value_type = typename field_type::value_type; BOOST_AUTO_TEST_CASE(minimal_math){ - test_zkevm_rw("minimal_math/", 500); + test_zkevm_rw({"minimal_math/"}, 500); } BOOST_AUTO_TEST_CASE(small_storage){ - test_zkevm_rw("small_stack_storage/", 500); + test_zkevm_rw({"small_stack_storage/"}, 500); } BOOST_AUTO_TEST_CASE(mstore8){ - test_zkevm_rw("mstore8/", 5000); + test_zkevm_rw({"mstore8/"}, 5000); } BOOST_AUTO_TEST_CASE(meminit){ - test_zkevm_rw("mem_init/", 10000); + test_zkevm_rw({"mem_init/"}, 10000); } BOOST_AUTO_TEST_CASE(calldatacopy){ - test_zkevm_rw("calldatacopy/", 10000); + test_zkevm_rw({"calldatacopy/"}, 10000); +} + +BOOST_AUTO_TEST_CASE(multiple_traces){ + test_zkevm_rw({"minimal_math/", "keccak/", "exp/"} , 3000); } BOOST_AUTO_TEST_SUITE_END() diff --git a/proof-producer/libs/assigner/include/nil/proof-generator/assigner/trace_parser.hpp b/proof-producer/libs/assigner/include/nil/proof-generator/assigner/trace_parser.hpp index 2e55e0defb..19b6c64855 100644 --- a/proof-producer/libs/assigner/include/nil/proof-generator/assigner/trace_parser.hpp +++ b/proof-producer/libs/assigner/include/nil/proof-generator/assigner/trace_parser.hpp @@ -166,7 +166,7 @@ namespace nil { // Convert memory operations for (const auto& pb_mop : pb_traces->memory_ops()) { - auto const value = string_to_bytes(pb_mop.value()); + auto value = string_to_bytes(pb_mop.value()); auto const op = blueprint::bbf::memory_rw_operation( static_cast(pb_mop.msg_id()), blueprint::zkevm_word_type(static_cast(pb_mop.index())), @@ -174,12 +174,12 @@ namespace nil { !pb_mop.is_read(), blueprint::zkevm_word_from_bytes(value) ); - rw_traces.push_back(op); + rw_traces.push_back(std::move(op)); } // Convert storage operations for (const auto& pb_sop : pb_traces->storage_ops()) { - const auto& op = blueprint::bbf::storage_rw_operation( + auto op = blueprint::bbf::storage_rw_operation( static_cast(pb_sop.msg_id()), blueprint::zkevm_word_from_string(static_cast(pb_sop.key())), static_cast(pb_sop.rw_idx()), @@ -192,17 +192,13 @@ namespace nil { rw_traces.push_back(std::move(op)); } - using nil::blueprint::bbf::rw_operation; - std::sort(rw_traces.begin(), rw_traces.end(), [](rw_operation a, rw_operation b){ - return a < b; - }); + std::sort(rw_traces.begin(), rw_traces.end(), std::less()); BOOST_LOG_TRIVIAL(debug) << "number RW operations " << rw_traces.size() << ":\n" << "stack " << pb_traces->stack_ops_size() << "\n" << "memory " << pb_traces->memory_ops_size() << "\n" << "storage " << pb_traces->storage_ops_size() << "\n"; - return rw_traces; } diff --git a/proof-producer/tests/bin/proof-producer/test_zkevm_bbf_circuits.cpp b/proof-producer/tests/bin/proof-producer/test_zkevm_bbf_circuits.cpp index 88aadf5374..f8731f6d20 100644 --- a/proof-producer/tests/bin/proof-producer/test_zkevm_bbf_circuits.cpp +++ b/proof-producer/tests/bin/proof-producer/test_zkevm_bbf_circuits.cpp @@ -4,7 +4,7 @@ #include #include -#include "nil/proof-generator/preset/preset.hpp" +#include namespace { @@ -15,7 +15,7 @@ namespace { bool skip_check{false}; // skip satisfiability check while running the test }; -} +} // namespace class ProverTests: public ::testing::TestWithParam { @@ -70,7 +70,7 @@ INSTANTIATE_TEST_SUITE_P(SimpleZkevm, ProverTests, ::testing::Values(Input{Simpl // Multiple calls of Counter contract increment function (several transactions) const std::string MultiTxIncrement = "increment_multi_tx.pb"; -INSTANTIATE_TEST_SUITE_P(MultiTxRw, ProverTests, ::testing::Values(Input{MultiTxIncrement, RW, true})); // https://github.com/NilFoundation/placeholder/issues/187 +INSTANTIATE_TEST_SUITE_P(MultiTxRw, ProverTests, ::testing::Values(Input{MultiTxIncrement, RW})); INSTANTIATE_TEST_SUITE_P(MultiTxBytecode, ProverTests, ::testing::Values(Input{MultiTxIncrement, BYTECODE, true})); // TODO INSTANTIATE_TEST_SUITE_P(MultiTxCopy, ProverTests, ::testing::Values(Input{MultiTxIncrement, COPY})); INSTANTIATE_TEST_SUITE_P(MultiTxZkevm, ProverTests, ::testing::Values(Input{MultiTxIncrement, ZKEVM, true})); // TODO