From 72bfd897178ca87ca69e9e52e221a4d3ed697257 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 21 Mar 2022 16:47:11 +0200 Subject: [PATCH] improved p2p protocol for relaying tx over tor --- src/currency_core/currency_config.h | 2 + src/currency_core/tx_pool.cpp | 2 +- .../currency_protocol_defs.h | 40 ++++-------- .../currency_protocol_handler.h | 15 +++-- .../currency_protocol_handler.inl | 61 ++++++++++++++----- .../currency_protocol_handler_common.h | 4 +- src/rpc/core_rpc_server.cpp | 4 +- src/wallet/wallet2.cpp | 7 ++- tests/core_tests/test_core_proxy.h | 2 +- 9 files changed, 78 insertions(+), 59 deletions(-) diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 29e76ab1..18e38c67 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -250,6 +250,8 @@ + static_assert(CURRENCY_MINER_TX_MAX_OUTS <= CURRENCY_TX_MAX_ALLOWED_OUTS, "Miner tx must obey normal tx max outs limit"); static_assert(PREMINE_AMOUNT / WALLET_MAX_ALLOWED_OUTPUT_AMOUNT < CURRENCY_MINER_TX_MAX_OUTS, "Premine can't be divided into reasonable number of outs"); +#define CURRENCY_RELAY_TXS_MAX_COUNT 5 \ No newline at end of file diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 7a65990e..581dfdb8 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -666,7 +666,7 @@ namespace currency bool tx_memory_pool::force_relay_pool() const { LOG_PRINT_GREEN("Preparing relay message...", LOG_LEVEL_0); - NOTIFY_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& k, const tx_details& v) { diff --git a/src/currency_protocol/currency_protocol_defs.h b/src/currency_protocol/currency_protocol_defs.h index 7b7d24f0..2a0eead6 100644 --- a/src/currency_protocol/currency_protocol_defs.h +++ b/src/currency_protocol/currency_protocol_defs.h @@ -71,7 +71,7 @@ namespace currency /************************************************************************/ /* */ /************************************************************************/ - struct NOTIFY_NEW_TRANSACTIONS + struct NOTIFY_OR_INVOKE_NEW_TRANSACTIONS { const static int ID = BC_COMMANDS_POOL_BASE + 2; @@ -83,6 +83,16 @@ namespace currency KV_SERIALIZE(txs) END_KV_SERIALIZE_MAP() }; + + struct response + { + std::string code; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(code) + END_KV_SERIALIZE_MAP() + }; + }; /************************************************************************/ /* */ @@ -174,34 +184,6 @@ namespace currency }; }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct INVOKE_NEW_TRANSACTION - { - const static int ID = BC_COMMANDS_POOL_BASE + 8; - - struct request - { - blobdata tx; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string code; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(code) - END_KV_SERIALIZE_MAP() - }; - - }; - } #include "currency_protocol_defs_print.h" diff --git a/src/currency_protocol/currency_protocol_handler.h b/src/currency_protocol/currency_protocol_handler.h index cae17241..1e420919 100644 --- a/src/currency_protocol/currency_protocol_handler.h +++ b/src/currency_protocol/currency_protocol_handler.h @@ -35,14 +35,15 @@ namespace currency typedef core_stat_info stat_info; typedef t_currency_protocol_handler currency_protocol_handler; typedef CORE_SYNC_DATA payload_type; - typedef std::pair relay_que_entry; + typedef std::pair relay_que_entry; t_currency_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint* p_net_layout); ~t_currency_protocol_handler(); BEGIN_INVOKE_MAP2(currency_protocol_handler) HANDLE_NOTIFY_T2(NOTIFY_NEW_BLOCK, ¤cy_protocol_handler::handle_notify_new_block) - HANDLE_NOTIFY_T2(NOTIFY_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_notify_new_transactions) + HANDLE_NOTIFY_T2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_notify_new_transactions) + HANDLE_INVOKE_T2(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_invoke_new_transaction) HANDLE_NOTIFY_T2(NOTIFY_REQUEST_GET_OBJECTS, ¤cy_protocol_handler::handle_request_get_objects) HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_GET_OBJECTS, ¤cy_protocol_handler::handle_response_get_objects) HANDLE_NOTIFY_T2(NOTIFY_REQUEST_CHAIN, ¤cy_protocol_handler::handle_request_chain) @@ -76,16 +77,18 @@ namespace currency private: //----------------- commands handlers ---------------------------------------------- int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& context); - int handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context); + int handle_notify_new_transactions(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& context); + int handle_invoke_new_transaction(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& req, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context); int handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context); int handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, currency_connection_context& context); int handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, currency_connection_context& context); int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, currency_connection_context& context); - + + //----------------- i_bc_protocol_layout --------------------------------------- virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context); - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context); + virtual bool relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context); //---------------------------------------------------------------------------------- //bool get_payload_sync_data(HANDSHAKE_DATA::request& hshd, currency_connection_context& context); bool request_missing_objects(currency_connection_context& context, bool check_having_blocks); @@ -93,7 +96,7 @@ namespace currency void relay_que_worker(); void process_current_relay_que(const std::list& que); bool check_stop_flag_and_drop_cc(currency_connection_context& context); - + int handle_new_transaction_from_net(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& req, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context, bool is_notify); t_core& m_core; nodetool::p2p_endpoint_stub m_p2p_stub; diff --git a/src/currency_protocol/currency_protocol_handler.inl b/src/currency_protocol/currency_protocol_handler.inl index 62e66448..2ec82588 100644 --- a/src/currency_protocol/currency_protocol_handler.inl +++ b/src/currency_protocol/currency_protocol_handler.inl @@ -369,48 +369,79 @@ namespace currency } //------------------------------------------------------------------------------------------------------------------------ template - int t_currency_protocol_handler::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context) + int t_currency_protocol_handler::handle_notify_new_transactions(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& context) + { + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response rsp_dummy = AUTO_VAL_INIT(rsp_dummy); + return this->handle_new_transaction_from_net(arg, rsp_dummy, context, true); + } + //------------------------------------------------------------------------------------------------------------------------ + template + int t_currency_protocol_handler::handle_invoke_new_transaction(int command, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& req, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context) + { + return this->handle_new_transaction_from_net(req, rsp, context, false); + } + //------------------------------------------------------------------------------------------------------------------------ + template + int t_currency_protocol_handler::handle_new_transaction_from_net(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response& rsp, currency_connection_context& context, bool is_notify) { //do not process requests if it comes from node wich is debugged if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) + { + rsp.code = API_RETURN_CODE_ACCESS_DENIED; return 1; + } //if(context.m_state != currency_connection_context::state_normal) // return 1; if (!this->is_synchronized()) + { + rsp.code = API_RETURN_CODE_BUSY; return 1; - + } + + uint64_t inital_tx_count = arg.txs.size(); + + if (inital_tx_count > CURRENCY_RELAY_TXS_MAX_COUNT) + { + LOG_PRINT_L1("NOTIFY_NEW_TRANSACTIONS: To many transactions in NOTIFY_OR_INVOKE_NEW_TRANSACTIONS(" << inital_tx_count << ")"); + rsp.code = API_RETURN_CODE_OVERFLOW; + return 1; + } + TIME_MEASURE_START_MS(new_transactions_handle_time); - for(auto tx_blob_it = arg.txs.begin(); tx_blob_it!=arg.txs.end();) + for (auto tx_blob_it = arg.txs.begin(); tx_blob_it != arg.txs.end();) { currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); m_core.handle_incoming_tx(*tx_blob_it, tvc, false); - if(tvc.m_verification_failed) + if (tvc.m_verification_failed) { LOG_PRINT_L0("NOTIFY_NEW_TRANSACTIONS: Tx verification failed, dropping connection"); - m_p2p->drop_connection(context); - + if(is_notify) + m_p2p->drop_connection(context); + else + rsp.code = API_RETURN_CODE_FAIL; return 1; } - if(tvc.m_should_be_relayed) + if (tvc.m_should_be_relayed) ++tx_blob_it; else arg.txs.erase(tx_blob_it++); } - if(arg.txs.size()) + if (arg.txs.size()) { //TODO: add announce usage here relay_transactions(arg, context); } TIME_MEASURE_FINISH_MS(new_transactions_handle_time); - LOG_PRINT_L2("NOTIFY_NEW_TRANSACTIONS: " << new_transactions_handle_time << "ms (inital_tx_count: " << inital_tx_count << ", relayed_tx_count: " << arg.txs.size() << ")"); - - return true; + LOG_PRINT_L2("NOTIFY_OR_INVOKE_NEW_TRANSACTIONS(is_notify=" << is_notify <<"): " << new_transactions_handle_time << "ms (inital_tx_count: " << inital_tx_count << ", relayed_tx_count: " << arg.txs.size() << ")"); + rsp.code = API_RETURN_CODE_OK; + return 1; } + //------------------------------------------------------------------------------------------------------------------------ template int t_currency_protocol_handler::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context) @@ -759,7 +790,7 @@ namespace currency m_p2p->get_connections(connections); for (auto& cc : connections) { - NOTIFY_NEW_TRANSACTIONS::request req = AUTO_VAL_INIT(req); + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request req = AUTO_VAL_INIT(req); for (auto& qe : que) { //exclude relaying to original sender @@ -769,7 +800,7 @@ namespace currency } if (req.txs.size()) { - post_notify(req, cc); + post_notify(req, cc); if (debug_ss.tellp()) debug_ss << ", "; @@ -947,7 +978,7 @@ namespace currency } //------------------------------------------------------------------------------------------------------------------------ template - bool t_currency_protocol_handler::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context) + bool t_currency_protocol_handler::relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context) { #ifdef ASYNC_RELAY_MODE { @@ -959,7 +990,7 @@ namespace currency //m_relay_que_cv.notify_all(); return true; #else - return relay_post_notify(arg, exclude_context); + return relay_post_notify(arg, exclude_context); #endif } } diff --git a/src/currency_protocol/currency_protocol_handler_common.h b/src/currency_protocol/currency_protocol_handler_common.h index 2bff506c..d07153f5 100644 --- a/src/currency_protocol/currency_protocol_handler_common.h +++ b/src/currency_protocol/currency_protocol_handler_common.h @@ -17,7 +17,7 @@ namespace currency struct i_currency_protocol { virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context)=0; - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context)=0; + virtual bool relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context)=0; //virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context)=0; }; @@ -30,7 +30,7 @@ namespace currency { return false; } - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& /*arg*/, currency_connection_context& /*exclude_context*/) + virtual bool relay_transactions(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& /*arg*/, currency_connection_context& /*exclude_context*/) { return false; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c16efcac..0f4d866c 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -705,7 +705,7 @@ namespace currency } - NOTIFY_NEW_TRANSACTIONS::request r; + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r; r.txs.push_back(tx_blob); m_core.get_protocol()->relay_transactions(r, fake_context); //TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes @@ -716,7 +716,7 @@ namespace currency bool core_rpc_server::on_force_relaey_raw_txs(const COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& req, COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& res, connection_context& cntx) { CHECK_CORE_READY(); - NOTIFY_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); + NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); for (const auto& t : req.txs_as_hex) { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 587c1b44..c36a8fc6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4616,14 +4616,15 @@ void wallet2::send_transaction_to_network(const transaction& tx) { continue;//THROW_IF_FALSE_WALLET_EX(false, error::no_connection_to_daemon, "Failed to connect to TOR node"); } - currency::NOTIFY_NEW_TRANSACTIONS::request p2p_req = AUTO_VAL_INIT(p2p_req); + currency::NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request p2p_req = AUTO_VAL_INIT(p2p_req); + currency::NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::response p2p_rsp = AUTO_VAL_INIT(p2p_rsp); p2p_req.txs.push_back(t_serializable_object_to_blob(tx)); std::string blob; epee::serialization::store_t_to_binary(p2p_req, blob); - p2p_client.notify(NOTIFY_NEW_TRANSACTIONS::ID, blob); + p2p_client.invoke(NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::ID, blob); p2p_client.disconnect(); - //checking if transaction got relayed + //checking if transaction got relayed to other nodes and //return; } } diff --git a/tests/core_tests/test_core_proxy.h b/tests/core_tests/test_core_proxy.h index 83694ecd..29898012 100644 --- a/tests/core_tests/test_core_proxy.h +++ b/tests/core_tests/test_core_proxy.h @@ -51,7 +51,7 @@ public: //----------------- i_currency_protocol --------------------------------------- virtual bool relay_block(currency::NOTIFY_NEW_BLOCK::request& /*arg*/, currency::currency_connection_context& /*exclude_context*/) override { return false; } - virtual bool relay_transactions(currency::NOTIFY_NEW_TRANSACTIONS::request& arg, currency::currency_connection_context& /*exclude_context*/) override + virtual bool relay_transactions(currency::NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request& arg, currency::currency_connection_context& /*exclude_context*/) override { if (m_core_listener) {