aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_basic/CMakeLists.txt1
-rw-r--r--src/cryptonote_basic/connection_context.cpp71
-rw-r--r--src/cryptonote_basic/connection_context.h8
-rw-r--r--src/cryptonote_core/blockchain.cpp18
-rw-r--r--src/cryptonote_core/blockchain.h4
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp9
-rw-r--r--src/cryptonote_core/cryptonote_core.h5
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl88
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp12
-rw-r--r--src/daemon/rpc_command_executor.cpp1
-rw-r--r--src/p2p/net_node.h1
-rw-r--r--src/p2p/net_node.inl16
-rw-r--r--src/rpc/core_rpc_server.cpp4
-rw-r--r--src/simplewallet/simplewallet.cpp13
-rw-r--r--src/wallet/wallet2.h1
15 files changed, 207 insertions, 45 deletions
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
index 113fd9d86..5286256c7 100644
--- a/src/cryptonote_basic/CMakeLists.txt
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -38,6 +38,7 @@ endif()
set(cryptonote_basic_sources
account.cpp
+ connection_context.cpp
cryptonote_basic_impl.cpp
cryptonote_format_utils.cpp
difficulty.cpp
diff --git a/src/cryptonote_basic/connection_context.cpp b/src/cryptonote_basic/connection_context.cpp
new file mode 100644
index 000000000..a0b8ca1f1
--- /dev/null
+++ b/src/cryptonote_basic/connection_context.cpp
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "connection_context.h"
+
+#include "cryptonote_protocol/cryptonote_protocol_defs.h"
+#include "p2p/p2p_protocol_defs.h"
+
+namespace cryptonote
+{
+ std::size_t cryptonote_connection_context::get_max_bytes(const int command) noexcept
+ {
+ switch (command)
+ {
+ case nodetool::COMMAND_HANDSHAKE_T<cryptonote::CORE_SYNC_DATA>::ID:
+ return 65536;
+ case nodetool::COMMAND_TIMED_SYNC_T<cryptonote::CORE_SYNC_DATA>::ID:
+ return 65536;
+ case nodetool::COMMAND_PING::ID:
+ return 4096;
+ case nodetool::COMMAND_REQUEST_SUPPORT_FLAGS::ID:
+ return 4096;
+ case cryptonote::NOTIFY_NEW_BLOCK::ID:
+ return 1024 * 1024 * 128; // 128 MB (max packet is a bit less than 100 MB though)
+ case cryptonote::NOTIFY_NEW_TRANSACTIONS::ID:
+ return 1024 * 1024 * 128; // 128 MB (max packet is a bit less than 100 MB though)
+ case cryptonote::NOTIFY_REQUEST_GET_OBJECTS::ID:
+ return 1024 * 1024 * 2; // 2 MB
+ case cryptonote::NOTIFY_RESPONSE_GET_OBJECTS::ID:
+ return 1024 * 1024 * 128; // 128 MB (max packet is a bit less than 100 MB though)
+ case cryptonote::NOTIFY_REQUEST_CHAIN::ID:
+ return 512 * 1024; // 512 kB
+ case cryptonote::NOTIFY_RESPONSE_CHAIN_ENTRY::ID:
+ return 1024 * 1024 * 4; // 4 MB
+ case cryptonote::NOTIFY_NEW_FLUFFY_BLOCK::ID:
+ return 1024 * 1024 * 4; // 4 MB, but it does not includes transaction data
+ case cryptonote::NOTIFY_REQUEST_FLUFFY_MISSING_TX::ID:
+ return 1024 * 1024; // 1 MB
+ case cryptonote::NOTIFY_GET_TXPOOL_COMPLEMENT::ID:
+ return 1024 * 1024 * 4; // 4 MB
+ default:
+ break;
+ };
+ return std::numeric_limits<size_t>::max();
+ }
+} // cryptonote
diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h
index 9e012f8f5..a7d688300 100644
--- a/src/cryptonote_basic/connection_context.h
+++ b/src/cryptonote_basic/connection_context.h
@@ -31,6 +31,7 @@
#pragma once
#include <unordered_set>
#include <atomic>
+#include <algorithm>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "net/net_utils_base.h"
#include "copyable_atomic.h"
@@ -38,7 +39,6 @@
namespace cryptonote
{
-
struct cryptonote_connection_context: public epee::net_utils::connection_context_base
{
cryptonote_connection_context(): m_state(state_before_handshake), m_remote_blockchain_height(0), m_last_response_height(0),
@@ -55,6 +55,12 @@ namespace cryptonote
state_normal
};
+ static constexpr int handshake_command() noexcept { return 1001; }
+ bool handshake_complete() const noexcept { return m_state != state_before_handshake; }
+
+ //! \return Maximum number of bytes permissible for `command`.
+ static size_t get_max_bytes(int command) noexcept;
+
state m_state;
std::vector<std::pair<crypto::hash, uint64_t>> m_needed_objects;
std::unordered_set<crypto::hash> m_requested_objects;
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 5b3b0527b..8ec624254 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -2758,32 +2758,44 @@ void Blockchain::flush_invalid_blocks()
m_invalid_blocks.clear();
}
//------------------------------------------------------------------
-bool Blockchain::have_block(const crypto::hash& id) const
+bool Blockchain::have_block_unlocked(const crypto::hash& id, int *where) const
{
+ // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
+ // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
+ // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
+ // lock if it is otherwise needed.
LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
if(m_db->block_exists(id))
{
LOG_PRINT_L2("block " << id << " found in main chain");
+ if (where) *where = HAVE_BLOCK_MAIN_CHAIN;
return true;
}
if(m_db->get_alt_block(id, NULL, NULL))
{
LOG_PRINT_L2("block " << id << " found in alternative chains");
+ if (where) *where = HAVE_BLOCK_ALT_CHAIN;
return true;
}
if(m_invalid_blocks.count(id))
{
LOG_PRINT_L2("block " << id << " found in m_invalid_blocks");
+ if (where) *where = HAVE_BLOCK_INVALID;
return true;
}
return false;
}
//------------------------------------------------------------------
+bool Blockchain::have_block(const crypto::hash& id, int *where) const
+{
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return have_block_unlocked(id, where);
+}
+//------------------------------------------------------------------
bool Blockchain::handle_block_to_main_chain(const block& bl, block_verification_context& bvc, bool notify/* = true*/)
{
LOG_PRINT_L3("Blockchain::" << __func__);
@@ -4716,6 +4728,8 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector
CHECK_AND_ASSERT_MES(weights.empty() || weights.size() == hashes.size(), 0, "Unexpected weights size");
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+
// easy case: height >= hashes
if (height >= m_blocks_hash_of_hashes.size() * HASH_OF_HASHES_STEP)
return hashes.size();
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 07238b719..5291f1338 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -377,10 +377,12 @@ namespace cryptonote
* for a block with the given hash
*
* @param id the hash to search for
+ * @param where the type of block, if non NULL
*
* @return true if the block is known, else false
*/
- bool have_block(const crypto::hash& id) const;
+ bool have_block_unlocked(const crypto::hash& id, int *where = NULL) const;
+ bool have_block(const crypto::hash& id, int *where = NULL) const;
/**
* @brief gets the total number of transactions on the main chain
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 507c47a51..12125fb9d 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1625,9 +1625,14 @@ namespace cryptonote
return m_mempool.get_transactions_count(include_sensitive_txes);
}
//-----------------------------------------------------------------------------------------------
- bool core::have_block(const crypto::hash& id) const
+ bool core::have_block_unlocked(const crypto::hash& id, int *where) const
{
- return m_blockchain_storage.have_block(id);
+ return m_blockchain_storage.have_block_unlocked(id, where);
+ }
+ //-----------------------------------------------------------------------------------------------
+ bool core::have_block(const crypto::hash& id, int *where) const
+ {
+ return m_blockchain_storage.have_block(id, where);
}
//-----------------------------------------------------------------------------------------------
bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) const
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 24d0f9e76..8891540a9 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -55,6 +55,8 @@
PUSH_WARNINGS
DISABLE_VS_WARNINGS(4355)
+enum { HAVE_BLOCK_MAIN_CHAIN, HAVE_BLOCK_ALT_CHAIN, HAVE_BLOCK_INVALID };
+
namespace cryptonote
{
struct test_options {
@@ -543,7 +545,8 @@ namespace cryptonote
*
* @note see Blockchain::have_block
*/
- bool have_block(const crypto::hash& id) const;
+ bool have_block_unlocked(const crypto::hash& id, int *where = NULL) const;
+ bool have_block(const crypto::hash& id, int *where = NULL) const;
/**
* @copydoc Blockchain::get_short_chain_history
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 22e87465f..b57fc0f0f 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -137,7 +137,7 @@ namespace cryptonote
CHECK_AND_ASSERT_MES_CC( context.m_callback_request_count > 0, false, "false callback fired, but context.m_callback_request_count=" << context.m_callback_request_count);
--context.m_callback_request_count;
- if(context.m_state == cryptonote_connection_context::state_synchronizing)
+ if(context.m_state == cryptonote_connection_context::state_synchronizing && context.m_last_request_time == boost::posix_time::not_a_date_time)
{
NOTIFY_REQUEST_CHAIN::request r = {};
context.m_needed_objects.clear();
@@ -549,6 +549,7 @@ namespace cryptonote
}
std::vector<tx_blob_entry> have_tx;
+ have_tx.reserve(new_block.tx_hashes.size());
// Instead of requesting missing transactions by hash like BTC,
// we do it by index (thanks to a suggestion from moneromooo) because
@@ -557,6 +558,7 @@ namespace cryptonote
// Also, remember to pepper some whitespace changes around to bother
// moneromooo ... only because I <3 him.
std::vector<uint64_t> need_tx_indices;
+ need_tx_indices.reserve(new_block.tx_hashes.size());
transaction tx;
crypto::hash tx_hash;
@@ -829,6 +831,7 @@ namespace cryptonote
}
std::vector<crypto::hash> txids;
+ txids.reserve(b.tx_hashes.size());
NOTIFY_NEW_FLUFFY_BLOCK::request fluffy_response;
fluffy_response.b.block = t_serializable_object_to_blob(b);
fluffy_response.current_blockchain_height = arg.current_blockchain_height;
@@ -2189,6 +2192,7 @@ skip:
if (span.second > 0)
{
is_next = true;
+ req.blocks.reserve(hashes.size());
for (const auto &hash: hashes)
{
req.blocks.push_back(hash);
@@ -2247,6 +2251,7 @@ skip:
if (span.second > 0)
{
is_next = true;
+ req.blocks.reserve(hashes.size());
for (const auto &hash: hashes)
{
req.blocks.push_back(hash);
@@ -2280,6 +2285,7 @@ skip:
return false;
}
+ req.blocks.reserve(req.blocks.size() + span.second);
for (size_t n = 0; n < span.second; ++n)
{
req.blocks.push_back(context.m_needed_objects[n].first);
@@ -2570,17 +2576,6 @@ skip:
return 1;
}
- std::unordered_set<crypto::hash> hashes;
- for (const auto &h: arg.m_block_ids)
- {
- if (!hashes.insert(h).second)
- {
- LOG_ERROR_CCONTEXT("sent duplicate block, dropping connection");
- drop_connection(context, true, false);
- return 1;
- }
- }
-
uint64_t n_use_blocks = m_core.prevalidate_block_hashes(arg.start_height, arg.m_block_ids, arg.m_block_weights);
if (n_use_blocks == 0 || n_use_blocks + HASH_OF_HASHES_STEP <= arg.m_block_ids.size())
{
@@ -2590,20 +2585,77 @@ skip:
}
context.m_needed_objects.clear();
+ context.m_needed_objects.reserve(arg.m_block_ids.size());
uint64_t added = 0;
std::unordered_set<crypto::hash> blocks_found;
+ bool first = true;
+ bool expect_unknown = false;
for (size_t i = 0; i < arg.m_block_ids.size(); ++i)
{
if (!blocks_found.insert(arg.m_block_ids[i]).second)
{
LOG_ERROR_CCONTEXT("Duplicate blocks in chain entry response, dropping connection");
- drop_connection(context, true, false);
+ drop_connection_with_score(context, 5, false);
return 1;
}
+ int where;
+ const bool have_block = m_core.have_block_unlocked(arg.m_block_ids[i], &where);
+ if (first)
+ {
+ if (!have_block && !m_block_queue.requested(arg.m_block_ids[i]) && !m_block_queue.have(arg.m_block_ids[i]))
+ {
+ LOG_ERROR_CCONTEXT("First block hash is unknown, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ if (!have_block)
+ expect_unknown = true;
+ }
+ if (!first)
+ {
+ // after the first, blocks may be known or unknown, but if they are known,
+ // they should be at the same height if on the main chain
+ if (have_block)
+ {
+ switch (where)
+ {
+ default:
+ case HAVE_BLOCK_INVALID:
+ LOG_ERROR_CCONTEXT("Block is invalid or known without known type, dropping connection");
+ drop_connection(context, true, false);
+ return 1;
+ case HAVE_BLOCK_MAIN_CHAIN:
+ if (expect_unknown)
+ {
+ LOG_ERROR_CCONTEXT("Block is on the main chain, but we did not expect a known block, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ if (m_core.get_block_id_by_height(arg.start_height + i) != arg.m_block_ids[i])
+ {
+ LOG_ERROR_CCONTEXT("Block is on the main chain, but not at the expected height, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ break;
+ case HAVE_BLOCK_ALT_CHAIN:
+ if (expect_unknown)
+ {
+ LOG_ERROR_CCONTEXT("Block is on the main chain, but we did not expect a known block, dropping connection");
+ drop_connection_with_score(context, 5, false);
+ return 1;
+ }
+ break;
+ }
+ }
+ else
+ expect_unknown = true;
+ }
const uint64_t block_weight = arg.m_block_weights.empty() ? 0 : arg.m_block_weights[i];
context.m_needed_objects.push_back(std::make_pair(arg.m_block_ids[i], block_weight));
if (++added == n_use_blocks)
break;
+ first = false;
}
context.m_last_response_height -= arg.m_block_ids.size() - n_use_blocks;
@@ -2634,6 +2686,7 @@ skip:
std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> fullConnections, fluffyConnections;
m_p2p->for_each_connection([this, &exclude_context, &fullConnections, &fluffyConnections](connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)
{
+ // peer_id also filters out connections before handshake
if (peer_id && exclude_context.m_connection_id != context.m_connection_id && context.m_remote_address.get_zone() == epee::net_utils::zone::public_)
{
if(m_core.fluffy_blocks_enabled() && (support_flags & P2P_SUPPORT_FLAG_FLUFFY_BLOCKS))
@@ -2794,12 +2847,15 @@ skip:
epee::string_tools::to_string_hex(context.m_pruning_seed) <<
"), score " << score << ", flush_all_spans " << flush_all_spans);
- if (score > 0)
- m_p2p->add_host_fail(context.m_remote_address, score);
-
m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
+ // copy since dropping the connection will invalidate the context, and thus the address
+ const auto remote_address = context.m_remote_address;
+
m_p2p->drop_connection(context);
+
+ if (score > 0)
+ m_p2p->add_host_fail(remote_address, score);
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index 21363972d..1e9f3e399 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -51,14 +51,6 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.p2p.tx"
-namespace
-{
- int get_command_from_message(const epee::byte_slice &msg)
- {
- return msg.size() >= sizeof(epee::levin::bucket_head2) ? SWAP32LE(((epee::levin::bucket_head2*)msg.data())->m_command) : 0;
- }
-}
-
namespace cryptonote
{
namespace levin
@@ -212,7 +204,7 @@ namespace levin
{
const epee::byte_slice blob = make_tx_payload(std::move(txs), pad, fluff);
p2p.for_connection(destination, [&blob](detail::p2p_context& context) {
- on_levin_traffic(context, true, true, false, blob.size(), get_command_from_message(blob));
+ on_levin_traffic(context, true, true, false, blob.size(), NOTIFY_NEW_TRANSACTIONS::ID);
return true;
});
return p2p.notify(NOTIFY_NEW_TRANSACTIONS::ID, epee::to_span(blob), destination);
@@ -443,7 +435,7 @@ namespace levin
zone->p2p->foreach_connection([txs, now, &zone, &source, &in_duration, &out_duration, &next_flush] (detail::p2p_context& context)
{
// When i2p/tor, only fluff to outbound connections
- if (source != context.m_connection_id && (zone->nzone == epee::net_utils::zone::public_ || !context.m_is_income))
+ if (context.handshake_complete() && source != context.m_connection_id && (zone->nzone == epee::net_utils::zone::public_ || !context.m_is_income))
{
if (context.fluff_txs.empty())
context.flush_time = now + (context.m_is_income ? in_duration() : out_duration());
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 04feb55fd..5a7d4dd4e 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -2275,6 +2275,7 @@ bool t_rpc_command_executor::sync_info()
tools::success_msg_writer() << "Next needed pruning seed: " << res.next_needed_pruning_seed;
tools::success_msg_writer() << std::to_string(res.peers.size()) << " peers";
+ tools::success_msg_writer() << "Remote Host Peer_ID State Prune_Seed Height DL kB/s, Queued Blocks / MB";
for (const auto &p: res.peers)
{
std::string address = epee::string_tools::pad_string(p.info.address, 24);
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 9fba5d636..59a6e5091 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -139,6 +139,7 @@ namespace nodetool
typedef COMMAND_HANDSHAKE_T<typename t_payload_net_handler::payload_type> COMMAND_HANDSHAKE;
typedef COMMAND_TIMED_SYNC_T<typename t_payload_net_handler::payload_type> COMMAND_TIMED_SYNC;
+ static_assert(p2p_connection_context::handshake_command() == COMMAND_HANDSHAKE::ID, "invalid handshake command id");
typedef epee::net_utils::boosted_tcp_server<epee::levin::async_protocol_handler<p2p_connection_context>> net_server;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index e99c8a090..05af22a7f 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -1224,8 +1224,9 @@ namespace nodetool
if(!handle_remote_peerlist(rsp.local_peerlist_new, context))
{
LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection.");
+ const auto remote_address = context.m_remote_address;
m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id );
- add_host_fail(context.m_remote_address);
+ add_host_fail(remote_address);
}
if(!context.m_is_income)
m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address, context.m_pruning_seed, context.m_rpc_port, context.m_rpc_credits_per_hash);
@@ -1389,7 +1390,7 @@ namespace nodetool
if(just_take_peerlist)
{
zone.m_net_server.get_config_object().close(con->m_connection_id);
- LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
+ MDEBUG(na.str() << "CONNECTION HANDSHAKED OK AND CLOSED.");
return true;
}
@@ -1451,7 +1452,7 @@ namespace nodetool
zone.m_net_server.get_config_object().close(con->m_connection_id);
- LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
+ MDEBUG(na.str() << "CONNECTION HANDSHAKED OK AND CLOSED.");
return true;
}
@@ -2156,6 +2157,7 @@ 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_));
+ CRITICAL_REGION_LOCAL(m_blocked_hosts_lock);
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);
});
@@ -2478,12 +2480,14 @@ namespace nodetool
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_handshake(int command, typename COMMAND_HANDSHAKE::request& arg, typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
{
+ // copy since dropping the connection will invalidate the context, and thus the address
+ const auto remote_address = context.m_remote_address;
+
if(arg.node_data.network_id != m_network_id)
{
-
LOG_INFO_CC(context, "WRONG NETWORK AGENT CONNECTED! id=" << arg.node_data.network_id);
drop_connection(context);
- add_host_fail(context.m_remote_address);
+ add_host_fail(remote_address);
return 1;
}
@@ -2491,7 +2495,7 @@ namespace nodetool
{
LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came not from incoming connection");
drop_connection(context);
- add_host_fail(context.m_remote_address);
+ add_host_fail(remote_address);
return 1;
}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 5b2043de6..db228dd94 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -452,7 +452,7 @@ namespace cryptonote
m_core.get_blockchain_top(res.height, top_hash);
++res.height; // turn top block height into blockchain height
res.top_block_hash = string_tools::pod_to_hex(top_hash);
- res.target_height = m_core.get_target_blockchain_height();
+ res.target_height = m_p2p.get_payload_object().is_synchronized() ? 0 : m_core.get_target_blockchain_height();
store_difficulty(m_core.get_blockchain_storage().get_difficulty_for_next_block(), res.difficulty, res.wide_difficulty, res.difficulty_top64);
res.target = m_core.get_blockchain_storage().get_difficulty_target();
res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
@@ -2913,7 +2913,7 @@ namespace cryptonote
crypto::hash top_hash;
m_core.get_blockchain_top(res.height, top_hash);
++res.height; // turn top block height into blockchain height
- res.target_height = m_core.get_target_blockchain_height();
+ res.target_height = m_p2p.get_payload_object().is_synchronized() ? 0 : m_core.get_target_blockchain_height();
res.next_needed_pruning_seed = m_p2p.get_payload_object().get_next_needed_pruning_stripe().second;
for (const auto &c: m_p2p.get_payload_object().get_connections())
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 0635520c6..dfd6adf3a 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -4765,9 +4765,14 @@ bool simple_wallet::try_connect_to_daemon(bool silent, uint32_t* version)
if (!m_wallet->check_connection(version))
{
if (!silent)
- fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_wallet->get_daemon_address() << ". " <<
- tr("Daemon either is not started or wrong port was passed. "
- "Please make sure daemon is running or change the daemon address using the 'set_daemon' command.");
+ {
+ if (m_wallet->is_offline())
+ fail_msg_writer() << tr("wallet failed to connect to daemon, because it is set to offline mode");
+ else
+ fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_wallet->get_daemon_address() << ". " <<
+ tr("Daemon either is not started or wrong port was passed. "
+ "Please make sure daemon is running or change the daemon address using the 'set_daemon' command.");
+ }
return false;
}
if (!m_allow_mismatched_daemon_version && ((*version >> 16) != CORE_RPC_VERSION_MAJOR))
@@ -9298,7 +9303,7 @@ bool simple_wallet::run()
refresh_main(0, ResetNone, true);
- m_auto_refresh_enabled = m_wallet->auto_refresh();
+ m_auto_refresh_enabled = !m_wallet->is_offline() && m_wallet->auto_refresh();
m_idle_thread = boost::thread([&]{wallet_idle_thread();});
message_writer(console_color_green, false) << "Background refresh thread started";
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 68f03db72..2e455c40c 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1549,6 +1549,7 @@ private:
void finish_rescan_bc_keep_key_images(uint64_t transfer_height, const crypto::hash &hash);
void enable_dns(bool enable) { m_use_dns = enable; }
void set_offline(bool offline = true);
+ bool is_offline() const { return m_offline; }
uint64_t credits() const { return m_rpc_payment_state.credits; }
void credit_report(uint64_t &expected_spent, uint64_t &discrepancy) const { expected_spent = m_rpc_payment_state.expected_spent; discrepancy = m_rpc_payment_state.discrepancy; }