aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_utilities/blockchain_ancestry.cpp1
-rw-r--r--src/blockchain_utilities/blockchain_blackball.cpp1
-rw-r--r--src/blockchain_utilities/blockchain_depth.cpp1
-rw-r--r--src/blockchain_utilities/blockchain_prune.cpp2
-rw-r--r--src/blockchain_utilities/blockchain_prune_known_spent_data.cpp1
-rw-r--r--src/blockchain_utilities/blockchain_stats.cpp1
-rw-r--r--src/blockchain_utilities/blockchain_usage.cpp1
-rw-r--r--src/checkpoints/checkpoints.cpp2
-rw-r--r--src/common/dns_utils.cpp29
-rw-r--r--src/common/dns_utils.h21
-rw-r--r--src/common/i18n.cpp4
-rw-r--r--src/crypto/rx-slow-hash.c28
-rw-r--r--src/cryptonote_basic/connection_context.h2
-rw-r--r--src/cryptonote_basic/miner.cpp1
-rw-r--r--src/cryptonote_core/blockchain.cpp1
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp2
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h4
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h9
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl89
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler_common.h2
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp23
-rw-r--r--src/daemon/command_parser_executor.cpp63
-rw-r--r--src/daemon/command_server.cpp2
-rw-r--r--src/daemon/rpc_command_executor.cpp4
-rw-r--r--src/daemon/rpc_command_executor.h3
-rw-r--r--src/mnemonics/electrum-words.cpp8
-rw-r--r--src/mnemonics/electrum-words.h2
-rw-r--r--src/net/CMakeLists.txt8
-rw-r--r--src/net/error.cpp7
-rw-r--r--src/net/error.h7
-rw-r--r--src/net/resolve.cpp71
-rw-r--r--src/net/resolve.h47
-rw-r--r--src/p2p/net_node.h5
-rw-r--r--src/p2p/net_node.inl56
-rw-r--r--src/p2p/net_node_common.h15
-rw-r--r--src/p2p/net_peerlist.h9
-rw-r--r--src/rpc/bootstrap_daemon.cpp21
-rw-r--r--src/rpc/bootstrap_daemon.h12
-rw-r--r--src/rpc/core_rpc_server.cpp88
-rw-r--r--src/rpc/core_rpc_server.h11
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h2
-rw-r--r--src/rpc/core_rpc_server_error_codes.h4
-rw-r--r--src/rpc/rpc_payment.cpp1
-rw-r--r--src/serialization/binary_archive.h9
-rw-r--r--src/serialization/container.h23
-rw-r--r--src/serialization/json_archive.h2
-rw-r--r--src/serialization/pair.h19
-rw-r--r--src/simplewallet/simplewallet.cpp23
-rw-r--r--src/simplewallet/simplewallet.h1
-rw-r--r--src/wallet/api/pending_transaction.cpp1
-rw-r--r--src/wallet/api/wallet.cpp11
-rw-r--r--src/wallet/api/wallet.h3
-rw-r--r--src/wallet/api/wallet2_api.h8
-rw-r--r--src/wallet/message_store.cpp2
-rw-r--r--src/wallet/wallet2.cpp24
-rw-r--r--src/wallet/wallet2.h12
-rw-r--r--src/wallet/wallet_rpc_payments.cpp91
-rw-r--r--src/wallet/wallet_rpc_server.cpp32
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h2
59 files changed, 665 insertions, 269 deletions
diff --git a/src/blockchain_utilities/blockchain_ancestry.cpp b/src/blockchain_utilities/blockchain_ancestry.cpp
index b1b238427..99a84606d 100644
--- a/src/blockchain_utilities/blockchain_ancestry.cpp
+++ b/src/blockchain_utilities/blockchain_ancestry.cpp
@@ -32,6 +32,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp>
+#include <boost/filesystem/path.hpp>
#include "common/unordered_containers_boost_serialization.h"
#include "common/command_line.h"
#include "common/varint.h"
diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp
index e439895bf..18a37434c 100644
--- a/src/blockchain_utilities/blockchain_blackball.cpp
+++ b/src/blockchain_utilities/blockchain_blackball.cpp
@@ -28,6 +28,7 @@
#include <boost/range/adaptor/transformed.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
#include "common/unordered_containers_boost_serialization.h"
#include "common/command_line.h"
#include "common/varint.h"
diff --git a/src/blockchain_utilities/blockchain_depth.cpp b/src/blockchain_utilities/blockchain_depth.cpp
index 6199586bf..8c3c3a009 100644
--- a/src/blockchain_utilities/blockchain_depth.cpp
+++ b/src/blockchain_utilities/blockchain_depth.cpp
@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/range/adaptor/transformed.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
#include "common/command_line.h"
#include "common/varint.h"
diff --git a/src/blockchain_utilities/blockchain_prune.cpp b/src/blockchain_utilities/blockchain_prune.cpp
index 9a9d58c46..b1c599f3a 100644
--- a/src/blockchain_utilities/blockchain_prune.cpp
+++ b/src/blockchain_utilities/blockchain_prune.cpp
@@ -29,6 +29,8 @@
#include <array>
#include <lmdb.h>
#include <boost/algorithm/string.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem.hpp>
#include "common/command_line.h"
#include "common/pruning.h"
#include "cryptonote_core/cryptonote_core.h"
diff --git a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp
index 1a54778a7..78a662134 100644
--- a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp
+++ b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp
@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
#include "common/command_line.h"
#include "serialization/crypto.h"
#include "cryptonote_core/tx_pool.h"
diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp
index 1f728b4e5..5f5ca6abf 100644
--- a/src/blockchain_utilities/blockchain_stats.cpp
+++ b/src/blockchain_utilities/blockchain_stats.cpp
@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
#include "common/command_line.h"
#include "common/varint.h"
#include "cryptonote_basic/cryptonote_boost_serialization.h"
diff --git a/src/blockchain_utilities/blockchain_usage.cpp b/src/blockchain_utilities/blockchain_usage.cpp
index 095e6c503..8356ef420 100644
--- a/src/blockchain_utilities/blockchain_usage.cpp
+++ b/src/blockchain_utilities/blockchain_usage.cpp
@@ -28,6 +28,7 @@
#include <boost/range/adaptor/transformed.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem/path.hpp>
#include "common/command_line.h"
#include "common/varint.h"
#include "cryptonote_core/tx_pool.h"
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index c88a630cc..6b48d8723 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -34,6 +34,8 @@
#include "string_tools.h"
#include "storages/portable_storage_template_helper.h" // epee json include
#include "serialization/keyvalue_serialization.h"
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem.hpp>
#include <functional>
#include <vector>
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index c31d1dd96..f0b617798 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -37,6 +37,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/optional.hpp>
+#include <boost/utility/string_ref.hpp>
using namespace epee;
#undef MONERO_DEFAULT_LOG_CATEGORY
@@ -124,6 +125,7 @@ static const char *get_record_name(int record_type)
case DNS_TYPE_A: return "A";
case DNS_TYPE_TXT: return "TXT";
case DNS_TYPE_AAAA: return "AAAA";
+ case DNS_TYPE_TLSA: return "TLSA";
default: return "unknown";
}
}
@@ -186,6 +188,13 @@ boost::optional<std::string> txt_to_string(const char* src, size_t len)
return std::string(src+1, len-1);
}
+boost::optional<std::string> tlsa_to_string(const char* src, size_t len)
+{
+ if (len < 4)
+ return boost::none;
+ return std::string(src, len);
+}
+
// custom smart pointer.
// TODO: see if std::auto_ptr and the like support custom destructors
template<typename type, void (*freefunc)(type*)>
@@ -326,11 +335,15 @@ std::vector<std::string> DNSResolver::get_record(const std::string& url, int rec
// destructor takes care of cleanup
ub_result_ptr result;
+ MDEBUG("Performing DNSSEC " << get_record_name(record_type) << " record query for " << url);
+
// call DNS resolver, blocking. if return value not zero, something went wrong
if (!ub_resolve(m_data->m_ub_context, string_copy(url.c_str()), record_type, DNS_CLASS_IN, &result))
{
dnssec_available = (result->secure || result->bogus);
dnssec_valid = result->secure && !result->bogus;
+ if (dnssec_available && !dnssec_valid)
+ MWARNING("Invalid DNSSEC " << get_record_name(record_type) << " record signature for " << url << ": " << result->why_bogus);
if (result->havedata)
{
for (size_t i=0; result->data[i] != NULL; i++)
@@ -338,8 +351,9 @@ std::vector<std::string> DNSResolver::get_record(const std::string& url, int rec
boost::optional<std::string> res = (*reader)(result->data[i], result->len[i]);
if (res)
{
- MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url);
- addresses.push_back(*res);
+ // do not dump dns record directly from dns into log
+ MINFO("Found " << get_record_name(record_type) << " record for " << url);
+ addresses.push_back(std::move(*res));
}
}
}
@@ -363,6 +377,17 @@ std::vector<std::string> DNSResolver::get_txt_record(const std::string& url, boo
return get_record(url, DNS_TYPE_TXT, txt_to_string, dnssec_available, dnssec_valid);
}
+std::vector<std::string> DNSResolver::get_tlsa_tcp_record(const boost::string_ref url, const boost::string_ref port, bool& dnssec_available, bool& dnssec_valid)
+{
+ std::string service_addr;
+ service_addr.reserve(url.size() + port.size() + 7);
+ service_addr.push_back('_');
+ service_addr.append(port.data(), port.size());
+ service_addr.append("._tcp.");
+ service_addr.append(url.data(), url.size());
+ return get_record(service_addr, DNS_TYPE_TLSA, tlsa_to_string, dnssec_available, dnssec_valid);
+}
+
std::string DNSResolver::get_dns_format_from_oa_address(const std::string& oa_addr)
{
std::string addr(oa_addr);
diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h
index 30c4cced2..99e91bc54 100644
--- a/src/common/dns_utils.h
+++ b/src/common/dns_utils.h
@@ -31,15 +31,17 @@
#include <string>
#include <functional>
#include <boost/optional/optional_fwd.hpp>
+#include <boost/utility/string_ref_fwd.hpp>
namespace tools
{
// RFC defines for record types and classes for DNS, gleaned from ldns source
-const static int DNS_CLASS_IN = 1;
-const static int DNS_TYPE_A = 1;
-const static int DNS_TYPE_TXT = 16;
-const static int DNS_TYPE_AAAA = 8;
+constexpr const int DNS_CLASS_IN = 1;
+constexpr const int DNS_TYPE_A = 1;
+constexpr const int DNS_TYPE_TXT = 16;
+constexpr const int DNS_TYPE_AAAA = 8;
+constexpr const int DNS_TYPE_TLSA = 52;
struct DNSResolverData;
@@ -106,6 +108,17 @@ public:
std::vector<std::string> get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid);
/**
+ * @brief gets all TLSA TCP records from a DNS query for the supplied URL;
+ * if no TLSA record present returns an empty vector.
+ *
+ * @param url A string containing a URL to query for
+ * @param port The service port number (as string) to query
+ *
+ * @return A vector of strings containing all TLSA records; or an empty vector
+ */
+ std::vector<std::string> get_tlsa_tcp_record(boost::string_ref url, boost::string_ref port, bool& dnssec_available, bool& dnssec_valid);
+
+ /**
* @brief Gets a DNS address from OpenAlias format
*
* If the address looks good, but contains one @ symbol, replace that with a .
diff --git a/src/common/i18n.cpp b/src/common/i18n.cpp
index ebc367b3a..051220ee1 100644
--- a/src/common/i18n.cpp
+++ b/src/common/i18n.cpp
@@ -35,6 +35,10 @@
#include "common/i18n.h"
#include "translation_files.h"
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem.hpp>
+#include <algorithm>
+
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "i18n"
diff --git a/src/crypto/rx-slow-hash.c b/src/crypto/rx-slow-hash.c
index fa35a32e2..801987e37 100644
--- a/src/crypto/rx-slow-hash.c
+++ b/src/crypto/rx-slow-hash.c
@@ -264,12 +264,14 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
cache = rx_sp->rs_cache;
if (cache == NULL) {
- if (cache == NULL) {
+ if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES)) {
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
if (cache == NULL) {
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX cache");
- cache = randomx_alloc_cache(flags);
}
+ }
+ if (cache == NULL) {
+ cache = randomx_alloc_cache(flags);
if (cache == NULL)
local_abort("Couldn't allocate RandomX cache");
}
@@ -291,11 +293,14 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
CTHR_MUTEX_LOCK(rx_dataset_mutex);
if (!rx_dataset_nomem) {
if (rx_dataset == NULL) {
- rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
- if (rx_dataset == NULL) {
- mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
- rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
+ if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES)) {
+ rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
+ if (rx_dataset == NULL) {
+ mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
+ }
}
+ if (rx_dataset == NULL)
+ rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
if (rx_dataset != NULL)
rx_initdata(rx_sp->rs_cache, miners, seedheight);
}
@@ -311,11 +316,14 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
}
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
}
- rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
- if(rx_vm == NULL) { //large pages failed
- mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
- rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
+ if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES)) {
+ rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
+ if(rx_vm == NULL) { //large pages failed
+ mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
+ }
}
+ if (rx_vm == NULL)
+ rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
if(rx_vm == NULL) {//fallback if everything fails
flags = RANDOMX_FLAG_DEFAULT | (miners ? RANDOMX_FLAG_FULL_MEM : 0);
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h
index a7d688300..ee26a0c07 100644
--- a/src/cryptonote_basic/connection_context.h
+++ b/src/cryptonote_basic/connection_context.h
@@ -77,6 +77,8 @@ namespace cryptonote
int m_expect_response;
uint64_t m_expect_height;
size_t m_num_requested;
+ epee::copyable_atomic m_new_stripe_notification{0};
+ epee::copyable_atomic m_idle_peer_notification{0};
};
inline std::string get_protocol_state_string(cryptonote_connection_context::state s)
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 29f6dce5a..ae514aac6 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -44,6 +44,7 @@
#include "string_tools.h"
#include "storages/portable_storage_template_helper.h"
#include "boost/logic/tribool.hpp"
+#include <boost/filesystem.hpp>
#ifdef __APPLE__
#include <sys/times.h>
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index cdad39a2c..a3d695b85 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -57,6 +57,7 @@
#include "common/notify.h"
#include "common/varint.h"
#include "common/pruning.h"
+#include "time_helper.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "blockchain"
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 57104fd59..beae55b35 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -57,6 +57,8 @@ using namespace epee;
#include "hardforks/hardforks.h"
#include "version.h"
+#include <boost/filesystem.hpp>
+
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "cn"
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index dbdf409b5..73cdd31cd 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -44,10 +44,10 @@ namespace cryptonote
typedef std::pair<uint64_t, rct::ctkey> output_entry;
std::vector<output_entry> outputs; //index + key + optional ringct commitment
- size_t real_output; //index in outputs vector of real output_entry
+ uint64_t real_output; //index in outputs vector of real output_entry
crypto::public_key real_out_tx_key; //incoming real tx public key
std::vector<crypto::public_key> real_out_additional_tx_keys; //incoming real tx additional public keys
- size_t real_output_in_tx_index; //index in transaction outputs vector
+ uint64_t real_output_in_tx_index; //index in transaction outputs vector
uint64_t amount; //money
bool rct; //true if the output is rct
rct::key mask; //ringct amount mask
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 28530f3e7..80dd2bc39 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -46,6 +46,8 @@
#include "block_queue.h"
#include "common/perf_timer.h"
#include "cryptonote_basic/connection_context.h"
+#include "net/levin_base.h"
+#include "p2p/net_node_common.h"
#include <boost/circular_buffer.hpp>
PUSH_WARNINGS
@@ -195,10 +197,11 @@ namespace cryptonote
bool post_notify(typename t_parameter::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parameter).name() << " -->");
- epee::byte_slice blob;
- epee::serialization::store_t_to_binary(arg, blob, 256 * 1024); // optimize for block responses
+
+ epee::levin::message_writer out{256 * 1024}; // optimize for block responses
+ epee::serialization::store_t_to_binary(arg, out.buffer);
//handler_response_blocks_now(blob.size()); // XXX
- return m_p2p->invoke_notify_to_peer(t_parameter::ID, epee::to_span(blob), context);
+ return m_p2p->invoke_notify_to_peer(t_parameter::ID, std::move(out), context);
}
};
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index c798dbcdb..afc81f552 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -137,6 +137,41 @@ namespace cryptonote
CHECK_AND_ASSERT_MES_CC( context.m_callback_request_count > 0, false, "false callback fired, but context.m_callback_request_count=" << context.m_callback_request_count);
--context.m_callback_request_count;
+ uint32_t notified = true;
+ if (context.m_idle_peer_notification.compare_exchange_strong(notified, not notified))
+ {
+ if (context.m_state == cryptonote_connection_context::state_synchronizing && context.m_last_request_time != boost::date_time::not_a_date_time)
+ {
+ const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
+ const boost::posix_time::time_duration dt = now - context.m_last_request_time;
+ const auto ms = dt.total_microseconds();
+ if (ms > IDLE_PEER_KICK_TIME || (context.m_expect_response && ms > NON_RESPONSIVE_PEER_KICK_TIME))
+ {
+ if (context.m_score-- >= 0)
+ {
+ MINFO(context << " kicking idle peer, last update " << (dt.total_microseconds() / 1.e6) << " seconds ago, expecting " << (int)context.m_expect_response);
+ context.m_last_request_time = boost::date_time::not_a_date_time;
+ context.m_expect_response = 0;
+ context.m_expect_height = 0;
+ context.m_state = cryptonote_connection_context::state_standby; // we'll go back to adding, then (if we can't), download
+ }
+ else
+ {
+ MINFO(context << "dropping idle peer with negative score");
+ drop_connection_with_score(context, context.m_expect_response == 0 ? 1 : 5, false);
+ return false;
+ }
+ }
+ }
+ }
+
+ notified = true;
+ if (context.m_new_stripe_notification.compare_exchange_strong(notified, not notified))
+ {
+ if (context.m_state == cryptonote_connection_context::state_normal)
+ context.m_state = cryptonote_connection_context::state_synchronizing;
+ }
+
if(context.m_state == cryptonote_connection_context::state_synchronizing && context.m_last_request_time == boost::posix_time::not_a_date_time)
{
NOTIFY_REQUEST_CHAIN::request r = {};
@@ -1687,7 +1722,7 @@ skip:
const uint32_t peer_stripe = tools::get_pruning_stripe(context.m_pruning_seed);
if (stripe && peer_stripe && peer_stripe != stripe)
return true;
- context.m_state = cryptonote_connection_context::state_synchronizing;
+ context.m_new_stripe_notification = true;
LOG_PRINT_CCONTEXT_L2("requesting callback");
++context.m_callback_request_count;
m_p2p->request_callback(context);
@@ -1710,7 +1745,6 @@ skip:
bool t_cryptonote_protocol_handler<t_core>::kick_idle_peers()
{
MTRACE("Checking for idle peers...");
- std::vector<std::pair<boost::uuids::uuid, unsigned>> idle_peers;
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 && context.m_last_request_time != boost::date_time::not_a_date_time)
@@ -1720,36 +1754,16 @@ skip:
const auto ms = dt.total_microseconds();
if (ms > IDLE_PEER_KICK_TIME || (context.m_expect_response && ms > NON_RESPONSIVE_PEER_KICK_TIME))
{
- if (context.m_score-- >= 0)
- {
- MINFO(context << " kicking idle peer, last update " << (dt.total_microseconds() / 1.e6) << " seconds ago, expecting " << (int)context.m_expect_response);
- LOG_PRINT_CCONTEXT_L2("requesting callback");
- context.m_last_request_time = boost::date_time::not_a_date_time;
- context.m_expect_response = 0;
- context.m_expect_height = 0;
- context.m_state = cryptonote_connection_context::state_standby; // we'll go back to adding, then (if we can't), download
- ++context.m_callback_request_count;
- m_p2p->request_callback(context);
- }
- else
- {
- idle_peers.push_back(std::make_pair(context.m_connection_id, context.m_expect_response == 0 ? 1 : 5));
- }
+ context.m_idle_peer_notification = true;
+ LOG_PRINT_CCONTEXT_L2("requesting callback");
+ ++context.m_callback_request_count;
+ m_p2p->request_callback(context);
+ MLOG_PEER_STATE("requesting callback");
}
}
return true;
});
- for (const auto &e: idle_peers)
- {
- const auto &uuid = e.first;
- m_p2p->for_connection(uuid, [&](cryptonote_connection_context& ctx, nodetool::peerid_type peer_id, uint32_t f)->bool{
- MINFO(ctx << "dropping idle peer with negative score");
- drop_connection_with_score(ctx, e.second, false);
- return true;
- });
- }
-
return true;
}
//------------------------------------------------------------------------------------------------------------------------
@@ -2699,15 +2713,15 @@ skip:
// send fluffy ones first, we want to encourage people to run that
if (!fluffyConnections.empty())
{
- epee::byte_slice fluffyBlob;
- epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob, 32 * 1024);
- m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, epee::to_span(fluffyBlob), std::move(fluffyConnections));
+ epee::levin::message_writer fluffyBlob{32 * 1024};
+ epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob.buffer);
+ m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, std::move(fluffyBlob), std::move(fluffyConnections));
}
if (!fullConnections.empty())
{
- epee::byte_slice fullBlob;
- epee::serialization::store_t_to_binary(arg, fullBlob, 128 * 1024);
- m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, epee::to_span(fullBlob), std::move(fullConnections));
+ epee::levin::message_writer fullBlob{128 * 1024};
+ epee::serialization::store_t_to_binary(arg, fullBlob.buffer);
+ m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, std::move(fullBlob), std::move(fullConnections));
}
return true;
@@ -2840,15 +2854,12 @@ skip:
epee::string_tools::to_string_hex(context.m_pruning_seed) <<
"), score " << score << ", flush_all_spans " << flush_all_spans);
- m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
+ if (score > 0)
+ m_p2p->add_host_fail(context.m_remote_address, score);
- // copy since dropping the connection will invalidate the context, and thus the address
- const auto remote_address = context.m_remote_address;
+ m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
m_p2p->drop_connection(context);
-
- if (score > 0)
- m_p2p->add_host_fail(remote_address, score);
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
index 79c2edf1d..57b1d049c 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
@@ -30,8 +30,8 @@
#pragma once
-#include "p2p/net_node_common.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
+#include "cryptonote_protocol/enums.h"
#include "cryptonote_basic/connection_context.h"
namespace cryptonote
{
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index 1e9f3e399..0b065c3c3 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -159,7 +159,7 @@ namespace levin
return get_out_connections(p2p, get_blockchain_height(p2p, core));
}
- epee::byte_slice make_tx_payload(std::vector<blobdata>&& txs, const bool pad, const bool fluff)
+ epee::levin::message_writer make_tx_message(std::vector<blobdata>&& txs, const bool pad, const bool fluff)
{
NOTIFY_NEW_TRANSACTIONS::request request{};
request.txs = std::move(txs);
@@ -193,21 +193,17 @@ namespace levin
// if the size of _ moved enough, we might lose byte in size encoding, we don't care
}
- epee::byte_slice fullBlob;
- if (!epee::serialization::store_t_to_binary(request, fullBlob))
+ epee::levin::message_writer out;
+ if (!epee::serialization::store_t_to_binary(request, out.buffer))
throw std::runtime_error{"Failed to serialize to epee binary format"};
- return fullBlob;
+ return out;
}
bool make_payload_send_txs(connections& p2p, std::vector<blobdata>&& txs, const boost::uuids::uuid& destination, const bool pad, const bool fluff)
{
- const epee::byte_slice blob = make_tx_payload(std::move(txs), pad, fluff);
- p2p.for_connection(destination, [&blob](detail::p2p_context& context) {
- on_levin_traffic(context, true, true, false, blob.size(), NOTIFY_NEW_TRANSACTIONS::ID);
- return true;
- });
- return p2p.notify(NOTIFY_NEW_TRANSACTIONS::ID, epee::to_span(blob), destination);
+ epee::byte_slice blob = make_tx_message(std::move(txs), pad, fluff).finalize_notify(NOTIFY_NEW_TRANSACTIONS::ID);
+ return p2p.send(std::move(blob), destination);
}
/* The current design uses `asio::strand`s. The documentation isn't as clear
@@ -653,10 +649,6 @@ namespace levin
else
message = zone_->noise.clone();
- zone_->p2p->for_connection(channel.connection, [&](detail::p2p_context& context) {
- on_levin_traffic(context, true, true, false, message.size(), "noise");
- return true;
- });
if (zone_->p2p->send(std::move(message), channel.connection))
{
if (!channel.queue.empty() && channel.active.empty())
@@ -816,9 +808,8 @@ namespace levin
// Padding is not useful when using noise mode. Send as stem so receiver
// forwards in Dandelion++ mode.
- const epee::byte_slice payload = make_tx_payload(std::move(txs), false, false);
epee::byte_slice message = epee::levin::make_fragmented_notify(
- zone_->noise, NOTIFY_NEW_TRANSACTIONS::ID, epee::to_span(payload)
+ zone_->noise.size(), NOTIFY_NEW_TRANSACTIONS::ID, make_tx_message(std::move(txs), false, false)
);
if (CRYPTONOTE_MAX_FRAGMENTS * zone_->noise.size() < message.size())
{
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 5a7560874..abca614cc 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -30,6 +30,7 @@
#include "common/command_line.h"
#include "net/parse.h"
#include "daemon/command_parser_executor.h"
+#include <boost/filesystem.hpp>
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "daemon"
@@ -986,17 +987,67 @@ bool t_command_parser_executor::check_blockchain_pruning(const std::vector<std::
bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::string>& args)
{
- const size_t args_count = args.size();
- if (args_count < 1 || args_count > 3)
+ struct parsed_t
+ {
+ std::string address;
+ std::string user;
+ std::string password;
+ std::string proxy;
+ };
+
+ boost::optional<parsed_t> parsed = [&args]() -> boost::optional<parsed_t> {
+ const size_t args_count = args.size();
+ if (args_count == 0)
+ {
+ return {};
+ }
+ if (args[0] == "auto")
+ {
+ if (args_count == 1)
+ {
+ return {{args[0], "", "", ""}};
+ }
+ if (args_count == 2)
+ {
+ return {{args[0], "", "", args[1]}};
+ }
+ }
+ else if (args[0] == "none")
+ {
+ if (args_count == 1)
+ {
+ return {{"", "", "", ""}};
+ }
+ }
+ else
+ {
+ if (args_count == 1)
+ {
+ return {{args[0], "", "", ""}};
+ }
+ if (args_count == 2)
+ {
+ return {{args[0], "", "", args[1]}};
+ }
+ if (args_count == 3)
+ {
+ return {{args[0], args[1], args[2], ""}};
+ }
+ if (args_count == 4)
+ {
+ return {{args[0], args[1], args[2], args[3]}};
+ }
+ }
+ return {};
+ }();
+
+ if (!parsed)
{
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(
- args[0] != "none" ? args[0] : std::string(),
- args_count > 1 ? args[1] : std::string(),
- args_count > 2 ? args[2] : std::string());
+ return m_executor.set_bootstrap_daemon(parsed->address, parsed->user, parsed->password, parsed->proxy);
}
bool t_command_parser_executor::flush_cache(const std::vector<std::string>& args)
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index 4768bb842..63f44c4cd 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -326,7 +326,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"set_bootstrap_daemon"
, std::bind(&t_command_parser_executor::set_bootstrap_daemon, &m_parser, p::_1)
- , "set_bootstrap_daemon (auto | none | host[:port] [username] [password])"
+ , "set_bootstrap_daemon (auto | none | host[:port] [username] [password]) [proxy_ip:proxy_port]"
, "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced.\n"
"Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
);
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 8194fe642..16e6a304c 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -2405,7 +2405,8 @@ bool t_rpc_command_executor::check_blockchain_pruning()
bool t_rpc_command_executor::set_bootstrap_daemon(
const std::string &address,
const std::string &username,
- const std::string &password)
+ const std::string &password,
+ const std::string &proxy)
{
cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req;
cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res;
@@ -2414,6 +2415,7 @@ bool t_rpc_command_executor::set_bootstrap_daemon(
req.address = address;
req.username = username;
req.password = password;
+ req.proxy = proxy;
if (m_is_rpc)
{
diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h
index 6fb5d6903..118f04731 100644
--- a/src/daemon/rpc_command_executor.h
+++ b/src/daemon/rpc_command_executor.h
@@ -168,7 +168,8 @@ public:
bool set_bootstrap_daemon(
const std::string &address,
const std::string &username,
- const std::string &password);
+ const std::string &password,
+ const std::string &proxy);
bool rpc_payments();
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp
index b6bc22a3d..8c79a53ca 100644
--- a/src/mnemonics/electrum-words.cpp
+++ b/src/mnemonics/electrum-words.cpp
@@ -491,6 +491,14 @@ namespace crypto
return "<language not found>";
}
+ bool is_valid_language(const std::string &language)
+ {
+ const std::vector<const Language::Base*> language_instances = get_language_list();
+ for (std::vector<const Language::Base*>::const_iterator it = language_instances.begin(); it != language_instances.end(); it++)
+ if ((*it)->get_english_language_name() == language || (*it)->get_language_name() == language)
+ return true;
+ return false;
+ }
}
}
diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h
index 8d4c5be66..eb0c99e0b 100644
--- a/src/mnemonics/electrum-words.h
+++ b/src/mnemonics/electrum-words.h
@@ -124,6 +124,8 @@ namespace crypto
* \return the name of the language in English
*/
std::string get_english_name_for(const std::string &name);
+
+ bool is_valid_language(const std::string &language);
}
}
diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt
index afcd42ef7..e93e27bcd 100644
--- a/src/net/CMakeLists.txt
+++ b/src/net/CMakeLists.txt
@@ -26,10 +26,10 @@
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-set(net_sources dandelionpp.cpp error.cpp http.cpp i2p_address.cpp parse.cpp socks.cpp
- socks_connect.cpp tor_address.cpp zmq.cpp)
-set(net_headers dandelionpp.h error.h http.cpp i2p_address.h parse.h socks.h socks_connect.h
- tor_address.h zmq.h)
+set(net_sources dandelionpp.cpp error.cpp http.cpp i2p_address.cpp parse.cpp resolve.cpp
+ socks.cpp socks_connect.cpp tor_address.cpp zmq.cpp)
+set(net_headers dandelionpp.h error.h http.cpp i2p_address.h parse.h socks.h resolve.h
+ socks_connect.h tor_address.h zmq.h)
monero_add_library(net ${net_sources} ${net_headers})
target_link_libraries(net common epee ${ZMQ_LIB} ${Boost_ASIO_LIBRARY})
diff --git a/src/net/error.cpp b/src/net/error.cpp
index 037f44d52..d2e713bc5 100644
--- a/src/net/error.cpp
+++ b/src/net/error.cpp
@@ -47,12 +47,18 @@ namespace
{
switch (net::error(value))
{
+ case net::error::bogus_dnssec:
+ return "Invalid response signature from DNSSEC enabled domain";
+ case net::error::dns_query_failure:
+ return "Failed to retrieve desired DNS record";
case net::error::expected_tld:
return "Expected top-level domain";
case net::error::invalid_host:
return "Host value is not valid";
case net::error::invalid_i2p_address:
return "Invalid I2P address";
+ case net::error::invalid_mask:
+ return "CIDR netmask outside of 0-32 range";
case net::error::invalid_port:
return "Invalid port value (expected 0-65535)";
case net::error::invalid_tor_address:
@@ -71,6 +77,7 @@ namespace
switch (net::error(value))
{
case net::error::invalid_port:
+ case net::error::invalid_mask:
return std::errc::result_out_of_range;
case net::error::expected_tld:
case net::error::invalid_tor_address:
diff --git a/src/net/error.h b/src/net/error.h
index 7c852dd20..746eb0ecb 100644
--- a/src/net/error.h
+++ b/src/net/error.h
@@ -37,13 +37,16 @@ namespace net
enum class error : int
{
// 0 reserved for success (as per expect<T>)
- expected_tld = 1, //!< Expected a tld
+ bogus_dnssec = 1, //!< Invalid response signature from DNSSEC enabled domain
+ dns_query_failure, //!< Failed to retrieve desired DNS record
+ expected_tld, //!< Expected a tld
invalid_host, //!< Hostname is not valid
invalid_i2p_address,
+ invalid_mask, //!< Outside of 0-32 range
invalid_port, //!< Outside of 0-65535 range
invalid_tor_address,//!< Invalid base32 or length
unsupported_address,//!< Type not supported by `get_network_address`
- invalid_mask, //!< Outside of 0-32 range
+
};
//! \return `std::error_category` for `net` namespace.
diff --git a/src/net/resolve.cpp b/src/net/resolve.cpp
new file mode 100644
index 000000000..1b43cf6c4
--- /dev/null
+++ b/src/net/resolve.cpp
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "net/resolve.h"
+
+#include <boost/utility/string_ref.hpp>
+#include "common/dns_utils.h"
+#include "common/expect.h"
+#include "net/error.h"
+
+namespace net
+{
+namespace dnssec
+{
+ expect<service_response> resolve_hostname(const std::string& addr, const std::string& tlsa_port)
+ {
+ // use basic (blocking) unbound for now, possibly refactor later
+ tools::DNSResolver& resolver = tools::DNSResolver::instance();
+
+ bool dnssec_available = false;
+ bool dnssec_valid = false;
+ std::vector<std::string> ip_records = resolver.get_ipv4(addr, dnssec_available, dnssec_valid);
+
+ if (dnssec_available && !dnssec_valid)
+ return {net::error::bogus_dnssec};
+
+ if (ip_records.empty())
+ {
+ ip_records = resolver.get_ipv6(addr, dnssec_available, dnssec_valid);
+ if (dnssec_available && !dnssec_valid)
+ return {net::error::bogus_dnssec};
+ if (ip_records.empty())
+ return {net::error::dns_query_failure};
+ }
+
+ std::vector<std::string> tlsa{};
+ if (dnssec_available && !tlsa_port.empty())
+ {
+ tlsa = resolver.get_tlsa_tcp_record(addr, tlsa_port, dnssec_available, dnssec_valid);
+ if (!dnssec_valid)
+ return {net::error::bogus_dnssec};
+ }
+ return {{std::move(ip_records), std::move(tlsa)}};
+ }
+} // dnssec
+} // net
diff --git a/src/net/resolve.h b/src/net/resolve.h
new file mode 100644
index 000000000..46bd8e617
--- /dev/null
+++ b/src/net/resolve.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string>
+#include <vector>
+
+template<typename> class expect;
+
+namespace net
+{
+namespace dnssec
+{
+ struct service_response
+ {
+ std::vector<std::string> ip; //!< IPv4/6 records in dotted or semicolon notation
+ std::vector<std::string> tlsa; //!< DANE/TLSA records
+ };
+
+ //! \return IP + (optionally) DANE/TLSA records, failing if DNSSEC signature is "bogus"
+ expect<service_response> resolve_hostname(const std::string& addr, const std::string& tlsa_port = {});
+} // dnssec
+} // net
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index db931122e..f2888674b 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -344,10 +344,9 @@ namespace nodetool
virtual void on_connection_close(p2p_connection_context& context);
virtual void callback(p2p_connection_context& context);
//----------------- i_p2p_endpoint -------------------------------------------------------------
- virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections);
+ virtual bool relay_notify_to_list(int command, epee::levin::message_writer message, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections) final;
virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay);
- virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context);
- virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context);
+ virtual bool invoke_notify_to_peer(int command, epee::levin::message_writer message, const epee::net_utils::connection_context_base& context) final;
virtual bool drop_connection(const epee::net_utils::connection_context_base& context);
virtual void request_callback(const epee::net_utils::connection_context_base& context);
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 07b45b9bd..e1d6d1e10 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -1203,9 +1203,8 @@ namespace nodetool
if(!handle_remote_peerlist(rsp.local_peerlist_new, context))
{
LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection.");
- const auto remote_address = context.m_remote_address;
m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id );
- add_host_fail(remote_address);
+ add_host_fail(context.m_remote_address);
}
if(!context.m_is_income)
m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address, context.m_pruning_seed, context.m_rpc_port, context.m_rpc_credits_per_hash);
@@ -1230,8 +1229,8 @@ namespace nodetool
if(!max_index)
return 0;
- size_t x = crypto::rand<size_t>()%(max_index+1);
- size_t res = (x*x*x)/(max_index*max_index); //parabola \/
+ size_t x = crypto::rand<size_t>()%(16*max_index+1);
+ size_t res = (x*x*x)/(max_index*max_index*16*16*16); //parabola \/
MDEBUG("Random connection index=" << res << "(x="<< x << ", max_index=" << max_index << ")");
return res;
}
@@ -1369,7 +1368,7 @@ namespace nodetool
if(just_take_peerlist)
{
zone.m_net_server.get_config_object().close(con->m_connection_id);
- MDEBUG(na.str() << "CONNECTION HANDSHAKED OK AND CLOSED.");
+ LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
return true;
}
@@ -1431,7 +1430,7 @@ namespace nodetool
zone.m_net_server.get_config_object().close(con->m_connection_id);
- MDEBUG(na.str() << "CONNECTION HANDSHAKED OK AND CLOSED.");
+ LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
return true;
}
@@ -2003,15 +2002,22 @@ namespace nodetool
{
if (ip.empty())
continue;
+ auto subnet = net::get_ipv4_subnet_address(ip);
+ if (subnet)
+ {
+ block_subnet(*subnet, DNS_BLOCKLIST_LIFETIME);
+ ++good;
+ continue;
+ }
const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(ip, 0);
- if (!parsed_addr)
+ if (parsed_addr)
{
- MWARNING("Invalid IP address from DNS blocklist: " << ip << " - " << parsed_addr.error());
- ++bad;
+ block_host(*parsed_addr, DNS_BLOCKLIST_LIFETIME, true);
+ ++good;
continue;
}
- block_host(*parsed_addr, DNS_BLOCKLIST_LIFETIME, true);
- ++good;
+ MWARNING("Invalid IP address or subnet from DNS blocklist: " << ip << " - " << parsed_addr.error());
+ ++bad;
}
}
if (good > 0)
@@ -2169,8 +2175,9 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)
+ bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, epee::levin::message_writer data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)
{
+ epee::byte_slice message = data_buff.finalize_notify(command);
std::sort(connections.begin(), connections.end());
auto zone = m_network_zones.begin();
for(const auto& c_id: connections)
@@ -2188,7 +2195,7 @@ namespace nodetool
++zone;
}
if (zone->first == c_id.first)
- zone->second.m_net_server.get_config_object().notify(command, data_buff, c_id.second);
+ zone->second.m_net_server.get_config_object().send(message.clone(), c_id.second);
}
return true;
}
@@ -2255,24 +2262,13 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)
+ bool node_server<t_payload_net_handler>::invoke_notify_to_peer(const int command, epee::levin::message_writer message, const epee::net_utils::connection_context_base& context)
{
if(is_filtered_command(context.m_remote_address, command))
return false;
network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
- int res = zone.m_net_server.get_config_object().notify(command, req_buff, context.m_connection_id);
- return res > 0;
- }
- //-----------------------------------------------------------------------------------
- template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
- {
- if(is_filtered_command(context.m_remote_address, command))
- return false;
-
- network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
- int res = zone.m_net_server.get_config_object().invoke(command, req_buff, resp_buff, context.m_connection_id);
+ int res = zone.m_net_server.get_config_object().send(message.finalize_notify(command), context.m_connection_id);
return res > 0;
}
//-----------------------------------------------------------------------------------
@@ -2458,14 +2454,12 @@ namespace nodetool
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_handshake(int command, typename COMMAND_HANDSHAKE::request& arg, typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
{
- // copy since dropping the connection will invalidate the context, and thus the address
- const auto remote_address = context.m_remote_address;
-
if(arg.node_data.network_id != m_network_id)
{
+
LOG_INFO_CC(context, "WRONG NETWORK AGENT CONNECTED! id=" << arg.node_data.network_id);
drop_connection(context);
- add_host_fail(remote_address);
+ add_host_fail(context.m_remote_address);
return 1;
}
@@ -2473,7 +2467,7 @@ namespace nodetool
{
LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came not from incoming connection");
drop_connection(context);
- add_host_fail(remote_address);
+ add_host_fail(context.m_remote_address);
return 1;
}
diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h
index 0da758ad4..92b7596ae 100644
--- a/src/p2p/net_node_common.h
+++ b/src/p2p/net_node_common.h
@@ -40,6 +40,8 @@
#include "net/net_utils_base.h"
#include "p2p_protocol_defs.h"
+namespace epee { namespace levin { class message_writer; } }
+
namespace nodetool
{
@@ -49,10 +51,9 @@ namespace nodetool
template<class t_connection_context>
struct i_p2p_endpoint
{
- virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)=0;
+ virtual bool relay_notify_to_list(int command, epee::levin::message_writer message, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)=0;
virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay)=0;
- virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0;
- virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)=0;
+ virtual bool invoke_notify_to_peer(int command, epee::levin::message_writer message, const epee::net_utils::connection_context_base& context)=0;
virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0;
virtual void request_callback(const epee::net_utils::connection_context_base& context)=0;
virtual uint64_t get_public_connections_count()=0;
@@ -71,7 +72,7 @@ namespace nodetool
template<class t_connection_context>
struct p2p_endpoint_stub: public i_p2p_endpoint<t_connection_context>
{
- virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)
+ virtual bool relay_notify_to_list(int command, epee::levin::message_writer message, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)
{
return false;
}
@@ -79,11 +80,7 @@ namespace nodetool
{
return epee::net_utils::zone::invalid;
}
- virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
- {
- return false;
- }
- virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)
+ virtual bool invoke_notify_to_peer(int command, epee::levin::message_writer message, const epee::net_utils::connection_context_base& context)
{
return true;
}
diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h
index c794b0f3b..d8de6abe9 100644
--- a/src/p2p/net_peerlist.h
+++ b/src/p2p/net_peerlist.h
@@ -110,7 +110,7 @@ namespace nodetool
bool get_gray_peer_by_index(peerlist_entry& p, size_t i);
template<typename F> bool foreach(bool white, const F &f);
void evict_host_from_white_peerlist(const peerlist_entry& pr);
- bool append_with_peer_white(const peerlist_entry& pr);
+ bool append_with_peer_white(const peerlist_entry& pr, bool trust_last_seen = false);
bool append_with_peer_gray(const peerlist_entry& pr);
bool append_with_peer_anchor(const anchor_peerlist_entry& ple);
bool set_peer_just_seen(peerid_type peer, const epee::net_utils::network_address& addr, uint32_t pruning_seed, uint16_t rpc_port, uint32_t rpc_credits_per_hash);
@@ -329,12 +329,12 @@ namespace nodetool
ple.pruning_seed = pruning_seed;
ple.rpc_port = rpc_port;
ple.rpc_credits_per_hash = rpc_credits_per_hash;
- return append_with_peer_white(ple);
+ return append_with_peer_white(ple, true);
CATCH_ENTRY_L0("peerlist_manager::set_peer_just_seen()", false);
}
//--------------------------------------------------------------------------------------------------
inline
- bool peerlist_manager::append_with_peer_white(const peerlist_entry& ple)
+ bool peerlist_manager::append_with_peer_white(const peerlist_entry& ple, bool trust_last_seen)
{
TRY_ENTRY();
if(!is_host_allowed(ple.adr))
@@ -357,7 +357,8 @@ namespace nodetool
new_ple.pruning_seed = by_addr_it_wt->pruning_seed;
if (by_addr_it_wt->rpc_port && ple.rpc_port == 0) // guard against older nodes not passing RPC port around
new_ple.rpc_port = by_addr_it_wt->rpc_port;
- new_ple.last_seen = by_addr_it_wt->last_seen; // do not overwrite the last seen timestamp, incoming peer list are untrusted
+ if (!trust_last_seen)
+ new_ple.last_seen = by_addr_it_wt->last_seen; // do not overwrite the last seen timestamp, incoming peer lists are untrusted
m_peers_white.replace(by_addr_it_wt, new_ple);
}
//remove from gray list, if need
diff --git a/src/rpc/bootstrap_daemon.cpp b/src/rpc/bootstrap_daemon.cpp
index 2fdd28406..ffea906d5 100644
--- a/src/rpc/bootstrap_daemon.cpp
+++ b/src/rpc/bootstrap_daemon.cpp
@@ -7,6 +7,7 @@
#include "crypto/crypto.h"
#include "cryptonote_core/cryptonote_core.h"
#include "misc_log_ex.h"
+#include "net/parse.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc.bootstrap_daemon"
@@ -16,19 +17,23 @@ namespace cryptonote
bootstrap_daemon::bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes,
- bool rpc_payment_enabled)
+ bool rpc_payment_enabled,
+ const std::string &proxy)
: m_selector(new bootstrap_node::selector_auto(std::move(get_public_nodes)))
, m_rpc_payment_enabled(rpc_payment_enabled)
{
+ set_proxy(proxy);
}
bootstrap_daemon::bootstrap_daemon(
const std::string &address,
boost::optional<epee::net_utils::http::login> credentials,
- bool rpc_payment_enabled)
+ bool rpc_payment_enabled,
+ const std::string &proxy)
: m_selector(nullptr)
, m_rpc_payment_enabled(rpc_payment_enabled)
{
+ set_proxy(proxy);
if (!set_server(address, std::move(credentials)))
{
throw std::runtime_error("invalid bootstrap daemon address or credentials");
@@ -78,6 +83,18 @@ namespace cryptonote
return success;
}
+ void bootstrap_daemon::set_proxy(const std::string &address)
+ {
+ if (!address.empty() && !net::get_tcp_endpoint(address))
+ {
+ throw std::runtime_error("invalid proxy address format");
+ }
+ if (!m_http_client.set_proxy(address))
+ {
+ throw std::runtime_error("failed to set proxy address");
+ }
+ }
+
bool bootstrap_daemon::set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials /* = boost::none */)
{
if (!m_http_client.set_server(address, credentials))
diff --git a/src/rpc/bootstrap_daemon.h b/src/rpc/bootstrap_daemon.h
index d54042b11..1e4477123 100644
--- a/src/rpc/bootstrap_daemon.h
+++ b/src/rpc/bootstrap_daemon.h
@@ -8,7 +8,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/utility/string_ref.hpp>
-#include "net/http_client.h"
+#include "net/http.h"
#include "storages/http_abstract_invoke.h"
#include "bootstrap_node_selector.h"
@@ -21,11 +21,13 @@ namespace cryptonote
public:
bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes,
- bool rpc_payment_enabled);
+ bool rpc_payment_enabled,
+ const std::string &proxy);
bootstrap_daemon(
const std::string &address,
boost::optional<epee::net_utils::http::login> credentials,
- bool rpc_payment_enabled);
+ bool rpc_payment_enabled,
+ const std::string &proxy);
std::string address() const noexcept;
boost::optional<std::pair<uint64_t, uint64_t>> get_height();
@@ -72,12 +74,14 @@ namespace cryptonote
return handle_result(result, result_struct.status);
}
+ void set_proxy(const std::string &address);
+
private:
bool set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials = boost::none);
bool switch_server_if_needed();
private:
- epee::net_utils::http::http_simple_client m_http_client;
+ net::http::client m_http_client;
const bool m_rpc_payment_enabled;
const std::unique_ptr<bootstrap_node::selector> m_selector;
boost::mutex m_selector_mutex;
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 0c6e2ec8f..ded545efa 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -30,6 +30,7 @@
#include <boost/preprocessor/stringize.hpp>
#include <boost/uuid/nil_generator.hpp>
+#include <boost/filesystem.hpp>
#include "include_base_utils.h"
#include "string_tools.h"
using namespace epee;
@@ -155,6 +156,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_restricted_rpc);
command_line::add_arg(desc, arg_bootstrap_daemon_address);
command_line::add_arg(desc, arg_bootstrap_daemon_login);
+ command_line::add_arg(desc, arg_bootstrap_daemon_proxy);
cryptonote::rpc_args::init_options(desc, true);
command_line::add_arg(desc, arg_rpc_payment_address);
command_line::add_arg(desc, arg_rpc_payment_difficulty);
@@ -173,7 +175,10 @@ namespace cryptonote
, m_rpc_payment_allow_free_loopback(false)
{}
//------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const std::string &username_password)
+ bool core_rpc_server::set_bootstrap_daemon(
+ const std::string &address,
+ const std::string &username_password,
+ const std::string &proxy)
{
boost::optional<epee::net_utils::http::login> credentials;
const auto loc = username_password.find(':');
@@ -181,7 +186,7 @@ namespace cryptonote
{
credentials = epee::net_utils::http::login(username_password.substr(0, loc), username_password.substr(loc + 1));
}
- return set_bootstrap_daemon(address, credentials);
+ return set_bootstrap_daemon(address, credentials, proxy);
}
//------------------------------------------------------------------------------------------------------------------------------
std::map<std::string, bool> core_rpc_server::get_public_nodes(uint32_t credits_per_hash_threshold/* = 0*/)
@@ -218,7 +223,10 @@ namespace cryptonote
return result;
}
//------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials)
+ bool core_rpc_server::set_bootstrap_daemon(
+ const std::string &address,
+ const boost::optional<epee::net_utils::http::login> &credentials,
+ const std::string &proxy)
{
boost::unique_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
@@ -234,11 +242,11 @@ namespace cryptonote
auto get_nodes = [this]() {
return get_public_nodes(credits_per_hash_threshold);
};
- m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled));
+ m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled, proxy));
}
else
{
- m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled));
+ m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled, proxy));
}
m_should_use_bootstrap_daemon = m_bootstrap_daemon.get() != nullptr;
@@ -320,8 +328,10 @@ namespace cryptonote
MWARNING("The RPC server is accessible from the outside, but no RPC payment was setup. RPC access will be free for all.");
}
- if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
- command_line::get_arg(vm, arg_bootstrap_daemon_login)))
+ if (!set_bootstrap_daemon(
+ command_line::get_arg(vm, arg_bootstrap_daemon_address),
+ command_line::get_arg(vm, arg_bootstrap_daemon_login),
+ command_line::get_arg(vm, arg_bootstrap_daemon_proxy)))
{
MFATAL("Failed to parse bootstrap daemon address");
return false;
@@ -595,7 +605,7 @@ namespace cryptonote
if (max_blocks == 0)
{
res.status = CORE_RPC_STATUS_PAYMENT_REQUIRED;
- return false;
+ return true;
}
}
@@ -604,7 +614,7 @@ namespace cryptonote
{
res.status = "Failed";
add_host_fail(ctx);
- return false;
+ return true;
}
CHECK_PAYMENT_SAME_TS(req, res, bs.size() * COST_PER_BLOCK);
@@ -640,12 +650,12 @@ namespace cryptonote
if (!r)
{
res.status = "Failed";
- return false;
+ return true;
}
if (indices.size() != n_txes_to_lookup || res.output_indices.back().indices.size() != (req.no_miner_tx ? 1 : 0))
{
res.status = "Failed";
- return false;
+ return true;
}
for (size_t i = 0; i < indices.size(); ++i)
res.output_indices.back().indices.push_back({std::move(indices[i])});
@@ -668,7 +678,7 @@ namespace cryptonote
if(!m_core.get_alternative_blocks(blks))
{
res.status = "Failed";
- return false;
+ return true;
}
res.blks_hashes.reserve(blks.size());
@@ -739,7 +749,7 @@ namespace cryptonote
{
res.status = "Failed";
add_host_fail(ctx);
- return false;
+ return true;
}
CHECK_PAYMENT_SAME_TS(req, res, res.m_block_ids.size() * COST_PER_BLOCK_HASH);
@@ -1070,7 +1080,7 @@ namespace cryptonote
if (!r)
{
res.status = "Failed";
- return false;
+ return true;
}
}
}
@@ -1446,7 +1456,8 @@ namespace cryptonote
res.status = peer_list_res.status;
if (!success)
{
- return false;
+ res.status = "Failed to get peer list";
+ return true;
}
if (res.status != CORE_RPC_STATUS_OK)
{
@@ -1617,15 +1628,15 @@ namespace cryptonote
{
credentials = epee::net_utils::http::login(req.username, req.password);
}
-
- if (set_bootstrap_daemon(req.address, credentials))
+
+ if (set_bootstrap_daemon(req.address, credentials, req.proxy))
{
res.status = CORE_RPC_STATUS_OK;
}
else
{
res.status = "Failed to set bootstrap daemon";
- }
+ }
return true;
}
@@ -1648,7 +1659,7 @@ namespace cryptonote
if (m_should_use_bootstrap_daemon)
{
res.status = "This command is unsupported for bootstrap daemon";
- return false;
+ return true;
}
}
res.count = m_core.get_current_blockchain_height();
@@ -1664,7 +1675,7 @@ namespace cryptonote
if (m_should_use_bootstrap_daemon)
{
res = "This command is unsupported for bootstrap daemon";
- return false;
+ return true;
}
}
if(req.size() != 1)
@@ -1974,7 +1985,8 @@ namespace cryptonote
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
if (m_should_use_bootstrap_daemon)
{
- res.status = "This command is unsupported for bootstrap daemon";
+ error_resp.code = CORE_RPC_ERROR_CODE_UNSUPPORTED_BOOTSTRAP;
+ error_resp.message = "This command is unsupported for bootstrap daemon";
return false;
}
}
@@ -2666,7 +2678,7 @@ namespace cryptonote
if (!m_core.get_blockchain_storage().flush_txes_from_pool(txids))
{
res.status = "Failed to remove one or more tx(es)";
- return false;
+ return true;
}
if (failed)
@@ -2675,7 +2687,7 @@ namespace cryptonote
res.status = "Failed to parse txid";
else
res.status = "Failed to parse some of the txids";
- return false;
+ return true;
}
res.status = CORE_RPC_STATUS_OK;
@@ -2834,7 +2846,7 @@ namespace cryptonote
if (req.limit_down != -1)
{
res.status = CORE_RPC_ERROR_CODE_WRONG_PARAM;
- return false;
+ return true;
}
epee::net_utils::connection_basic::set_rate_down_limit(nodetool::default_limit_down);
}
@@ -2848,7 +2860,7 @@ namespace cryptonote
if (req.limit_up != -1)
{
res.status = CORE_RPC_ERROR_CODE_WRONG_PARAM;
- return false;
+ return true;
}
epee::net_utils::connection_basic::set_rate_up_limit(nodetool::default_limit_up);
}
@@ -2952,17 +2964,17 @@ namespace cryptonote
if (!tools::download(path.string(), res.auto_uri))
{
MERROR("Failed to download " << res.auto_uri);
- return false;
+ return true;
}
if (!tools::sha256sum(path.string(), file_hash))
{
MERROR("Failed to hash " << path);
- return false;
+ return true;
}
if (hash != epee::string_tools::pod_to_hex(file_hash))
{
MERROR("Download from " << res.auto_uri << " does not match the expected hash");
- return false;
+ return true;
}
MINFO("New version downloaded to " << path);
}
@@ -3037,6 +3049,8 @@ namespace cryptonote
if (failed)
{
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = res.status;
return false;
}
@@ -3148,7 +3162,7 @@ namespace cryptonote
if (!req.binary)
{
res.status = "Binary only call";
- return false;
+ return true;
}
try
{
@@ -3160,7 +3174,7 @@ namespace cryptonote
if (!data)
{
res.status = "Failed to get output distribution";
- return false;
+ return true;
}
res.distributions.push_back({std::move(*data), amount, "", req.binary, req.compress});
@@ -3169,7 +3183,7 @@ namespace cryptonote
catch (const std::exception &e)
{
res.status = "Failed to get output distribution";
- return false;
+ return true;
}
res.status = CORE_RPC_STATUS_OK;
@@ -3403,7 +3417,8 @@ namespace cryptonote
if (!m_rpc_payment)
{
- res.status = "Payments not enabled";
+ error_resp.code = CORE_RPC_ERROR_CODE_PAYMENTS_NOT_ENABLED;
+ error_resp.message = "Payments not enabled";
return false;
}
@@ -3431,7 +3446,8 @@ namespace cryptonote
if (!m_rpc_payment)
{
- res.status = "Payments not enabled";
+ error_resp.code = CORE_RPC_ERROR_CODE_PAYMENTS_NOT_ENABLED;
+ error_resp.message = "Payments not enabled";
return false;
}
@@ -3488,6 +3504,12 @@ namespace cryptonote
, ""
};
+ const command_line::arg_descriptor<std::string> core_rpc_server::arg_bootstrap_daemon_proxy = {
+ "bootstrap-daemon-proxy"
+ , "<ip>:<port> socks proxy to use for bootstrap daemon connections"
+ , ""
+ };
+
const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_payment_address = {
"rpc-payment-address"
, "Restrict RPC to clients sending micropayment to this address"
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 6736a6b7f..b21e43ab0 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -72,6 +72,7 @@ namespace cryptonote
static const command_line::arg_descriptor<bool> arg_rpc_ssl_allow_any_cert;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_login;
+ static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_proxy;
static const command_line::arg_descriptor<std::string> arg_rpc_payment_address;
static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_difficulty;
static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_credits;
@@ -270,8 +271,14 @@ private:
uint64_t get_block_reward(const block& blk);
bool fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash);
std::map<std::string, bool> get_public_nodes(uint32_t credits_per_hash_threshold = 0);
- bool set_bootstrap_daemon(const std::string &address, const std::string &username_password);
- bool set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials);
+ bool set_bootstrap_daemon(
+ const std::string &address,
+ const std::string &username_password,
+ const std::string &proxy);
+ bool set_bootstrap_daemon(
+ const std::string &address,
+ const boost::optional<epee::net_utils::http::login> &credentials,
+ const std::string &proxy);
enum invoke_http_mode { JON, BIN, JON_RPC };
template <typename COMMAND_TYPE>
bool use_bootstrap_daemon_if_necessary(const invoke_http_mode &mode, const std::string &command_name, const typename COMMAND_TYPE::request& req, typename COMMAND_TYPE::response& res, bool &r);
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index e7bcb5570..5ebe4f654 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -1659,11 +1659,13 @@ namespace cryptonote
std::string address;
std::string username;
std::string password;
+ std::string proxy;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
KV_SERIALIZE(username)
KV_SERIALIZE(password)
+ KV_SERIALIZE(proxy)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
diff --git a/src/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h
index 1458049ab..232df0373 100644
--- a/src/rpc/core_rpc_server_error_codes.h
+++ b/src/rpc/core_rpc_server_error_codes.h
@@ -49,6 +49,8 @@
#define CORE_RPC_ERROR_CODE_DUPLICATE_PAYMENT -17
#define CORE_RPC_ERROR_CODE_STALE_PAYMENT -18
#define CORE_RPC_ERROR_CODE_RESTRICTED -19
+#define CORE_RPC_ERROR_CODE_UNSUPPORTED_BOOTSTRAP -20
+#define CORE_RPC_ERROR_CODE_PAYMENTS_NOT_ENABLED -21
static inline const char *get_rpc_server_error_message(int64_t code)
{
@@ -72,6 +74,8 @@ static inline const char *get_rpc_server_error_message(int64_t code)
case CORE_RPC_ERROR_CODE_DUPLICATE_PAYMENT: return "Duplicate payment";
case CORE_RPC_ERROR_CODE_STALE_PAYMENT: return "Stale payment";
case CORE_RPC_ERROR_CODE_RESTRICTED: return "Parameters beyond restricted allowance";
+ case CORE_RPC_ERROR_CODE_UNSUPPORTED_BOOTSTRAP: return "Command is unsupported in bootstrap mode";
+ case CORE_RPC_ERROR_CODE_PAYMENTS_NOT_ENABLED: return "Payments not enabled";
default: MERROR("Unknown error: " << code); return "Unknown error";
}
}
diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp
index 176f11fa3..bf6584f72 100644
--- a/src/rpc/rpc_payment.cpp
+++ b/src/rpc/rpc_payment.cpp
@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/archive/portable_binary_iarchive.hpp>
+#include <boost/filesystem.hpp>
#include "cryptonote_config.h"
#include "include_base_utils.h"
#include "string_tools.h"
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h
index 80104c8f7..49ca8aa57 100644
--- a/src/serialization/binary_archive.h
+++ b/src/serialization/binary_archive.h
@@ -98,7 +98,7 @@ template <>
struct binary_archive<false> : public binary_archive_base<std::istream, false>
{
- explicit binary_archive(stream_type &s) : base_type(s) {
+ explicit binary_archive(stream_type &s) : base_type(s), varint_bug_backward_compatibility_(false) {
stream_type::pos_type pos = stream_.tellg();
stream_.seekg(0, std::ios_base::end);
eof_pos_ = stream_.tellg();
@@ -173,8 +173,13 @@ struct binary_archive<false> : public binary_archive_base<std::istream, false>
assert(stream_.tellg() <= eof_pos_);
return eof_pos_ - stream_.tellg();
}
+
+ void enable_varint_bug_backward_compatibility() { varint_bug_backward_compatibility_ = true; }
+ bool varint_bug_backward_compatibility_enabled() const { return varint_bug_backward_compatibility_; }
+
protected:
std::streamoff eof_pos_;
+ bool varint_bug_backward_compatibility_;
};
template <>
@@ -227,6 +232,8 @@ struct binary_archive<true> : public binary_archive_base<std::ostream, true>
void write_variant_tag(variant_tag_type t) {
serialize_int(t);
}
+
+ bool varint_bug_backward_compatibility_enabled() const { return false; }
};
POP_WARNINGS
diff --git a/src/serialization/container.h b/src/serialization/container.h
index d5e75bb4f..a4997c8ae 100644
--- a/src/serialization/container.h
+++ b/src/serialization/container.h
@@ -32,22 +32,27 @@ namespace serialization
{
namespace detail
{
- template <typename Archive, class T>
- bool serialize_container_element(Archive& ar, T& e)
+ template<typename T>
+ inline constexpr bool use_container_varint() noexcept
{
- return ::do_serialize(ar, e);
+ return std::is_integral<T>::value && std::is_unsigned<T>::value && sizeof(T) > 1;
}
- template <typename Archive>
- bool serialize_container_element(Archive& ar, uint32_t& e)
+ template <typename Archive, class T>
+ typename std::enable_if<!use_container_varint<T>(), bool>::type
+ serialize_container_element(Archive& ar, T& e)
{
- ar.serialize_varint(e);
- return true;
+ return ::do_serialize(ar, e);
}
- template <typename Archive>
- bool serialize_container_element(Archive& ar, uint64_t& e)
+ template<typename Archive, typename T>
+ typename std::enable_if<use_container_varint<T>(), bool>::type
+ serialize_container_element(Archive& ar, T& e)
{
+ static constexpr const bool previously_varint = std::is_same<uint64_t, T>() || std::is_same<uint32_t, T>();
+
+ if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
+ return ::do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}
diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h
index 50dd5bbd0..3f98b5101 100644
--- a/src/serialization/json_archive.h
+++ b/src/serialization/json_archive.h
@@ -84,6 +84,8 @@ struct json_archive_base
void end_variant() { end_object(); }
Stream &stream() { return stream_; }
+ bool varint_bug_backward_compatibility_enabled() const { return false; }
+
protected:
void make_indent()
{
diff --git a/src/serialization/pair.h b/src/serialization/pair.h
index 18280d837..44aafa04d 100644
--- a/src/serialization/pair.h
+++ b/src/serialization/pair.h
@@ -30,21 +30,34 @@
#pragma once
#include <memory>
+#include <boost/type_traits/make_unsigned.hpp>
#include "serialization.h"
namespace serialization
{
namespace detail
{
+ template<typename T>
+ inline constexpr bool use_pair_varint() noexcept
+ {
+ return std::is_integral<T>::value && std::is_unsigned<T>::value && sizeof(T) > 1;
+ }
+
template <typename Archive, class T>
- bool serialize_pair_element(Archive& ar, T& e)
+ typename std::enable_if<!use_pair_varint<T>(), bool>::type
+ serialize_pair_element(Archive& ar, T& e)
{
return ::do_serialize(ar, e);
}
- template <typename Archive>
- bool serialize_pair_element(Archive& ar, uint64_t& e)
+ template<typename Archive, typename T>
+ typename std::enable_if<use_pair_varint<T>(), bool>::type
+ serialize_pair_element(Archive& ar, T& e)
{
+ static constexpr const bool previously_varint = std::is_same<uint64_t, T>();
+
+ if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
+ return ::do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 2a3c33f48..da6501183 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -50,6 +50,7 @@
#include <boost/format.hpp>
#include <boost/regex.hpp>
#include <boost/range/adaptor/transformed.hpp>
+#include <boost/filesystem.hpp>
#include "include_base_utils.h"
#include "console_handler.h"
#include "common/i18n.h"
@@ -276,7 +277,7 @@ namespace
const char* USAGE_PUBLIC_NODES("public_nodes");
const char* USAGE_WELCOME("welcome");
const char* USAGE_RPC_PAYMENT_INFO("rpc_payment_info");
- const char* USAGE_START_MINING_FOR_RPC("start_mining_for_rpc");
+ const char* USAGE_START_MINING_FOR_RPC("start_mining_for_rpc [<number_of_threads>]");
const char* USAGE_STOP_MINING_FOR_RPC("stop_mining_for_rpc");
const char* USAGE_SHOW_QR_CODE("show_qr_code [<subaddress_index>]");
const char* USAGE_VERSION("version");
@@ -2361,6 +2362,24 @@ bool simple_wallet::start_mining_for_rpc(const std::vector<std::string> &args)
if (!try_connect_to_daemon())
return true;
+ bool ok = true;
+ if(args.size() >= 1)
+ {
+ uint16_t num = 0;
+ ok = string_tools::get_xtype_from_string(num, args[0]);
+ m_rpc_payment_threads = num;
+ }
+ else
+ {
+ m_rpc_payment_threads = 0;
+ }
+
+ if (!ok)
+ {
+ PRINT_USAGE(USAGE_START_MINING_FOR_RPC);
+ return true;
+ }
+
LOCK_IDLE_SCOPE();
bool payment_required;
@@ -9327,7 +9346,7 @@ bool simple_wallet::check_rpc_payment()
fail_msg_writer() << tr("Error mining to daemon: ") << error;
m_cmd_binder.print_prompt();
};
- bool ret = m_wallet->search_for_rpc_payment(target, startfunc, contfunc, foundfunc, errorfunc);
+ bool ret = m_wallet->search_for_rpc_payment(target, m_rpc_payment_threads, startfunc, contfunc, foundfunc, errorfunc);
if (!ret)
{
fail_msg_writer() << tr("Failed to start mining for RPC payment");
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index af654e0dd..8780bee1d 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -464,6 +464,7 @@ namespace cryptonote
std::atomic<bool> m_need_payment;
boost::posix_time::ptime m_last_rpc_payment_mining_time;
bool m_rpc_payment_mining_requested;
+ uint32_t m_rpc_payment_threads = 0;
bool m_daemon_rpc_payment_message_displayed;
float m_rpc_payment_hash_rate;
std::atomic<bool> m_suspend_rpc_payment_mining;
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index 24f6d37db..b28ffd64c 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -40,6 +40,7 @@
#include <vector>
#include <sstream>
#include <boost/format.hpp>
+#include <boost/filesystem.hpp>
using namespace std;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 4f923ce54..3bbd9ce0b 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -45,10 +45,8 @@
#include <sstream>
#include <unordered_map>
-#ifdef WIN32
#include <boost/locale.hpp>
#include <boost/filesystem.hpp>
-#endif
using namespace std;
using namespace cryptonote;
@@ -791,11 +789,11 @@ bool WalletImpl::close(bool store)
return result;
}
-std::string WalletImpl::seed() const
+std::string WalletImpl::seed(const std::string& seed_offset) const
{
epee::wipeable_string seed;
if (m_wallet)
- m_wallet->get_seed(seed);
+ m_wallet->get_seed(seed, seed_offset);
return std::string(seed.data(), seed.size()); // TODO
}
@@ -2104,6 +2102,11 @@ bool WalletImpl::watchOnly() const
return m_wallet->watch_only();
}
+bool WalletImpl::isDeterministic() const
+{
+ return m_wallet->is_deterministic();
+}
+
void WalletImpl::clearStatus() const
{
boost::lock_guard<boost::mutex> l(m_statusMutex);
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index e501d3943..0f3614bb4 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -81,7 +81,7 @@ public:
const std::string &device_name);
Device getDeviceType() const override;
bool close(bool store = true);
- std::string seed() const override;
+ std::string seed(const std::string& seed_offset = "") const override;
std::string getSeedLanguage() const override;
void setSeedLanguage(const std::string &arg) override;
// void setListener(Listener *) {}
@@ -129,6 +129,7 @@ public:
void setRecoveringFromDevice(bool recoveringFromDevice) override;
void setSubaddressLookahead(uint32_t major, uint32_t minor) override;
bool watchOnly() const override;
+ bool isDeterministic() const override;
bool rescanSpent() override;
NetworkType nettype() const override {return static_cast<NetworkType>(m_wallet->nettype());}
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index b40b6763f..b1cebedaf 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -446,7 +446,7 @@ struct Wallet
};
virtual ~Wallet() = 0;
- virtual std::string seed() const = 0;
+ virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual std::string getSeedLanguage() const = 0;
virtual void setSeedLanguage(const std::string &arg) = 0;
//! returns wallet status (Status_Ok | Status_Error)
@@ -627,6 +627,12 @@ struct Wallet
virtual bool watchOnly() const = 0;
/**
+ * @brief isDeterministic - checks if wallet keys are deterministic
+ * @return - true if deterministic
+ */
+ virtual bool isDeterministic() const = 0;
+
+ /**
* @brief blockChainHeight - returns current blockchain height
* @return
*/
diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp
index 87cb75fbf..b7b29420b 100644
--- a/src/wallet/message_store.cpp
+++ b/src/wallet/message_store.cpp
@@ -30,6 +30,8 @@
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/filesystem.hpp>
#include <fstream>
#include <sstream>
#include "file_io_utils.h"
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index e298eca53..0af896c76 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -5706,6 +5706,16 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
if (::serialization::serialize(ar, *this))
if (::serialization::check_stream_state(ar))
loaded = true;
+ if (!loaded)
+ {
+ std::stringstream iss;
+ iss << cache_data;
+ binary_archive<false> ar(iss);
+ ar.enable_varint_bug_backward_compatibility();
+ if (::serialization::serialize(ar, *this))
+ if (::serialization::check_stream_state(ar))
+ loaded = true;
+ }
}
catch(...) { }
@@ -6025,7 +6035,7 @@ uint64_t wallet2::balance(uint32_t index_major, bool strict) const
{
uint64_t amount = 0;
if(m_light_wallet)
- return m_light_wallet_unlocked_balance;
+ return m_light_wallet_balance;
for (const auto& i : balance_per_subaddress(index_major, strict))
amount += i.second;
return amount;
@@ -6039,7 +6049,7 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
if (time_to_unlock)
*time_to_unlock = 0;
if(m_light_wallet)
- return m_light_wallet_balance;
+ return m_light_wallet_unlocked_balance;
for (const auto& i : unlocked_balance_per_subaddress(index_major, strict))
{
amount += i.second.first;
@@ -12528,7 +12538,7 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
bool wallet2::export_key_images(const std::string &filename, bool all) const
{
PERF_TIMER(export_key_images);
- std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
const uint32_t offset = ski.first;
@@ -12555,7 +12565,7 @@ bool wallet2::export_key_images(const std::string &filename, bool all) const
}
//----------------------------------------------------------------------------------------------------
-std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
+std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
{
PERF_TIMER(export_key_images_raw);
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
@@ -13052,7 +13062,7 @@ void wallet2::import_blockchain(const std::tuple<size_t, crypto::hash, std::vect
m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx);
}
//----------------------------------------------------------------------------------------------------
-std::pair<size_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs(bool all) const
+std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs(bool all) const
{
PERF_TIMER(export_outputs);
std::vector<tools::wallet2::transfer_details> outs;
@@ -13092,7 +13102,7 @@ std::string wallet2::export_outputs_to_str(bool all) const
return magic + ciphertext;
}
//----------------------------------------------------------------------------------------------------
-size_t wallet2::import_outputs(const std::pair<size_t, std::vector<tools::wallet2::transfer_details>> &outputs)
+size_t wallet2::import_outputs(const std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> &outputs)
{
PERF_TIMER(import_outputs);
@@ -13198,7 +13208,7 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st)
try
{
std::string body(data, headerlen);
- std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs;
+ std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> outputs;
try
{
std::stringstream iss;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index e5a5136a4..e96a6b51c 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -327,7 +327,7 @@ private:
uint64_t m_block_height;
cryptonote::transaction_prefix m_tx;
crypto::hash m_txid;
- size_t m_internal_output_index;
+ uint64_t m_internal_output_index;
uint64_t m_global_output_index;
bool m_spent;
bool m_frozen;
@@ -338,7 +338,7 @@ private:
bool m_rct;
bool m_key_image_known;
bool m_key_image_request; // view wallets: we want to request it; cold wallets: it was requested
- size_t m_pk_index;
+ uint64_t m_pk_index;
cryptonote::subaddress_index m_subaddr_index;
bool m_key_image_partial;
std::vector<rct::key> m_multisig_k;
@@ -1372,9 +1372,9 @@ private:
bool verify_with_public_key(const std::string &data, const crypto::public_key &public_key, const std::string &signature) const;
// Import/Export wallet data
- std::pair<size_t, std::vector<tools::wallet2::transfer_details>> export_outputs(bool all = false) const;
+ std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> export_outputs(bool all = false) const;
std::string export_outputs_to_str(bool all = false) const;
- size_t import_outputs(const std::pair<size_t, std::vector<tools::wallet2::transfer_details>> &outputs);
+ size_t import_outputs(const std::pair<uint64_t, std::vector<tools::wallet2::transfer_details>> &outputs);
size_t import_outputs_from_str(const std::string &outputs_st);
payment_container export_payments() const;
void import_payments(const payment_container &payments);
@@ -1382,7 +1382,7 @@ private:
std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> export_blockchain() const;
void import_blockchain(const std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> &bc);
bool export_key_images(const std::string &filename, bool all = false) const;
- std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const;
+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const;
uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true);
uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent);
bool import_key_images(std::vector<crypto::key_image> key_images, size_t offset=0, boost::optional<std::unordered_set<size_t>> selected_transfers=boost::none);
@@ -1428,7 +1428,7 @@ private:
bool get_rpc_payment_info(bool mining, bool &payment_required, uint64_t &credits, uint64_t &diff, uint64_t &credits_per_hash_found, cryptonote::blobdata &hashing_blob, uint64_t &height, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, uint32_t &cookie);
bool daemon_requires_payment();
bool make_rpc_payment(uint32_t nonce, uint32_t cookie, uint64_t &credits, uint64_t &balance);
- bool search_for_rpc_payment(uint64_t credits_target, const std::function<bool(uint64_t, uint64_t)> &startfunc, const std::function<bool(unsigned)> &contfunc, const std::function<bool(uint64_t)> &foundfunc = NULL, const std::function<void(const std::string&)> &errorfunc = NULL);
+ bool search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads, const std::function<bool(uint64_t, uint64_t)> &startfunc, const std::function<bool(unsigned)> &contfunc, const std::function<bool(uint64_t)> &foundfunc = NULL, const std::function<void(const std::string&)> &errorfunc = NULL);
template<typename T> void handle_payment_changes(const T &res, std::true_type) {
if (res.status == CORE_RPC_STATUS_OK || res.status == CORE_RPC_STATUS_PAYMENT_REQUIRED)
m_rpc_payment_state.credits = res.credits;
diff --git a/src/wallet/wallet_rpc_payments.cpp b/src/wallet/wallet_rpc_payments.cpp
index 6527b1384..bf278f695 100644
--- a/src/wallet/wallet_rpc_payments.cpp
+++ b/src/wallet/wallet_rpc_payments.cpp
@@ -42,6 +42,7 @@
#include "cryptonote_basic/blobdatatype.h"
#include "common/i18n.h"
#include "common/util.h"
+#include "common/threadpool.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2.rpc_payments"
@@ -101,7 +102,7 @@ bool wallet2::make_rpc_payment(uint32_t nonce, uint32_t cookie, uint64_t &credit
return true;
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::search_for_rpc_payment(uint64_t credits_target, const std::function<bool(uint64_t, uint64_t)> &startfunc, const std::function<bool(unsigned)> &contfunc, const std::function<bool(uint64_t)> &foundfunc, const std::function<void(const std::string&)> &errorfunc)
+bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads, const std::function<bool(uint64_t, uint64_t)> &startfunc, const std::function<bool(unsigned)> &contfunc, const std::function<bool(uint64_t)> &foundfunc, const std::function<void(const std::string&)> &errorfunc)
{
bool need_payment = false;
bool payment_required;
@@ -139,49 +140,65 @@ bool wallet2::search_for_rpc_payment(uint64_t credits_target, const std::functio
continue;
}
- crypto::hash hash;
- const uint32_t local_nonce = nonce++; // wrapping's OK
- *(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(local_nonce);
- const uint8_t major_version = hashing_blob[0];
- if (major_version >= RX_BLOCK_VERSION)
- {
- const int miners = 1;
- crypto::rx_slow_hash(height, seed_height, seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data, miners, 0);
- }
- else
+ if(n_threads == 0)
+ n_threads = boost::thread::hardware_concurrency();
+
+ std::vector<crypto::hash> hash(n_threads);
+ tools::threadpool& tpool = tools::threadpool::getInstance();
+ tools::threadpool::waiter waiter(tpool);
+
+ const uint32_t local_nonce = nonce += n_threads; // wrapping's OK
+ for (size_t i = 0; i < n_threads; i++)
{
- int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0;
- crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash, cn_variant, height);
+ tpool.submit(&waiter, [&, i] {
+ *(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(local_nonce-i);
+ const uint8_t major_version = hashing_blob[0];
+ if (major_version >= RX_BLOCK_VERSION)
+ {
+ const int miners = 1;
+ crypto::rx_slow_hash(height, seed_height, seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data, miners, 0);
+ }
+ else
+ {
+ int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0;
+ crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash[i], cn_variant, height);
+ }
+ });
}
- ++n_hashes;
- if (cryptonote::check_hash(hash, diff))
+ waiter.wait();
+ n_hashes += n_threads;
+
+ for(size_t i=0; i < n_threads; i++)
{
- uint64_t credits, balance;
- try
+ if (cryptonote::check_hash(hash[i], diff))
{
- make_rpc_payment(local_nonce, cookie, credits, balance);
- if (credits != credits_per_hash_found)
+ uint64_t credits, balance;
+ try
{
- MERROR("Found nonce, but daemon did not credit us with the expected amount");
+ make_rpc_payment(local_nonce-i, cookie, credits, balance);
+ if (credits != credits_per_hash_found)
+ {
+ MERROR("Found nonce, but daemon did not credit us with the expected amount");
+ if (errorfunc)
+ errorfunc("Found nonce, but daemon did not credit us with the expected amount");
+ return false;
+ }
+ MDEBUG("Found nonce " << local_nonce-i << " at diff " << diff << ", gets us " << credits_per_hash_found << ", now " << balance << " credits");
+ if (!foundfunc(credits))
+ break;
+ }
+ catch (const tools::error::wallet_coded_rpc_error &e)
+ {
+ MWARNING("Found a local_nonce at diff " << diff << ", but failed to send it to the daemon");
if (errorfunc)
- errorfunc("Found nonce, but daemon did not credit us with the expected amount");
- return false;
+ errorfunc("Found nonce, but daemon errored out with error " + std::to_string(e.code()) + ": " + e.status() + ", continuing");
+ }
+ catch (const std::exception &e)
+ {
+ MWARNING("Found a local_nonce at diff " << diff << ", but failed to send it to the daemon");
+ if (errorfunc)
+ errorfunc("Found nonce, but daemon errored out with: '" + std::string(e.what()) + "', continuing");
}
- MDEBUG("Found nonce " << local_nonce << " at diff " << diff << ", gets us " << credits_per_hash_found << ", now " << balance << " credits");
- if (!foundfunc(credits))
- break;
- }
- catch (const tools::error::wallet_coded_rpc_error &e)
- {
- MWARNING("Found a local_nonce at diff " << diff << ", but failed to send it to the daemon");
- if (errorfunc)
- errorfunc("Found nonce, but daemon errored out with error " + std::to_string(e.code()) + ": " + e.status() + ", continuing");
- }
- catch (const std::exception &e)
- {
- MWARNING("Found a local_nonce at diff " << diff << ", but failed to send it to the daemon");
- if (errorfunc)
- errorfunc("Found nonce, but daemon errored out with: '" + std::string(e.what()) + "', continuing");
}
}
}
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index b09e24d31..b39a40b64 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -2702,7 +2702,7 @@ namespace tools
if (!m_wallet) return not_open(er);
try
{
- std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
res.offset = ski.first;
res.signed_key_images.resize(ski.second.size());
for (size_t n = 0; n < ski.second.size(); ++n)
@@ -3154,17 +3154,7 @@ namespace tools
}
std::string wallet_file = req.filename.empty() ? "" : (m_wallet_dir + "/" + req.filename);
{
- std::vector<std::string> languages;
- crypto::ElectrumWords::get_language_list(languages, false);
- std::vector<std::string>::iterator it;
-
- it = std::find(languages.begin(), languages.end(), req.language);
- if (it == languages.end())
- {
- crypto::ElectrumWords::get_language_list(languages, true);
- it = std::find(languages.begin(), languages.end(), req.language);
- }
- if (it == languages.end())
+ if (!crypto::ElectrumWords::is_valid_language(req.language))
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = "Unknown language: " + req.language;
@@ -3582,6 +3572,17 @@ namespace tools
return false;
}
+ if (!req.language.empty())
+ {
+ if (!crypto::ElectrumWords::is_valid_language(req.language))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = "The specified seed language is invalid.";
+ return false;
+ }
+ wal->set_seed_language(req.language);
+ }
+
// set blockheight if given
try
{
@@ -3725,12 +3726,7 @@ namespace tools
er.message = "Wallet was using the old seed language. You need to specify a new seed language.";
return false;
}
- std::vector<std::string> language_list;
- std::vector<std::string> language_list_en;
- crypto::ElectrumWords::get_language_list(language_list);
- crypto::ElectrumWords::get_language_list(language_list_en, true);
- if (std::find(language_list.begin(), language_list.end(), req.language) == language_list.end() &&
- std::find(language_list_en.begin(), language_list_en.end(), req.language) == language_list_en.end())
+ if (!crypto::ElectrumWords::is_valid_language(req.language))
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = "Wallet was using the old seed language, and the specified new seed language is invalid.";
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index abc7702f7..0002508a2 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -2214,6 +2214,7 @@ namespace wallet_rpc
std::string viewkey;
std::string password;
bool autosave_current;
+ std::string language;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
@@ -2223,6 +2224,7 @@ namespace wallet_rpc
KV_SERIALIZE(viewkey)
KV_SERIALIZE(password)
KV_SERIALIZE_OPT(autosave_current, true)
+ KV_SERIALIZE(language)
END_KV_SERIALIZE_MAP()
};