Merge pull request #6214

054b4c7 protocol: request txpool contents when synced (moneromooo-monero)
This commit is contained in:
luigi1111 2020-03-31 13:32:55 -05:00
commit 096e2135dd
No known key found for this signature in database
GPG Key ID: F4ACA0183641E010
9 changed files with 147 additions and 0 deletions

View File

@ -1935,6 +1935,12 @@ namespace cryptonote
{ {
m_blockchain_storage.flush_invalid_blocks(); m_blockchain_storage.flush_invalid_blocks();
} }
//-----------------------------------------------------------------------------------------------
bool core::get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes)
{
return m_mempool.get_complement(hashes, txes);
}
//-----------------------------------------------------------------------------------------------
bool core::update_blockchain_pruning() bool core::update_blockchain_pruning()
{ {
return m_blockchain_storage.update_blockchain_pruning(); return m_blockchain_storage.update_blockchain_pruning();

View File

@ -854,6 +854,15 @@ namespace cryptonote
*/ */
void flush_invalid_blocks(); void flush_invalid_blocks();
/**
* @brief returns the set of transactions in the txpool which are not in the argument
*
* @param hashes hashes of transactions to exclude from the result
*
* @return true iff success, false otherwise
*/
bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes);
private: private:
/** /**

View File

@ -576,6 +576,39 @@ namespace cryptonote
return true; return true;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool tx_memory_pool::get_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
m_blockchain.for_all_txpool_txes([this, &hashes, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
const auto relay_method = meta.get_relay_method();
if (relay_method != relay_method::block && relay_method != relay_method::fluff)
return true;
const auto i = std::find(hashes.begin(), hashes.end(), txid);
if (i == hashes.end())
{
cryptonote::blobdata bd;
try
{
if (!m_blockchain.get_txpool_tx_blob(txid, bd, cryptonote::relay_category::broadcasted))
{
MERROR("Failed to get blob for txpool transaction " << txid);
return true;
}
txes.emplace_back(std::move(bd));
}
catch (const std::exception &e)
{
MERROR("Failed to get blob for txpool transaction " << txid << ": " << e.what());
return true;
}
}
return true;
}, false);
return true;
}
//---------------------------------------------------------------------------------
void tx_memory_pool::on_idle() void tx_memory_pool::on_idle()
{ {
m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();}); m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});

View File

@ -441,6 +441,11 @@ namespace cryptonote
*/ */
bool get_transaction_info(const crypto::hash &txid, tx_details &td) const; bool get_transaction_info(const crypto::hash &txid, tx_details &td) const;
/**
* @brief get transactions not in the passed set
*/
bool get_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) const;
private: private:
/** /**

View File

@ -354,4 +354,22 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<request_t> request; typedef epee::misc_utils::struct_init<request_t> request;
}; };
/************************************************************************/
/* */
/************************************************************************/
struct NOTIFY_GET_TXPOOL_COMPLEMENT
{
const static int ID = BC_COMMANDS_POOL_BASE + 10;
struct request_t
{
std::vector<crypto::hash> hashes;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(hashes)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
};
} }

View File

@ -90,6 +90,7 @@ namespace cryptonote
HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_CHAIN_ENTRY, &cryptonote_protocol_handler::handle_response_chain_entry) HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_CHAIN_ENTRY, &cryptonote_protocol_handler::handle_response_chain_entry)
HANDLE_NOTIFY_T2(NOTIFY_NEW_FLUFFY_BLOCK, &cryptonote_protocol_handler::handle_notify_new_fluffy_block) HANDLE_NOTIFY_T2(NOTIFY_NEW_FLUFFY_BLOCK, &cryptonote_protocol_handler::handle_notify_new_fluffy_block)
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_FLUFFY_MISSING_TX, &cryptonote_protocol_handler::handle_request_fluffy_missing_tx) HANDLE_NOTIFY_T2(NOTIFY_REQUEST_FLUFFY_MISSING_TX, &cryptonote_protocol_handler::handle_request_fluffy_missing_tx)
HANDLE_NOTIFY_T2(NOTIFY_GET_TXPOOL_COMPLEMENT, &cryptonote_protocol_handler::handle_notify_get_txpool_complement)
END_INVOKE_MAP2() END_INVOKE_MAP2()
bool on_idle(); bool on_idle();
@ -124,6 +125,7 @@ namespace cryptonote
int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, cryptonote_connection_context& context); int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, cryptonote_connection_context& context);
int handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context); int handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context);
int handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context); int handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context);
int handle_notify_get_txpool_complement(int command, NOTIFY_GET_TXPOOL_COMPLEMENT::request& arg, cryptonote_connection_context& context);
//----------------- i_bc_protocol_layout --------------------------------------- //----------------- i_bc_protocol_layout ---------------------------------------
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context); virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context);
@ -144,6 +146,7 @@ namespace cryptonote
int try_add_next_blocks(cryptonote_connection_context &context); int try_add_next_blocks(cryptonote_connection_context &context);
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe); void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe);
void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const; void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
bool request_txpool_complement(cryptonote_connection_context &context);
t_core& m_core; t_core& m_core;
@ -153,6 +156,7 @@ namespace cryptonote
std::atomic<bool> m_synchronized; std::atomic<bool> m_synchronized;
std::atomic<bool> m_stopping; std::atomic<bool> m_stopping;
std::atomic<bool> m_no_sync; std::atomic<bool> m_no_sync;
std::atomic<bool> m_ask_for_txpool_complement;
boost::mutex m_sync_lock; boost::mutex m_sync_lock;
block_queue m_block_queue; block_queue m_block_queue;
epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker; epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker;

View File

@ -83,6 +83,7 @@ namespace cryptonote
m_p2p(p_net_layout), m_p2p(p_net_layout),
m_syncronized_connections_count(0), m_syncronized_connections_count(0),
m_synchronized(offline), m_synchronized(offline),
m_ask_for_txpool_complement(true),
m_stopping(false), m_stopping(false),
m_no_sync(false) m_no_sync(false)
@ -879,6 +880,34 @@ namespace cryptonote
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
template<class t_core> template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_notify_get_txpool_complement(int command, NOTIFY_GET_TXPOOL_COMPLEMENT::request& arg, cryptonote_connection_context& context)
{
MLOG_P2P_MESSAGE("Received NOTIFY_GET_TXPOOL_COMPLEMENT (" << arg.hashes.size() << " txes)");
std::vector<std::pair<cryptonote::blobdata, block>> local_blocks;
std::vector<cryptonote::blobdata> local_txs;
std::vector<cryptonote::blobdata> txes;
if (!m_core.get_txpool_complement(arg.hashes, txes))
{
LOG_ERROR_CCONTEXT("failed to get txpool complement");
return 1;
}
NOTIFY_NEW_TRANSACTIONS::request new_txes;
new_txes.txs = std::move(txes);
MLOG_P2P_MESSAGE
(
"-->>NOTIFY_NEW_TRANSACTIONS: "
<< ", txs.size()=" << new_txes.txs.size()
);
post_notify<NOTIFY_NEW_TRANSACTIONS>(new_txes, context);
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& context) int t_cryptonote_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& context)
{ {
MLOG_P2P_MESSAGE("Received NOTIFY_NEW_TRANSACTIONS (" << arg.txs.size() << " txes)"); MLOG_P2P_MESSAGE("Received NOTIFY_NEW_TRANSACTIONS (" << arg.txs.size() << " txes)");
@ -2195,6 +2224,27 @@ skip:
} }
m_core.safesyncmode(true); m_core.safesyncmode(true);
m_p2p->clear_used_stripe_peers(); m_p2p->clear_used_stripe_peers();
// ask for txpool complement from any suitable node if we did not yet
val_expected = true;
if (m_ask_for_txpool_complement.compare_exchange_strong(val_expected, false))
{
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool
{
if(context.m_state < cryptonote_connection_context::state_synchronizing)
{
MDEBUG(context << "not ready, ignoring");
return true;
}
if (!request_txpool_complement(context))
{
MERROR(context << "Failed to request txpool complement");
return true;
}
return false;
});
}
return true; return true;
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
@ -2348,6 +2398,21 @@ skip:
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
template<class t_core> template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::request_txpool_complement(cryptonote_connection_context &context)
{
NOTIFY_GET_TXPOOL_COMPLEMENT::request r = {};
if (!m_core.get_pool_transaction_hashes(r.hashes, false))
{
MERROR("Failed to get txpool hashes");
return false;
}
MLOG_P2P_MESSAGE("-->>NOTIFY_GET_TXPOOL_COMPLEMENT: hashes.size()=" << r.hashes.size() );
post_notify<NOTIFY_GET_TXPOOL_COMPLEMENT>(r, context);
MLOG_PEER_STATE("requesting txpool complement");
return true;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
std::string t_cryptonote_protocol_handler<t_core>::get_peers_overview() const std::string t_cryptonote_protocol_handler<t_core>::get_peers_overview() const
{ {
std::stringstream ss; std::stringstream ss;
@ -2457,7 +2522,10 @@ skip:
MINFO("Target height decreasing from " << previous_target << " to " << target); MINFO("Target height decreasing from " << previous_target << " to " << target);
m_core.set_target_blockchain_height(target); m_core.set_target_blockchain_height(target);
if (target == 0 && context.m_state > cryptonote_connection_context::state_before_handshake && !m_stopping) if (target == 0 && context.m_state > cryptonote_connection_context::state_before_handshake && !m_stopping)
{
MCWARNING("global", "monerod is now disconnected from the network"); MCWARNING("global", "monerod is now disconnected from the network");
m_ask_for_txpool_complement = true;
}
} }
m_block_queue.flush_spans(context.m_connection_id, false); m_block_queue.flush_spans(context.m_connection_id, false);

View File

@ -109,5 +109,7 @@ namespace tests
bool pad_transactions() const { return false; } bool pad_transactions() const { return false; }
uint32_t get_blockchain_pruning_seed() const { return 0; } uint32_t get_blockchain_pruning_seed() const { return 0; }
bool prune_blockchain(uint32_t pruning_seed) const { return true; } bool prune_blockchain(uint32_t pruning_seed) const { return true; }
bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) { return false; }
bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const { return false; }
}; };
} }

View File

@ -90,6 +90,8 @@ public:
bool prune_blockchain(uint32_t pruning_seed = 0) { return true; } bool prune_blockchain(uint32_t pruning_seed = 0) { return true; }
bool is_within_compiled_block_hash_area(uint64_t height) const { return false; } bool is_within_compiled_block_hash_area(uint64_t height) const { return false; }
bool has_block_weights(uint64_t height, uint64_t nblocks) const { return false; } bool has_block_weights(uint64_t height, uint64_t nblocks) const { return false; }
bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) { return false; }
bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const { return false; }
void stop() {} void stop() {}
}; };