Skip to content

Commit

Permalink
Fix mempool key image privacy bug
Browse files Browse the repository at this point in the history
  • Loading branch information
vtnerd committed Aug 1, 2019
1 parent b864375 commit c2b9d09
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 16 deletions.
10 changes: 5 additions & 5 deletions src/cryptonote_core/tx_pool.cpp
Expand Up @@ -835,21 +835,21 @@ 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)
{
MERROR("Failed to get tx meta from txpool: " << e.what());
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;
}
Expand Down
2 changes: 2 additions & 0 deletions tests/core_tests/CMakeLists.txt
Expand Up @@ -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
Expand All @@ -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
Expand Down
29 changes: 18 additions & 11 deletions tests/core_tests/chaingen.h
Expand Up @@ -108,17 +108,18 @@ typedef serialized_object<cryptonote::transaction> 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)
{
}

Expand All @@ -128,8 +129,8 @@ struct event_visitor_settings
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/)
{
ar & valid_mask;
ar & txs_keeped_by_block;
ar & mask;
ar & toggle;
}
};

Expand Down Expand Up @@ -504,6 +505,7 @@ struct push_core_event_visitor: public boost::static_visitor<bool>
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<test_event_entry>& events, t_test_class& validator)
Expand All @@ -512,6 +514,7 @@ struct push_core_event_visitor: public boost::static_visitor<bool>
, m_validator(validator)
, m_ev_index(0)
, m_txs_keeped_by_block(false)
, m_txs_do_not_relay(false)
{
}

Expand All @@ -530,9 +533,13 @@ struct push_core_event_visitor: public boost::static_visitor<bool>
{
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;
Expand All @@ -544,7 +551,7 @@ struct push_core_event_visitor: public boost::static_visitor<bool>

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");
Expand Down
4 changes: 4 additions & 0 deletions tests/core_tests/chaingen_main.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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<false>);
GENERATE_AND_PLAY(gen_double_spend_in_tx<true>);
Expand Down
131 changes: 131 additions & 0 deletions 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<cryptonote::tx_source_entry> sources; \
cryptonote::tx_source_entry se; \
se.amount = tx_0.vout[0].amount; \
se.push_output(0, boost::get<cryptonote::txout_to_key>(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<cryptonote::tx_destination_entry> destinations; \
destinations.push_back(de); \
\
cryptonote::transaction tx_1; \
if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), 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<test_event_entry>& /*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<test_event_entry>& /*events*/)
{
++m_all_tx_count;
return true;
}

bool txpool_base::check_txpool_spent_keys(cryptonote::core& c, size_t /*ev_index*/, const std::vector<test_event_entry>& events)
{
std::vector<cryptonote::tx_info> infos{};
std::vector<cryptonote::spent_key_image_info> 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<test_event_entry>& 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<test_event_entry>& 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;
}


60 changes: 60 additions & 0 deletions 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<test_event_entry>& events);
bool increase_all_tx_count(cryptonote::core& c, size_t /*ev_index*/, const std::vector<test_event_entry>& events);
bool check_txpool_spent_keys(cryptonote::core& c, size_t /*ev_index*/, const std::vector<test_event_entry>& events);
};

struct txpool_spend_key_public : txpool_base
{
txpool_spend_key_public() : txpool_base()
{}

bool generate(std::vector<test_event_entry>& events) const;
};

struct txpool_spend_key_all : txpool_base
{
txpool_spend_key_all() : txpool_base()
{}

bool generate(std::vector<test_event_entry>& events);
};

0 comments on commit c2b9d09

Please sign in to comment.