mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
Adding support for hidden (anonymity) txpool
This commit is contained in:
parent
3e3db92303
commit
5d7ae2d279
35 changed files with 1372 additions and 316 deletions
|
@ -160,8 +160,8 @@ string tx2str(const cryptonote::transaction& tx, const cryptonote::hash256& tx_h
|
|||
return ss.str();
|
||||
}*/
|
||||
|
||||
bool tests::proxy_core::handle_incoming_tx(const cryptonote::tx_blob_entry& tx_blob, cryptonote::tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) {
|
||||
if (!keeped_by_block)
|
||||
bool tests::proxy_core::handle_incoming_tx(const cryptonote::tx_blob_entry& tx_blob, cryptonote::tx_verification_context& tvc, cryptonote::relay_method tx_relay, bool relayed) {
|
||||
if (tx_relay != cryptonote::relay_method::block)
|
||||
return true;
|
||||
|
||||
crypto::hash tx_hash = null_hash;
|
||||
|
@ -190,13 +190,13 @@ bool tests::proxy_core::handle_incoming_tx(const cryptonote::tx_blob_entry& tx_b
|
|||
return true;
|
||||
}
|
||||
|
||||
bool tests::proxy_core::handle_incoming_txs(const std::vector<tx_blob_entry>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
|
||||
bool tests::proxy_core::handle_incoming_txs(const std::vector<tx_blob_entry>& tx_blobs, std::vector<tx_verification_context>& tvc, cryptonote::relay_method tx_relay, bool relayed)
|
||||
{
|
||||
tvc.resize(tx_blobs.size());
|
||||
size_t i = 0;
|
||||
for (const auto &tx_blob: tx_blobs)
|
||||
{
|
||||
if (!handle_incoming_tx(tx_blob, tvc[i], keeped_by_block, relayed, do_not_relay))
|
||||
if (!handle_incoming_tx(tx_blob, tvc[i], tx_relay, relayed))
|
||||
return false;
|
||||
++i;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||
#include "cryptonote_basic/verification_context.h"
|
||||
#include "cryptonote_core/i_core_events.h"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace tests
|
||||
|
@ -51,7 +52,7 @@ namespace tests
|
|||
: height(_height), id(_id), longhash(_longhash), blk(_blk), blob(_blob), txes(_txes) { }
|
||||
};
|
||||
|
||||
class proxy_core
|
||||
class proxy_core : public cryptonote::i_core_events
|
||||
{
|
||||
cryptonote::block m_genesis;
|
||||
std::list<crypto::hash> m_known_block_list;
|
||||
|
@ -75,8 +76,8 @@ namespace tests
|
|||
bool get_stat_info(cryptonote::core_stat_info& st_inf){return true;}
|
||||
bool have_block(const crypto::hash& id);
|
||||
void get_blockchain_top(uint64_t& height, crypto::hash& top_id);
|
||||
bool handle_incoming_tx(const cryptonote::tx_blob_entry& tx_blob, cryptonote::tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay);
|
||||
bool handle_incoming_txs(const std::vector<cryptonote::tx_blob_entry>& tx_blobs, std::vector<cryptonote::tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay);
|
||||
bool handle_incoming_tx(const cryptonote::tx_blob_entry& tx_blob, cryptonote::tx_verification_context& tvc, cryptonote::relay_method tx_relay, bool relayed);
|
||||
bool handle_incoming_txs(const std::vector<cryptonote::tx_blob_entry>& tx_blobs, std::vector<cryptonote::tx_verification_context>& tvc, cryptonote::relay_method tx_relay, bool relayed);
|
||||
bool handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block, cryptonote::block_verification_context& bvc, bool update_miner_blocktemplate = true);
|
||||
void pause_mine(){}
|
||||
void resume_mine(){}
|
||||
|
@ -90,9 +91,9 @@ namespace tests
|
|||
bool cleanup_handle_incoming_blocks(bool force_sync = false) { return true; }
|
||||
uint64_t get_target_blockchain_height() const { return 1; }
|
||||
size_t get_block_sync_size(uint64_t height) const { return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; }
|
||||
virtual void on_transaction_relayed(const cryptonote::blobdata& tx) {}
|
||||
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, cryptonote::relay_method tx_relay) {}
|
||||
cryptonote::network_type get_nettype() const { return cryptonote::MAINNET; }
|
||||
bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob) const { return false; }
|
||||
bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob, cryptonote::relay_category tx_category) const { return false; }
|
||||
bool pool_has_tx(const crypto::hash &txid) const { return false; }
|
||||
bool get_blocks(uint64_t start_offset, size_t count, std::vector<std::pair<cryptonote::blobdata, cryptonote::block>>& blocks, std::vector<cryptonote::blobdata>& txs) const { return false; }
|
||||
bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::transaction>& txs, std::vector<crypto::hash>& missed_txs) const { return false; }
|
||||
|
|
|
@ -40,6 +40,7 @@ set(core_tests_sources
|
|||
ring_signature_1.cpp
|
||||
transaction_tests.cpp
|
||||
tx_validation.cpp
|
||||
tx_pool.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
|
||||
tx_pool.h
|
||||
transaction_tests.h
|
||||
tx_validation.h
|
||||
v2_tests.h
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "cryptonote_core/cryptonote_core.h"
|
||||
#include "cryptonote_protocol/enums.h"
|
||||
#include "cryptonote_basic/cryptonote_boost_serialization.h"
|
||||
#include "misc_language.h"
|
||||
|
||||
|
@ -108,17 +109,17 @@ typedef serialized_object<cryptonote::transaction> serialized_transaction;
|
|||
|
||||
struct event_visitor_settings
|
||||
{
|
||||
int valid_mask;
|
||||
bool txs_keeped_by_block;
|
||||
int mask;
|
||||
|
||||
enum settings
|
||||
{
|
||||
set_txs_keeped_by_block = 1 << 0
|
||||
set_txs_keeped_by_block = 1 << 0,
|
||||
set_txs_do_not_relay = 1 << 1,
|
||||
set_local_relay = 1 << 2
|
||||
};
|
||||
|
||||
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)
|
||||
: mask(a_mask)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -128,8 +129,7 @@ private:
|
|||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int /*version*/)
|
||||
{
|
||||
ar & valid_mask;
|
||||
ar & txs_keeped_by_block;
|
||||
ar & mask;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -503,7 +503,7 @@ private:
|
|||
t_test_class& m_validator;
|
||||
size_t m_ev_index;
|
||||
|
||||
bool m_txs_keeped_by_block;
|
||||
cryptonote::relay_method m_tx_relay;
|
||||
|
||||
public:
|
||||
push_core_event_visitor(cryptonote::core& c, const std::vector<test_event_entry>& events, t_test_class& validator)
|
||||
|
@ -511,7 +511,7 @@ public:
|
|||
, m_events(events)
|
||||
, m_validator(validator)
|
||||
, m_ev_index(0)
|
||||
, m_txs_keeped_by_block(false)
|
||||
, m_tx_relay(cryptonote::relay_method::flood)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -530,9 +530,21 @@ public:
|
|||
{
|
||||
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_tx_relay = cryptonote::relay_method::block;
|
||||
}
|
||||
else if (settings.mask & event_visitor_settings::set_local_relay)
|
||||
{
|
||||
m_tx_relay = cryptonote::relay_method::local;
|
||||
}
|
||||
else if (settings.mask & event_visitor_settings::set_txs_do_not_relay)
|
||||
{
|
||||
m_tx_relay = cryptonote::relay_method::none;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tx_relay = cryptonote::relay_method::flood;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -544,7 +556,7 @@ public:
|
|||
|
||||
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), crypto::null_hash}, tvc, m_txs_keeped_by_block, false, false);
|
||||
m_c.handle_incoming_tx({t_serializable_object_to_blob(tx), crypto::null_hash}, tvc, m_tx_relay, false);
|
||||
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");
|
||||
|
@ -564,7 +576,7 @@ public:
|
|||
tvcs.push_back(tvc0);
|
||||
}
|
||||
size_t pool_size = m_c.get_pool_transactions_count();
|
||||
m_c.handle_incoming_txs(tx_blobs, tvcs, m_txs_keeped_by_block, false, false);
|
||||
m_c.handle_incoming_txs(tx_blobs, tvcs, m_tx_relay, false);
|
||||
size_t tx_added = m_c.get_pool_transactions_count() - pool_size;
|
||||
bool r = m_validator.check_tx_verification_context_array(tvcs, tx_added, m_ev_index, txs);
|
||||
CHECK_AND_NO_ASSERT_MES(r, false, "tx verification context check failed");
|
||||
|
@ -644,7 +656,7 @@ public:
|
|||
|
||||
cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
size_t pool_size = m_c.get_pool_transactions_count();
|
||||
m_c.handle_incoming_tx(sr_tx.data, tvc, m_txs_keeped_by_block, false, false);
|
||||
m_c.handle_incoming_tx(sr_tx.data, tvc, m_tx_relay, false);
|
||||
bool tx_added = pool_size + 1 == m_c.get_pool_transactions_count();
|
||||
|
||||
cryptonote::transaction tx;
|
||||
|
@ -955,7 +967,7 @@ inline bool do_replay_file(const std::string& filename)
|
|||
|
||||
#define MAKE_MINER_TX_MANUALLY(TX, BLK) MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, 0)
|
||||
|
||||
#define SET_EVENT_VISITOR_SETT(VEC_EVENTS, SETT, VAL) VEC_EVENTS.push_back(event_visitor_settings(SETT, VAL));
|
||||
#define SET_EVENT_VISITOR_SETT(VEC_EVENTS, SETT) VEC_EVENTS.push_back(event_visitor_settings(SETT));
|
||||
|
||||
#define GENERATE(filename, genclass) \
|
||||
{ \
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "chaingen_tests_list.h"
|
||||
#include "common/util.h"
|
||||
#include "common/command_line.h"
|
||||
#include "tx_pool.h"
|
||||
#include "transaction_tests.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
@ -155,6 +156,12 @@ 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);
|
||||
GENERATE_AND_PLAY(txpool_spend_key_all);
|
||||
GENERATE_AND_PLAY(txpool_double_spend_norelay);
|
||||
GENERATE_AND_PLAY(txpool_double_spend_local);
|
||||
|
||||
// Double spend
|
||||
GENERATE_AND_PLAY(gen_double_spend_in_tx<false>);
|
||||
GENERATE_AND_PLAY(gen_double_spend_in_tx<true>);
|
||||
|
|
|
@ -46,7 +46,7 @@ bool gen_double_spend_in_different_chains::generate(std::vector<test_event_entry
|
|||
{
|
||||
INIT_DOUBLE_SPEND_TEST();
|
||||
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, true);
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block);
|
||||
MAKE_TX(events, tx_1, bob_account, alice_account, send_amount / 2 - TESTS_DEFAULT_FEE, blk_1);
|
||||
events.pop_back();
|
||||
MAKE_TX(events, tx_2, bob_account, alice_account, send_amount - TESTS_DEFAULT_FEE, blk_1);
|
||||
|
@ -96,3 +96,4 @@ bool gen_double_spend_in_different_chains::check_double_spend(cryptonote::core&
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ bool gen_double_spend_in_tx<txs_keeped_by_block>::generate(std::vector<test_even
|
|||
if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_1, 0))
|
||||
return false;
|
||||
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block);
|
||||
SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0);
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
events.push_back(tx_1);
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
|
@ -163,7 +163,7 @@ bool gen_double_spend_in_the_same_block<txs_keeped_by_block>::generate(std::vect
|
|||
INIT_DOUBLE_SPEND_TEST();
|
||||
|
||||
DO_CALLBACK(events, "mark_last_valid_block");
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block);
|
||||
SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0);
|
||||
|
||||
MAKE_TX_LIST_START(events, txs_1, bob_account, alice_account, send_amount - TESTS_DEFAULT_FEE, blk_1);
|
||||
cryptonote::transaction tx_1 = txs_1.front();
|
||||
|
@ -190,7 +190,7 @@ bool gen_double_spend_in_different_blocks<txs_keeped_by_block>::generate(std::ve
|
|||
INIT_DOUBLE_SPEND_TEST();
|
||||
|
||||
DO_CALLBACK(events, "mark_last_valid_block");
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block);
|
||||
SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0);
|
||||
|
||||
// Create two identical transactions, but don't push it to events list
|
||||
MAKE_TX(events, tx_blk_2, bob_account, alice_account, send_amount - TESTS_DEFAULT_FEE, blk_1);
|
||||
|
@ -220,7 +220,7 @@ bool gen_double_spend_in_alt_chain_in_the_same_block<txs_keeped_by_block>::gener
|
|||
{
|
||||
INIT_DOUBLE_SPEND_TEST();
|
||||
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block);
|
||||
SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0);
|
||||
|
||||
// Main chain
|
||||
MAKE_NEXT_BLOCK(events, blk_2, blk_1r, miner_account);
|
||||
|
@ -255,7 +255,7 @@ bool gen_double_spend_in_alt_chain_in_different_blocks<txs_keeped_by_block>::gen
|
|||
{
|
||||
INIT_DOUBLE_SPEND_TEST();
|
||||
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block);
|
||||
SET_EVENT_VISITOR_SETT(events, txs_keeped_by_block ? event_visitor_settings::set_txs_keeped_by_block : 0);
|
||||
|
||||
// Main chain
|
||||
MAKE_NEXT_BLOCK(events, blk_2, blk_1r, miner_account);
|
||||
|
|
561
tests/core_tests/tx_pool.cpp
Normal file
561
tests/core_tests/tx_pool.cpp
Normal file
|
@ -0,0 +1,561 @@
|
|||
// 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 "tx_pool.h"
|
||||
|
||||
#include <boost/chrono/chrono.hpp>
|
||||
#include <boost/thread/thread_only.hpp>
|
||||
#include <limits>
|
||||
#include "string_tools.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); \
|
||||
|
||||
|
||||
txpool_base::txpool_base()
|
||||
: test_chain_unit_base()
|
||||
, m_broadcasted_tx_count(0)
|
||||
, m_all_tx_count(0)
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(txpool_spend_key_public, increase_broadcasted_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_broadcasted_tx_count(cryptonote::core& /*c*/, size_t /*ev_index*/, const std::vector<test_event_entry>& /*events*/)
|
||||
{
|
||||
++m_broadcasted_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_broadcasted_tx_count || key_images.size() != m_broadcasted_tx_count)
|
||||
{
|
||||
MERROR("Failed broadcasted spent keys retrieval - Expected Broadcasted Count: " << m_broadcasted_tx_count << " Actual Info Count: " << infos.size() << " Actual Key Image Count: " << key_images.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
infos.clear();
|
||||
key_images.clear();
|
||||
if (!c.get_pool_transactions_and_spent_keys_info(infos, key_images, false) || infos.size() != m_broadcasted_tx_count || key_images.size() != m_broadcasted_tx_count)
|
||||
{
|
||||
MERROR("Failed broadcasted spent keys retrieval - Expected Broadcasted Count: " << m_broadcasted_tx_count << " Actual Info Count: " << infos.size() << " Actual Key Image Count: " << key_images.size());
|
||||
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)
|
||||
{
|
||||
MERROR("Failed all spent keys retrieval - Expected All Count: " << m_all_tx_count << " Actual Info Count: " << infos.size() << " Actual Key Image Count: " << key_images.size());
|
||||
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_broadcasted_tx_count");
|
||||
DO_CALLBACK(events, "increase_all_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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
txpool_double_spend_base::txpool_double_spend_base()
|
||||
: txpool_base()
|
||||
, m_broadcasted_hashes()
|
||||
, m_no_relay_hashes()
|
||||
, m_all_hashes()
|
||||
, m_no_new_index(0)
|
||||
, m_new_timestamp_index(0)
|
||||
, m_last_tx(crypto::hash{})
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, mark_no_new);
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, mark_timestamp_change);
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, timestamp_change_pause);
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, check_unchanged);
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, check_new_broadcasted);
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, check_new_hidden);
|
||||
REGISTER_CALLBACK_METHOD(txpool_double_spend_base, check_new_no_relay);
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::mark_no_new(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
|
||||
{
|
||||
m_no_new_index = ev_index + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::mark_timestamp_change(cryptonote::core& /*c*/, size_t ev_index, const std::vector<test_event_entry>& /*events*/)
|
||||
{
|
||||
m_new_timestamp_index = ev_index + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::timestamp_change_pause(cryptonote::core& /*c*/, size_t /*ev_index*/, const std::vector<test_event_entry>& /*events*/)
|
||||
{
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds{1} + boost::chrono::milliseconds{100});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::check_changed(cryptonote::core& c, const size_t ev_index, relay_test condition)
|
||||
{
|
||||
const std::size_t public_hash_count = m_broadcasted_hashes.size();
|
||||
const std::size_t all_hash_count = m_all_hashes.size();
|
||||
|
||||
const std::size_t new_broadcasted_hash_count = m_broadcasted_hashes.size() + unsigned(condition == relay_test::broadcasted);
|
||||
const std::size_t new_all_hash_count = m_all_hashes.size() + unsigned(condition == relay_test::hidden) + unsigned(condition == relay_test::no_relay);
|
||||
|
||||
std::vector<crypto::hash> hashes{};
|
||||
if (!c.get_pool_transaction_hashes(hashes))
|
||||
{
|
||||
MERROR("Failed to get broadcasted transaction pool hashes");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const crypto::hash& hash : hashes)
|
||||
m_broadcasted_hashes.insert(hash);
|
||||
|
||||
if (new_broadcasted_hash_count != m_broadcasted_hashes.size())
|
||||
{
|
||||
MERROR("Expected " << new_broadcasted_hash_count << " broadcasted hashes but got " << m_broadcasted_hashes.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_broadcasted_hashes.size() != c.get_pool_transactions_count())
|
||||
{
|
||||
MERROR("Expected " << m_broadcasted_hashes.size() << " broadcasted hashes but got " << c.get_pool_transactions_count());
|
||||
return false;
|
||||
}
|
||||
|
||||
hashes.clear();
|
||||
if (!c.get_pool_transaction_hashes(hashes, false))
|
||||
{
|
||||
MERROR("Failed to get broadcasted transaction pool hashes");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const crypto::hash& hash : hashes)
|
||||
m_all_hashes.insert(std::make_pair(hash, 0));
|
||||
|
||||
if (new_broadcasted_hash_count != m_broadcasted_hashes.size())
|
||||
{
|
||||
MERROR("Expected " << new_broadcasted_hash_count << " broadcasted hashes but got " << m_broadcasted_hashes.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
hashes.clear();
|
||||
if (!c.get_pool_transaction_hashes(hashes, true))
|
||||
{
|
||||
|
||||
MERROR("Failed to get all transaction pool hashes");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const crypto::hash& hash : hashes)
|
||||
m_all_hashes.insert(std::make_pair(hash, 0));
|
||||
|
||||
if (new_all_hash_count != m_all_hashes.size())
|
||||
{
|
||||
MERROR("Expected " << new_all_hash_count << " all hashes but got " << m_all_hashes.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (condition == relay_test::no_relay)
|
||||
{
|
||||
if (!m_no_relay_hashes.insert(m_last_tx).second)
|
||||
{
|
||||
MERROR("Expected new no_relay tx but got a duplicate legacy tx");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const crypto::hash& hash : m_no_relay_hashes)
|
||||
{
|
||||
if (!c.pool_has_tx(hash))
|
||||
{
|
||||
MERROR("Expected public tx " << hash << " to be listed in pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check receive time changes
|
||||
{
|
||||
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, true) || infos.size() != m_all_hashes.size())
|
||||
{
|
||||
MERROR("Unable to retrieve all txpool metadata");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const cryptonote::tx_info& info : infos)
|
||||
{
|
||||
crypto::hash tx_hash;
|
||||
if (!epee::string_tools::hex_to_pod(info.id_hash, tx_hash))
|
||||
{
|
||||
MERROR("Unable to convert tx_hash hex to binary");
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto entry = m_all_hashes.find(tx_hash);
|
||||
if (entry == m_all_hashes.end())
|
||||
{
|
||||
MERROR("Unable to find tx_hash in set of tracked hashes");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_new_timestamp_index == ev_index && m_last_tx == tx_hash)
|
||||
{
|
||||
if (entry->second >= info.receive_time)
|
||||
{
|
||||
MERROR("Last relay time did not change as expected - last at " << entry->second << " and current at " << info.receive_time);
|
||||
return false;
|
||||
}
|
||||
entry->second = info.receive_time;
|
||||
}
|
||||
else if (entry->second != info.receive_time)
|
||||
{
|
||||
MERROR("Last relayed time changed unexpectedly from " << entry->second << " to " << info.receive_time);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<cryptonote::transaction> txes{};
|
||||
if (!c.get_pool_transactions(txes))
|
||||
{
|
||||
MERROR("Failed to get broadcasted transactions from pool");
|
||||
return false;
|
||||
}
|
||||
|
||||
hashes.clear();
|
||||
for (const cryptonote::transaction& tx : txes)
|
||||
hashes.push_back(cryptonote::get_transaction_hash(tx));
|
||||
|
||||
std::unordered_set<crypto::hash> public_hashes = m_broadcasted_hashes;
|
||||
for (const crypto::hash& hash : hashes)
|
||||
{
|
||||
if (!c.pool_has_tx(hash))
|
||||
{
|
||||
MERROR("Expected broadcasted tx " << hash << " to be listed in pool");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!public_hashes.erase(hash))
|
||||
{
|
||||
MERROR("An unexected transaction was returned from the public pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!public_hashes.empty())
|
||||
{
|
||||
MERROR(public_hashes.size() << " transaction(s) were missing from the public pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<cryptonote::transaction> txes{};
|
||||
if (!c.get_pool_transactions(txes, false))
|
||||
{
|
||||
MERROR("Failed to get broadcasted transactions from pool");
|
||||
return false;
|
||||
}
|
||||
|
||||
hashes.clear();
|
||||
for (const cryptonote::transaction& tx : txes)
|
||||
hashes.push_back(cryptonote::get_transaction_hash(tx));
|
||||
|
||||
std::unordered_set<crypto::hash> public_hashes = m_broadcasted_hashes;
|
||||
for (const crypto::hash& hash : hashes)
|
||||
{
|
||||
|
||||
if (!public_hashes.erase(hash))
|
||||
{
|
||||
MERROR("An unexected transaction was returned from the public pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!public_hashes.empty())
|
||||
{
|
||||
MERROR(public_hashes.size() << " transaction(s) were missing from the public pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<cryptonote::transaction> txes{};
|
||||
if (!c.get_pool_transactions(txes, true))
|
||||
{
|
||||
MERROR("Failed to get all transactions from pool");
|
||||
return false;
|
||||
}
|
||||
|
||||
hashes.clear();
|
||||
for (const cryptonote::transaction& tx : txes)
|
||||
hashes.push_back(cryptonote::get_transaction_hash(tx));
|
||||
|
||||
std::unordered_map<crypto::hash, uint64_t> all_hashes = m_all_hashes;
|
||||
for (const crypto::hash& hash : hashes)
|
||||
{
|
||||
if (!all_hashes.erase(hash))
|
||||
{
|
||||
MERROR("An unexected transaction was returned from the all pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!all_hashes.empty())
|
||||
{
|
||||
MERROR(m_broadcasted_hashes.size() << " transaction(s) were missing from the all pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<cryptonote::tx_backlog_entry> entries{};
|
||||
if (!c.get_txpool_backlog(entries))
|
||||
{
|
||||
MERROR("Failed to get broadcasted txpool backlog");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_broadcasted_hashes.size() != entries.size())
|
||||
{
|
||||
MERROR("Expected " << m_broadcasted_hashes.size() << " in the broadcasted txpool backlog but got " << entries.size());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::pair<crypto::hash, uint64_t>& hash : m_all_hashes)
|
||||
{
|
||||
cryptonote::blobdata tx_blob{};
|
||||
if (!c.get_pool_transaction(hash.first, tx_blob, cryptonote::relay_category::all))
|
||||
{
|
||||
MERROR("Failed to retrieve tx expected to be in pool: " << hash.first);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::unordered_map<crypto::hash, uint64_t> difference = m_all_hashes;
|
||||
for (const crypto::hash& hash : m_broadcasted_hashes)
|
||||
difference.erase(hash);
|
||||
|
||||
for (const crypto::hash& hash : m_no_relay_hashes)
|
||||
difference.erase(hash);
|
||||
|
||||
for (const std::pair<crypto::hash, uint64_t>& hash : difference)
|
||||
{
|
||||
if (c.pool_has_tx(hash.first))
|
||||
{
|
||||
MERROR("Did not expect private/hidden tx " << hash.first << " to be listed in pool");
|
||||
return false;
|
||||
}
|
||||
|
||||
cryptonote::blobdata tx_blob{};
|
||||
if (c.get_pool_transaction(hash.first, tx_blob, cryptonote::relay_category::broadcasted))
|
||||
{
|
||||
MERROR("Tx " << hash.first << " is not supposed to be in broadcasted pool");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c.get_pool_transaction(hash.first, tx_blob, cryptonote::relay_category::all))
|
||||
{
|
||||
MERROR("Tx " << hash.first << " blob could not be retrieved from pool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cryptonote::txpool_stats stats{};
|
||||
if (!c.get_pool_transaction_stats(stats) || stats.txs_total != m_broadcasted_hashes.size())
|
||||
{
|
||||
MERROR("Expected broadcasted stats to list " << m_broadcasted_hashes.size() << " txes but got " << stats.txs_total);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c.get_pool_transaction_stats(stats, false) || stats.txs_total != m_broadcasted_hashes.size())
|
||||
{
|
||||
MERROR("Expected broadcasted stats to list " << m_broadcasted_hashes.size() << " txes but got " << stats.txs_total);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c.get_pool_transaction_stats(stats, true) || stats.txs_total != m_all_hashes.size())
|
||||
{
|
||||
MERROR("Expected all stats to list " << m_all_hashes.size() << " txes but got " << stats.txs_total);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<cryptonote::rpc::tx_in_pool> infos{};
|
||||
cryptonote::rpc::key_images_with_tx_hashes key_images{};
|
||||
if (!c.get_pool_for_rpc(infos, key_images) || infos.size() != m_broadcasted_hashes.size() || key_images.size() != m_broadcasted_hashes.size())
|
||||
{
|
||||
MERROR("Expected broadcasted rpc data to return " << m_broadcasted_hashes.size() << " but got " << infos.size() << " infos and " << key_images.size() << "key images");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::check_unchanged(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& /*events */)
|
||||
{
|
||||
return check_changed(c, ev_index, relay_test::no_change);
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::check_new_broadcasted(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& /*events */)
|
||||
{
|
||||
return check_changed(c, ev_index, relay_test::broadcasted);
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::check_new_hidden(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& /*events */)
|
||||
{
|
||||
return check_changed(c, ev_index, relay_test::hidden);
|
||||
}
|
||||
bool txpool_double_spend_base::check_new_no_relay(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& /*events */)
|
||||
{
|
||||
return check_changed(c, ev_index, relay_test::no_relay);
|
||||
}
|
||||
|
||||
bool txpool_double_spend_base::check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_idx, const cryptonote::transaction& tx)
|
||||
{
|
||||
m_last_tx = cryptonote::get_transaction_hash(tx);
|
||||
if (m_no_new_index == event_idx)
|
||||
return !tvc.m_verifivation_failed && !tx_added;
|
||||
else
|
||||
return !tvc.m_verifivation_failed && tx_added;
|
||||
}
|
||||
|
||||
bool txpool_double_spend_norelay::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
INIT_MEMPOOL_TEST();
|
||||
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_do_not_relay);
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
|
||||
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");
|
||||
DO_CALLBACK(events, "mark_timestamp_change");
|
||||
DO_CALLBACK(events, "check_new_no_relay");
|
||||
DO_CALLBACK(events, "timestamp_change_pause");
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
events.push_back(tx_0);
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
DO_CALLBACK(events, "check_unchanged");
|
||||
SET_EVENT_VISITOR_SETT(events, 0);
|
||||
DO_CALLBACK(events, "timestamp_change_pause");
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
events.push_back(tx_0);
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
DO_CALLBACK(events, "check_unchanged");
|
||||
|
||||
// kepped by block currently does not change txpool status
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block);
|
||||
DO_CALLBACK(events, "timestamp_change_pause");
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
events.push_back(tx_0);
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
DO_CALLBACK(events, "check_unchanged");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool txpool_double_spend_local::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
INIT_MEMPOOL_TEST();
|
||||
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_local_relay);
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
|
||||
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");
|
||||
DO_CALLBACK(events, "mark_timestamp_change");
|
||||
DO_CALLBACK(events, "check_new_hidden");
|
||||
DO_CALLBACK(events, "timestamp_change_pause");
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
events.push_back(tx_0);
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
DO_CALLBACK(events, "mark_timestamp_change");
|
||||
DO_CALLBACK(events, "check_unchanged");
|
||||
SET_EVENT_VISITOR_SETT(events, 0);
|
||||
DO_CALLBACK(events, "timestamp_change_pause");
|
||||
events.push_back(tx_0);
|
||||
DO_CALLBACK(events, "increase_broadcasted_tx_count");
|
||||
DO_CALLBACK(events, "check_txpool_spent_keys");
|
||||
DO_CALLBACK(events, "mark_timestamp_change");
|
||||
DO_CALLBACK(events, "check_new_broadcasted");
|
||||
DO_CALLBACK(events, "timestamp_change_pause");
|
||||
DO_CALLBACK(events, "mark_no_new");
|
||||
events.push_back(tx_0);
|
||||
DO_CALLBACK(events, "check_unchanged");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
118
tests/core_tests/tx_pool.h
Normal file
118
tests/core_tests/tx_pool.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
// 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 <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "chaingen.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
enum class relay_test
|
||||
{
|
||||
no_change = 0, //!< No expected changes to the txpool
|
||||
broadcasted, //!< A new block or fluff/flood tx is expected in txpool
|
||||
hidden, //!< A new stem or local tx is expected in txpool
|
||||
no_relay //!< A new no relay is expected in txpool
|
||||
};
|
||||
|
||||
class txpool_base : public test_chain_unit_base
|
||||
{
|
||||
size_t m_broadcasted_tx_count;
|
||||
size_t m_all_tx_count;
|
||||
|
||||
public:
|
||||
txpool_base();
|
||||
|
||||
bool increase_broadcasted_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);
|
||||
};
|
||||
|
||||
class txpool_double_spend_base : public txpool_base
|
||||
{
|
||||
std::unordered_set<crypto::hash> m_broadcasted_hashes;
|
||||
std::unordered_set<crypto::hash> m_no_relay_hashes;
|
||||
std::unordered_map<crypto::hash, uint64_t> m_all_hashes;
|
||||
size_t m_no_new_index;
|
||||
size_t m_new_timestamp_index;
|
||||
crypto::hash m_last_tx;
|
||||
|
||||
bool check_changed(cryptonote::core& c, size_t ev_index, relay_test condition);
|
||||
|
||||
public:
|
||||
txpool_double_spend_base();
|
||||
|
||||
bool mark_no_new(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool mark_timestamp_change(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
//! Pause for 1 second, so that `receive_time` for tx meta changes (tx hidden from public rpc being updated)
|
||||
bool timestamp_change_pause(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
bool check_unchanged(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool check_new_broadcasted(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool check_new_hidden(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool check_new_no_relay(cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
bool check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_idx, const cryptonote::transaction& /*tx*/);
|
||||
};
|
||||
|
||||
struct txpool_double_spend_norelay : txpool_double_spend_base
|
||||
{
|
||||
txpool_double_spend_norelay()
|
||||
: txpool_double_spend_base()
|
||||
{}
|
||||
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
|
||||
struct txpool_double_spend_local : txpool_double_spend_base
|
||||
{
|
||||
txpool_double_spend_local()
|
||||
: txpool_double_spend_base()
|
||||
{}
|
||||
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
|
@ -32,6 +32,7 @@
|
|||
#include "cryptonote_core/cryptonote_core.h"
|
||||
#include "p2p/net_node.h"
|
||||
#include "p2p/net_node.inl"
|
||||
#include "cryptonote_core/i_core_events.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_handler.inl"
|
||||
|
||||
|
@ -43,7 +44,7 @@ namespace cryptonote {
|
|||
class blockchain_storage;
|
||||
}
|
||||
|
||||
class test_core
|
||||
class test_core : public cryptonote::i_core_events
|
||||
{
|
||||
public:
|
||||
void on_synchronized(){}
|
||||
|
@ -56,8 +57,8 @@ public:
|
|||
bool get_stat_info(cryptonote::core_stat_info& st_inf) const {return true;}
|
||||
bool have_block(const crypto::hash& id) const {return true;}
|
||||
void get_blockchain_top(uint64_t& height, crypto::hash& top_id)const{height=0;top_id=crypto::null_hash;}
|
||||
bool handle_incoming_tx(const cryptonote::tx_blob_entry& tx_blob, cryptonote::tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { return true; }
|
||||
bool handle_incoming_txs(const std::vector<cryptonote::tx_blob_entry>& tx_blob, std::vector<cryptonote::tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { return true; }
|
||||
bool handle_incoming_tx(const cryptonote::tx_blob_entry& tx_blob, cryptonote::tx_verification_context& tvc, cryptonote::relay_method tx_relay, bool relayed) { return true; }
|
||||
bool handle_incoming_txs(const std::vector<cryptonote::tx_blob_entry>& tx_blob, std::vector<cryptonote::tx_verification_context>& tvc, cryptonote::relay_method tx_relay, bool relayed) { return true; }
|
||||
bool handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block, cryptonote::block_verification_context& bvc, bool update_miner_blocktemplate = true) { return true; }
|
||||
void pause_mine(){}
|
||||
void resume_mine(){}
|
||||
|
@ -71,9 +72,9 @@ public:
|
|||
bool cleanup_handle_incoming_blocks(bool force_sync = false) { return true; }
|
||||
uint64_t get_target_blockchain_height() const { return 1; }
|
||||
size_t get_block_sync_size(uint64_t height) const { return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; }
|
||||
virtual void on_transaction_relayed(const cryptonote::blobdata& tx) {}
|
||||
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, cryptonote::relay_method tx_relay) {}
|
||||
cryptonote::network_type get_nettype() const { return cryptonote::MAINNET; }
|
||||
bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob) const { return false; }
|
||||
bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob, cryptonote::relay_category tx_category) const { return false; }
|
||||
bool pool_has_tx(const crypto::hash &txid) const { return false; }
|
||||
bool get_blocks(uint64_t start_offset, size_t count, std::vector<std::pair<cryptonote::blobdata, cryptonote::block>>& blocks, std::vector<cryptonote::blobdata>& txs) const { return false; }
|
||||
bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::vector<cryptonote::transaction>& txs, std::vector<crypto::hash>& missed_txs) const { return false; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue