aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md10
-rw-r--r--contrib/gitian/README.md4
-rw-r--r--src/blocks/checkpoints.datbin281028 -> 282180 bytes
-rw-r--r--src/checkpoints/checkpoints.cpp1
-rw-r--r--src/common/util.cpp11
-rw-r--r--src/common/util.h1
-rw-r--r--src/cryptonote_basic/connection_context.h3
-rw-r--r--src/cryptonote_config.h2
-rw-r--r--src/cryptonote_core/blockchain.cpp2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl55
-rw-r--r--src/daemon/command_parser_executor.cpp12
-rw-r--r--src/daemon/rpc_command_executor.cpp4
-rw-r--r--src/p2p/net_node.cpp1
-rw-r--r--src/p2p/net_node.h7
-rw-r--r--src/p2p/net_node.inl72
-rw-r--r--src/p2p/net_node_common.h4
-rw-r--r--src/rpc/core_rpc_server.cpp10
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h8
-rw-r--r--src/simplewallet/simplewallet.cpp47
-rw-r--r--src/version.cpp.in2
-rw-r--r--src/wallet/wallet2.cpp1
-rw-r--r--tests/core_proxy/core_proxy.h1
-rw-r--r--tests/unit_tests/node_server.cpp1
24 files changed, 206 insertions, 55 deletions
diff --git a/README.md b/README.md
index 5d2682299..db1ca8869 100644
--- a/README.md
+++ b/README.md
@@ -134,8 +134,8 @@ Dates are provided in the format YYYY-MM-DD.
| 1788000 | 2019-03-09 | v10 | v0.14.0.0 | v0.14.1.2 | New PoW based on Cryptonight-R, new block weight algorithm, slightly more efficient RingCT format
| 1788720 | 2019-03-10 | v11 | v0.14.0.0 | v0.14.1.2 | forbid old RingCT transaction format
| 1978433 | 2019-11-30* | v12 | v0.15.0.0 | v0.16.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs
-| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.1.7 | New CLSAG transaction format
-| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.1.7 | forbid old MLSAG transaction format
+| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.1.8 | New CLSAG transaction format
+| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.1.8 | forbid old MLSAG transaction format
| XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX |
X's indicate that these details have not been determined as of commit date.
@@ -295,7 +295,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/monero-project/monero.git
cd monero
- git checkout tags/v0.17.1.7
+ git checkout tags/v0.17.1.8
```
* Build:
@@ -412,10 +412,10 @@ application.
cd monero
```
-* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.17.1.7'. If you don't care about the version and just want binaries from master, skip this step:
+* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.17.1.8'. If you don't care about the version and just want binaries from master, skip this step:
```bash
- git checkout v0.17.1.7
+ git checkout v0.17.1.8
```
* If you are on a 64-bit system, run:
diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md
index 9f5857363..a6f68e569 100644
--- a/contrib/gitian/README.md
+++ b/contrib/gitian/README.md
@@ -126,7 +126,7 @@ Setup for LXC:
```bash
GH_USER=fluffypony
-VERSION=v0.17.1.7
+VERSION=v0.17.1.8
./gitian-build.py --setup $GH_USER $VERSION
```
@@ -182,7 +182,7 @@ If you chose to do detached signing using `--detach-sign` above (recommended), y
```bash
GH_USER=fluffypony
-VERSION=v0.17.1.7
+VERSION=v0.17.1.8
gpg --detach-sign ${VERSION}-linux/${GH_USER}/monero-linux-*-build.assert
gpg --detach-sign ${VERSION}-win/${GH_USER}/monero-win-*-build.assert
diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat
index 64bbd9dfa..e20709f7c 100644
--- a/src/blocks/checkpoints.dat
+++ b/src/blocks/checkpoints.dat
Binary files differ
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index 7a2cc0a5a..375f27555 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -244,6 +244,7 @@ namespace cryptonote
ADD_CHECKPOINT2(2235500, "3eac1a1253495733e10d00fd5e8e1639741566d91bae38bc6d3342af6b75da53", "0x10cea232ce71d23");
ADD_CHECKPOINT2(2244000, "f06b8a19a75070cd002414d9d3ce59cf6b11ed9db464c6b84d3f22abbff84fae", "0x112b3331539f585");
ADD_CHECKPOINT2(2248500, "125d0872f00b54730b1e6f925f9d211b0158dd0e254de8cefa371f2e7aba5118", "0x115c89ab7abec4a");
+ ADD_CHECKPOINT2(2257500, "99643c32f27b157c6952a67af7dbe07ca819e71df386fa9379a344686d2950cf", "0x11c2f448d4f8830");
return true;
}
diff --git a/src/common/util.cpp b/src/common/util.cpp
index 433cb4919..9dffe6ebe 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -871,10 +871,19 @@ std::string get_nix_version_display_string()
return max_concurrency;
}
+ bool is_privacy_preserving_network(const std::string &address)
+ {
+ if (boost::ends_with(address, ".onion"))
+ return true;
+ if (boost::ends_with(address, ".i2p"))
+ return true;
+ return false;
+ }
+
bool is_local_address(const std::string &address)
{
// always assume Tor/I2P addresses to be untrusted by default
- if (boost::ends_with(address, ".onion") || boost::ends_with(address, ".i2p"))
+ if (is_privacy_preserving_network(address))
{
MDEBUG("Address '" << address << "' is Tor/I2P, non local");
return false;
diff --git a/src/common/util.h b/src/common/util.h
index 0c3409ea1..6366e5cb4 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -228,6 +228,7 @@ namespace tools
unsigned get_max_concurrency();
bool is_local_address(const std::string &address);
+ bool is_privacy_preserving_network(const std::string &address);
int vercmp(const char *v0, const char *v1); // returns < 0, 0, > 0, similar to strcmp, but more human friendly than lexical - does not attempt to validate
bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash);
diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h
index dfc59631f..a735ae06b 100644
--- a/src/cryptonote_basic/connection_context.h
+++ b/src/cryptonote_basic/connection_context.h
@@ -44,7 +44,7 @@ namespace cryptonote
cryptonote_connection_context(): m_state(state_before_handshake), m_remote_blockchain_height(0), m_last_response_height(0),
m_last_request_time(boost::date_time::not_a_date_time), m_callback_request_count(0),
m_last_known_hash(crypto::null_hash), m_pruning_seed(0), m_rpc_port(0), m_rpc_credits_per_hash(0), m_anchor(false), m_score(0),
- m_expect_response(0) {}
+ m_expect_response(0), m_num_requested(0) {}
enum state
{
@@ -70,6 +70,7 @@ namespace cryptonote
int32_t m_score;
int m_expect_response;
uint64_t m_expect_height;
+ size_t m_num_requested;
};
inline std::string get_protocol_state_string(cryptonote_connection_context::state s)
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index 21f2bf81e..97706f745 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -197,6 +197,8 @@
#define RPC_CREDITS_PER_HASH_SCALE ((float)(1<<24))
+#define DNS_BLOCKLIST_LIFETIME (86400 * 8)
+
// New constants are intended to go here
namespace config
{
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 04fa1ebdc..1e6df49da 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -5376,7 +5376,7 @@ void Blockchain::cancel()
}
#if defined(PER_BLOCK_CHECKPOINT)
-static const char expected_block_hashes_hash[] = "9df68e5d89dc3789768c4701c5dea3fd32c1df22acc439c29b775eb54cefbf29";
+static const char expected_block_hashes_hash[] = "9fcc97979d033efad4d6513ff20195f0caaa20fa878a088d6b28a87402354bc1";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{
if (get_checkpoints == nullptr || !m_fast_sync)
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 0599c69f9..f06614056 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -149,7 +149,7 @@ namespace cryptonote
bool update_sync_search();
int try_add_next_blocks(cryptonote_connection_context &context);
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe);
- void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
+ size_t skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
bool request_txpool_complement(cryptonote_connection_context &context);
void hit_score(cryptonote_connection_context &context, int32_t score);
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 2e0f67486..aa0e870b6 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -409,6 +409,7 @@ namespace cryptonote
++context.m_callback_request_count;
m_p2p->request_callback(context);
MLOG_PEER_STATE("requesting callback");
+ context.m_num_requested = 0;
return true;
}
//------------------------------------------------------------------------------------------------------------------------
@@ -1990,7 +1991,7 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
- void t_cryptonote_protocol_handler<t_core>::skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const
+ size_t t_cryptonote_protocol_handler<t_core>::skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const
{
// take out blocks we already have
size_t skip = 0;
@@ -2007,6 +2008,7 @@ skip:
MDEBUG(context << "skipping " << skip << "/" << context.m_needed_objects.size() << " blocks");
context.m_needed_objects = std::vector<std::pair<crypto::hash, uint64_t>>(context.m_needed_objects.begin() + skip, context.m_needed_objects.end());
}
+ return skip;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
@@ -2060,7 +2062,11 @@ skip:
const size_t block_queue_size_threshold = m_block_download_max_size ? m_block_download_max_size : BLOCK_QUEUE_SIZE_THRESHOLD;
bool queue_proceed = nspans < BLOCK_QUEUE_NSPANS_THRESHOLD || size < block_queue_size_threshold;
// get rid of blocks we already requested, or already have
- skip_unneeded_hashes(context, true);
+ if (skip_unneeded_hashes(context, true) && context.m_needed_objects.empty() && context.m_num_requested == 0)
+ {
+ MERROR(context << "Nothing we can request from this peer, and we did not request anything previously");
+ return false;
+ }
uint64_t next_needed_height = m_block_queue.get_next_needed_height(bc_height);
uint64_t next_block_height;
if (context.m_needed_objects.empty())
@@ -2196,7 +2202,11 @@ skip:
context.m_last_response_height = 0;
goto skip;
}
- skip_unneeded_hashes(context, false);
+ if (skip_unneeded_hashes(context, false) && context.m_needed_objects.empty() && context.m_num_requested == 0)
+ {
+ MERROR(context << "Nothing we can request from this peer, and we did not request anything previously");
+ return false;
+ }
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
@@ -2293,35 +2303,22 @@ skip:
<< "/" << tools::get_pruning_stripe(span.first + span.second - 1, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES)
<< ", ours " << tools::get_pruning_stripe(m_core.get_blockchain_pruning_seed()) << ", peer stripe " << tools::get_pruning_stripe(context.m_pruning_seed));
+ context.m_num_requested += req.blocks.size();
post_notify<NOTIFY_REQUEST_GET_OBJECTS>(req, context);
MLOG_PEER_STATE("requesting objects");
return true;
}
- // if we're still around, we might be at a point where the peer is pruned, so we could either
- // drop it to make space for other peers, or ask for a span further down the line
- const uint32_t next_stripe = get_next_needed_pruning_stripe().first;
- const uint32_t peer_stripe = tools::get_pruning_stripe(context.m_pruning_seed);
- const uint32_t local_stripe = tools::get_pruning_stripe(m_core.get_blockchain_pruning_seed());
- if (!(m_sync_pruned_blocks && peer_stripe == local_stripe) && next_stripe && peer_stripe && next_stripe != peer_stripe)
+ // we can do nothing, so drop this peer to make room for others unless we think we've downloaded all we need
+ const uint64_t blockchain_height = m_core.get_current_blockchain_height();
+ if (std::max(blockchain_height, m_block_queue.get_next_needed_height(blockchain_height)) >= m_core.get_target_blockchain_height())
{
- // at this point, we have to either close the connection, or start getting blocks past the
- // current point, or become dormant
- MDEBUG(context << "this peer is pruned at seed " << epee::string_tools::to_string_hex(context.m_pruning_seed) <<
- ", next stripe needed is " << next_stripe);
- if (!context.m_is_income)
- {
- if (should_drop_connection(context, next_stripe))
- {
- m_p2p->add_used_stripe_peer(context);
- return false; // drop outgoing connections
- }
- }
- // we'll get back stuck waiting for the go ahead
context.m_state = cryptonote_connection_context::state_normal;
MLOG_PEER_STATE("Nothing to do for now, switching to normal state");
return true;
}
+ MLOG_PEER_STATE("We can download nothing from this peer, dropping");
+ return false;
}
skip:
@@ -2562,6 +2559,8 @@ skip:
}
std::unordered_set<crypto::hash> hashes;
+ uint64_t height = arg.start_height;
+ const uint64_t blockchain_height = m_core.get_current_blockchain_height();
for (const auto &h: arg.m_block_ids)
{
if (!hashes.insert(h).second)
@@ -2570,6 +2569,17 @@ skip:
drop_connection(context, true, false);
return 1;
}
+ if (height < blockchain_height)
+ {
+ const crypto::hash block_in_chain = m_core.get_block_id_by_height(height);
+ if ((height < context.m_expect_height - 1 && block_in_chain == h) || (height == context.m_expect_height - 1 && block_in_chain != h))
+ {
+ LOG_ERROR_CCONTEXT("sent existing block " << h << " at height " << height << ", expected height was " << context.m_expect_height << ", dropping connection");
+ drop_connection(context, true, false);
+ return 1;
+ }
+ }
+ ++height;
}
uint64_t n_use_blocks = m_core.prevalidate_block_hashes(arg.start_height, arg.m_block_ids, arg.m_block_weights);
@@ -2608,6 +2618,7 @@ skip:
if (arg.total_height > m_core.get_target_blockchain_height())
m_core.set_target_blockchain_height(arg.total_height);
+ context.m_num_requested = 0;
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 6695c3ecd..ab1a8881e 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -620,13 +620,19 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
std::ifstream ifs(ban_list_path.string());
for (std::string line; std::getline(ifs, line); )
{
+ auto subnet = net::get_ipv4_subnet_address(line);
+ if (subnet)
+ {
+ ret &= m_executor.ban(subnet->str(), seconds);
+ continue;
+ }
const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(line, 0);
- if (!parsed_addr)
+ if (parsed_addr)
{
- std::cout << "Invalid IP address: " << line << " - " << parsed_addr.error() << std::endl;
+ ret &= m_executor.ban(parsed_addr->host_str(), seconds);
continue;
}
- ret &= m_executor.ban(parsed_addr->host_str(), seconds);
+ std::cout << "Invalid IP address or IPv4 subnet: " << line << std::endl;
}
return ret;
}
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index adaa9bc0e..04feb55fd 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -191,6 +191,9 @@ bool t_rpc_command_executor::print_peer_list(bool white, bool gray, size_t limit
cryptonote::COMMAND_RPC_GET_PEER_LIST::response res;
std::string failure_message = "Couldn't retrieve peer list";
+
+ req.include_blocked = true;
+
if (m_is_rpc)
{
if (!m_rpc_client->rpc_request(req, res, "/get_peer_list", failure_message.c_str()))
@@ -237,6 +240,7 @@ bool t_rpc_command_executor::print_peer_list_stats() {
std::string failure_message = "Couldn't retrieve peer list";
req.public_only = false;
+ req.include_blocked = true;
if (m_is_rpc)
{
diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp
index aee1fa593..8dd551d1e 100644
--- a/src/p2p/net_node.cpp
+++ b/src/p2p/net_node.cpp
@@ -149,6 +149,7 @@ namespace nodetool
const command_line::arg_descriptor<std::string> arg_ban_list = {"ban-list", "Specify ban list file, one IP address per line"};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
const command_line::arg_descriptor<bool> arg_no_sync = {"no-sync", "Don't synchronize the blockchain with other peers", false};
+ const command_line::arg_descriptor<bool> arg_enable_dns_blocklist = {"enable-dns-blocklist", "Apply realtime blocklist from DNS", false};
const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
const command_line::arg_descriptor<std::string> arg_igd = {"igd", "UPnP port mapping (disabled, enabled, delayed)", "delayed"};
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index f13b36a82..9fba5d636 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -287,7 +287,7 @@ namespace nodetool
uint32_t get_max_out_public_peers() const;
void change_max_in_public_peers(size_t count);
uint32_t get_max_in_public_peers() const;
- virtual bool block_host(epee::net_utils::network_address address, time_t seconds = P2P_IP_BLOCKTIME);
+ virtual bool block_host(epee::net_utils::network_address address, time_t seconds = P2P_IP_BLOCKTIME, bool add_only = false);
virtual bool unblock_host(const epee::net_utils::network_address &address);
virtual bool block_subnet(const epee::net_utils::ipv4_network_subnet &subnet, time_t seconds = P2P_IP_BLOCKTIME);
virtual bool unblock_subnet(const epee::net_utils::ipv4_network_subnet &subnet);
@@ -369,6 +369,7 @@ namespace nodetool
bool peer_sync_idle_maker();
bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false);
bool do_peer_timed_sync(const epee::net_utils::connection_context_base& context, peerid_type peer_id);
+ bool update_dns_blocklist();
bool make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist);
bool make_new_connection_from_peerlist(network_zone& zone, bool use_white_list);
@@ -474,6 +475,7 @@ namespace nodetool
epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval;
epee::math_helper::once_a_time_seconds<60> m_gray_peerlist_housekeeping_interval;
epee::math_helper::once_a_time_seconds<3600, false> m_incoming_connections_interval;
+ epee::math_helper::once_a_time_seconds<7000> m_dns_blocklist_interval;
std::list<epee::net_utils::network_address> m_priority_peers;
std::vector<epee::net_utils::network_address> m_exclusive_peers;
@@ -512,6 +514,8 @@ namespace nodetool
cryptonote::network_type m_nettype;
epee::net_utils::ssl_support_t m_ssl_support;
+
+ bool m_enable_dns_blocklist;
};
const int64_t default_limit_up = P2P_DEFAULT_LIMIT_RATE_UP; // kB/s
@@ -533,6 +537,7 @@ namespace nodetool
extern const command_line::arg_descriptor<std::string> arg_ban_list;
extern const command_line::arg_descriptor<bool> arg_p2p_hide_my_port;
extern const command_line::arg_descriptor<bool> arg_no_sync;
+ extern const command_line::arg_descriptor<bool> arg_enable_dns_blocklist;
extern const command_line::arg_descriptor<bool> arg_no_igd;
extern const command_line::arg_descriptor<std::string> arg_igd;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 128d17155..b8b937de4 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -37,6 +37,7 @@
#include <boost/optional/optional.hpp>
#include <boost/thread/thread.hpp>
#include <boost/uuid/uuid_io.hpp>
+#include <boost/algorithm/string.hpp>
#include <atomic>
#include <functional>
#include <limits>
@@ -120,6 +121,7 @@ namespace nodetool
command_line::add_arg(desc, arg_ban_list);
command_line::add_arg(desc, arg_p2p_hide_my_port);
command_line::add_arg(desc, arg_no_sync);
+ command_line::add_arg(desc, arg_enable_dns_blocklist);
command_line::add_arg(desc, arg_no_igd);
command_line::add_arg(desc, arg_igd);
command_line::add_arg(desc, arg_out_peers);
@@ -226,7 +228,7 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::block_host(epee::net_utils::network_address addr, time_t seconds)
+ bool node_server<t_payload_net_handler>::block_host(epee::net_utils::network_address addr, time_t seconds, bool add_only)
{
if(!addr.is_blockable())
return false;
@@ -240,7 +242,11 @@ namespace nodetool
else
limit = now + seconds;
const std::string host_str = addr.host_str();
- m_blocked_hosts[host_str] = limit;
+ auto it = m_blocked_hosts.find(host_str);
+ if (it == m_blocked_hosts.end())
+ m_blocked_hosts[host_str] = limit;
+ else if (it->second < limit || !add_only)
+ it->second = limit;
// drop any connection to that address. This should only have to look into
// the zone related to the connection, but really make sure everything is
@@ -260,6 +266,8 @@ namespace nodetool
peerlist_entry pe{};
pe.adr = addr;
zone.second.m_peerlist.remove_from_peer_white(pe);
+ zone.second.m_peerlist.remove_from_peer_gray(pe);
+ zone.second.m_peerlist.remove_from_peer_anchor(addr);
for (const auto &c: conns)
zone.second.m_net_server.get_config_object().close(c);
@@ -481,13 +489,19 @@ namespace nodetool
std::istringstream iss(banned_ips);
for (std::string line; std::getline(iss, line); )
{
+ auto subnet = net::get_ipv4_subnet_address(line);
+ if (subnet)
+ {
+ block_subnet(*subnet, std::numeric_limits<time_t>::max());
+ continue;
+ }
const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(line, 0);
- if (!parsed_addr)
+ if (parsed_addr)
{
- MERROR("Invalid IP address: " << line << " - " << parsed_addr.error());
+ block_host(*parsed_addr, std::numeric_limits<time_t>::max());
continue;
}
- block_host(*parsed_addr, std::numeric_limits<time_t>::max());
+ MERROR("Invalid IP address or IPv4 subnet: " << line);
}
}
@@ -497,6 +511,8 @@ namespace nodetool
if (command_line::has_arg(vm, arg_no_sync))
m_payload_handler.set_no_sync(true);
+ m_enable_dns_blocklist = command_line::get_arg(vm, arg_enable_dns_blocklist);
+
if ( !set_max_out_peers(public_zone, command_line::get_arg(vm, arg_out_peers) ) )
return false;
else
@@ -1971,6 +1987,52 @@ namespace nodetool
m_gray_peerlist_housekeeping_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::gray_peerlist_housekeeping, this));
m_peerlist_store_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::store_config, this));
m_incoming_connections_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::check_incoming_connections, this));
+ m_dns_blocklist_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::update_dns_blocklist, this));
+ return true;
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::update_dns_blocklist()
+ {
+ if (!m_enable_dns_blocklist)
+ return true;
+ if (m_nettype != cryptonote::MAINNET)
+ return true;
+
+ static const std::vector<std::string> dns_urls = {
+ "blocklist.moneropulse.se"
+ , "blocklist.moneropulse.org"
+ , "blocklist.moneropulse.net"
+ , "blocklist.moneropulse.no"
+ , "blocklist.moneropulse.fr"
+ , "blocklist.moneropulse.de"
+ , "blocklist.moneropulse.ch"
+ };
+
+ std::vector<std::string> records;
+ if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls))
+ return true;
+
+ unsigned good = 0, bad = 0;
+ for (const auto& record : records)
+ {
+ std::vector<std::string> ips;
+ boost::split(ips, record, boost::is_any_of(";"));
+ for (const auto &ip: ips)
+ {
+ const expect<epee::net_utils::network_address> parsed_addr = net::get_network_address(ip, 0);
+ if (!parsed_addr)
+ {
+ MWARNING("Invalid IP address from DNS blocklist: " << ip << " - " << parsed_addr.error());
+ ++bad;
+ continue;
+ }
+ block_host(*parsed_addr, DNS_BLOCKLIST_LIFETIME, true);
+ ++good;
+ }
+ }
+ if (good > 0)
+ MINFO(good << " addresses added to the blocklist");
return true;
}
//-----------------------------------------------------------------------------------
diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h
index f1490a0db..0da758ad4 100644
--- a/src/p2p/net_node_common.h
+++ b/src/p2p/net_node_common.h
@@ -58,7 +58,7 @@ namespace nodetool
virtual uint64_t get_public_connections_count()=0;
virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0;
virtual bool for_connection(const boost::uuids::uuid&, std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0;
- virtual bool block_host(epee::net_utils::network_address address, time_t seconds = 0)=0;
+ virtual bool block_host(epee::net_utils::network_address address, time_t seconds = 0, bool add_only = false)=0;
virtual bool unblock_host(const epee::net_utils::network_address &address)=0;
virtual std::map<std::string, time_t> get_blocked_hosts()=0;
virtual std::map<epee::net_utils::ipv4_network_subnet, time_t> get_blocked_subnets()=0;
@@ -108,7 +108,7 @@ namespace nodetool
{
return false;
}
- virtual bool block_host(epee::net_utils::network_address address, time_t seconds)
+ virtual bool block_host(epee::net_utils::network_address address, time_t seconds, bool add_only)
{
return true;
}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index e6ad93312..1abeb3903 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -190,6 +190,7 @@ namespace cryptonote
request.gray = true;
request.white = true;
+ request.include_blocked = false;
if (!on_get_public_nodes(request, response) || response.status != CORE_RPC_STATUS_OK)
{
return {};
@@ -499,6 +500,7 @@ namespace cryptonote
res.update_available = restricted ? false : m_core.is_update_available();
res.version = restricted ? "" : MONERO_VERSION_FULL;
res.busy_syncing = m_p2p.get_payload_object().is_busy_syncing();
+ res.synchronized = check_core_ready();
res.status = CORE_RPC_STATUS_OK;
return true;
@@ -1382,6 +1384,8 @@ namespace cryptonote
for (auto & entry : white_list)
{
+ if (!req.include_blocked && m_p2p.is_host_blocked(entry.adr, NULL))
+ continue;
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(),
entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port, entry.rpc_credits_per_hash);
@@ -1394,6 +1398,8 @@ namespace cryptonote
for (auto & entry : gray_list)
{
+ if (!req.include_blocked && m_p2p.is_host_blocked(entry.adr, NULL))
+ continue;
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(),
entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port, entry.rpc_credits_per_hash);
@@ -1412,8 +1418,10 @@ namespace cryptonote
{
RPC_TRACKER(get_public_nodes);
+ COMMAND_RPC_GET_PEER_LIST::request peer_list_req;
COMMAND_RPC_GET_PEER_LIST::response peer_list_res;
- const bool success = on_get_peer_list(COMMAND_RPC_GET_PEER_LIST::request(), peer_list_res, ctx);
+ peer_list_req.include_blocked = req.include_blocked;
+ const bool success = on_get_peer_list(peer_list_req, peer_list_res, ctx);
res.status = peer_list_res.status;
if (!success)
{
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 21e981eae..bbcb27f1c 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -88,7 +88,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 3
-#define CORE_RPC_VERSION_MINOR 4
+#define CORE_RPC_VERSION_MINOR 5
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -686,6 +686,7 @@ namespace cryptonote
bool update_available;
bool busy_syncing;
std::string version;
+ bool synchronized;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_response_base)
@@ -726,6 +727,7 @@ namespace cryptonote
KV_SERIALIZE(update_available)
KV_SERIALIZE(busy_syncing)
KV_SERIALIZE(version)
+ KV_SERIALIZE(synchronized)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -1193,10 +1195,12 @@ namespace cryptonote
struct request_t: public rpc_request_base
{
bool public_only;
+ bool include_blocked;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_request_base)
KV_SERIALIZE_OPT(public_only, true)
+ KV_SERIALIZE_OPT(include_blocked, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1242,11 +1246,13 @@ namespace cryptonote
{
bool gray;
bool white;
+ bool include_blocked;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_request_base)
KV_SERIALIZE_OPT(gray, false)
KV_SERIALIZE_OPT(white, true)
+ KV_SERIALIZE_OPT(include_blocked, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 7b26d21fb..9f4fabc02 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -181,7 +181,7 @@ namespace
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
const char* USAGE_START_MINING("start_mining [<number_of_threads>] [bg_mining] [ignore_battery]");
- const char* USAGE_SET_DAEMON("set_daemon <host>[:<port>] [trusted|untrusted]");
+ const char* USAGE_SET_DAEMON("set_daemon <host>[:<port>] [trusted|untrusted|this-is-probably-a-spy-node]");
const char* USAGE_SHOW_BALANCE("balance [detail]");
const char* USAGE_INCOMING_TRANSFERS("incoming_transfers [available|unavailable] [verbose] [uses] [index=<N1>[,<N2>[,...]]]");
const char* USAGE_PAYMENTS("payments <PID_1> [<PID_2> ... <PID_N>]");
@@ -2286,6 +2286,7 @@ bool simple_wallet::public_nodes(const std::vector<std::string> &args)
{
fail_msg_writer() << tr("Error retrieving public node list: ") << e.what();
}
+ message_writer(console_color_red, true) << tr("Most of these nodes are probably spies. You should not use them unless connecting via Tor or I2P");
return true;
}
@@ -3222,7 +3223,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("set_daemon",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::set_daemon, _1),
tr(USAGE_SET_DAEMON),
- tr("Set another daemon to connect to."));
+ tr("Set another daemon to connect to. If it's not yours, it'll probably spy on you."));
m_cmd_binder.set_handler("save_bc",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::save_bc, _1),
tr("Save the current blockchain data."));
@@ -5507,21 +5508,51 @@ bool simple_wallet::set_daemon(const std::vector<std::string>& args)
} else {
daemon_url = args[0];
}
- LOCK_IDLE_SCOPE();
- m_wallet->init(daemon_url);
+ epee::net_utils::http::url_content parsed{};
+ const bool r = epee::net_utils::parse_url(daemon_url, parsed);
+ if (!r)
+ {
+ fail_msg_writer() << tr("Failed to parse address");
+ return true;
+ }
+
+ std::string trusted;
if (args.size() == 2)
{
if (args[1] == "trusted")
- m_wallet->set_trusted_daemon(true);
+ trusted = "trusted";
else if (args[1] == "untrusted")
- m_wallet->set_trusted_daemon(false);
+ trusted = "untrusted";
+ else if (args[1] == "this-is-probably-a-spy-node")
+ trusted = "this-is-probably-a-spy-node";
else
{
- fail_msg_writer() << tr("Expected trusted or untrusted, got ") << args[1] << ": assuming untrusted";
- m_wallet->set_trusted_daemon(false);
+ fail_msg_writer() << tr("Expected trusted, untrusted or this-is-probably-a-spy-node got ") << args[1];
+ return true;
}
}
+
+ if (!tools::is_privacy_preserving_network(parsed.host) && !tools::is_local_address(parsed.host))
+ {
+ if (trusted == "untrusted" || trusted == "")
+ {
+ fail_msg_writer() << tr("This is not Tor/I2P address, and is not a trusted daemon.");
+ fail_msg_writer() << tr("Either use your own trusted node, connect via Tor or I2P, or pass this-is-probably-a-spy-node and be spied on.");
+ return true;
+ }
+
+ if (parsed.schema != "https")
+ message_writer(console_color_red) << tr("Warning: connecting to a non-local daemon without SSL, passive adversaries will be able to spy on you.");
+ }
+
+ LOCK_IDLE_SCOPE();
+ m_wallet->init(daemon_url);
+
+ if (!trusted.empty())
+ {
+ m_wallet->set_trusted_daemon(trusted == "trusted");
+ }
else
{
m_wallet->set_trusted_daemon(false);
diff --git a/src/version.cpp.in b/src/version.cpp.in
index e32b902c2..e54900507 100644
--- a/src/version.cpp.in
+++ b/src/version.cpp.in
@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
-#define DEF_MONERO_VERSION "0.17.1.7"
+#define DEF_MONERO_VERSION "0.17.1.8"
#define DEF_MONERO_RELEASE_NAME "Oxygen Orion"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 299e427ce..a004c8855 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -14159,6 +14159,7 @@ std::vector<cryptonote::public_node> wallet2::get_public_nodes(bool white_only)
req.white = true;
req.gray = !white_only;
+ req.include_blocked = false;
{
const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h
index ecfcc18ae..ebc3a89c2 100644
--- a/tests/core_proxy/core_proxy.h
+++ b/tests/core_proxy/core_proxy.h
@@ -112,5 +112,6 @@ namespace tests
bool prune_blockchain(uint32_t pruning_seed) const { return true; }
bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) { return false; }
bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const { return false; }
+ crypto::hash get_block_id_by_height(uint64_t height) const { return crypto::null_hash; }
};
}
diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp
index 0191e5aa4..0569d3748 100644
--- a/tests/unit_tests/node_server.cpp
+++ b/tests/unit_tests/node_server.cpp
@@ -93,6 +93,7 @@ public:
bool has_block_weights(uint64_t height, uint64_t nblocks) const { return false; }
bool get_txpool_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) { return false; }
bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const { return false; }
+ crypto::hash get_block_id_by_height(uint64_t height) const { return crypto::null_hash; }
void stop() {}
};