diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 49d5a8ccc6c..353c7dee7a8 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -835,9 +835,8 @@ namespace cryptonote MERROR("Failed to get tx meta from txpool"); return false; } - if (!meta.relayed) - // Do not include that transaction if in restricted mode and it's not relayed - continue; + if (!meta.do_not_relay) + ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash)); } catch (const std::exception &e) { @@ -845,11 +844,12 @@ namespace cryptonote return false; } } - ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash)); + else // include sensitive data + ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash)); } // Only return key images for which we have at least one tx that we can show for them if (!ki.txs_hashes.empty()) - key_image_infos.push_back(ki); + key_image_infos.push_back(std::move(ki)); } return true; } diff --git a/tests/core_tests/CMakeLists.txt b/tests/core_tests/CMakeLists.txt index f93cbf3ad21..17bc8aae985 100644 --- a/tests/core_tests/CMakeLists.txt +++ b/tests/core_tests/CMakeLists.txt @@ -40,6 +40,7 @@ set(core_tests_sources ring_signature_1.cpp transaction_tests.cpp tx_validation.cpp + txpool.cpp v2_tests.cpp rct.cpp bulletproofs.cpp @@ -57,6 +58,7 @@ set(core_tests_headers integer_overflow.h multisig.h ring_signature_1.h + txpool.h transaction_tests.h tx_validation.h v2_tests.h diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index c0d31bb8a73..081ac7317c2 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -108,17 +108,18 @@ typedef serialized_object serialized_transaction; struct event_visitor_settings { - int valid_mask; - bool txs_keeped_by_block; + int mask; + bool toggle; enum settings { - set_txs_keeped_by_block = 1 << 0 + set_txs_keeped_by_block = 1 << 0, + set_txs_do_not_relay = 1 << 1 }; - event_visitor_settings(int a_valid_mask = 0, bool a_txs_keeped_by_block = false) - : valid_mask(a_valid_mask) - , txs_keeped_by_block(a_txs_keeped_by_block) + event_visitor_settings(int a_mask = 0, bool a_toggle = false) + : mask(a_mask) + , toggle(a_toggle) { } @@ -128,8 +129,8 @@ struct event_visitor_settings template void serialize(Archive & ar, const unsigned int /*version*/) { - ar & valid_mask; - ar & txs_keeped_by_block; + ar & mask; + ar & toggle; } }; @@ -504,6 +505,7 @@ struct push_core_event_visitor: public boost::static_visitor size_t m_ev_index; bool m_txs_keeped_by_block; + bool m_txs_do_not_relay; public: push_core_event_visitor(cryptonote::core& c, const std::vector& events, t_test_class& validator) @@ -512,6 +514,7 @@ struct push_core_event_visitor: public boost::static_visitor , m_validator(validator) , m_ev_index(0) , m_txs_keeped_by_block(false) + , m_txs_do_not_relay(false) { } @@ -530,9 +533,13 @@ struct push_core_event_visitor: public boost::static_visitor { log_event("event_visitor_settings"); - if (settings.valid_mask & event_visitor_settings::set_txs_keeped_by_block) + if (settings.mask & event_visitor_settings::set_txs_keeped_by_block) { - m_txs_keeped_by_block = settings.txs_keeped_by_block; + m_txs_keeped_by_block = settings.toggle; + } + else if (settings.mask & event_visitor_settings::set_txs_do_not_relay) + { + m_txs_do_not_relay = settings.toggle; } return true; @@ -544,7 +551,7 @@ struct push_core_event_visitor: public boost::static_visitor cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); size_t pool_size = m_c.get_pool_transactions_count(); - m_c.handle_incoming_tx(t_serializable_object_to_blob(tx), tvc, m_txs_keeped_by_block, false, false); + m_c.handle_incoming_tx(t_serializable_object_to_blob(tx), tvc, m_txs_keeped_by_block, false, m_txs_do_not_relay); bool tx_added = pool_size + 1 == m_c.get_pool_transactions_count(); bool r = m_validator.check_tx_verification_context(tvc, tx_added, m_ev_index, tx); CHECK_AND_NO_ASSERT_MES(r, false, "tx verification context check failed"); diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 8406f416ffc..7246dc2c2f6 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -32,6 +32,7 @@ #include "chaingen_tests_list.h" #include "common/util.h" #include "common/command_line.h" +#include "txpool.h" #include "transaction_tests.h" namespace po = boost::program_options; @@ -155,6 +156,9 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_tx_output_is_not_txout_to_key); GENERATE_AND_PLAY(gen_tx_signatures_are_invalid); + // Mempool + GENERATE_AND_PLAY(txpool_spend_key_public); + // Double spend GENERATE_AND_PLAY(gen_double_spend_in_tx); GENERATE_AND_PLAY(gen_double_spend_in_tx); diff --git a/tests/core_tests/txpool.cpp b/tests/core_tests/txpool.cpp new file mode 100644 index 00000000000..0c908659570 --- /dev/null +++ b/tests/core_tests/txpool.cpp @@ -0,0 +1,131 @@ +// Copyright (c) 2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "txpool.h" + +#define INIT_MEMPOOL_TEST() \ + uint64_t send_amount = 1000; \ + uint64_t ts_start = 1338224400; \ + GENERATE_ACCOUNT(miner_account); \ + GENERATE_ACCOUNT(bob_account); \ + MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start); \ + REWIND_BLOCKS(events, blk_0r, blk_0, miner_account); \ + + /* + MAKE_TX(events, tx_0, miner_account, bob_account, send_amount, blk_0); \ + \ + std::vector sources; \ + cryptonote::tx_source_entry se; \ + se.amount = tx_0.vout[0].amount; \ + se.push_output(0, boost::get(tx_0.vout[0].target).key, se.amount); \ + se.real_output = 0; \ + se.rct = false; \ + se.real_out_tx_key = get_tx_pub_key_from_extra(tx_0); \ + se.real_output_in_tx_index = 0; \ + sources.push_back(se); \ + \ + cryptonote::tx_destination_entry de; \ + de.addr = miner_account.get_keys().m_account_address; \ + de.amount = se.amount - TESTS_DEFAULT_FEE; \ + std::vector destinations; \ + destinations.push_back(de); \ + \ + cryptonote::transaction tx_1; \ + if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector(), tx_1, 0)) \ + return false; */ + + +txpool_base::txpool_base() + : test_chain_unit_base() + , m_public_tx_count(0) + , m_all_tx_count(0) +{ + REGISTER_CALLBACK_METHOD(txpool_spend_key_public, increase_public_tx_count); + REGISTER_CALLBACK_METHOD(txpool_spend_key_public, increase_all_tx_count); + REGISTER_CALLBACK_METHOD(txpool_spend_key_public, check_txpool_spent_keys); +} + +bool txpool_base::increase_public_tx_count(cryptonote::core& /*c*/, size_t /*ev_index*/, const std::vector& /*events*/) +{ + ++m_public_tx_count; + ++m_all_tx_count; + return true; +} + +bool txpool_base::increase_all_tx_count(cryptonote::core& /*c*/, size_t /*ev_index*/, const std::vector& /*events*/) +{ + ++m_all_tx_count; + return true; +} + +bool txpool_base::check_txpool_spent_keys(cryptonote::core& c, size_t /*ev_index*/, const std::vector& events) +{ + std::vector infos{}; + std::vector key_images{}; + if (!c.get_pool_transactions_and_spent_keys_info(infos, key_images) || infos.size() != m_all_tx_count || key_images.size() != m_all_tx_count) + return false; + + infos.clear(); + key_images.clear(); + if (!c.get_pool_transactions_and_spent_keys_info(infos, key_images, true) || infos.size() != m_all_tx_count || key_images.size() != m_all_tx_count) + return false; + + infos.clear(); + key_images.clear(); + if (!c.get_pool_transactions_and_spent_keys_info(infos, key_images, false) || infos.size() != m_public_tx_count || key_images.size() != m_public_tx_count) + return false; + + return true; +} + +bool txpool_spend_key_public::generate(std::vector& events) const +{ + INIT_MEMPOOL_TEST(); + + DO_CALLBACK(events, "check_txpool_spent_keys"); + MAKE_TX(events, tx_0, miner_account, bob_account, send_amount, blk_0); + DO_CALLBACK(events, "increase_public_tx_count"); + DO_CALLBACK(events, "check_txpool_spent_keys"); + + return true; +} + +bool txpool_spend_key_all::generate(std::vector& events) +{ + INIT_MEMPOOL_TEST(); + SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_do_not_relay, true); + + DO_CALLBACK(events, "check_txpool_spent_keys"); + MAKE_TX(events, tx_0, miner_account, bob_account, send_amount, blk_0); + DO_CALLBACK(events, "increase_all_tx_count"); + DO_CALLBACK(events, "check_txpool_spent_keys"); + + return true; +} + + diff --git a/tests/core_tests/txpool.h b/tests/core_tests/txpool.h new file mode 100644 index 00000000000..ef0fa5d1614 --- /dev/null +++ b/tests/core_tests/txpool.h @@ -0,0 +1,60 @@ +// Copyright (c) 2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#include "chaingen.h" + +class txpool_base : public test_chain_unit_base +{ + size_t m_public_tx_count; + size_t m_all_tx_count; + +public: + txpool_base(); + + bool increase_public_tx_count(cryptonote::core& c, size_t /*ev_index*/, const std::vector& events); + bool increase_all_tx_count(cryptonote::core& c, size_t /*ev_index*/, const std::vector& events); + bool check_txpool_spent_keys(cryptonote::core& c, size_t /*ev_index*/, const std::vector& events); +}; + +struct txpool_spend_key_public : txpool_base +{ + txpool_spend_key_public() : txpool_base() + {} + + bool generate(std::vector& events) const; +}; + +struct txpool_spend_key_all : txpool_base +{ + txpool_spend_key_all() : txpool_base() + {} + + bool generate(std::vector& events); +};