aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/epee/include/net/net_helper.h5
-rw-r--r--contrib/epee/include/net/net_ssl.h6
-rw-r--r--contrib/epee/src/CMakeLists.txt4
-rw-r--r--contrib/epee/src/net_ssl.cpp27
-rw-r--r--external/easylogging++/ea_config.h2
-rw-r--r--external/easylogging++/easylogging++.cc11
-rw-r--r--external/easylogging++/easylogging++.h1
m---------external/randomx0
-rw-r--r--src/crypto/rx-slow-hash.c40
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl2
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp17
-rw-r--r--src/cryptonote_protocol/levin_notify.h2
-rw-r--r--src/p2p/net_node.inl13
-rw-r--r--tests/unit_tests/levin.cpp97
14 files changed, 173 insertions, 54 deletions
diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h
index 2b02eafa4..81545e502 100644
--- a/contrib/epee/include/net/net_helper.h
+++ b/contrib/epee/include/net/net_helper.h
@@ -108,11 +108,12 @@ namespace net_utils
m_ssl_options(epee::net_utils::ssl_support_t::e_ssl_support_autodetect),
m_initialized(true),
m_connected(false),
- m_deadline(m_io_service),
+ m_deadline(m_io_service, std::chrono::steady_clock::time_point::max()),
m_shutdowned(0),
m_bytes_sent(0),
m_bytes_received(0)
{
+ check_deadline();
}
/*! The first/second parameters are host/port respectively. The third
@@ -177,7 +178,7 @@ namespace net_utils
// SSL Options
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
{
- if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, addr))
+ if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, addr, timeout))
{
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
{
diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h
index 3a97dfdaf..d2c1c1a3a 100644
--- a/contrib/epee/include/net/net_ssl.h
+++ b/contrib/epee/include/net/net_ssl.h
@@ -128,7 +128,11 @@ namespace net_utils
\return True if the SSL handshake completes with peer verification
settings. */
- bool handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type, const std::string& host = {}) const;
+ bool handshake(
+ boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
+ boost::asio::ssl::stream_base::handshake_type type,
+ const std::string& host = {},
+ std::chrono::milliseconds timeout = std::chrono::seconds(15)) const;
};
// https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index 5c92e32bd..9b9fa5a47 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -29,7 +29,7 @@
add_library(epee STATIC byte_slice.cpp hex.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp
levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp)
-if (USE_READLINE AND (GNU_READLINE_FOUND OR DEPENDS AND NOT MINGW))
+if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
add_library(epee_readline STATIC readline_buffer.cpp)
endif()
@@ -62,7 +62,7 @@ target_link_libraries(epee
${OPENSSL_LIBRARIES}
${EXTRA_LIBRARIES})
-if (USE_READLINE AND (GNU_READLINE_FOUND OR DEPENDS AND NOT MINGW))
+if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
target_link_libraries(epee_readline
PUBLIC
easylogging
diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp
index 7d48d2a64..c7dca1914 100644
--- a/contrib/epee/src/net_ssl.cpp
+++ b/contrib/epee/src/net_ssl.cpp
@@ -28,9 +28,11 @@
#include <string.h>
#include <boost/asio/ssl.hpp>
+#include <boost/lambda/lambda.hpp>
#include <openssl/ssl.h>
#include <openssl/pem.h>
#include "misc_log_ex.h"
+#include "net/net_helper.h"
#include "net/net_ssl.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@@ -456,7 +458,11 @@ bool ssl_options_t::has_fingerprint(boost::asio::ssl::verify_context &ctx) const
return false;
}
-bool ssl_options_t::handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type, const std::string& host) const
+bool ssl_options_t::handshake(
+ boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
+ boost::asio::ssl::stream_base::handshake_type type,
+ const std::string& host,
+ std::chrono::milliseconds timeout) const
{
socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true));
@@ -502,8 +508,23 @@ bool ssl_options_t::handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::soc
});
}
- boost::system::error_code ec;
- socket.handshake(type, ec);
+ auto& io_service = GET_IO_SERVICE(socket);
+ boost::asio::steady_timer deadline(io_service, timeout);
+ deadline.async_wait([&socket](const boost::system::error_code& error) {
+ if (error != boost::asio::error::operation_aborted)
+ {
+ socket.next_layer().close();
+ }
+ });
+
+ boost::system::error_code ec = boost::asio::error::would_block;
+ socket.async_handshake(type, boost::lambda::var(ec) = boost::lambda::_1);
+ while (ec == boost::asio::error::would_block)
+ {
+ io_service.reset();
+ io_service.run_one();
+ }
+
if (ec)
{
MERROR("SSL handshake failed, connection dropped: " << ec.message());
diff --git a/external/easylogging++/ea_config.h b/external/easylogging++/ea_config.h
index 4fb48ce3e..5bc603391 100644
--- a/external/easylogging++/ea_config.h
+++ b/external/easylogging++/ea_config.h
@@ -9,7 +9,7 @@
#define ELPP_UTC_DATETIME
#ifdef EASYLOGGING_CC
-#if !(!defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__)
+#if !(!defined __GLIBC__ || !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__)
#define ELPP_FEATURE_CRASH_LOG
#endif
#endif
diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc
index b89fd3daf..0f83e1de2 100644
--- a/external/easylogging++/easylogging++.cc
+++ b/external/easylogging++/easylogging++.cc
@@ -683,6 +683,11 @@ void LogBuilder::convertToColoredOutput(base::type::string_t* logLine, Level lev
}
}
+void LogBuilder::setColor(Color color, bool bright) {
+ if (m_termSupportsColor)
+ el::base::utils::setConsoleColor(color, bright);
+}
+
// Logger
Logger::Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference) :
@@ -2496,11 +2501,11 @@ void DefaultLogDispatchCallback::dispatch(base::type::string_t&& rawLinePrefix,
if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) {
const el::Level level = m_data->logMessage()->level();
const el::Color color = m_data->logMessage()->color();
- el::base::utils::setConsoleColor(el::base::utils::colorFromLevel(level), false);
+ m_data->logMessage()->logger()->logBuilder()->setColor(el::base::utils::colorFromLevel(level), false);
ELPP_COUT << rawLinePrefix;
- el::base::utils::setConsoleColor(color == el::Color::Default ? el::base::utils::colorFromLevel(level): color, color != el::Color::Default);
+ m_data->logMessage()->logger()->logBuilder()->setColor(color == el::Color::Default ? el::base::utils::colorFromLevel(level): color, color != el::Color::Default);
ELPP_COUT << rawLinePayload;
- el::base::utils::setConsoleColor(el::Color::Default, false);
+ m_data->logMessage()->logger()->logBuilder()->setColor(el::Color::Default, false);
ELPP_COUT << std::flush;
}
}
diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h
index a10b0c8e6..398afd20a 100644
--- a/external/easylogging++/easylogging++.h
+++ b/external/easylogging++/easylogging++.h
@@ -2235,6 +2235,7 @@ class LogBuilder : base::NoCopy {
}
virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0;
void convertToColoredOutput(base::type::string_t* logLine, Level level, Color color);
+ void setColor(Color color, bool bright);
private:
bool m_termSupportsColor;
friend class el::base::DefaultLogDispatchCallback;
diff --git a/external/randomx b/external/randomx
-Subproject 519b9cf70540bdd996e806251cde335c8eef8ac
+Subproject 298cc77095c8992e30ecdd4ca0aa09a969a62bc
diff --git a/src/crypto/rx-slow-hash.c b/src/crypto/rx-slow-hash.c
index ada372864..59bd89d13 100644
--- a/src/crypto/rx-slow-hash.c
+++ b/src/crypto/rx-slow-hash.c
@@ -50,7 +50,7 @@
typedef struct rx_state {
CTHR_MUTEX_TYPE rs_mutex;
- char rs_hash[32];
+ char rs_hash[HASH_SIZE];
uint64_t rs_height;
randomx_cache *rs_cache;
} rx_state;
@@ -63,7 +63,6 @@ static rx_state rx_s[2] = {{CTHR_MUTEX_INIT,{0},0,0},{CTHR_MUTEX_INIT,{0},0,0}};
static randomx_dataset *rx_dataset;
static uint64_t rx_dataset_height;
static THREADV randomx_vm *rx_vm = NULL;
-static THREADV int rx_toggle;
static void local_abort(const char *msg)
{
@@ -162,8 +161,11 @@ void rx_reorg(const uint64_t split_height) {
int i;
CTHR_MUTEX_LOCK(rx_mutex);
for (i=0; i<2; i++) {
- if (split_height < rx_s[i].rs_height)
+ if (split_height <= rx_s[i].rs_height) {
+ if (rx_s[i].rs_height == rx_dataset_height)
+ rx_dataset_height = 1;
rx_s[i].rs_height = 1; /* set to an invalid seed height */
+ }
}
CTHR_MUTEX_UNLOCK(rx_mutex);
}
@@ -233,27 +235,27 @@ static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_
void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length,
char *hash, int miners, int is_alt) {
uint64_t s_height = rx_seedheight(mainheight);
- int changed = 0;
- int toggle = is_alt ? s_height : seedheight;
+ int toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) != 0;
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
rx_state *rx_sp;
randomx_cache *cache;
- toggle = (toggle & SEEDHASH_EPOCH_BLOCKS) != 0;
CTHR_MUTEX_LOCK(rx_mutex);
/* if alt block but with same seed as mainchain, no need for alt cache */
- if (is_alt && s_height == seedheight && !memcmp(rx_s[toggle].rs_hash, seedhash, sizeof(rx_s[toggle].rs_hash)))
- is_alt = 0;
-
+ if (is_alt) {
+ if (s_height == seedheight && !memcmp(rx_s[toggle].rs_hash, seedhash, HASH_SIZE))
+ is_alt = 0;
+ } else {
/* RPC could request an earlier block on mainchain */
- if (!is_alt && s_height > seedheight)
- is_alt = 1;
+ if (s_height > seedheight)
+ is_alt = 1;
+ /* miner can be ahead of mainchain */
+ else if (s_height < seedheight)
+ toggle ^= 1;
+ }
toggle ^= (is_alt != 0);
- if (toggle != rx_toggle)
- changed = 1;
- rx_toggle = toggle;
rx_sp = &rx_s[toggle];
CTHR_MUTEX_LOCK(rx_sp->rs_mutex);
@@ -273,12 +275,11 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
local_abort("Couldn't allocate RandomX cache");
}
}
- if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, sizeof(rx_sp->rs_hash))) {
- randomx_init_cache(cache, seedhash, 32);
+ if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, HASH_SIZE)) {
+ randomx_init_cache(cache, seedhash, HASH_SIZE);
rx_sp->rs_cache = cache;
rx_sp->rs_height = seedheight;
- memcpy(rx_sp->rs_hash, seedhash, sizeof(rx_sp->rs_hash));
- changed = 1;
+ memcpy(rx_sp->rs_hash, seedhash, HASH_SIZE);
}
if (rx_vm == NULL) {
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
@@ -324,7 +325,8 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
if (rx_dataset != NULL && rx_dataset_height != seedheight)
rx_initdata(cache, miners, seedheight);
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
- } else if (changed) {
+ } else {
+ /* this is a no-op if the cache hasn't changed */
randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
}
/* mainchain users can run in parallel */
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 82f9f96a0..4437c6a3a 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -2059,7 +2059,7 @@ skip:
bool t_cryptonote_protocol_handler<t_core>::on_connection_synchronized()
{
bool val_expected = false;
- if(m_synchronized.compare_exchange_strong(val_expected, true))
+ if(!m_core.is_within_compiled_block_hash_area(m_core.get_current_blockchain_height()) && m_synchronized.compare_exchange_strong(val_expected, true))
{
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
<< "You are now synchronized with the network. You may now start monero-wallet-cli." << ENDL
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index 26cd93b5a..4b41b5bfc 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -187,14 +187,15 @@ namespace levin
{
struct zone
{
- explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in)
+ explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, bool is_public)
: p2p(std::move(p2p)),
noise(std::move(noise_in)),
next_epoch(io_service),
strand(io_service),
map(),
channels(),
- connection_count(0)
+ connection_count(0),
+ is_public(is_public)
{
for (std::size_t count = 0; !noise.empty() && count < CRYPTONOTE_NOISE_CHANNELS; ++count)
channels.emplace_back(io_service);
@@ -207,6 +208,7 @@ namespace levin
net::dandelionpp::connection_map map;//!< Tracks outgoing uuid's for noise channels or Dandelion++ stems
std::deque<noise_channel> channels; //!< Never touch after init; only update elements on `noise_channel.strand`
std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time
+ const bool is_public; //!< Zone is public ipv4/ipv6 connections
};
} // detail
@@ -276,7 +278,10 @@ namespace levin
std::vector<boost::uuids::uuid> connections;
connections.reserve(connection_id_reserve_size);
zone_->p2p->foreach_connection([this, &connections] (detail::p2p_context& context) {
- if (this->source_ != context.m_connection_id)
+ /* Only send to outgoing connections when "flooding" over i2p/tor.
+ Otherwise this makes the tx linkable to a hidden service address,
+ making things linkable across connections. */
+ if (this->source_ != context.m_connection_id && (this->zone_->is_public || !context.m_is_income))
connections.emplace_back(context.m_connection_id);
return true;
});
@@ -476,8 +481,8 @@ namespace levin
};
} // anonymous
- notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise)
- : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise)))
+ notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, bool is_public)
+ : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), is_public))
{
if (!zone_->p2p)
throw std::logic_error{"cryptonote::levin::notify cannot have nullptr p2p argument"};
@@ -528,7 +533,7 @@ namespace levin
channel.next_noise.cancel();
}
- bool notify::send_txs(std::vector<cryptonote::blobdata> txs, const boost::uuids::uuid& source, const bool pad_txs)
+ bool notify::send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, const bool pad_txs)
{
if (!zone_)
return false;
diff --git a/src/cryptonote_protocol/levin_notify.h b/src/cryptonote_protocol/levin_notify.h
index 82d22680a..484243af5 100644
--- a/src/cryptonote_protocol/levin_notify.h
+++ b/src/cryptonote_protocol/levin_notify.h
@@ -86,7 +86,7 @@ namespace levin
{}
//! Construct an instance with available notification `zones`.
- explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise);
+ explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, bool is_public);
notify(const notify&) = delete;
notify(notify&&) = default;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 24c87cef8..bb77ea658 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -384,7 +384,7 @@ namespace nodetool
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
m_require_ipv4 = command_line::get_arg(vm, arg_p2p_require_ipv4);
public_zone.m_notifier = cryptonote::levin::notify{
- public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr
+ public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, true
};
if (command_line::has_arg(vm, arg_p2p_add_peer))
@@ -495,7 +495,7 @@ namespace nodetool
}
zone.m_notifier = cryptonote::levin::notify{
- zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise)
+ zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), false
};
}
@@ -670,11 +670,18 @@ namespace nodetool
std::vector<std::vector<std::string>> dns_results;
dns_results.resize(m_seed_nodes_list.size());
+ // some libc implementation provide only a very small stack
+ // for threads, e.g. musl only gives +- 80kb, which is not
+ // enough to do a resolve with unbound. we request a stack
+ // of 1 mb, which should be plenty
+ boost::thread::attributes thread_attributes;
+ thread_attributes.set_stack_size(1024*1024);
+
std::list<boost::thread> dns_threads;
uint64_t result_index = 0;
for (const std::string& addr_str : m_seed_nodes_list)
{
- boost::thread th = boost::thread([=, &dns_results, &addr_str]
+ boost::thread th = boost::thread(thread_attributes, [=, &dns_results, &addr_str]
{
MDEBUG("dns_threads[" << result_index << "] created for: " << addr_str);
// TODO: care about dnssec avail/valid
diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp
index 3188167f9..e5ca4e41e 100644
--- a/tests/unit_tests/levin.cpp
+++ b/tests/unit_tests/levin.cpp
@@ -38,6 +38,7 @@
#include "byte_slice.h"
#include "crypto/crypto.h"
#include "cryptonote_basic/connection_context.h"
+#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "cryptonote_protocol/levin_notify.h"
#include "int-util.h"
@@ -119,12 +120,13 @@ namespace
epee::levin::async_protocol_handler<cryptonote::levin::detail::p2p_context> handler_;
public:
- test_connection(boost::asio::io_service& io_service, cryptonote::levin::connections& connections, boost::uuids::random_generator& random_generator)
- : context_(),
- endpoint_(io_service),
+ test_connection(boost::asio::io_service& io_service, cryptonote::levin::connections& connections, boost::uuids::random_generator& random_generator, const bool is_incoming)
+ : endpoint_(io_service),
+ context_(),
handler_(std::addressof(endpoint_), connections, context_)
{
- const_cast<boost::uuids::uuid&>(context_.m_connection_id) = random_generator();
+ using base_type = epee::net_utils::connection_context_base;
+ static_cast<base_type&>(context_) = base_type{random_generator(), {}, is_incoming, false};
handler_.after_init_connection();
}
@@ -262,19 +264,19 @@ namespace
EXPECT_EQ(0u, receiver_.notified_size());
}
- void add_connection()
+ void add_connection(const bool is_incoming)
{
- contexts_.emplace_back(io_service_, *connections_, random_generator_);
+ contexts_.emplace_back(io_service_, *connections_, random_generator_, is_incoming);
EXPECT_TRUE(connection_ids_.emplace(contexts_.back().get_id()).second);
EXPECT_EQ(connection_ids_.size(), connections_->get_connections_count());
}
- cryptonote::levin::notify make_notifier(const std::size_t noise_size)
+ cryptonote::levin::notify make_notifier(const std::size_t noise_size, bool is_public)
{
epee::byte_slice noise = nullptr;
if (noise_size)
noise = epee::levin::make_noise_notify(noise_size);
- return cryptonote::levin::notify{io_service_, connections_, std::move(noise)};
+ return cryptonote::levin::notify{io_service_, connections_, std::move(noise), is_public};
}
boost::uuids::random_generator random_generator_;
@@ -437,10 +439,10 @@ TEST_F(levin_notify, defaulted)
TEST_F(levin_notify, flood)
{
- cryptonote::levin::notify notifier = make_notifier(0);
+ cryptonote::levin::notify notifier = make_notifier(0, true);
for (unsigned count = 0; count < 10; ++count)
- add_connection();
+ add_connection(count % 2 == 0);
{
const auto status = notifier.get_status();
@@ -500,16 +502,87 @@ TEST_F(levin_notify, flood)
}
}
+TEST_F(levin_notify, private_flood)
+{
+ cryptonote::levin::notify notifier = make_notifier(0, false);
+
+ for (unsigned count = 0; count < 10; ++count)
+ add_connection(count % 2 == 0);
+
+ {
+ const auto status = notifier.get_status();
+ EXPECT_FALSE(status.has_noise);
+ EXPECT_FALSE(status.connections_filled);
+ }
+ notifier.new_out_connection();
+ io_service_.poll();
+ {
+ const auto status = notifier.get_status();
+ EXPECT_FALSE(status.has_noise);
+ EXPECT_FALSE(status.connections_filled); // not tracked
+ }
+
+ std::vector<cryptonote::blobdata> txs(2);
+ txs[0].resize(100, 'e');
+ txs[1].resize(200, 'f');
+
+ ASSERT_EQ(10u, contexts_.size());
+ {
+ auto context = contexts_.begin();
+ EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), false));
+
+ io_service_.reset();
+ ASSERT_LT(0u, io_service_.poll());
+ EXPECT_EQ(0u, context->process_send_queue());
+ for (++context; context != contexts_.end(); ++context)
+ {
+ const bool is_incoming = ((context - contexts_.begin()) % 2 == 0);
+ EXPECT_EQ(is_incoming ? 0u : 1u, context->process_send_queue());
+ }
+
+ ASSERT_EQ(5u, receiver_.notified_size());
+ for (unsigned count = 0; count < 5; ++count)
+ {
+ auto notification = receiver_.get_notification<cryptonote::NOTIFY_NEW_TRANSACTIONS>().second;
+ EXPECT_EQ(txs, notification.txs);
+ EXPECT_TRUE(notification._.empty());
+ }
+ }
+
+ ASSERT_EQ(10u, contexts_.size());
+ {
+ auto context = contexts_.begin();
+ EXPECT_TRUE(notifier.send_txs(txs, context->get_id(), true));
+
+ io_service_.reset();
+ ASSERT_LT(0u, io_service_.poll());
+ EXPECT_EQ(0u, context->process_send_queue());
+ for (++context; context != contexts_.end(); ++context)
+ {
+ const bool is_incoming = ((context - contexts_.begin()) % 2 == 0);
+ EXPECT_EQ(is_incoming ? 0u : 1u, context->process_send_queue());
+ }
+
+ ASSERT_EQ(5u, receiver_.notified_size());
+ for (unsigned count = 0; count < 5; ++count)
+ {
+ auto notification = receiver_.get_notification<cryptonote::NOTIFY_NEW_TRANSACTIONS>().second;
+ EXPECT_EQ(txs, notification.txs);
+ EXPECT_FALSE(notification._.empty());
+ }
+ }
+}
+
TEST_F(levin_notify, noise)
{
for (unsigned count = 0; count < 10; ++count)
- add_connection();
+ add_connection(count % 2 == 0);
std::vector<cryptonote::blobdata> txs(1);
txs[0].resize(1900, 'h');
const boost::uuids::uuid incoming_id = random_generator_();
- cryptonote::levin::notify notifier = make_notifier(2048);
+ cryptonote::levin::notify notifier = make_notifier(2048, false);
{
const auto status = notifier.get_status();