aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_config.h2
-rw-r--r--src/cryptonote_core/cryptonote_core.h4
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp27
-rw-r--r--src/cryptonote_protocol/levin_notify.h2
-rw-r--r--src/daemon/command_parser_executor.cpp300
-rw-r--r--src/daemon/command_server.cpp4
-rw-r--r--src/device/device_ledger.cpp43
-rw-r--r--src/device/device_ledger.hpp65
-rw-r--r--src/p2p/net_node.cpp1
-rw-r--r--src/p2p/net_node.h24
-rw-r--r--src/p2p/net_node.inl149
-rw-r--r--src/rpc/CMakeLists.txt2
-rw-r--r--src/rpc/core_rpc_server.cpp9
-rw-r--r--src/wallet/api/transaction_history.cpp17
-rw-r--r--src/wallet/api/transaction_history.h1
-rw-r--r--src/wallet/api/transaction_info.cpp11
-rw-r--r--src/wallet/api/transaction_info.h4
-rw-r--r--src/wallet/api/wallet.cpp5
-rw-r--r--src/wallet/api/wallet.h1
-rw-r--r--src/wallet/api/wallet2_api.h8
-rw-r--r--src/wallet/wallet2.cpp8
21 files changed, 445 insertions, 242 deletions
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index a4db99f83..bc17b7e81 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -128,7 +128,7 @@
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000
-#define P2P_DEFAULT_CONNECTIONS_COUNT 8
+#define P2P_DEFAULT_CONNECTIONS_COUNT 12
#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //secondes
#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size
#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 7c578ac51..b008d026e 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -224,14 +224,14 @@ namespace cryptonote
*
* @return true if the block was added to the main chain, otherwise false
*/
- virtual bool handle_block_found(block& b, block_verification_context &bvc);
+ virtual bool handle_block_found(block& b, block_verification_context &bvc) override;
/**
* @copydoc Blockchain::create_block_template
*
* @note see Blockchain::create_block_template
*/
- virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
+ virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash) override;
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
/**
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index dbd11e7d0..634750cab 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -233,7 +233,7 @@ namespace levin
{
struct zone
{
- explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, bool is_public, bool pad_txs)
+ explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, epee::net_utils::zone zone, bool pad_txs)
: p2p(std::move(p2p)),
noise(std::move(noise_in)),
next_epoch(io_service),
@@ -243,7 +243,7 @@ namespace levin
channels(),
flush_time(std::chrono::steady_clock::time_point::max()),
connection_count(0),
- is_public(is_public),
+ nzone(zone),
pad_txs(pad_txs),
fluffing(false)
{
@@ -260,7 +260,7 @@ namespace levin
std::deque<noise_channel> channels; //!< Never touch after init; only update elements on `noise_channel.strand`
std::chrono::steady_clock::time_point flush_time; //!< Next expected Dandelion++ fluff flush
std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time
- const bool is_public; //!< Zone is public ipv4/ipv6 connections
+ const epee::net_utils::zone nzone; //!< Zone is public ipv4/ipv6 connections, or i2p or tor
const bool pad_txs; //!< Pad txs to the next boundary for privacy
bool fluffing; //!< Zone is in Dandelion++ fluff epoch
};
@@ -297,7 +297,8 @@ namespace levin
if (!channel.connection.is_nil())
channel.queue.push_back(std::move(message_));
else if (destination_ == 0 && zone_->connection_count == 0)
- MWARNING("Unable to send transaction(s) over anonymity network - no available outbound connections");
+ MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
+ " - no available outbound connections");
}
};
@@ -410,7 +411,7 @@ namespace levin
zone->p2p->foreach_connection([txs, now, &zone, &source, &in_duration, &out_duration, &next_flush, &available] (detail::p2p_context& context)
{
// When i2p/tor, only fluff to outbound connections
- if (source != context.m_connection_id && (zone->is_public || !context.m_is_income))
+ if (source != context.m_connection_id && (zone->nzone == epee::net_utils::zone::public_ || !context.m_is_income))
{
available = true;
if (context.fluff_txs.empty())
@@ -577,7 +578,7 @@ namespace levin
assert(zone_->strand.running_in_this_thread());
- if (zone_->is_public)
+ if (zone_->nzone == epee::net_utils::zone::public_)
MDEBUG("Starting new Dandelion++ epoch: " << (fluffing_ ? "fluff" : "stem"));
zone_->map = std::move(map_);
@@ -645,10 +646,12 @@ namespace levin
{
channel.active = nullptr;
channel.connection = boost::uuids::nil_uuid();
+ auto height = core_->get_target_blockchain_height();
- auto connections = get_out_connections(*zone_->p2p, core_->get_target_blockchain_height());
+ auto connections = get_out_connections(*zone_->p2p, height);
if (connections.empty())
- MWARNING("Lost all outbound connections to anonymity network - currently unable to send transaction(s)");
+ MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
+ " - no suitable outbound connections at height " << height);
zone_->strand.post(update_channels{zone_, std::move(connections)});
}
@@ -691,15 +694,15 @@ namespace levin
};
} // anonymous
- notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, const bool is_public, const bool pad_txs, i_core_events& core)
- : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), is_public, pad_txs))
+ notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core)
+ : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), zone, pad_txs))
, core_(std::addressof(core))
{
if (!zone_->p2p)
throw std::logic_error{"cryptonote::levin::notify cannot have nullptr p2p argument"};
const bool noise_enabled = !zone_->noise.empty();
- if (noise_enabled || is_public)
+ if (noise_enabled || zone == epee::net_utils::zone::public_)
{
const auto now = std::chrono::steady_clock::now();
const auto min_epoch = noise_enabled ? noise_min_epoch : dandelionpp_min_epoch;
@@ -821,7 +824,7 @@ namespace levin
case relay_method::stem:
case relay_method::forward:
case relay_method::local:
- if (zone_->is_public)
+ if (zone_->nzone == epee::net_utils::zone::public_)
{
// this will change a local/forward tx to stem or fluff ...
zone_->strand.dispatch(
diff --git a/src/cryptonote_protocol/levin_notify.h b/src/cryptonote_protocol/levin_notify.h
index 43b61aead..abbf9d461 100644
--- a/src/cryptonote_protocol/levin_notify.h
+++ b/src/cryptonote_protocol/levin_notify.h
@@ -85,7 +85,7 @@ namespace levin
{}
//! Construct an instance with available notification `zones`.
- explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, bool is_public, bool pad_txs, i_core_events& core);
+ explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core);
notify(const notify&) = delete;
notify(notify&&) = default;
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 504b104b0..aac891c4a 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -50,7 +50,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
{
if (args.size() > 3)
{
- std::cout << "use: print_pl [white] [gray] [<limit>] [pruned] [publicrpc]" << std::endl;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
return true;
}
@@ -79,7 +79,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
}
else if (!epee::string_tools::get_xtype_from_string(limit, args[i]))
{
- std::cout << "unexpected argument: " << args[i] << std::endl;
+ std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
return true;
}
}
@@ -90,56 +90,79 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
bool t_command_parser_executor::print_peer_list_stats(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_peer_list_stats();
}
bool t_command_parser_executor::save_blockchain(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
-
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.save_blockchain();
}
bool t_command_parser_executor::show_hash_rate(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.show_hash_rate();
}
bool t_command_parser_executor::hide_hash_rate(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.hide_hash_rate();
}
bool t_command_parser_executor::show_difficulty(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.show_difficulty();
}
bool t_command_parser_executor::show_status(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.show_status();
}
bool t_command_parser_executor::print_connections(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_connections();
}
bool t_command_parser_executor::print_net_stats(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_net_stats();
}
@@ -148,8 +171,8 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str
{
if(!args.size())
{
- std::cout << "need block index parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
uint64_t start_index = 0;
uint64_t end_index = 0;
@@ -158,20 +181,20 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str
int64_t nblocks;
if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]))
{
- std::cout << "wrong number of blocks" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.print_blockchain_info(nblocks, (uint64_t)-nblocks);
}
if(!epee::string_tools::get_xtype_from_string(start_index, args[0]))
{
- std::cout << "wrong starter block index parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong starter block index parameter. For more details, use the help command." << std::endl;
+ return true;
}
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(end_index, args[1]))
{
- std::cout << "wrong end block index parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong end block index parameter. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.print_blockchain_info(start_index, end_index);
@@ -181,7 +204,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
{
if(args.size() > 1)
{
- std::cout << "use: set_log [<log_level_number_0-4> | <categories>]" << std::endl;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
return true;
}
@@ -195,7 +218,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
{
if(4 < l)
{
- std::cout << "wrong number range, use: set_log <log_level_number_0-4>" << std::endl;
+ std::cout << "Invalid syntax: Wrong number range, use: set_log <log_level_number_0-4>. For more details, use the help command." << std::endl;
return true;
}
return m_executor.set_log_level(l);
@@ -208,7 +231,10 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
bool t_command_parser_executor::print_height(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_height();
}
@@ -223,14 +249,14 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
include_hex = true;
else
{
- std::cout << "unexpected argument: " << args[i] << std::endl;
+ std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
return true;
}
}
if (args.empty())
{
- std::cout << "expected: print_block (<block_hash> | <block_height>) [+hex]" << std::endl;
- return false;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
const std::string& arg = args.front();
@@ -248,7 +274,7 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
}
}
- return false;
+ return true;
}
bool t_command_parser_executor::print_transaction(const std::vector<std::string>& args)
@@ -267,13 +293,13 @@ bool t_command_parser_executor::print_transaction(const std::vector<std::string>
include_json = true;
else
{
- std::cout << "unexpected argument: " << args[i] << std::endl;
+ std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
return true;
}
}
if (args.empty())
{
- std::cout << "expected: print_tx <transaction_hash> [+meta] [+hex] [+json]" << std::endl;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
return true;
}
@@ -291,7 +317,7 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string
{
if (args.empty())
{
- std::cout << "expected: is_key_image_spent <key_image>" << std::endl;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
return true;
}
@@ -309,21 +335,30 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string
bool t_command_parser_executor::print_transaction_pool_long(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_transaction_pool_long();
}
bool t_command_parser_executor::print_transaction_pool_short(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_transaction_pool_short();
}
bool t_command_parser_executor::print_transaction_pool_stats(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_transaction_pool_stats();
}
@@ -332,7 +367,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
{
if(!args.size())
{
- std::cout << "Please specify a wallet address to mine for: start_mining <addr> [<threads>|auto]" << std::endl;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
return true;
}
@@ -353,7 +388,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
{
if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, address_str))
{
- std::cout << "target account address has wrong format" << std::endl;
+ std::cout << "Invalid syntax: Target account address has wrong format. For more details, use the help command." << std::endl;
return true;
}
else
@@ -389,9 +424,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
bool ignore_battery = false;
if(args.size() > 4)
{
- return false;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
}
-
+
if(args.size() == 4)
{
if(args[3] == "true" || command_line::is_yes(args[3]) || args[3] == "1")
@@ -400,10 +436,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
else if(args[3] != "false" && !command_line::is_no(args[3]) && args[3] != "0")
{
- return false;
+ std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl;
+ return true;
}
- }
-
+ }
+
if(args.size() >= 3)
{
if(args[2] == "true" || command_line::is_yes(args[2]) || args[2] == "1")
@@ -412,10 +449,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
else if(args[2] != "false" && !command_line::is_no(args[2]) && args[2] != "0")
{
- return false;
+ std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl;
+ return true;
}
}
-
+
if(args.size() >= 2)
{
if (args[1] == "auto" || args[1] == "autodetect")
@@ -436,7 +474,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
bool t_command_parser_executor::stop_mining(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.stop_mining();
}
@@ -448,21 +489,31 @@ bool t_command_parser_executor::mining_status(const std::vector<std::string>& ar
bool t_command_parser_executor::stop_daemon(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.stop_daemon();
}
bool t_command_parser_executor::print_status(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_status();
}
bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
{
- if(args.size()>1) return false;
+ if(args.size()>1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
+
if(args.size()==0) {
return m_executor.get_limit();
}
@@ -471,8 +522,8 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
limit = std::stoll(args[0]);
}
catch(const std::exception& ex) {
- std::cout << "failed to parse argument" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_limit(limit, limit);
@@ -480,7 +531,11 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& args)
{
- if(args.size()>1) return false;
+ if(args.size()>1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
+
if(args.size()==0) {
return m_executor.get_limit_up();
}
@@ -489,8 +544,8 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
limit = std::stoll(args[0]);
}
catch(const std::exception& ex) {
- std::cout << "failed to parse argument" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_limit(0, limit);
@@ -498,7 +553,11 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& args)
{
- if(args.size()>1) return false;
+ if(args.size()>1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
+
if(args.size()==0) {
return m_executor.get_limit_down();
}
@@ -507,8 +566,8 @@ bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& a
limit = std::stoll(args[0]);
}
catch(const std::exception& ex) {
- std::cout << "failed to parse argument" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_limit(limit, 0);
@@ -525,12 +584,13 @@ bool t_command_parser_executor::out_peers(const std::vector<std::string>& args)
set = true;
}
}
-
+
catch(const std::exception& ex) {
_erro("stoi exception");
- return false;
+ std::cout << "Invalid syntax: Failed to parse number. For more details, use the help command." << std::endl;
+ return true;
}
-
+
return m_executor.out_peers(set, limit);
}
@@ -548,7 +608,8 @@ bool t_command_parser_executor::in_peers(const std::vector<std::string>& args)
catch(const std::exception& ex) {
_erro("stoi exception");
- return false;
+ std::cout << "Invalid syntax: Failed to parse number." << std::endl;
+ return true;
}
return m_executor.in_peers(set, limit);
@@ -565,26 +626,37 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a
version = std::stoi(args[0]);
}
catch(const std::exception& ex) {
- return false;
+ std::cout << "Invalid syntax: Failed to parse version number. For more details, use the help command." << std::endl;
+ return true;
+ }
+ if (version <= 0 || version > 255) {
+ std::cout << "Invalid syntax: Unknown version number. Must be between 0 and 255. For more details, use the help command." << std::endl;
+ return true;
}
- if (version <= 0 || version > 255)
- return false;
}
else {
- return false;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.hard_fork_info(version);
}
bool t_command_parser_executor::show_bans(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
+
return m_executor.print_bans();
}
bool t_command_parser_executor::ban(const std::vector<std::string>& args)
{
- if (args.size() != 1 && args.size() != 2) return false;
+ if (args.size() != 1 && args.size() != 2) {
+ std::cout << "Invalid syntax: Expects one or two parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string ip = args[0];
time_t seconds = P2P_IP_BLOCKTIME;
if (args.size() > 1)
@@ -595,11 +667,13 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
}
catch (const std::exception &e)
{
- return false;
+ std::cout << "Invalid syntax: Failed to parse seconds. For more details, use the help command." << std::endl;
+ return true;
}
if (seconds == 0)
{
- return false;
+ std::cout << "Seconds must be greater than 0." << std::endl;
+ return true;
}
}
return m_executor.ban(ip, seconds);
@@ -607,21 +681,31 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
bool t_command_parser_executor::unban(const std::vector<std::string>& args)
{
- if (args.size() != 1) return false;
+ if (args.size() != 1) {
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
+ }
+
std::string ip = args[0];
return m_executor.unban(ip);
}
bool t_command_parser_executor::banned(const std::vector<std::string>& args)
{
- if (args.size() != 1) return false;
+ if (args.size() != 1) {
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string address = args[0];
return m_executor.banned(address);
}
bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& args)
{
- if (args.size() > 1) return false;
+ if (args.size() > 1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string txid;
if (args.size() == 1)
@@ -629,7 +713,7 @@ bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& arg
crypto::hash hash;
if (!parse_hash256(args[0], hash))
{
- std::cout << "failed to parse tx id" << std::endl;
+ std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl;
return true;
}
txid = args[0];
@@ -662,7 +746,7 @@ bool t_command_parser_executor::output_histogram(const std::vector<std::string>&
}
else
{
- std::cout << "Invalid syntax: more than two non-amount parameters" << std::endl;
+ std::cout << "Invalid syntax: More than two non-amount parameters. For more details, use the help command." << std::endl;
return true;
}
}
@@ -673,20 +757,21 @@ bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector<std::str
{
if(!args.size())
{
- std::cout << "need block height parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
+
uint64_t height = 0;
uint64_t count = 0;
if(!epee::string_tools::get_xtype_from_string(height, args[0]))
{
- std::cout << "wrong starter block height parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong starter block height parameter. For more details, use the help command." << std::endl;
+ return true;
}
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(count, args[1]))
{
std::cout << "wrong count parameter" << std::endl;
- return false;
+ return true;
}
return m_executor.print_coinbase_tx_sum(height, count);
@@ -696,8 +781,8 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a
{
if(args.size() > 1)
{
- std::cout << "usage: alt_chain_info [block_hash|>N|-N]" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
}
std::string tip;
@@ -709,16 +794,16 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a
{
if (!epee::string_tools::get_xtype_from_string(above, args[0].c_str() + 1))
{
- std::cout << "invalid above parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Invalid above parameter. For more details, use the help command." << std::endl;
+ return true;
}
}
else if (args[0].size() > 0 && args[0][0] == '-')
{
if (!epee::string_tools::get_xtype_from_string(last_blocks, args[0].c_str() + 1))
{
- std::cout << "invalid last_blocks parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Invalid last_blocks parameter. For more details, use the help command." << std::endl;
+ return true;
}
}
else
@@ -734,15 +819,15 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector
{
if(args.size() != 1)
{
- std::cout << "Exactly one parameter is needed" << std::endl;
- return false;
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
uint64_t nblocks = 0;
if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]) || nblocks == 0)
{
- std::cout << "wrong number of blocks" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.print_blockchain_dynamic_stats(nblocks);
@@ -750,10 +835,10 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector
bool t_command_parser_executor::update(const std::vector<std::string>& args)
{
- if(args.size() != 1)
+ if (args.size() != 1)
{
- std::cout << "Exactly one parameter is needed: check, download, or update" << std::endl;
- return false;
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.update(args.front());
@@ -761,13 +846,17 @@ bool t_command_parser_executor::update(const std::vector<std::string>& args)
bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
{
- if (args.size() != 1) return false;
+ if (args.size() != 1)
+ {
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string txid;
crypto::hash hash;
if (!parse_hash256(args[0], hash))
{
- std::cout << "failed to parse tx id" << std::endl;
+ std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl;
return true;
}
txid = args[0];
@@ -776,7 +865,10 @@ bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
bool t_command_parser_executor::sync_info(const std::vector<std::string>& args)
{
- if (args.size() != 0) return false;
+ if (args.size() != 0) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.sync_info();
}
@@ -785,8 +877,8 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
{
if (args.size() != 1)
{
- std::cout << "Exactly one parameter is needed" << std::endl;
- return false;
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
try
@@ -794,21 +886,24 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
uint64_t nblocks = boost::lexical_cast<uint64_t>(args[0]);
if (nblocks < 1)
{
- std::cout << "number of blocks must be greater than 0" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Number of blocks must be greater than 0. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.pop_blocks(nblocks);
}
catch (const boost::bad_lexical_cast&)
{
- std::cout << "number of blocks must be a number greater than 0" << std::endl;
+ std::cout << "Invalid syntax: Number of blocks must be a number greater than 0. For more details, use the help command." << std::endl;
}
- return false;
+ return true;
}
bool t_command_parser_executor::rpc_payments(const std::vector<std::string>& args)
{
- if (args.size() != 0) return false;
+ if (args.size() != 0) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.rpc_payments();
}
@@ -820,7 +915,11 @@ bool t_command_parser_executor::version(const std::vector<std::string>& args)
bool t_command_parser_executor::prune_blockchain(const std::vector<std::string>& args)
{
- if (args.size() > 1) return false;
+ if (args.size() > 1)
+ {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
if (args.empty() || args[0] != "confirm")
{
@@ -846,7 +945,8 @@ bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::stri
const size_t args_count = args.size();
if (args_count < 1 || args_count > 3)
{
- return false;
+ std::cout << "Invalid syntax: Wrong number of parameters. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_bootstrap_daemon(
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index ac4c30726..dd5f76188 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -223,7 +223,8 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"hard_fork_info"
, std::bind(&t_command_parser_executor::hard_fork_info, &m_parser, p::_1)
- , "Print the hard fork voting information."
+ , "hard_fork_info <version>"
+ , "Print the hard fork voting information. If given a version, prints whether is this version enabled."
);
m_command_lookup.set_handler(
"bans"
@@ -314,6 +315,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"prune_blockchain"
, std::bind(&t_command_parser_executor::prune_blockchain, &m_parser, p::_1)
+ , "prune_blockchain [confirm]"
, "Prune the blockchain."
);
m_command_lookup.set_handler(
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 3e0afeb65..384b776ee 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -83,44 +83,33 @@ namespace hw {
// Must be sorted in ascending order by the code
#define LEDGER_STATUS(status) {status, #status}
constexpr Status status_codes[] = {
- LEDGER_STATUS(SW_BYTES_REMAINING_00),
- LEDGER_STATUS(SW_WARNING_STATE_UNCHANGED),
- LEDGER_STATUS(SW_STATE_TERMINATED),
- LEDGER_STATUS(SW_MORE_DATA_AVAILABLE),
+ LEDGER_STATUS(SW_OK),
LEDGER_STATUS(SW_WRONG_LENGTH),
- LEDGER_STATUS(SW_LOGICAL_CHANNEL_NOT_SUPPORTED),
- LEDGER_STATUS(SW_SECURE_MESSAGING_NOT_SUPPORTED),
- LEDGER_STATUS(SW_LAST_COMMAND_EXPECTED),
- LEDGER_STATUS(SW_COMMAND_CHAINING_NOT_SUPPORTED),
+ LEDGER_STATUS(SW_SECURITY_PIN_LOCKED),
LEDGER_STATUS(SW_SECURITY_LOAD_KEY),
LEDGER_STATUS(SW_SECURITY_COMMITMENT_CONTROL),
LEDGER_STATUS(SW_SECURITY_AMOUNT_CHAIN_CONTROL),
LEDGER_STATUS(SW_SECURITY_COMMITMENT_CHAIN_CONTROL),
LEDGER_STATUS(SW_SECURITY_OUTKEYS_CHAIN_CONTROL),
LEDGER_STATUS(SW_SECURITY_MAXOUTPUT_REACHED),
- LEDGER_STATUS(SW_SECURITY_TRUSTED_INPUT),
- LEDGER_STATUS(SW_CLIENT_NOT_SUPPORTED),
- LEDGER_STATUS(SW_SECURITY_STATUS_NOT_SATISFIED),
- LEDGER_STATUS(SW_FILE_INVALID),
- LEDGER_STATUS(SW_PIN_BLOCKED),
- LEDGER_STATUS(SW_DATA_INVALID),
- LEDGER_STATUS(SW_CONDITIONS_NOT_SATISFIED),
+ LEDGER_STATUS(SW_SECURITY_HMAC),
+ LEDGER_STATUS(SW_SECURITY_RANGE_VALUE),
+ LEDGER_STATUS(SW_SECURITY_INTERNAL),
+ LEDGER_STATUS(SW_SECURITY_MAX_SIGNATURE_REACHED),
+ LEDGER_STATUS(SW_SECURITY_PREFIX_HASH),
+ LEDGER_STATUS(SW_SECURITY_LOCKED),
LEDGER_STATUS(SW_COMMAND_NOT_ALLOWED),
- LEDGER_STATUS(SW_APPLET_SELECT_FAILED),
+ LEDGER_STATUS(SW_SUBCOMMAND_NOT_ALLOWED),
+ LEDGER_STATUS(SW_DENY),
+ LEDGER_STATUS(SW_KEY_NOT_SET),
LEDGER_STATUS(SW_WRONG_DATA),
- LEDGER_STATUS(SW_FUNC_NOT_SUPPORTED),
- LEDGER_STATUS(SW_FILE_NOT_FOUND),
- LEDGER_STATUS(SW_RECORD_NOT_FOUND),
- LEDGER_STATUS(SW_FILE_FULL),
- LEDGER_STATUS(SW_INCORRECT_P1P2),
- LEDGER_STATUS(SW_REFERENCED_DATA_NOT_FOUND),
+ LEDGER_STATUS(SW_WRONG_DATA_RANGE),
+ LEDGER_STATUS(SW_IO_FULL),
+ LEDGER_STATUS(SW_CLIENT_NOT_SUPPORTED),
LEDGER_STATUS(SW_WRONG_P1P2),
- LEDGER_STATUS(SW_CORRECT_LENGTH_00),
LEDGER_STATUS(SW_INS_NOT_SUPPORTED),
- LEDGER_STATUS(SW_CLA_NOT_SUPPORTED),
- LEDGER_STATUS(SW_UNKNOWN),
- LEDGER_STATUS(SW_OK),
- LEDGER_STATUS(SW_ALGORITHM_UNSUPPORTED)
+ LEDGER_STATUS(SW_PROTOCOL_NOT_SUPPORTED),
+ LEDGER_STATUS(SW_UNKNOWN)
};
const char *Status::to_string(unsigned int code)
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 5cb834e02..00ff05ec5 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -59,44 +59,33 @@ namespace hw {
#ifdef WITH_DEVICE_LEDGER
// Origin: https://github.com/LedgerHQ/ledger-app-monero/blob/master/src/monero_types.h
- #define SW_BYTES_REMAINING_00 0x6100
- #define SW_WARNING_STATE_UNCHANGED 0x6200
- #define SW_STATE_TERMINATED 0x6285
- #define SW_MORE_DATA_AVAILABLE 0x6310
- #define SW_WRONG_LENGTH 0x6700
- #define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881
- #define SW_SECURE_MESSAGING_NOT_SUPPORTED 0x6882
- #define SW_LAST_COMMAND_EXPECTED 0x6883
- #define SW_COMMAND_CHAINING_NOT_SUPPORTED 0x6884
- #define SW_SECURITY_LOAD_KEY 0x6900
- #define SW_SECURITY_COMMITMENT_CONTROL 0x6911
- #define SW_SECURITY_AMOUNT_CHAIN_CONTROL 0x6912
- #define SW_SECURITY_COMMITMENT_CHAIN_CONTROL 0x6913
- #define SW_SECURITY_OUTKEYS_CHAIN_CONTROL 0x6914
- #define SW_SECURITY_MAXOUTPUT_REACHED 0x6915
- #define SW_SECURITY_TRUSTED_INPUT 0x6916
- #define SW_CLIENT_NOT_SUPPORTED 0x6930
- #define SW_SECURITY_STATUS_NOT_SATISFIED 0x6982
- #define SW_FILE_INVALID 0x6983
- #define SW_PIN_BLOCKED 0x6983
- #define SW_DATA_INVALID 0x6984
- #define SW_CONDITIONS_NOT_SATISFIED 0x6985
- #define SW_COMMAND_NOT_ALLOWED 0x6986
- #define SW_APPLET_SELECT_FAILED 0x6999
- #define SW_WRONG_DATA 0x6a80
- #define SW_FUNC_NOT_SUPPORTED 0x6a81
- #define SW_FILE_NOT_FOUND 0x6a82
- #define SW_RECORD_NOT_FOUND 0x6a83
- #define SW_FILE_FULL 0x6a84
- #define SW_INCORRECT_P1P2 0x6a86
- #define SW_REFERENCED_DATA_NOT_FOUND 0x6a88
- #define SW_WRONG_P1P2 0x6b00
- #define SW_CORRECT_LENGTH_00 0x6c00
- #define SW_INS_NOT_SUPPORTED 0x6d00
- #define SW_CLA_NOT_SUPPORTED 0x6e00
- #define SW_UNKNOWN 0x6f00
- #define SW_OK 0x9000
- #define SW_ALGORITHM_UNSUPPORTED 0x9484
+ #define SW_OK 0x9000
+ #define SW_WRONG_LENGTH 0x6700
+ #define SW_SECURITY_PIN_LOCKED 0x6910
+ #define SW_SECURITY_LOAD_KEY 0x6911
+ #define SW_SECURITY_COMMITMENT_CONTROL 0x6912
+ #define SW_SECURITY_AMOUNT_CHAIN_CONTROL 0x6913
+ #define SW_SECURITY_COMMITMENT_CHAIN_CONTROL 0x6914
+ #define SW_SECURITY_OUTKEYS_CHAIN_CONTROL 0x6915
+ #define SW_SECURITY_MAXOUTPUT_REACHED 0x6916
+ #define SW_SECURITY_HMAC 0x6917
+ #define SW_SECURITY_RANGE_VALUE 0x6918
+ #define SW_SECURITY_INTERNAL 0x6919
+ #define SW_SECURITY_MAX_SIGNATURE_REACHED 0x691A
+ #define SW_SECURITY_PREFIX_HASH 0x691B
+ #define SW_SECURITY_LOCKED 0x69EE
+ #define SW_COMMAND_NOT_ALLOWED 0x6980
+ #define SW_SUBCOMMAND_NOT_ALLOWED 0x6981
+ #define SW_DENY 0x6982
+ #define SW_KEY_NOT_SET 0x6983
+ #define SW_WRONG_DATA 0x6984
+ #define SW_WRONG_DATA_RANGE 0x6985
+ #define SW_IO_FULL 0x6986
+ #define SW_CLIENT_NOT_SUPPORTED 0x6A30
+ #define SW_WRONG_P1P2 0x6b00
+ #define SW_INS_NOT_SUPPORTED 0x6d00
+ #define SW_PROTOCOL_NOT_SUPPORTED 0x6e00
+ #define SW_UNKNOWN 0x6f00
namespace {
bool apdu_verbose =true;
diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp
index 1c5dca0d7..aee1fa593 100644
--- a/src/p2p/net_node.cpp
+++ b/src/p2p/net_node.cpp
@@ -146,6 +146,7 @@ namespace nodetool
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
const command_line::arg_descriptor<std::vector<std::string> > arg_tx_proxy = {"tx-proxy", "Send local txes through proxy: <network-type>,<socks-ip:port>[,max_connections][,disable_noise] i.e. \"tor,127.0.0.1:9050,100,disable_noise\""};
const command_line::arg_descriptor<std::vector<std::string> > arg_anonymous_inbound = {"anonymous-inbound", "<hidden-service-address>,<[bind-ip:]port>[,max_connections] i.e. \"x.onion,127.0.0.1:18083,100\""};
+ const command_line::arg_descriptor<std::string> arg_ban_list = {"ban-list", "Specify ban list file, one IP address per line"};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
const command_line::arg_descriptor<bool> arg_no_sync = {"no-sync", "Don't synchronize the blockchain with other peers", false};
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 97835edd4..87fec9994 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -164,6 +164,7 @@ namespace nodetool
network_zone()
: m_connect(nullptr),
m_net_server(epee::net_utils::e_connection_type_P2P),
+ m_seed_nodes(),
m_bind_ip(),
m_bind_ipv6_address(),
m_port(),
@@ -175,7 +176,9 @@ namespace nodetool
m_proxy_address(),
m_current_number_of_out_peers(0),
m_current_number_of_in_peers(0),
- m_can_pingback(false)
+ m_seed_nodes_lock(),
+ m_can_pingback(false),
+ m_seed_nodes_initialized(false)
{
set_config_defaults();
}
@@ -183,6 +186,7 @@ namespace nodetool
network_zone(boost::asio::io_service& public_service)
: m_connect(nullptr),
m_net_server(public_service, epee::net_utils::e_connection_type_P2P),
+ m_seed_nodes(),
m_bind_ip(),
m_bind_ipv6_address(),
m_port(),
@@ -194,13 +198,16 @@ namespace nodetool
m_proxy_address(),
m_current_number_of_out_peers(0),
m_current_number_of_in_peers(0),
- m_can_pingback(false)
+ m_seed_nodes_lock(),
+ m_can_pingback(false),
+ m_seed_nodes_initialized(false)
{
set_config_defaults();
}
connect_func* m_connect;
net_server m_net_server;
+ std::vector<epee::net_utils::network_address> m_seed_nodes;
std::string m_bind_ip;
std::string m_bind_ipv6_address;
std::string m_port;
@@ -212,7 +219,9 @@ namespace nodetool
boost::asio::ip::tcp::endpoint m_proxy_address;
std::atomic<unsigned int> m_current_number_of_out_peers;
std::atomic<unsigned int> m_current_number_of_in_peers;
+ boost::shared_mutex m_seed_nodes_lock;
bool m_can_pingback;
+ bool m_seed_nodes_initialized;
private:
void set_config_defaults() noexcept
@@ -383,9 +392,10 @@ namespace nodetool
void record_addr_failed(const epee::net_utils::network_address& addr);
bool is_addr_recently_failed(const epee::net_utils::network_address& addr);
bool is_priority_node(const epee::net_utils::network_address& na);
- std::set<std::string> get_seed_nodes(cryptonote::network_type nettype) const;
- std::set<std::string> get_seed_nodes();
- bool connect_to_seed();
+ std::set<std::string> get_ip_seed_nodes() const;
+ std::set<std::string> get_dns_seed_nodes();
+ std::set<std::string> get_seed_nodes(epee::net_utils::zone);
+ bool connect_to_seed(epee::net_utils::zone);
template <class Container>
bool connect_to_peerlist(const Container& peers);
@@ -467,9 +477,6 @@ namespace nodetool
std::list<epee::net_utils::network_address> m_priority_peers;
std::vector<epee::net_utils::network_address> m_exclusive_peers;
- std::vector<epee::net_utils::network_address> m_seed_nodes;
- bool m_seed_nodes_initialized = false;
- boost::shared_mutex m_seed_nodes_lock;
std::atomic_flag m_fallback_seed_nodes_added;
std::vector<nodetool::peerlist_entry> m_command_line_peers;
uint64_t m_peer_livetime;
@@ -523,6 +530,7 @@ namespace nodetool
extern const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node;
extern const command_line::arg_descriptor<std::vector<std::string> > arg_tx_proxy;
extern const command_line::arg_descriptor<std::vector<std::string> > arg_anonymous_inbound;
+ extern const command_line::arg_descriptor<std::string> arg_ban_list;
extern const command_line::arg_descriptor<bool> arg_p2p_hide_my_port;
extern const command_line::arg_descriptor<bool> arg_no_sync;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index aa16e93d5..81002baa4 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -106,6 +106,7 @@ namespace nodetool
command_line::add_arg(desc, arg_p2p_seed_node);
command_line::add_arg(desc, arg_tx_proxy);
command_line::add_arg(desc, arg_anonymous_inbound);
+ command_line::add_arg(desc, arg_ban_list);
command_line::add_arg(desc, arg_p2p_hide_my_port);
command_line::add_arg(desc, arg_no_sync);
command_line::add_arg(desc, arg_no_igd);
@@ -386,7 +387,7 @@ namespace nodetool
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4);
public_zone.m_notifier = cryptonote::levin::notify{
- public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, true, pad_txs, m_payload_handler.get_core()
+ public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core()
};
if (command_line::has_arg(vm, arg_p2p_add_peer))
@@ -435,12 +436,42 @@ namespace nodetool
if (command_line::has_arg(vm, arg_p2p_seed_node))
{
- boost::unique_lock<boost::shared_mutex> lock(m_seed_nodes_lock);
+ boost::unique_lock<boost::shared_mutex> lock(public_zone.m_seed_nodes_lock);
- if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, m_seed_nodes))
+ if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, public_zone.m_seed_nodes))
return false;
}
+ if (!command_line::is_arg_defaulted(vm, arg_ban_list))
+ {
+ const std::string ban_list = command_line::get_arg(vm, arg_ban_list);
+
+ const boost::filesystem::path ban_list_path(ban_list);
+ boost::system::error_code ec;
+ if (!boost::filesystem::exists(ban_list_path, ec))
+ {
+ throw std::runtime_error("Can't find ban list file " + ban_list + " - " + ec.message());
+ }
+
+ std::string banned_ips;
+ if (!epee::file_io_utils::load_file_to_string(ban_list_path.string(), banned_ips))
+ {
+ throw std::runtime_error("Failed to read ban list file " + ban_list);
+ }
+
+ std::istringstream iss(banned_ips);
+ for (std::string line; std::getline(iss, line); )
+ {
+ const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(line, 0);
+ if (!parsed_addr)
+ {
+ MERROR("Invalid IP address: " << line << " - " << parsed_addr.error());
+ continue;
+ }
+ block_host(*parsed_addr, std::numeric_limits<time_t>::max());
+ }
+ }
+
if(command_line::has_arg(vm, arg_p2p_hide_my_port))
m_hide_my_port = true;
@@ -499,7 +530,7 @@ namespace nodetool
}
zone.m_notifier = cryptonote::levin::notify{
- zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), false, pad_txs, m_payload_handler.get_core()
+ zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core()
};
}
@@ -598,21 +629,21 @@ namespace nodetool
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(cryptonote::network_type nettype) const
+ std::set<std::string> node_server<t_payload_net_handler>::get_ip_seed_nodes() const
{
std::set<std::string> full_addrs;
- if (nettype == cryptonote::TESTNET)
+ if (m_nettype == cryptonote::TESTNET)
{
full_addrs.insert("212.83.175.67:28080");
full_addrs.insert("212.83.172.165:28080");
full_addrs.insert("192.110.160.146:28080");
}
- else if (nettype == cryptonote::STAGENET)
+ else if (m_nettype == cryptonote::STAGENET)
{
full_addrs.insert("162.210.173.150:38080");
full_addrs.insert("192.110.160.146:38080");
}
- else if (nettype == cryptonote::FAKECHAIN)
+ else if (m_nettype == cryptonote::FAKECHAIN)
{
}
else
@@ -630,7 +661,7 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes()
+ std::set<std::string> node_server<t_payload_net_handler>::get_dns_seed_nodes()
{
if (!m_exclusive_peers.empty() || m_offline)
{
@@ -638,11 +669,11 @@ namespace nodetool
}
if (m_nettype == cryptonote::TESTNET)
{
- return get_seed_nodes(cryptonote::TESTNET);
+ return get_ip_seed_nodes();
}
if (m_nettype == cryptonote::STAGENET)
{
- return get_seed_nodes(cryptonote::STAGENET);
+ return get_ip_seed_nodes();
}
std::set<std::string> full_addrs;
@@ -730,7 +761,7 @@ namespace nodetool
else
MINFO("Not enough DNS seed nodes found, using fallback defaults too");
- for (const auto &peer: get_seed_nodes(cryptonote::MAINNET))
+ for (const auto &peer: get_ip_seed_nodes())
full_addrs.insert(peer);
m_fallback_seed_nodes_added.test_and_set();
}
@@ -739,6 +770,23 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
+ std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(epee::net_utils::zone zone)
+ {
+ switch (zone)
+ {
+ case epee::net_utils::zone::public_:
+ return get_dns_seed_nodes();
+ case epee::net_utils::zone::tor:
+ return {};
+ case epee::net_utils::zone::i2p:
+ return {};
+ default:
+ break;
+ }
+ throw std::logic_error{"Bad zone given to get_seed_nodes"};
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
typename node_server<t_payload_net_handler>::network_zone& node_server<t_payload_net_handler>::add_zone(const epee::net_utils::zone zone)
{
const auto zone_ = m_network_zones.lower_bound(zone);
@@ -1541,56 +1589,59 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::connect_to_seed()
+ bool node_server<t_payload_net_handler>::connect_to_seed(epee::net_utils::zone zone)
{
- boost::upgrade_lock<boost::shared_mutex> seed_nodes_upgrade_lock(m_seed_nodes_lock);
+ network_zone& server = m_network_zones.at(zone);
+ boost::upgrade_lock<boost::shared_mutex> seed_nodes_upgrade_lock(server.m_seed_nodes_lock);
- if (!m_seed_nodes_initialized)
+ if (!server.m_seed_nodes_initialized)
{
+ const std::uint16_t default_port = cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT;
boost::upgrade_to_unique_lock<boost::shared_mutex> seed_nodes_lock(seed_nodes_upgrade_lock);
- m_seed_nodes_initialized = true;
- for (const auto& full_addr : get_seed_nodes())
+ server.m_seed_nodes_initialized = true;
+ for (const auto& full_addr : get_seed_nodes(zone))
{
+ // seeds should have hostname converted to IP already
MDEBUG("Seed node: " << full_addr);
- append_net_address(m_seed_nodes, full_addr, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
+ server.m_seed_nodes.push_back(MONERO_UNWRAP(net::get_network_address(full_addr, default_port)));
}
- MDEBUG("Number of seed nodes: " << m_seed_nodes.size());
+ MDEBUG("Number of seed nodes: " << server.m_seed_nodes.size());
}
- if (m_seed_nodes.empty() || m_offline || !m_exclusive_peers.empty())
+ if (server.m_seed_nodes.empty() || m_offline || !m_exclusive_peers.empty())
return true;
size_t try_count = 0;
bool is_connected_to_at_least_one_seed_node = false;
- size_t current_index = crypto::rand_idx(m_seed_nodes.size());
- const net_server& server = m_network_zones.at(epee::net_utils::zone::public_).m_net_server;
+ size_t current_index = crypto::rand_idx(server.m_seed_nodes.size());
while(true)
{
- if(server.is_stop_signal_sent())
+ if(server.m_net_server.is_stop_signal_sent())
return false;
peerlist_entry pe_seed{};
- pe_seed.adr = m_seed_nodes[current_index];
+ pe_seed.adr = server.m_seed_nodes[current_index];
if (is_peer_used(pe_seed))
is_connected_to_at_least_one_seed_node = true;
- else if (try_to_connect_and_handshake_with_new_peer(m_seed_nodes[current_index], true))
+ else if (try_to_connect_and_handshake_with_new_peer(server.m_seed_nodes[current_index], true))
break;
- if(++try_count > m_seed_nodes.size())
+ if(++try_count > server.m_seed_nodes.size())
{
- if (!m_fallback_seed_nodes_added.test_and_set())
+ // only IP zone has fallback (to direct IP) seeds
+ if (zone == epee::net_utils::zone::public_ && !m_fallback_seed_nodes_added.test_and_set())
{
MWARNING("Failed to connect to any of seed peers, trying fallback seeds");
- current_index = m_seed_nodes.size() - 1;
+ current_index = server.m_seed_nodes.size() - 1;
{
boost::upgrade_to_unique_lock<boost::shared_mutex> seed_nodes_lock(seed_nodes_upgrade_lock);
- for (const auto &peer: get_seed_nodes(m_nettype))
+ for (const auto &peer: get_ip_seed_nodes())
{
MDEBUG("Fallback seed node: " << peer);
- append_net_address(m_seed_nodes, peer, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
+ append_net_address(server.m_seed_nodes, peer, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
}
}
- if (current_index == m_seed_nodes.size() - 1)
+ if (current_index == server.m_seed_nodes.size() - 1)
{
MWARNING("No fallback seeds, continuing without seeds");
break;
@@ -1604,7 +1655,7 @@ namespace nodetool
break;
}
}
- if(++current_index >= m_seed_nodes.size())
+ if(++current_index >= server.m_seed_nodes.size())
current_index = 0;
}
return true;
@@ -1620,20 +1671,21 @@ namespace nodetool
if (!m_exclusive_peers.empty()) return true;
- // Only have seeds in the public zone right now.
-
- size_t start_conn_count = get_public_outgoing_connections_count();
- if(!get_public_white_peers_count() && !connect_to_seed())
+ bool one_succeeded = false;
+ for(auto& zone : m_network_zones)
{
- return false;
- }
+ size_t start_conn_count = get_outgoing_connections_count(zone.second);
+ if(!zone.second.m_peerlist.get_white_peers_count() && !connect_to_seed(zone.first))
+ {
+ continue;
+ }
- if (!connect_to_peerlist(m_priority_peers)) return false;
+ if (zone.first == zone_type::public_ && !connect_to_peerlist(m_priority_peers)) continue;
- for(auto& zone : m_network_zones)
- {
size_t base_expected_white_connections = (zone.second.m_config.m_net_config.max_out_connection_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
+ // carefully avoid `continue` in nested loop
+
size_t conn_count = get_outgoing_connections_count(zone.second);
while(conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
{
@@ -1670,16 +1722,17 @@ namespace nodetool
}
conn_count = new_conn_count;
}
- }
- if (start_conn_count == get_public_outgoing_connections_count() && start_conn_count < m_network_zones.at(zone_type::public_).m_config.m_net_config.max_out_connection_count)
- {
- MINFO("Failed to connect to any, trying seeds");
- if (!connect_to_seed())
- return false;
+ if (start_conn_count == get_outgoing_connections_count(zone.second) && start_conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
+ {
+ MINFO("Failed to connect to any, trying seeds");
+ if (!connect_to_seed(zone.first))
+ continue;
+ }
+ one_succeeded = true;
}
- return true;
+ return one_succeeded;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt
index 19298c969..aa4102481 100644
--- a/src/rpc/CMakeLists.txt
+++ b/src/rpc/CMakeLists.txt
@@ -66,7 +66,7 @@ set(rpc_pub_headers zmq_pub.h)
set(daemon_rpc_server_headers)
-set(rpc_daemon_private_headers
+set(rpc_private_headers
bootstrap_daemon.h
core_rpc_server.h
rpc_payment.h
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 382b5815f..e72f60d05 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1137,7 +1137,7 @@ namespace cryptonote
if (!restricted)
{
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_bootstrap_daemon.get() != nullptr)
+ if (m_should_use_bootstrap_daemon)
{
skip_validation = !check_core_ready();
}
@@ -1669,6 +1669,13 @@ namespace cryptonote
return false;
}
+ uint64_t next_height;
+ crypto::rx_seedheights(height, &seed_height, &next_height);
+ if (next_height != seed_height)
+ next_seed_hash = m_core.get_block_id_by_height(next_height);
+ else
+ next_seed_hash = seed_hash;
+
if (extra_nonce.empty())
{
reserved_offset = 0;
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index bcb300889..3a8532db8 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -92,6 +92,17 @@ std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
return m_history;
}
+void TransactionHistoryImpl::setTxNote(const std::string &txid, const std::string &note)
+{
+ cryptonote::blobdata txid_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
+ return;
+ const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
+
+ m_wallet->m_wallet->set_tx_note(htxid, note);
+ refresh();
+}
+
void TransactionHistoryImpl::refresh()
{
// multithreaded access:
@@ -126,10 +137,12 @@ void TransactionHistoryImpl::refresh()
payment_id = payment_id.substr(0,16);
TransactionInfoImpl * ti = new TransactionInfoImpl();
ti->m_paymentid = payment_id;
+ ti->m_coinbase = pd.m_coinbase;
ti->m_amount = pd.m_amount;
ti->m_direction = TransactionInfo::Direction_In;
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash);
ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
ti->m_subaddrAccount = pd.m_subaddr_index.major;
ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
@@ -173,6 +186,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_Out;
ti->m_hash = string_tools::pod_to_hex(hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(hash);
ti->m_subaddrIndex = pd.m_subaddr_indices;
ti->m_subaddrAccount = pd.m_subaddr_account;
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
@@ -183,6 +197,7 @@ void TransactionHistoryImpl::refresh()
for (const auto &d: pd.m_dests) {
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
}
+
m_history.push_back(ti);
}
@@ -207,6 +222,7 @@ void TransactionHistoryImpl::refresh()
ti->m_failed = is_failed;
ti->m_pending = true;
ti->m_hash = string_tools::pod_to_hex(hash);
+ ti->m_description = m_wallet->m_wallet->get_tx_note(hash);
ti->m_subaddrIndex = pd.m_subaddr_indices;
ti->m_subaddrAccount = pd.m_subaddr_account;
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
@@ -230,6 +246,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_In;
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash);
ti->m_pending = true;
ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
ti->m_subaddrAccount = pd.m_subaddr_index.major;
diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h
index 8f3805788..60f12d771 100644
--- a/src/wallet/api/transaction_history.h
+++ b/src/wallet/api/transaction_history.h
@@ -45,6 +45,7 @@ public:
virtual TransactionInfo * transaction(const std::string &id) const;
virtual std::vector<TransactionInfo*> getAll() const;
virtual void refresh();
+ virtual void setTxNote(const std::string &txid, const std::string &note);
private:
diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp
index 5ae3a6937..33e7856db 100644
--- a/src/wallet/api/transaction_info.cpp
+++ b/src/wallet/api/transaction_info.cpp
@@ -45,6 +45,7 @@ TransactionInfoImpl::TransactionInfoImpl()
: m_direction(Direction_Out)
, m_pending(false)
, m_failed(false)
+ , m_coinbase(false)
, m_amount(0)
, m_fee(0)
, m_blockheight(0)
@@ -77,6 +78,11 @@ bool TransactionInfoImpl::isFailed() const
return m_failed;
}
+bool TransactionInfoImpl::isCoinbase() const
+{
+ return m_coinbase;
+}
+
uint64_t TransactionInfoImpl::amount() const
{
return m_amount;
@@ -92,6 +98,11 @@ uint64_t TransactionInfoImpl::blockHeight() const
return m_blockheight;
}
+std::string TransactionInfoImpl::description() const
+{
+ return m_description;
+}
+
std::set<uint32_t> TransactionInfoImpl::subaddrIndex() const
{
return m_subaddrIndex;
diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h
index 73bb7689d..8bc36a8e9 100644
--- a/src/wallet/api/transaction_info.h
+++ b/src/wallet/api/transaction_info.h
@@ -46,10 +46,12 @@ public:
//! true if hold
virtual bool isPending() const override;
virtual bool isFailed() const override;
+ virtual bool isCoinbase() const override;
virtual uint64_t amount() const override;
//! always 0 for incoming txes
virtual uint64_t fee() const override;
virtual uint64_t blockHeight() const override;
+ virtual std::string description() const override;
virtual std::set<uint32_t> subaddrIndex() const override;
virtual uint32_t subaddrAccount() const override;
virtual std::string label() const override;
@@ -65,9 +67,11 @@ private:
int m_direction;
bool m_pending;
bool m_failed;
+ bool m_coinbase;
uint64_t m_amount;
uint64_t m_fee;
uint64_t m_blockheight;
+ std::string m_description;
std::set<uint32_t> m_subaddrIndex; // always unique index for incoming transfers; can be multiple indices for outgoing transfers
uint32_t m_subaddrAccount;
std::string m_label;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 152a7dcd7..9acc8484c 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -910,6 +910,11 @@ std::string WalletImpl::path() const
return m_wallet->path();
}
+void WalletImpl::stop()
+{
+ m_wallet->stop();
+}
+
bool WalletImpl::store(const std::string &path)
{
clearStatus();
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index caf1e9ed4..3bf3e759b 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -99,6 +99,7 @@ public:
std::string publicSpendKey() const override;
std::string publicMultisigSignerKey() const override;
std::string path() const override;
+ void stop() override;
bool store(const std::string &path) override;
std::string filename() const override;
std::string keysFilename() const override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index c2559d1df..44928a422 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -182,9 +182,11 @@ struct TransactionInfo
virtual int direction() const = 0;
virtual bool isPending() const = 0;
virtual bool isFailed() const = 0;
+ virtual bool isCoinbase() const = 0;
virtual uint64_t amount() const = 0;
virtual uint64_t fee() const = 0;
virtual uint64_t blockHeight() const = 0;
+ virtual std::string description() const = 0;
virtual std::set<uint32_t> subaddrIndex() const = 0;
virtual uint32_t subaddrAccount() const = 0;
virtual std::string label() const = 0;
@@ -208,6 +210,7 @@ struct TransactionHistory
virtual TransactionInfo * transaction(const std::string &id) const = 0;
virtual std::vector<TransactionInfo*> getAll() const = 0;
virtual void refresh() = 0;
+ virtual void setTxNote(const std::string &txid, const std::string &note) = 0;
};
/**
@@ -508,6 +511,11 @@ struct Wallet
virtual std::string publicMultisigSignerKey() const = 0;
/*!
+ * \brief stop - interrupts wallet refresh() loop once (doesn't stop background refresh thread)
+ */
+ virtual void stop() = 0;
+
+ /*!
* \brief store - stores wallet to file.
* \param path - main filename to store wallet to. additionally stores address file and keys file.
* to store to the same file - just pass empty string;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index a3755ff08..7cbb4a910 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2961,6 +2961,8 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
MTRACE("update_pool_state got pool");
// remove any pending tx that's not in the pool
+ constexpr const std::chrono::seconds tx_propagation_timeout{CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE * 3 / 2};
+ const auto now = std::chrono::system_clock::now();
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
while (it != m_unconfirmed_txs.end())
{
@@ -2988,9 +2990,11 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
LOG_PRINT_L1("Pending txid " << txid << " not in pool, marking as not in pool");
pit->second.m_state = wallet2::unconfirmed_transfer_details::pending_not_in_pool;
}
- else if (pit->second.m_state == wallet2::unconfirmed_transfer_details::pending_not_in_pool && refreshed)
+ else if (pit->second.m_state == wallet2::unconfirmed_transfer_details::pending_not_in_pool && refreshed &&
+ now > std::chrono::system_clock::from_time_t(pit->second.m_sent_time) + tx_propagation_timeout)
{
- LOG_PRINT_L1("Pending txid " << txid << " not in pool, marking as failed");
+ LOG_PRINT_L1("Pending txid " << txid << " not in pool after " << tx_propagation_timeout.count() <<
+ " seconds, marking as failed");
pit->second.m_state = wallet2::unconfirmed_transfer_details::failed;
// the inputs aren't spent anymore, since the tx failed