aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/blockchain_db.h9
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp15
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h2
-rw-r--r--src/blockchain_db/testdb.h2
-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.h5
-rw-r--r--src/cryptonote_core/blockchain.cpp6
-rw-r--r--src/cryptonote_core/blockchain.h5
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp4
-rw-r--r--src/cryptonote_core/cryptonote_core.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h4
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl61
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp2
-rw-r--r--src/daemon/command_parser_executor.cpp48
-rw-r--r--src/daemon/command_server.cpp4
-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.inl88
-rw-r--r--src/p2p/net_node_common.h4
-rw-r--r--src/ringct/bulletproofs.cc2
-rw-r--r--src/rpc/core_rpc_server.cpp18
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h8
-rw-r--r--src/rpc/daemon_handler.cpp2
-rw-r--r--src/simplewallet/simplewallet.cpp77
-rw-r--r--src/wallet/wallet2.cpp1
28 files changed, 314 insertions, 82 deletions
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index abebb52b4..74bd72332 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1312,17 +1312,20 @@ public:
* height. The number of blocks returned is variable, based on the max_size passed.
*
* @param start_height the height of the first block
- * @param min_count the minimum number of blocks to return, if they exist
- * @param max_count the maximum number of blocks to return
+ * @param min_block_count the minimum number of blocks to return, if they exist
+ * @param max_block_count the maximum number of blocks to return
+ * @param max_tx_count the maximum number of txes to return
* @param max_size the maximum size of block/transaction data to return (will be exceeded by one blocks's worth at most, if min_count is met)
* @param blocks the returned block/transaction data
* @param pruned whether to return full or pruned tx data
* @param skip_coinbase whether to return or skip coinbase transactions (they're in blocks regardless)
* @param get_miner_tx_hash whether to calculate and return the miner (coinbase) tx hash
*
+ * The call will return at least min_block_count if possible, even if this contravenes max_tx_count
+ *
* @return true iff the blocks and transactions were found
*/
- virtual bool get_blocks_from(uint64_t start_height, size_t min_count, size_t max_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const = 0;
+ virtual bool get_blocks_from(uint64_t start_height, size_t min_block_count, size_t max_block_count, size_t max_tx_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const = 0;
/**
* @brief fetches the prunable transaction blob with the given hash
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 8aa958825..0aa2aee6f 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -3001,7 +3001,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const
if (! tx_found)
{
- LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
+ LOG_PRINT_L3("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
return false;
}
@@ -3032,7 +3032,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h, uint64_t& tx_id) const
bool ret = false;
if (get_result == MDB_NOTFOUND)
{
- LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
+ LOG_PRINT_L3("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
}
else if (get_result)
throw0(DB_ERROR(lmdb_error("DB error attempting to fetch transaction from hash", get_result).c_str()));
@@ -3171,7 +3171,7 @@ bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t coun
return true;
}
-bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_count, size_t max_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const
+bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_block_count, size_t max_block_count, size_t max_tx_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -3185,14 +3185,15 @@ bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_count, si
RCURSOR(txs_prunable);
}
- blocks.reserve(std::min<size_t>(max_count, 10000)); // guard against very large max count if only checking bytes
+ blocks.reserve(std::min<size_t>(max_block_count, 10000)); // guard against very large max count if only checking bytes
const uint64_t blockchain_height = height();
uint64_t size = 0;
+ size_t num_txes = 0;
MDB_val_copy<uint64_t> key(start_height);
MDB_val k, v, val_tx_id;
uint64_t tx_id = ~0;
MDB_cursor_op op = MDB_SET;
- for (uint64_t h = start_height; h < blockchain_height && blocks.size() < max_count && (size < max_size || blocks.size() < min_count); ++h)
+ for (uint64_t h = start_height; h < blockchain_height && blocks.size() < max_block_count && (size < max_size || blocks.size() < min_block_count); ++h)
{
MDB_cursor_op op = h == start_height ? MDB_SET : MDB_NEXT;
int result = mdb_cursor_get(m_cur_blocks, &key, &v, op);
@@ -3243,6 +3244,7 @@ bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_count, si
op = MDB_NEXT;
current_block.second.reserve(b.tx_hashes.size());
+ num_txes += b.tx_hashes.size() + (skip_coinbase ? 0 : 1);
for (const auto &tx_hash: b.tx_hashes)
{
// get pruned data
@@ -3262,6 +3264,9 @@ bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_count, si
current_block.second.push_back(std::make_pair(tx_hash, std::move(tx_blob)));
size += current_block.second.back().second.size();
}
+
+ if (blocks.size() >= min_block_count && num_txes >= max_tx_count)
+ break;
}
TXN_POSTFIX_RDONLY();
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 568882ae5..0e6d70039 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -257,7 +257,7 @@ public:
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const;
- virtual bool get_blocks_from(uint64_t start_height, size_t min_count, size_t max_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const;
+ virtual bool get_blocks_from(uint64_t start_height, size_t min_block_count, size_t max_block_count, size_t max_tx_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const;
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const;
diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h
index 9e74b33f1..e36026e07 100644
--- a/src/blockchain_db/testdb.h
+++ b/src/blockchain_db/testdb.h
@@ -70,7 +70,7 @@ public:
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const override { return false; }
- virtual bool get_blocks_from(uint64_t start_height, size_t min_count, size_t max_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const override { return false; }
+ virtual bool get_blocks_from(uint64_t start_height, size_t min_block_count, size_t max_block_count, size_t max_tx_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const override { return false; }
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const override { return false; }
virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; }
diff --git a/src/common/util.cpp b/src/common/util.cpp
index f8707d65c..445a11a75 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..9e012f8f5 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_expect_height(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..2cb28b2b1 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -124,7 +124,8 @@
#define CRYPTONOTE_MAX_FRAGMENTS 20 // ~20 * NOISE_BYTES max payload size for covert/noise send
-#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT 1000
+#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT 1000
+#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT 20000
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000
@@ -197,6 +198,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 ad27f1358..5b3b0527b 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -2701,7 +2701,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
// find split point between ours and foreign blockchain (or start at
// blockchain height <req_start_block>), and return up to max_count FULL
// blocks by reference.
-bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const
+bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
@@ -2726,8 +2726,8 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
db_rtxn_guard rtxn_guard(m_db);
total_height = get_current_blockchain_height();
- blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
- CHECK_AND_ASSERT_MES(m_db->get_blocks_from(start_height, 3, max_count, FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE, blocks, pruned, true, get_miner_tx_hash),
+ blocks.reserve(std::min(std::min(max_block_count, (size_t)10000), (size_t)(total_height - start_height)));
+ CHECK_AND_ASSERT_MES(m_db->get_blocks_from(start_height, 3, max_block_count, max_tx_count, FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE, blocks, pruned, true, get_miner_tx_hash),
false, "Error getting blocks");
return true;
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index a8e251c71..07238b719 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -465,11 +465,12 @@ namespace cryptonote
* @param total_height return-by-reference our current blockchain height
* @param start_height return-by-reference the height of the first block returned
* @param pruned whether to return full or pruned tx blobs
- * @param max_count the max number of blocks to get
+ * @param max_block_count the max number of blocks to get
+ * @param max_tx_count the max number of txes to get (it can get overshot by the last block's number of txes minus 1)
*
* @return true if a block found in common or req_start_block specified, else false
*/
- bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const;
+ bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const;
/**
* @brief retrieves a set of blocks and their transactions, and possibly other transactions
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 42b1c6c84..507c47a51 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1406,9 +1406,9 @@ namespace cryptonote
return m_blockchain_storage.find_blockchain_supplement(qblock_ids, clip_pruned, resp);
}
//-----------------------------------------------------------------------------------------------
- bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const
+ bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const
{
- return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, get_miner_tx_hash, max_count);
+ return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, get_miner_tx_hash, max_block_count, max_tx_count);
}
//-----------------------------------------------------------------------------------------------
bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 37981478c..24d0f9e76 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -564,7 +564,7 @@ namespace cryptonote
*
* @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::vector<std::pair<cryptonote::blobdata, std::vector<transaction> > >&, uint64_t&, uint64_t&, size_t) const
*/
- bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const;
+ bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const;
/**
* @copydoc Blockchain::get_tx_outputs_gindexs
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 6368f8190..28530f3e7 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -117,6 +117,8 @@ namespace cryptonote
std::string get_peers_overview() const;
std::pair<uint32_t, uint32_t> get_next_needed_pruning_stripe() const;
bool needs_new_sync_connections() const;
+ bool is_busy_syncing();
+
private:
//----------------- commands handlers ----------------------------------------------
int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context);
@@ -148,7 +150,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 2df5b74a8..22e87465f 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,17 @@ 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)
+ {
+ if (context.m_remote_blockchain_height > m_block_queue.get_next_needed_height(bc_height))
+ {
+ MERROR(context << "Nothing we can request from this peer, and we did not request anything previously");
+ return false;
+ }
+ MDEBUG(context << "Nothing to get from this peer, and it's not ahead of us, all done");
+ context.m_state = cryptonote_connection_context::state_normal;
+ return true;
+ }
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 +2208,17 @@ 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)
+ {
+ if (context.m_remote_blockchain_height > m_block_queue.get_next_needed_height(m_core.get_current_blockchain_height()))
+ {
+ MERROR(context << "Nothing we can request from this peer, and we did not request anything previously");
+ return false;
+ }
+ MDEBUG(context << "Nothing to get from this peer, and it's not ahead of us, all done");
+ context.m_state = cryptonote_connection_context::state_normal;
+ return true;
+ }
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 +2315,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:
@@ -2608,6 +2617,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;
}
//------------------------------------------------------------------------------------------------------------------------
@@ -2771,6 +2781,13 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
+ bool t_cryptonote_protocol_handler<t_core>::is_busy_syncing()
+ {
+ const boost::unique_lock<boost::mutex> sync{m_sync_lock, boost::try_to_lock};
+ return !sync.owns_lock();
+ }
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
void t_cryptonote_protocol_handler<t_core>::drop_connection_with_score(cryptonote_connection_context &context, unsigned score, bool flush_all_spans)
{
LOG_DEBUG_CC(context, "dropping connection id " << context.m_connection_id << " (pruning seed " <<
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index 318bcf4e1..21363972d 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -287,7 +287,6 @@ namespace levin
connection_count(0),
flush_callbacks(0),
nzone(zone),
- is_public(is_public),
pad_txs(pad_txs),
fluffing(false)
{
@@ -305,7 +304,6 @@ namespace levin
std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time
std::uint32_t flush_callbacks; //!< Number of active fluff flush callbacks queued
const epee::net_utils::zone nzone; //!< Zone is public ipv4/ipv6 connections, or i2p or tor
- const bool is_public; //!< Zone is public ipv4/ipv6 connections
const bool pad_txs; //!< Pad txs to the next boundary for privacy
bool fluffing; //!< Zone is in Dandelion++ fluff epoch
};
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index aac891c4a..5a7560874 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -28,6 +28,7 @@
#include "common/dns_utils.h"
#include "common/command_line.h"
+#include "net/parse.h"
#include "daemon/command_parser_executor.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@@ -657,7 +658,6 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
std::cout << "Invalid syntax: Expects one or two parameters. For more details, use the help command." << std::endl;
return true;
}
- std::string ip = args[0];
time_t seconds = P2P_IP_BLOCKTIME;
if (args.size() > 1)
{
@@ -676,7 +676,51 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
return true;
}
}
- return m_executor.ban(ip, seconds);
+ if (boost::starts_with(args[0], "@"))
+ {
+ const std::string ban_list = args[0].substr(1);
+
+ try
+ {
+ const boost::filesystem::path ban_list_path(ban_list);
+ boost::system::error_code ec;
+ if (!boost::filesystem::exists(ban_list_path, ec))
+ {
+ std::cout << "Can't find ban list file " + ban_list + " - " + ec.message() << std::endl;
+ return true;
+ }
+
+ bool ret = true;
+ 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)
+ {
+ ret &= m_executor.ban(parsed_addr->host_str(), seconds);
+ continue;
+ }
+ std::cout << "Invalid IP address or IPv4 subnet: " << line << std::endl;
+ }
+ return ret;
+ }
+ catch (const std::exception &e)
+ {
+ std::cout << "Error loading ban list: " << e.what() << std::endl;
+ return false;
+ }
+ }
+ else
+ {
+ const std::string ip = args[0];
+ return m_executor.ban(ip, seconds);
+ }
}
bool t_command_parser_executor::unban(const std::vector<std::string>& args)
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index dd5f76188..4768bb842 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -234,8 +234,8 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"ban"
, std::bind(&t_command_parser_executor::ban, &m_parser, p::_1)
- , "ban <IP> [<seconds>]"
- , "Ban a given <IP> for a given amount of <seconds>."
+ , "ban [<IP>|@<filename>] [<seconds>]"
+ , "Ban a given <IP> or list of IPs from a file for a given amount of <seconds>."
);
m_command_lookup.set_handler(
"unban"
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 8000835c4..bf053f0f2 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
@@ -804,6 +820,7 @@ namespace nodetool
"zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083",
};
}
+ return {};
case epee::net_utils::zone::i2p:
if (m_nettype == cryptonote::MAINNET)
{
@@ -811,7 +828,8 @@ namespace nodetool
"s3l6ke4ed3df466khuebb4poienoingwof7oxtbo6j4n56sghe3a.b32.i2p:18080",
"sel36x6fibfzujwvt4hf5gxolz6kd3jpvbjqg6o3ud2xtionyl2q.b32.i2p:18080"
};
- }
+ }
+ return {};
default:
break;
}
@@ -1963,6 +1981,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;
}
//-----------------------------------------------------------------------------------
@@ -2085,7 +2149,9 @@ namespace nodetool
LOG_DEBUG_CC(context, "REMOTE PEERLIST: remote peerlist size=" << peerlist_.size());
LOG_TRACE_CC(context, "REMOTE PEERLIST: " << ENDL << print_peerlist_to_string(peerlist_));
- return m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.merge_peerlist(peerlist_, [this](const peerlist_entry &pe) { return !is_addr_recently_failed(pe.adr); });
+ return m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.merge_peerlist(peerlist_, [this](const peerlist_entry &pe) {
+ return !is_addr_recently_failed(pe.adr) && is_remote_host_allowed(pe.adr);
+ });
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -2830,8 +2896,8 @@ namespace nodetool
const uint32_t index = stripe - 1;
CRITICAL_REGION_LOCAL(m_used_stripe_peers_mutex);
MINFO("adding stripe " << stripe << " peer: " << context.m_remote_address.str());
- std::remove_if(m_used_stripe_peers[index].begin(), m_used_stripe_peers[index].end(),
- [&context](const epee::net_utils::network_address &na){ return context.m_remote_address == na; });
+ m_used_stripe_peers[index].erase(std::remove_if(m_used_stripe_peers[index].begin(), m_used_stripe_peers[index].end(),
+ [&context](const epee::net_utils::network_address &na){ return context.m_remote_address == na; }), m_used_stripe_peers[index].end());
m_used_stripe_peers[index].push_back(context.m_remote_address);
}
@@ -2844,8 +2910,8 @@ namespace nodetool
const uint32_t index = stripe - 1;
CRITICAL_REGION_LOCAL(m_used_stripe_peers_mutex);
MINFO("removing stripe " << stripe << " peer: " << context.m_remote_address.str());
- std::remove_if(m_used_stripe_peers[index].begin(), m_used_stripe_peers[index].end(),
- [&context](const epee::net_utils::network_address &na){ return context.m_remote_address == na; });
+ m_used_stripe_peers[index].erase(std::remove_if(m_used_stripe_peers[index].begin(), m_used_stripe_peers[index].end(),
+ [&context](const epee::net_utils::network_address &na){ return context.m_remote_address == na; }), m_used_stripe_peers[index].end());
}
template<class t_payload_net_handler>
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/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc
index 359dfa879..a6e12c9b3 100644
--- a/src/ringct/bulletproofs.cc
+++ b/src/ringct/bulletproofs.cc
@@ -826,7 +826,7 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
proof_data.reserve(proofs.size());
size_t inv_offset = 0;
std::vector<rct::key> to_invert;
- to_invert.reserve(11 * sizeof(proofs));
+ to_invert.reserve(11 * proofs.size());
size_t max_logM = 0;
for (const Bulletproof *p: proofs)
{
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 144ffe888..5b2043de6 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.synchronized = check_core_ready();
+ res.busy_syncing = m_p2p.get_payload_object().is_busy_syncing();
res.status = CORE_RPC_STATUS_OK;
return true;
@@ -563,12 +565,12 @@ namespace cryptonote
}
}
- size_t max_blocks = COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT;
+ size_t max_blocks = COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT;
if (m_rpc_payment)
{
max_blocks = res.credits / COST_PER_BLOCK;
- if (max_blocks > COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)
- max_blocks = COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT;
+ if (max_blocks > COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT)
+ max_blocks = COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT;
if (max_blocks == 0)
{
res.status = CORE_RPC_STATUS_PAYMENT_REQUIRED;
@@ -577,7 +579,7 @@ namespace cryptonote
}
std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > > bs;
- if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, !req.no_miner_tx, max_blocks))
+ if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, !req.no_miner_tx, max_blocks, COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT))
{
res.status = "Failed";
add_host_fail(ctx);
@@ -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 10f7aac7a..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 3
+#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)
@@ -684,6 +684,7 @@ namespace cryptonote
bool was_bootstrap_ever_used;
uint64_t database_size;
bool update_available;
+ bool busy_syncing;
std::string version;
bool synchronized;
@@ -724,6 +725,7 @@ namespace cryptonote
KV_SERIALIZE(was_bootstrap_ever_used)
KV_SERIALIZE(database_size)
KV_SERIALIZE(update_available)
+ KV_SERIALIZE(busy_syncing)
KV_SERIALIZE(version)
KV_SERIALIZE(synchronized)
END_KV_SERIALIZE_MAP()
@@ -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/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp
index e256322cb..cdfc363a9 100644
--- a/src/rpc/daemon_handler.cpp
+++ b/src/rpc/daemon_handler.cpp
@@ -128,7 +128,7 @@ namespace rpc
{
std::vector<std::pair<std::pair<blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, blobdata> > > > blocks;
- if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, blocks, res.current_height, res.start_height, req.prune, true, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT))
+ if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, blocks, res.current_height, res.start_height, req.prune, true, COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT, COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT))
{
res.status = Message::STATUS_FAILED;
res.error_details = "core::find_blockchain_supplement() returned false";
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index a90bd3a39..0635520c6 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -143,6 +143,7 @@ typedef cryptonote::simple_wallet sw;
#define CREDITS_TARGET 50000
#define MAX_PAYMENT_DIFF 10000
#define MIN_PAYMENT_RATE 0.01f // per hash
+#define MAX_MNEW_ADDRESSES 1000
enum TransferType {
Transfer,
@@ -181,7 +182,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>]");
@@ -203,7 +204,7 @@ namespace
" account tag <tag_name> <account_index_1> [<account_index_2> ...]\n"
" account untag <account_index_1> [<account_index_2> ...]\n"
" account tag_description <tag_name> <description>");
- const char* USAGE_ADDRESS("address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> | device [<index>] | one-off <account> <subaddress>]");
+ const char* USAGE_ADDRESS("address [ new <label text with white spaces allowed> | mnew <amount of new addresses> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> | device [<index>] | one-off <account> <subaddress>]");
const char* USAGE_INTEGRATED_ADDRESS("integrated_address [device] [<payment_id> | <address>]");
const char* USAGE_ADDRESS_BOOK("address_book [(add (<address>|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]");
const char* USAGE_SET_VARIABLE("set <option> [<value>]");
@@ -2286,6 +2287,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;
}
@@ -3240,7 +3242,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."));
@@ -3320,7 +3322,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("address",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::print_address, _1),
tr(USAGE_ADDRESS),
- tr("If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If \"all\" is specified, the wallet shows all the existing addresses in the currently selected account. If \"new \" is specified, the wallet creates a new address with the provided label text (which can be empty). If \"label\" is specified, the wallet sets the label of the address specified by <index> to the provided label text. If \"one-off\" is specified, the address for the specified index is generated and displayed, and remembered by the wallet"));
+ tr("If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If \"all\" is specified, the wallet shows all the existing addresses in the currently selected account. If \"new \" is specified, the wallet creates a new address with the provided label text (which can be empty). If \"mnew\" is specified, the wallet creates as many new addresses as specified by the argument; the default label is set for the new addresses. If \"label\" is specified, the wallet sets the label of the address specified by <index> to the provided label text. If \"one-off\" is specified, the address for the specified index is generated and displayed, and remembered by the wallet"));
m_cmd_binder.set_handler("integrated_address",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::print_integrated_address, _1),
tr(USAGE_INTEGRATED_ADDRESS),
@@ -5527,20 +5529,50 @@ 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
{
@@ -9528,6 +9560,31 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
print_address_sub(m_wallet->get_num_subaddresses(m_current_subaddress_account) - 1);
m_wallet->device_show_address(m_current_subaddress_account, m_wallet->get_num_subaddresses(m_current_subaddress_account) - 1, boost::none);
}
+ else if (local_args[0] == "mnew")
+ {
+ local_args.erase(local_args.begin());
+ if (local_args.size() != 1)
+ {
+ fail_msg_writer() << tr("Expected exactly one argument for the amount of new addresses");
+ return true;
+ }
+ uint32_t n;
+ if (!epee::string_tools::get_xtype_from_string(n, local_args[0]))
+ {
+ fail_msg_writer() << tr("failed to parse the amount of new addresses: ") << local_args[0];
+ return true;
+ }
+ if (n > MAX_MNEW_ADDRESSES)
+ {
+ fail_msg_writer() << tr("the amount of new addresses must be lower or equal to ") << MAX_MNEW_ADDRESSES;
+ return true;
+ }
+ for (uint32_t i = 0; i < n; ++i)
+ {
+ m_wallet->add_subaddress(m_current_subaddress_account, tr("(Untitled address)"));
+ print_address_sub(m_wallet->get_num_subaddresses(m_current_subaddress_account) - 1);
+ }
+ }
else if (local_args[0] == "one-off")
{
local_args.erase(local_args.begin());
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 91b3c0535..d80335db8 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -14179,6 +14179,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};