Merge branch 'develop' into remove-process-confirmed

# Conflicts:
#	nano/node/blockprocessor.cpp
#	nano/node/blockprocessor.hpp
#	nano/node/confirming_set.cpp
#	nano/node/election.cpp
#	nano/node/node.cpp
This commit is contained in:
Piotr Wójcik 2024-10-28 13:06:55 +01:00
commit e0518c38e2
180 changed files with 2902 additions and 2305 deletions

View file

@ -16,7 +16,7 @@ jobs:
- { name: ASAN, ignore_errors: false, leak_check: false } - { name: ASAN, ignore_errors: false, leak_check: false }
- { name: ASAN_INT, ignore_errors: true, leak_check: false } - { name: ASAN_INT, ignore_errors: true, leak_check: false }
- { name: TSAN, ignore_errors: false } - { name: TSAN, ignore_errors: false }
- { name: LEAK, ignore_errors: true, leak_check: true } - { name: LEAK, ignore_errors: false, leak_check: true }
exclude: exclude:
# Bug when running with TSAN: "ThreadSanitizer: CHECK failed: sanitizer_deadlock_detector" # Bug when running with TSAN: "ThreadSanitizer: CHECK failed: sanitizer_deadlock_detector"
- BACKEND: rocksdb - BACKEND: rocksdb

View file

@ -466,6 +466,8 @@ set(BOOST_MODULE_LIBS
ratio ratio
rational rational
regex regex
scope
scope_exit
serialization serialization
smart_ptr smart_ptr
spirit spirit

View file

@ -48,7 +48,6 @@ cmake \
-DNANO_WARN_TO_ERR=ON \ -DNANO_WARN_TO_ERR=ON \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
-DQt5_DIR=${qt_dir} \ -DQt5_DIR=${qt_dir} \
${BACKTRACE:-} \
${SANITIZERS:-} \ ${SANITIZERS:-} \
.. ..

View file

@ -66,7 +66,6 @@ cmake \
-DCI_VERSION_PRE_RELEASE=${CI_VERSION_PRE_RELEASE:-OFF} \ -DCI_VERSION_PRE_RELEASE=${CI_VERSION_PRE_RELEASE:-OFF} \
${CMAKE_SANITIZER:-} \ ${CMAKE_SANITIZER:-} \
${CMAKE_QT_DIR:-} \ ${CMAKE_QT_DIR:-} \
${CMAKE_BACKTRACE:-} \
${SRC} ${SRC}
number_of_processors() { number_of_processors() {

View file

@ -35,10 +35,13 @@ add_executable(
network_filter.cpp network_filter.cpp
network_functions.cpp network_functions.cpp
node.cpp node.cpp
numbers.cpp
object_stream.cpp object_stream.cpp
observer_set.cpp
optimistic_scheduler.cpp optimistic_scheduler.cpp
processing_queue.cpp processing_queue.cpp
processor_service.cpp processor_service.cpp
random_pool.cpp
rep_crawler.cpp rep_crawler.cpp
receivable.cpp receivable.cpp
peer_history.cpp peer_history.cpp
@ -51,10 +54,10 @@ add_executable(
socket.cpp socket.cpp
system.cpp system.cpp
telemetry.cpp telemetry.cpp
thread_pool.cpp
throttle.cpp throttle.cpp
toml.cpp toml.cpp
timer.cpp timer.cpp
uint256_union.cpp
unchecked_map.cpp unchecked_map.cpp
utility.cpp utility.cpp
vote_cache.cpp vote_cache.cpp

View file

@ -1232,8 +1232,8 @@ TEST (active_elections, activate_inactive)
ASSERT_TIMELY_EQ (5s, 1, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_quorum, nano::stat::dir::out)); ASSERT_TIMELY_EQ (5s, 1, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_quorum, nano::stat::dir::out));
ASSERT_ALWAYS_EQ (50ms, 0, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_conf_height, nano::stat::dir::out)); ASSERT_ALWAYS_EQ (50ms, 0, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_conf_height, nano::stat::dir::out));
// The first block was not active so no activation takes place // Cementing of send should activate open
ASSERT_FALSE (node.active.active (open->qualified_root ()) || node.block_confirmed_or_being_confirmed (open->hash ())); ASSERT_TIMELY (5s, node.active.active (open->qualified_root ()));
} }
TEST (active_elections, list_active) TEST (active_elections, list_active)
@ -1308,7 +1308,9 @@ TEST (active_elections, vacancy)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (nano::dev::genesis->hash ())) .work (*system.work.generate (nano::dev::genesis->hash ()))
.build (); .build ();
node.active.vacancy_update = [&updated] () { updated = true; }; node.active.vacancy_updated.add ([&updated] () {
updated = true;
});
ASSERT_EQ (nano::block_status::progress, node.process (send)); ASSERT_EQ (nano::block_status::progress, node.process (send));
ASSERT_EQ (1, node.active.vacancy (nano::election_behavior::priority)); ASSERT_EQ (1, node.active.vacancy (nano::election_behavior::priority));
ASSERT_EQ (0, node.active.size ()); ASSERT_EQ (0, node.active.size ());

View file

@ -314,10 +314,10 @@ TEST (block_store, pending_iterator)
auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants);
ASSERT_TRUE (!store->init_error ()); ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_write ()); auto transaction (store->tx_begin_write ());
ASSERT_EQ (store->pending.end (), store->pending.begin (transaction)); ASSERT_EQ (store->pending.end (transaction), store->pending.begin (transaction));
store->pending.put (transaction, nano::pending_key (1, 2), { 2, 3, nano::epoch::epoch_1 }); store->pending.put (transaction, nano::pending_key (1, 2), { 2, 3, nano::epoch::epoch_1 });
auto current (store->pending.begin (transaction)); auto current (store->pending.begin (transaction));
ASSERT_NE (store->pending.end (), current); ASSERT_NE (store->pending.end (transaction), current);
nano::pending_key key1 (current->first); nano::pending_key key1 (current->first);
ASSERT_EQ (nano::account (1), key1.account); ASSERT_EQ (nano::account (1), key1.account);
ASSERT_EQ (nano::block_hash (2), key1.hash); ASSERT_EQ (nano::block_hash (2), key1.hash);
@ -411,7 +411,7 @@ TEST (block_store, empty_accounts)
ASSERT_TRUE (!store->init_error ()); ASSERT_TRUE (!store->init_error ());
auto transaction (store->tx_begin_read ()); auto transaction (store->tx_begin_read ());
auto begin (store->account.begin (transaction)); auto begin (store->account.begin (transaction));
auto end (store->account.end ()); auto end (store->account.end (transaction));
ASSERT_EQ (end, begin); ASSERT_EQ (end, begin);
} }
@ -498,7 +498,7 @@ TEST (block_store, one_account)
store->confirmation_height.put (transaction, account, { 20, nano::block_hash (15) }); store->confirmation_height.put (transaction, account, { 20, nano::block_hash (15) });
store->account.put (transaction, account, { hash, account, hash, 42, 100, 200, nano::epoch::epoch_0 }); store->account.put (transaction, account, { hash, account, hash, 42, 100, 200, nano::epoch::epoch_0 });
auto begin (store->account.begin (transaction)); auto begin (store->account.begin (transaction));
auto end (store->account.end ()); auto end (store->account.end (transaction));
ASSERT_NE (end, begin); ASSERT_NE (end, begin);
ASSERT_EQ (account, nano::account (begin->first)); ASSERT_EQ (account, nano::account (begin->first));
nano::account_info info (begin->second); nano::account_info info (begin->second);
@ -567,7 +567,7 @@ TEST (block_store, two_account)
store->confirmation_height.put (transaction, account2, { 30, nano::block_hash (20) }); store->confirmation_height.put (transaction, account2, { 30, nano::block_hash (20) });
store->account.put (transaction, account2, { hash2, account2, hash2, 84, 200, 400, nano::epoch::epoch_0 }); store->account.put (transaction, account2, { hash2, account2, hash2, 84, 200, 400, nano::epoch::epoch_0 });
auto begin (store->account.begin (transaction)); auto begin (store->account.begin (transaction));
auto end (store->account.end ()); auto end (store->account.end (transaction));
ASSERT_NE (end, begin); ASSERT_NE (end, begin);
ASSERT_EQ (account1, nano::account (begin->first)); ASSERT_EQ (account1, nano::account (begin->first));
nano::account_info info1 (begin->second); nano::account_info info1 (begin->second);
@ -787,7 +787,7 @@ TEST (block_store, large_iteration)
std::unordered_set<nano::account> accounts2; std::unordered_set<nano::account> accounts2;
nano::account previous{}; nano::account previous{};
auto transaction (store->tx_begin_read ()); auto transaction (store->tx_begin_read ());
for (auto i (store->account.begin (transaction, 0)), n (store->account.end ()); i != n; ++i) for (auto i (store->account.begin (transaction, 0)), n (store->account.end (transaction)); i != n; ++i)
{ {
nano::account current (i->first); nano::account current (i->first);
ASSERT_GT (current.number (), previous.number ()); ASSERT_GT (current.number (), previous.number ());
@ -798,7 +798,7 @@ TEST (block_store, large_iteration)
// Reverse iteration // Reverse iteration
std::unordered_set<nano::account> accounts3; std::unordered_set<nano::account> accounts3;
previous = std::numeric_limits<nano::uint256_t>::max (); previous = std::numeric_limits<nano::uint256_t>::max ();
for (auto i (store->account.rbegin (transaction)), n (store->account.end ()); i != n; --i) for (auto i (store->account.rbegin (transaction)), n (store->account.rend (transaction)); i != n; ++i)
{ {
nano::account current (i->first); nano::account current (i->first);
ASSERT_LT (current.number (), previous.number ()); ASSERT_LT (current.number (), previous.number ());
@ -1253,8 +1253,8 @@ TEST (block_store, online_weight)
{ {
auto transaction (store->tx_begin_write ()); auto transaction (store->tx_begin_write ());
ASSERT_EQ (0, store->online_weight.count (transaction)); ASSERT_EQ (0, store->online_weight.count (transaction));
ASSERT_EQ (store->online_weight.end (), store->online_weight.begin (transaction)); ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.begin (transaction));
ASSERT_EQ (store->online_weight.end (), store->online_weight.rbegin (transaction)); ASSERT_EQ (store->online_weight.rend (transaction), store->online_weight.rbegin (transaction));
store->online_weight.put (transaction, 1, 2); store->online_weight.put (transaction, 1, 2);
store->online_weight.put (transaction, 3, 4); store->online_weight.put (transaction, 3, 4);
} }
@ -1262,22 +1262,22 @@ TEST (block_store, online_weight)
auto transaction (store->tx_begin_write ()); auto transaction (store->tx_begin_write ());
ASSERT_EQ (2, store->online_weight.count (transaction)); ASSERT_EQ (2, store->online_weight.count (transaction));
auto item (store->online_weight.begin (transaction)); auto item (store->online_weight.begin (transaction));
ASSERT_NE (store->online_weight.end (), item); ASSERT_NE (store->online_weight.end (transaction), item);
ASSERT_EQ (1, item->first); ASSERT_EQ (1, item->first);
ASSERT_EQ (2, item->second.number ()); ASSERT_EQ (2, item->second.number ());
auto item_last (store->online_weight.rbegin (transaction)); auto item_last (store->online_weight.rbegin (transaction));
ASSERT_NE (store->online_weight.end (), item_last); ASSERT_NE (store->online_weight.rend (transaction), item_last);
ASSERT_EQ (3, item_last->first); ASSERT_EQ (3, item_last->first);
ASSERT_EQ (4, item_last->second.number ()); ASSERT_EQ (4, item_last->second.number ());
store->online_weight.del (transaction, 1); store->online_weight.del (transaction, 1);
ASSERT_EQ (1, store->online_weight.count (transaction)); ASSERT_EQ (1, store->online_weight.count (transaction));
ASSERT_EQ (store->online_weight.begin (transaction), store->online_weight.rbegin (transaction)); ASSERT_EQ (*store->online_weight.begin (transaction), *store->online_weight.rbegin (transaction));
store->online_weight.del (transaction, 3); store->online_weight.del (transaction, 3);
} }
auto transaction (store->tx_begin_read ()); auto transaction (store->tx_begin_read ());
ASSERT_EQ (0, store->online_weight.count (transaction)); ASSERT_EQ (0, store->online_weight.count (transaction));
ASSERT_EQ (store->online_weight.end (), store->online_weight.begin (transaction)); ASSERT_EQ (store->online_weight.end (transaction), store->online_weight.begin (transaction));
ASSERT_EQ (store->online_weight.end (), store->online_weight.rbegin (transaction)); ASSERT_EQ (store->online_weight.rend (transaction), store->online_weight.rbegin (transaction));
} }
TEST (block_store, pruned_blocks) TEST (block_store, pruned_blocks)

View file

@ -2406,7 +2406,7 @@ TEST (ledger, state_account)
.work (*pool.generate (nano::dev::genesis->hash ())) .work (*pool.generate (nano::dev::genesis->hash ()))
.build (); .build ();
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1)); ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send1));
ASSERT_EQ (nano::dev::genesis_key.pub, ledger.any.block_account (transaction, send1->hash ())); ASSERT_EQ (nano::dev::genesis_key.pub, ledger.any.block_account (transaction, send1->hash ()).value ());
} }
TEST (ledger, state_send_receive) TEST (ledger, state_send_receive)
@ -5464,7 +5464,7 @@ TEST (ledger, migrate_lmdb_to_rocksdb)
ASSERT_TRUE (rocksdb_store.pending.get (rocksdb_transaction, nano::pending_key (nano::dev::genesis_key.pub, send->hash ()))); ASSERT_TRUE (rocksdb_store.pending.get (rocksdb_transaction, nano::pending_key (nano::dev::genesis_key.pub, send->hash ())));
for (auto i = rocksdb_store.online_weight.begin (rocksdb_transaction); i != rocksdb_store.online_weight.end (); ++i) for (auto i = rocksdb_store.online_weight.begin (rocksdb_transaction); i != rocksdb_store.online_weight.end (rocksdb_transaction); ++i)
{ {
ASSERT_EQ (i->first, 100); ASSERT_EQ (i->first, 100);
ASSERT_EQ (i->second, 2); ASSERT_EQ (i->second, 2);

View file

@ -1024,14 +1024,13 @@ TEST (network, loopback_channel)
auto & node2 = *system.nodes[1]; auto & node2 = *system.nodes[1];
nano::transport::inproc::channel channel1 (node1, node1); nano::transport::inproc::channel channel1 (node1, node1);
ASSERT_EQ (channel1.get_type (), nano::transport::transport_type::loopback); ASSERT_EQ (channel1.get_type (), nano::transport::transport_type::loopback);
ASSERT_EQ (channel1.get_endpoint (), node1.network.endpoint ()); ASSERT_EQ (channel1.get_remote_endpoint (), node1.network.endpoint ());
ASSERT_EQ (channel1.get_tcp_endpoint (), nano::transport::map_endpoint_to_tcp (node1.network.endpoint ()));
ASSERT_EQ (channel1.get_network_version (), node1.network_params.network.protocol_version); ASSERT_EQ (channel1.get_network_version (), node1.network_params.network.protocol_version);
ASSERT_EQ (channel1.get_node_id (), node1.node_id.pub); ASSERT_EQ (channel1.get_node_id (), node1.node_id.pub);
ASSERT_EQ (channel1.get_node_id_optional ().value_or (0), node1.node_id.pub); ASSERT_EQ (channel1.get_node_id_optional ().value_or (0), node1.node_id.pub);
nano::transport::inproc::channel channel2 (node2, node2); nano::transport::inproc::channel channel2 (node2, node2);
++node1.network.port; ++node1.network.port;
ASSERT_NE (channel1.get_endpoint (), node1.network.endpoint ()); ASSERT_NE (channel1.get_remote_endpoint (), node1.network.endpoint ());
} }
// Ensure the network filters messages with the incorrect magic number // Ensure the network filters messages with the incorrect magic number

View file

@ -2703,7 +2703,7 @@ TEST (node, peer_history_restart)
ASSERT_TIMELY (10s, !node2->network.empty ()); ASSERT_TIMELY (10s, !node2->network.empty ());
// Confirm that the peers match with the endpoints we are expecting // Confirm that the peers match with the endpoints we are expecting
auto list (node2->network.list (2)); auto list (node2->network.list (2));
ASSERT_EQ (node1->network.endpoint (), list[0]->get_endpoint ()); ASSERT_EQ (node1->network.endpoint (), list[0]->get_remote_endpoint ());
ASSERT_EQ (1, node2->network.size ()); ASSERT_EQ (1, node2->network.size ());
system.stop_node (*node2); system.stop_node (*node2);
} }
@ -2726,7 +2726,7 @@ TEST (node, peer_history_restart)
ASSERT_TIMELY (10s, !node3->network.empty ()); ASSERT_TIMELY (10s, !node3->network.empty ());
// Confirm that the peers match with the endpoints we are expecting // Confirm that the peers match with the endpoints we are expecting
auto list (node3->network.list (2)); auto list (node3->network.list (2));
ASSERT_EQ (node1->network.endpoint (), list[0]->get_endpoint ()); ASSERT_EQ (node1->network.endpoint (), list[0]->get_remote_endpoint ());
ASSERT_EQ (1, node3->network.size ()); ASSERT_EQ (1, node3->network.size ());
system.stop_node (*node3); system.stop_node (*node3);
} }
@ -2788,11 +2788,11 @@ TEST (node, bidirectional_tcp)
ASSERT_EQ (1, node2->network.size ()); ASSERT_EQ (1, node2->network.size ());
auto list1 (node1->network.list (1)); auto list1 (node1->network.list (1));
ASSERT_EQ (nano::transport::transport_type::tcp, list1[0]->get_type ()); ASSERT_EQ (nano::transport::transport_type::tcp, list1[0]->get_type ());
ASSERT_NE (node2->network.endpoint (), list1[0]->get_endpoint ()); // Ephemeral port ASSERT_NE (node2->network.endpoint (), list1[0]->get_remote_endpoint ()); // Ephemeral port
ASSERT_EQ (node2->node_id.pub, list1[0]->get_node_id ()); ASSERT_EQ (node2->node_id.pub, list1[0]->get_node_id ());
auto list2 (node2->network.list (1)); auto list2 (node2->network.list (1));
ASSERT_EQ (nano::transport::transport_type::tcp, list2[0]->get_type ()); ASSERT_EQ (nano::transport::transport_type::tcp, list2[0]->get_type ());
ASSERT_EQ (node1->network.endpoint (), list2[0]->get_endpoint ()); ASSERT_EQ (node1->network.endpoint (), list2[0]->get_remote_endpoint ());
ASSERT_EQ (node1->node_id.pub, list2[0]->get_node_id ()); ASSERT_EQ (node1->node_id.pub, list2[0]->get_node_id ());
// Test block propagation from node 1 // Test block propagation from node 1
nano::keypair key; nano::keypair key;

View file

@ -1,27 +1,192 @@
#include <nano/crypto_lib/random_pool.hpp> #include <nano/lib/numbers.hpp>
#include <nano/secure/common.hpp> #include <nano/secure/common.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <boost/container_hash/hash.hpp>
#include <thread> #include <thread>
#include <unordered_set>
TEST (numbers, identity)
{
ASSERT_EQ (1, nano::uint128_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint256_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint512_union (1).number ().convert_to<uint8_t> ());
}
namespace namespace
{ {
template <typename Union, typename Bound> template <typename Type>
void assert_union_types (); void check_operator_less_than (Type lhs, Type rhs)
{
ASSERT_TRUE (lhs < rhs);
ASSERT_FALSE (rhs < lhs);
ASSERT_FALSE (lhs < lhs);
ASSERT_FALSE (rhs < rhs);
}
template <typename Union, typename Bound> template <typename Type>
void test_union_operator_less_than (); void test_operator_less_than ()
{
using underlying_t = typename Type::underlying_type;
template <typename Num> // Small
void check_operator_less_than (Num lhs, Num rhs); check_operator_less_than (Type{ 123 }, Type{ 124 });
check_operator_less_than (Type{ 124 }, Type{ 125 });
template <typename Union, typename Bound> // Medium
void test_union_operator_greater_than (); check_operator_less_than (Type{ std::numeric_limits<uint16_t>::max () - 1 }, Type{ std::numeric_limits<uint16_t>::max () + 1 });
check_operator_less_than (Type{ std::numeric_limits<uint32_t>::max () - 12345678 }, Type{ std::numeric_limits<uint32_t>::max () - 123456 });
template <typename Num> // Large
void check_operator_greater_than (Num lhs, Num rhs); check_operator_less_than (Type{ std::numeric_limits<uint64_t>::max () - 555555555555 }, Type{ std::numeric_limits<uint64_t>::max () - 1 });
// Boundary values
check_operator_less_than (Type{ std::numeric_limits<underlying_t>::min () }, Type{ std::numeric_limits<underlying_t>::max () });
}
template <typename Type>
void check_operator_greater_than (Type lhs, Type rhs)
{
ASSERT_TRUE (lhs > rhs);
ASSERT_FALSE (rhs > lhs);
ASSERT_FALSE (lhs > lhs);
ASSERT_FALSE (rhs > rhs);
}
template <typename Type>
void test_operator_greater_than ()
{
using underlying_t = typename Type::underlying_type;
// Small
check_operator_greater_than (Type{ 124 }, Type{ 123 });
check_operator_greater_than (Type{ 125 }, Type{ 124 });
// Medium
check_operator_greater_than (Type{ std::numeric_limits<uint16_t>::max () + 1 }, Type{ std::numeric_limits<uint16_t>::max () - 1 });
check_operator_greater_than (Type{ std::numeric_limits<uint32_t>::max () - 123456 }, Type{ std::numeric_limits<uint32_t>::max () - 12345678 });
// Large
check_operator_greater_than (Type{ std::numeric_limits<uint64_t>::max () - 1 }, Type{ std::numeric_limits<uint64_t>::max () - 555555555555 });
// Boundary values
check_operator_greater_than (Type{ std::numeric_limits<underlying_t>::max () }, Type{ std::numeric_limits<underlying_t>::min () });
}
template <typename Type>
void test_comparison ()
{
test_operator_less_than<Type> ();
test_operator_greater_than<Type> ();
}
}
TEST (numbers, comparison)
{
test_comparison<nano::uint128_union> ();
test_comparison<nano::uint256_union> ();
test_comparison<nano::uint512_union> ();
test_comparison<nano::block_hash> ();
test_comparison<nano::public_key> ();
test_comparison<nano::hash_or_account> ();
test_comparison<nano::link> ();
test_comparison<nano::root> ();
test_comparison<nano::raw_key> ();
test_comparison<nano::wallet_id> ();
test_comparison<nano::qualified_root> ();
}
namespace
{
template <typename Type, template <typename> class Hash>
void test_hashing ()
{
Hash<Type> hash;
using underlying_t = typename Type::underlying_type;
// Basic equality tests
ASSERT_EQ (hash (Type{}), hash (Type{}));
ASSERT_EQ (hash (Type{ 123 }), hash (Type{ 123 }));
// Basic inequality tests
ASSERT_NE (hash (Type{ 123 }), hash (Type{ 124 }));
ASSERT_NE (hash (Type{ 0 }), hash (Type{ 1 }));
// Boundary value tests
constexpr auto min_val = std::numeric_limits<underlying_t>::min ();
constexpr auto max_val = std::numeric_limits<underlying_t>::max ();
// Min/Max tests
ASSERT_EQ (hash (Type{ min_val }), hash (Type{ min_val }));
ASSERT_EQ (hash (Type{ max_val }), hash (Type{ max_val }));
ASSERT_NE (hash (Type{ min_val }), hash (Type{ max_val }));
// Near boundary tests
ASSERT_NE (hash (Type{ min_val }), hash (Type{ min_val + 1 }));
ASSERT_NE (hash (Type{ max_val }), hash (Type{ max_val - 1 }));
ASSERT_NE (hash (Type{ min_val + 1 }), hash (Type{ max_val }));
ASSERT_NE (hash (Type{ max_val - 1 }), hash (Type{ min_val }));
// Common value tests
std::vector<underlying_t> common_values = {
0, // Zero
1, // One
42, // Common test value
0xFF, // Byte boundary
0xFFFF, // Word boundary
min_val, // Minimum
max_val, // Maximum
max_val / 2, // Middle value
min_val + (max_val / 2) // Offset middle
};
// Test all common values against each other
for (size_t i = 0; i < common_values.size (); ++i)
{
for (size_t j = i + 1; j < common_values.size (); ++j)
{
if (common_values[i] != common_values[j])
{
ASSERT_NE (hash (Type{ common_values[i] }), hash (Type{ common_values[j] }));
}
else
{
ASSERT_EQ (hash (Type{ common_values[i] }), hash (Type{ common_values[j] }));
}
}
}
}
}
TEST (numbers, hashing)
{
// Using std::hash
test_hashing<nano::uint128_union, std::hash> ();
test_hashing<nano::uint256_union, std::hash> ();
test_hashing<nano::uint512_union, std::hash> ();
test_hashing<nano::block_hash, std::hash> ();
test_hashing<nano::public_key, std::hash> ();
test_hashing<nano::hash_or_account, std::hash> ();
test_hashing<nano::link, std::hash> ();
test_hashing<nano::root, std::hash> ();
test_hashing<nano::raw_key, std::hash> ();
test_hashing<nano::wallet_id, std::hash> ();
test_hashing<nano::qualified_root, std::hash> ();
// Using boost::hash
test_hashing<nano::uint128_union, boost::hash> ();
test_hashing<nano::uint256_union, boost::hash> ();
test_hashing<nano::uint512_union, boost::hash> ();
test_hashing<nano::block_hash, boost::hash> ();
test_hashing<nano::public_key, boost::hash> ();
test_hashing<nano::hash_or_account, boost::hash> ();
test_hashing<nano::link, boost::hash> ();
test_hashing<nano::root, boost::hash> ();
test_hashing<nano::raw_key, boost::hash> ();
test_hashing<nano::wallet_id, boost::hash> ();
test_hashing<nano::qualified_root, boost::hash> ();
} }
TEST (uint128_union, decode_dec) TEST (uint128_union, decode_dec)
@ -64,16 +229,6 @@ TEST (uint128_union, decode_dec_overflow)
ASSERT_TRUE (error); ASSERT_TRUE (error);
} }
TEST (uint128_union, operator_less_than)
{
test_union_operator_less_than<nano::uint128_union, nano::uint128_t> ();
}
TEST (uint128_union, operator_greater_than)
{
test_union_operator_greater_than<nano::uint128_union, nano::uint128_t> ();
}
struct test_punct : std::moneypunct<char> struct test_punct : std::moneypunct<char>
{ {
pattern do_pos_format () const pattern do_pos_format () const
@ -149,13 +304,6 @@ TEST (uint128_union, decode_decimal)
ASSERT_EQ (1230 * nano::Knano_ratio, amount.number ()); ASSERT_EQ (1230 * nano::Knano_ratio, amount.number ());
} }
TEST (unions, identity)
{
ASSERT_EQ (1, nano::uint128_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint256_union (1).number ().convert_to<uint8_t> ());
ASSERT_EQ (1, nano::uint512_union (1).number ().convert_to<uint8_t> ());
}
TEST (uint256_union, key_encryption) TEST (uint256_union, key_encryption)
{ {
nano::keypair key1; nano::keypair key1;
@ -449,11 +597,6 @@ TEST (uint256_union, bounds)
ASSERT_TRUE (key.decode_account (bad2)); ASSERT_TRUE (key.decode_account (bad2));
} }
TEST (uint256_union, operator_less_than)
{
test_union_operator_less_than<nano::uint256_union, nano::uint256_t> ();
}
TEST (uint64_t, parse) TEST (uint64_t, parse)
{ {
uint64_t value0 (1); uint64_t value0 (1);
@ -504,114 +647,4 @@ TEST (uint512_union, hash)
ASSERT_NE (h (x1), h (x2)); ASSERT_NE (h (x1), h (x2));
} }
} }
} }
namespace
{
template <typename Union, typename Bound>
void assert_union_types ()
{
static_assert ((std::is_same<Union, nano::uint128_union>::value && std::is_same<Bound, nano::uint128_t>::value) || (std::is_same<Union, nano::uint256_union>::value && std::is_same<Bound, nano::uint256_t>::value) || (std::is_same<Union, nano::uint512_union>::value && std::is_same<Bound, nano::uint512_t>::value),
"Union type needs to be consistent with the lower/upper Bound type");
}
template <typename Union, typename Bound>
void test_union_operator_less_than ()
{
assert_union_types<Union, Bound> ();
// Small
check_operator_less_than (Union (123), Union (124));
check_operator_less_than (Union (124), Union (125));
// Medium
check_operator_less_than (Union (std::numeric_limits<uint16_t>::max () - 1), Union (std::numeric_limits<uint16_t>::max () + 1));
check_operator_less_than (Union (std::numeric_limits<uint32_t>::max () - 12345678), Union (std::numeric_limits<uint32_t>::max () - 123456));
// Large
check_operator_less_than (Union (std::numeric_limits<uint64_t>::max () - 555555555555), Union (std::numeric_limits<uint64_t>::max () - 1));
// Boundary values
check_operator_less_than (Union (std::numeric_limits<Bound>::min ()), Union (std::numeric_limits<Bound>::max ()));
}
template <typename Num>
void check_operator_less_than (Num lhs, Num rhs)
{
ASSERT_TRUE (lhs < rhs);
ASSERT_FALSE (rhs < lhs);
ASSERT_FALSE (lhs < lhs);
ASSERT_FALSE (rhs < rhs);
}
template <typename Union, typename Bound>
void test_union_operator_greater_than ()
{
assert_union_types<Union, Bound> ();
// Small
check_operator_greater_than (Union (124), Union (123));
check_operator_greater_than (Union (125), Union (124));
// Medium
check_operator_greater_than (Union (std::numeric_limits<uint16_t>::max () + 1), Union (std::numeric_limits<uint16_t>::max () - 1));
check_operator_greater_than (Union (std::numeric_limits<uint32_t>::max () - 123456), Union (std::numeric_limits<uint32_t>::max () - 12345678));
// Large
check_operator_greater_than (Union (std::numeric_limits<uint64_t>::max () - 1), Union (std::numeric_limits<uint64_t>::max () - 555555555555));
// Boundary values
check_operator_greater_than (Union (std::numeric_limits<Bound>::max ()), Union (std::numeric_limits<Bound>::min ()));
}
template <typename Num>
void check_operator_greater_than (Num lhs, Num rhs)
{
ASSERT_TRUE (lhs > rhs);
ASSERT_FALSE (rhs > lhs);
ASSERT_FALSE (lhs > lhs);
ASSERT_FALSE (rhs > rhs);
}
}
TEST (random_pool, multithreading)
{
std::vector<std::thread> threads;
for (auto i = 0; i < 100; ++i)
{
threads.emplace_back ([] () {
nano::uint256_union number;
nano::random_pool::generate_block (number.bytes.data (), number.bytes.size ());
});
}
for (auto & i : threads)
{
i.join ();
}
}
// Test that random 64bit numbers are within the given range
TEST (random_pool, generate_word64)
{
int occurrences[10] = { 0 };
for (auto i = 0; i < 1000; ++i)
{
auto random = nano::random_pool::generate_word64 (1, 9);
ASSERT_TRUE (random >= 1 && random <= 9);
occurrences[random] += 1;
}
for (auto i = 1; i < 10; ++i)
{
ASSERT_GT (occurrences[i], 0);
}
}
// Test random numbers > uint32 max
TEST (random_pool, generate_word64_big_number)
{
uint64_t min = static_cast<uint64_t> (std::numeric_limits<uint32_t>::max ()) + 1;
uint64_t max = std::numeric_limits<uint64_t>::max ();
auto big_random = nano::random_pool::generate_word64 (min, max);
ASSERT_GE (big_random, min);
}

View file

@ -0,0 +1,129 @@
#include <nano/lib/observer_set.hpp>
#include <nano/lib/timer.hpp>
#include <gtest/gtest.h>
#include <atomic>
#include <thread>
using namespace std::chrono_literals;
TEST (observer_set, notify_one)
{
nano::observer_set<int> set;
int value{ 0 };
set.add ([&value] (int v) {
value = v;
});
set.notify (1);
ASSERT_EQ (1, value);
}
TEST (observer_set, notify_multiple)
{
nano::observer_set<int> set;
int value{ 0 };
set.add ([&value] (int v) {
value = v;
});
set.add ([&value] (int v) {
value += v;
});
set.notify (1);
ASSERT_EQ (2, value);
}
TEST (observer_set, notify_empty)
{
nano::observer_set<int> set;
set.notify (1);
}
TEST (observer_set, notify_multiple_types)
{
nano::observer_set<int, std::string> set;
int value{ 0 };
std::string str;
set.add ([&value, &str] (int v, std::string s) {
value = v;
str = s;
});
set.notify (1, "test");
ASSERT_EQ (1, value);
ASSERT_EQ ("test", str);
}
TEST (observer_set, empty_params)
{
nano::observer_set<> set;
set.notify ();
}
// Make sure there are no TSAN warnings
TEST (observer_set, parallel_notify)
{
nano::observer_set<int> set;
std::atomic<int> value{ 0 };
set.add ([&value] (int v) {
std::this_thread::sleep_for (100ms);
value = v;
});
nano::timer timer{ nano::timer_state::started };
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i)
{
threads.emplace_back ([&set] {
set.notify (1);
});
}
for (auto & thread : threads)
{
thread.join ();
}
ASSERT_EQ (1, value);
// Notification should be done in parallel
ASSERT_LT (timer.since_start (), 300ms);
}
namespace
{
struct move_only
{
move_only () = default;
move_only (move_only &&) = default;
move_only & operator= (move_only &&) = default;
move_only (move_only const &) = delete;
move_only & operator= (move_only const &) = delete;
};
struct copy_throw
{
copy_throw () = default;
copy_throw (copy_throw &&) = default;
copy_throw & operator= (copy_throw &&) = default;
copy_throw (copy_throw const &)
{
throw std::runtime_error ("copy_throw");
}
copy_throw & operator= (copy_throw const &) = delete;
};
}
// Ensure that parameters are not unnecessarily copied, this should compile
TEST (observer_set, move_only)
{
nano::observer_set<move_only> set;
set.add ([] (move_only const &) {
});
move_only value;
set.notify (value);
}
TEST (observer_set, copy_throw)
{
nano::observer_set<copy_throw> set;
set.add ([] (copy_throw const &) {
});
copy_throw value;
ASSERT_NO_THROW (set.notify (value));
}

View file

@ -79,16 +79,12 @@ TEST (peer_container, tcp_channel_cleanup_works)
ASSERT_NE (nullptr, channel1); ASSERT_NE (nullptr, channel1);
// set the last packet sent for channel1 only to guarantee it contains a value. // set the last packet sent for channel1 only to guarantee it contains a value.
// it won't be necessarily the same use by the cleanup cutoff time // it won't be necessarily the same use by the cleanup cutoff time
node1.network.tcp_channels.modify (channel1, [&now] (auto channel) { channel1->set_last_packet_sent (now - std::chrono::seconds (5));
channel->set_last_packet_sent (now - std::chrono::seconds (5));
});
auto channel2 = nano::test::establish_tcp (system, node1, outer_node2->network.endpoint ()); auto channel2 = nano::test::establish_tcp (system, node1, outer_node2->network.endpoint ());
ASSERT_NE (nullptr, channel2); ASSERT_NE (nullptr, channel2);
// set the last packet sent for channel2 only to guarantee it contains a value. // set the last packet sent for channel2 only to guarantee it contains a value.
// it won't be necessarily the same use by the cleanup cutoff time // it won't be necessarily the same use by the cleanup cutoff time
node1.network.tcp_channels.modify (channel2, [&now] (auto channel) { channel2->set_last_packet_sent (now + std::chrono::seconds (1));
channel->set_last_packet_sent (now + std::chrono::seconds (1));
});
ASSERT_EQ (2, node1.network.size ()); ASSERT_EQ (2, node1.network.size ());
ASSERT_EQ (2, node1.network.tcp_channels.size ()); ASSERT_EQ (2, node1.network.tcp_channels.size ());

View file

@ -0,0 +1,48 @@
#include <nano/crypto_lib/random_pool.hpp>
#include <nano/lib/numbers.hpp>
#include <gtest/gtest.h>
#include <thread>
TEST (random_pool, multithreading)
{
std::vector<std::thread> threads;
for (auto i = 0; i < 100; ++i)
{
threads.emplace_back ([] () {
nano::uint256_union number;
nano::random_pool::generate_block (number.bytes.data (), number.bytes.size ());
});
}
for (auto & i : threads)
{
i.join ();
}
}
// Test that random 64bit numbers are within the given range
TEST (random_pool, generate_word64)
{
int occurrences[10] = { 0 };
for (auto i = 0; i < 1000; ++i)
{
auto random = nano::random_pool::generate_word64 (1, 9);
ASSERT_TRUE (random >= 1 && random <= 9);
occurrences[random] += 1;
}
for (auto i = 1; i < 10; ++i)
{
ASSERT_GT (occurrences[i], 0);
}
}
// Test random numbers > uint32 max
TEST (random_pool, generate_word64_big_number)
{
uint64_t min = static_cast<uint64_t> (std::numeric_limits<uint32_t>::max ()) + 1;
uint64_t max = std::numeric_limits<uint64_t>::max ();
auto big_random = nano::random_pool::generate_word64 (min, max);
ASSERT_GE (big_random, min);
}

View file

@ -230,7 +230,7 @@ TEST (request_aggregator, two_endpoints)
auto dummy_channel1 = std::make_shared<nano::transport::inproc::channel> (node1, node1); auto dummy_channel1 = std::make_shared<nano::transport::inproc::channel> (node1, node1);
auto dummy_channel2 = std::make_shared<nano::transport::inproc::channel> (node2, node2); auto dummy_channel2 = std::make_shared<nano::transport::inproc::channel> (node2, node2);
ASSERT_NE (nano::transport::map_endpoint_to_v6 (dummy_channel1->get_endpoint ()), nano::transport::map_endpoint_to_v6 (dummy_channel2->get_endpoint ())); ASSERT_NE (nano::transport::map_endpoint_to_v6 (dummy_channel1->get_remote_endpoint ()), nano::transport::map_endpoint_to_v6 (dummy_channel2->get_remote_endpoint ()));
std::vector<std::pair<nano::block_hash, nano::root>> request{ { send1->hash (), send1->root () } }; std::vector<std::pair<nano::block_hash, nano::root>> request{ { send1->hash (), send1->root () } };

View file

@ -95,9 +95,9 @@ TEST (system, DISABLED_generate_send_new)
{ {
auto transaction (node1.store.tx_begin_read ()); auto transaction (node1.store.tx_begin_read ());
auto iterator1 (node1.store.account.begin (transaction)); auto iterator1 (node1.store.account.begin (transaction));
ASSERT_NE (node1.store.account.end (), iterator1); ASSERT_NE (node1.store.account.end (transaction), iterator1);
++iterator1; ++iterator1;
ASSERT_EQ (node1.store.account.end (), iterator1); ASSERT_EQ (node1.store.account.end (transaction), iterator1);
} }
nano::keypair stake_preserver; nano::keypair stake_preserver;
auto send_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true)); auto send_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true));
@ -130,13 +130,13 @@ TEST (system, DISABLED_generate_send_new)
new_account = iterator2->first; new_account = iterator2->first;
} }
++iterator2; ++iterator2;
ASSERT_NE (system.wallet (0)->store.end (), iterator2); ASSERT_NE (system.wallet (0)->store.end (transaction), iterator2);
if (iterator2->first != nano::dev::genesis_key.pub) if (iterator2->first != nano::dev::genesis_key.pub)
{ {
new_account = iterator2->first; new_account = iterator2->first;
} }
++iterator2; ++iterator2;
ASSERT_EQ (system.wallet (0)->store.end (), iterator2); ASSERT_EQ (system.wallet (0)->store.end (transaction), iterator2);
ASSERT_FALSE (new_account.is_zero ()); ASSERT_FALSE (new_account.is_zero ());
} }
ASSERT_TIMELY (10s, node1.balance (new_account) != 0); ASSERT_TIMELY (10s, node1.balance (new_account) != 0);

View file

@ -68,18 +68,18 @@ TEST (telemetry, basic)
ASSERT_NE (nullptr, channel); ASSERT_NE (nullptr, channel);
std::optional<nano::telemetry_data> telemetry_data; std::optional<nano::telemetry_data> telemetry_data;
ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
ASSERT_EQ (node_server->get_node_id (), telemetry_data->node_id); ASSERT_EQ (node_server->get_node_id (), telemetry_data->node_id);
// Check the metrics are correct // Check the metrics are correct
ASSERT_TRUE (nano::test::compare_telemetry (*telemetry_data, *node_server)); ASSERT_TRUE (nano::test::compare_telemetry (*telemetry_data, *node_server));
// Call again straight away // Call again straight away
auto telemetry_data_2 = node_client->telemetry.get_telemetry (channel->get_endpoint ()); auto telemetry_data_2 = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ());
ASSERT_TRUE (telemetry_data_2); ASSERT_TRUE (telemetry_data_2);
// Call again straight away // Call again straight away
auto telemetry_data_3 = node_client->telemetry.get_telemetry (channel->get_endpoint ()); auto telemetry_data_3 = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ());
ASSERT_TRUE (telemetry_data_3); ASSERT_TRUE (telemetry_data_3);
// we expect at least one consecutive repeat of telemetry // we expect at least one consecutive repeat of telemetry
@ -89,7 +89,7 @@ TEST (telemetry, basic)
WAIT (3s); WAIT (3s);
std::optional<nano::telemetry_data> telemetry_data_4; std::optional<nano::telemetry_data> telemetry_data_4;
ASSERT_TIMELY (5s, telemetry_data_4 = node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data_4 = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
ASSERT_NE (*telemetry_data, *telemetry_data_4); ASSERT_NE (*telemetry_data, *telemetry_data_4);
} }
@ -120,13 +120,13 @@ TEST (telemetry, disconnected)
ASSERT_NE (nullptr, channel); ASSERT_NE (nullptr, channel);
// Ensure telemetry is available before disconnecting // Ensure telemetry is available before disconnecting
ASSERT_TIMELY (5s, node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
system.stop_node (*node_server); system.stop_node (*node_server);
ASSERT_TRUE (channel); ASSERT_TRUE (channel);
// Ensure telemetry from disconnected peer is removed // Ensure telemetry from disconnected peer is removed
ASSERT_TIMELY (5s, !node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, !node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
} }
TEST (telemetry, dos_tcp) TEST (telemetry, dos_tcp)
@ -185,14 +185,14 @@ TEST (telemetry, disable_metrics)
node_client->telemetry.trigger (); node_client->telemetry.trigger ();
ASSERT_NEVER (1s, node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_NEVER (1s, node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
// It should still be able to receive metrics though // It should still be able to receive metrics though
auto channel1 = node_server->network.find_node_id (node_client->get_node_id ()); auto channel1 = node_server->network.find_node_id (node_client->get_node_id ());
ASSERT_NE (nullptr, channel1); ASSERT_NE (nullptr, channel1);
std::optional<nano::telemetry_data> telemetry_data; std::optional<nano::telemetry_data> telemetry_data;
ASSERT_TIMELY (5s, telemetry_data = node_server->telemetry.get_telemetry (channel1->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data = node_server->telemetry.get_telemetry (channel1->get_remote_endpoint ()));
ASSERT_TRUE (nano::test::compare_telemetry (*telemetry_data, *node_client)); ASSERT_TRUE (nano::test::compare_telemetry (*telemetry_data, *node_client));
} }
@ -237,7 +237,7 @@ TEST (telemetry, maker_pruning)
ASSERT_NE (nullptr, channel); ASSERT_NE (nullptr, channel);
std::optional<nano::telemetry_data> telemetry_data; std::optional<nano::telemetry_data> telemetry_data;
ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
ASSERT_EQ (node_server->get_node_id (), telemetry_data->node_id); ASSERT_EQ (node_server->get_node_id (), telemetry_data->node_id);
// Ensure telemetry response indicates pruned node // Ensure telemetry response indicates pruned node

View file

@ -0,0 +1,96 @@
#include <nano/lib/thread_pool.hpp>
#include <nano/lib/timer.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
#include <future>
TEST (thread_pool, thread_pool)
{
std::atomic<bool> passed_sleep{ false };
auto func = [&passed_sleep] () {
std::this_thread::sleep_for (std::chrono::seconds (1));
passed_sleep = true;
};
nano::thread_pool workers (1u, nano::thread_role::name::unknown);
nano::test::start_stop_guard stop_guard{ workers };
workers.post (func);
ASSERT_FALSE (passed_sleep);
nano::timer<std::chrono::milliseconds> timer_l;
timer_l.start ();
while (!passed_sleep)
{
if (timer_l.since_start () > std::chrono::seconds (10))
{
break;
}
}
ASSERT_TRUE (passed_sleep);
}
TEST (thread_pool, one)
{
std::atomic<bool> done (false);
nano::mutex mutex;
nano::condition_variable condition;
nano::thread_pool workers (1u, nano::thread_role::name::unknown);
nano::test::start_stop_guard stop_guard{ workers };
workers.post ([&] () {
{
nano::lock_guard<nano::mutex> lock{ mutex };
done = true;
}
condition.notify_one ();
});
nano::unique_lock<nano::mutex> unique{ mutex };
condition.wait (unique, [&] () { return !!done; });
}
TEST (thread_pool, many)
{
std::atomic<int> count (0);
nano::mutex mutex;
nano::condition_variable condition;
nano::thread_pool workers (50u, nano::thread_role::name::unknown);
nano::test::start_stop_guard stop_guard{ workers };
for (auto i (0); i < 50; ++i)
{
workers.post ([&] () {
{
nano::lock_guard<nano::mutex> lock{ mutex };
count += 1;
}
condition.notify_one ();
});
}
nano::unique_lock<nano::mutex> unique{ mutex };
condition.wait (unique, [&] () { return count == 50; });
}
TEST (thread_pool, top_execution)
{
int value1 (0);
int value2 (0);
nano::mutex mutex;
std::promise<bool> promise;
nano::thread_pool workers (1u, nano::thread_role::name::unknown);
nano::test::start_stop_guard stop_guard{ workers };
workers.post ([&] () {
nano::lock_guard<nano::mutex> lock{ mutex };
value1 = 1;
value2 = 1;
});
workers.post_delayed (std::chrono::milliseconds (1), [&] () {
nano::lock_guard<nano::mutex> lock{ mutex };
value2 = 2;
promise.set_value (false);
});
promise.get_future ().get ();
nano::lock_guard<nano::mutex> lock{ mutex };
ASSERT_EQ (1, value1);
ASSERT_EQ (2, value2);
}

View file

@ -191,7 +191,6 @@ TEST (toml, daemon_config_deserialize_defaults)
ASSERT_EQ (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time); ASSERT_EQ (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time);
ASSERT_EQ (conf.node.use_memory_pools, defaults.node.use_memory_pools); ASSERT_EQ (conf.node.use_memory_pools, defaults.node.use_memory_pools);
ASSERT_EQ (conf.node.vote_generator_delay, defaults.node.vote_generator_delay); ASSERT_EQ (conf.node.vote_generator_delay, defaults.node.vote_generator_delay);
ASSERT_EQ (conf.node.vote_generator_threshold, defaults.node.vote_generator_threshold);
ASSERT_EQ (conf.node.vote_minimum, defaults.node.vote_minimum); ASSERT_EQ (conf.node.vote_minimum, defaults.node.vote_minimum);
ASSERT_EQ (conf.node.work_peers, defaults.node.work_peers); ASSERT_EQ (conf.node.work_peers, defaults.node.work_peers);
ASSERT_EQ (conf.node.work_threads, defaults.node.work_threads); ASSERT_EQ (conf.node.work_threads, defaults.node.work_threads);
@ -456,7 +455,6 @@ TEST (toml, daemon_config_deserialize_no_defaults)
unchecked_cutoff_time = 999 unchecked_cutoff_time = 999
use_memory_pools = false use_memory_pools = false
vote_generator_delay = 999 vote_generator_delay = 999
vote_generator_threshold = 9
vote_minimum = "999" vote_minimum = "999"
work_peers = ["dev.org:999"] work_peers = ["dev.org:999"]
work_threads = 999 work_threads = 999
@ -700,7 +698,6 @@ TEST (toml, daemon_config_deserialize_no_defaults)
ASSERT_NE (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time); ASSERT_NE (conf.node.unchecked_cutoff_time, defaults.node.unchecked_cutoff_time);
ASSERT_NE (conf.node.use_memory_pools, defaults.node.use_memory_pools); ASSERT_NE (conf.node.use_memory_pools, defaults.node.use_memory_pools);
ASSERT_NE (conf.node.vote_generator_delay, defaults.node.vote_generator_delay); ASSERT_NE (conf.node.vote_generator_delay, defaults.node.vote_generator_delay);
ASSERT_NE (conf.node.vote_generator_threshold, defaults.node.vote_generator_threshold);
ASSERT_NE (conf.node.vote_minimum, defaults.node.vote_minimum); ASSERT_NE (conf.node.vote_minimum, defaults.node.vote_minimum);
ASSERT_NE (conf.node.work_peers, defaults.node.work_peers); ASSERT_NE (conf.node.work_peers, defaults.node.work_peers);
ASSERT_NE (conf.node.work_threads, defaults.node.work_threads); ASSERT_NE (conf.node.work_threads, defaults.node.work_threads);

View file

@ -1,6 +1,6 @@
#include <nano/lib/optional_ptr.hpp> #include <nano/lib/optional_ptr.hpp>
#include <nano/lib/rate_limiting.hpp> #include <nano/lib/rate_limiting.hpp>
#include <nano/lib/thread_pool.hpp> #include <nano/lib/relaxed_atomic.hpp>
#include <nano/lib/timer.hpp> #include <nano/lib/timer.hpp>
#include <nano/lib/utility.hpp> #include <nano/lib/utility.hpp>
#include <nano/secure/pending_info.hpp> #include <nano/secure/pending_info.hpp>
@ -146,91 +146,6 @@ TEST (optional_ptr, basic)
ASSERT_EQ (opt->z, 3); ASSERT_EQ (opt->z, 3);
} }
TEST (thread, thread_pool)
{
std::atomic<bool> passed_sleep{ false };
auto func = [&passed_sleep] () {
std::this_thread::sleep_for (std::chrono::seconds (1));
passed_sleep = true;
};
nano::thread_pool workers (1u, nano::thread_role::name::unknown);
workers.push_task (func);
ASSERT_FALSE (passed_sleep);
nano::timer<std::chrono::milliseconds> timer_l;
timer_l.start ();
while (!passed_sleep)
{
if (timer_l.since_start () > std::chrono::seconds (10))
{
break;
}
}
ASSERT_TRUE (passed_sleep);
}
TEST (thread_pool_alarm, one)
{
std::atomic<bool> done (false);
nano::mutex mutex;
nano::condition_variable condition;
nano::thread_pool workers (1u, nano::thread_role::name::unknown);
workers.add_timed_task (std::chrono::steady_clock::now (), [&] () {
{
nano::lock_guard<nano::mutex> lock{ mutex };
done = true;
}
condition.notify_one ();
});
nano::unique_lock<nano::mutex> unique{ mutex };
condition.wait (unique, [&] () { return !!done; });
}
TEST (thread_pool_alarm, many)
{
std::atomic<int> count (0);
nano::mutex mutex;
nano::condition_variable condition;
nano::thread_pool workers (50u, nano::thread_role::name::unknown);
for (auto i (0); i < 50; ++i)
{
workers.add_timed_task (std::chrono::steady_clock::now (), [&] () {
{
nano::lock_guard<nano::mutex> lock{ mutex };
count += 1;
}
condition.notify_one ();
});
}
nano::unique_lock<nano::mutex> unique{ mutex };
condition.wait (unique, [&] () { return count == 50; });
}
TEST (thread_pool_alarm, top_execution)
{
int value1 (0);
int value2 (0);
nano::mutex mutex;
std::promise<bool> promise;
nano::thread_pool workers (1u, nano::thread_role::name::unknown);
workers.add_timed_task (std::chrono::steady_clock::now (), [&] () {
nano::lock_guard<nano::mutex> lock{ mutex };
value1 = 1;
value2 = 1;
});
workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (1), [&] () {
nano::lock_guard<nano::mutex> lock{ mutex };
value2 = 2;
promise.set_value (false);
});
promise.get_future ().get ();
nano::lock_guard<nano::mutex> lock{ mutex };
ASSERT_EQ (1, value1);
ASSERT_EQ (2, value2);
}
TEST (filesystem, remove_all_files) TEST (filesystem, remove_all_files)
{ {
auto path = nano::unique_path (); auto path = nano::unique_path ();

View file

@ -104,7 +104,7 @@ TEST (wallet, empty_iteration)
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
ASSERT_FALSE (init); ASSERT_FALSE (init);
auto i (wallet.begin (transaction)); auto i (wallet.begin (transaction));
auto j (wallet.end ()); auto j (wallet.end (transaction));
ASSERT_EQ (i, j); ASSERT_EQ (i, j);
} }
@ -119,7 +119,7 @@ TEST (wallet, one_item_iteration)
ASSERT_FALSE (init); ASSERT_FALSE (init);
nano::keypair key1; nano::keypair key1;
wallet.insert_adhoc (transaction, key1.prv); wallet.insert_adhoc (transaction, key1.prv);
for (auto i (wallet.begin (transaction)), j (wallet.end ()); i != j; ++i) for (auto i (wallet.begin (transaction)), j (wallet.end (transaction)); i != j; ++i)
{ {
ASSERT_EQ (key1.pub, nano::uint256_union (i->first)); ASSERT_EQ (key1.pub, nano::uint256_union (i->first));
nano::raw_key password; nano::raw_key password;
@ -147,7 +147,7 @@ TEST (wallet, two_item_iteration)
ASSERT_FALSE (init); ASSERT_FALSE (init);
wallet.insert_adhoc (transaction, key1.prv); wallet.insert_adhoc (transaction, key1.prv);
wallet.insert_adhoc (transaction, key2.prv); wallet.insert_adhoc (transaction, key2.prv);
for (auto i (wallet.begin (transaction)), j (wallet.end ()); i != j; ++i) for (auto i (wallet.begin (transaction)), j (wallet.end (transaction)); i != j; ++i)
{ {
pubs.insert (i->first); pubs.insert (i->first);
nano::raw_key password; nano::raw_key password;
@ -266,7 +266,7 @@ TEST (wallet, find_none)
nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0"); nano::wallet_store wallet (init, kdf, transaction, env, nano::dev::genesis_key.pub, 1, "0");
ASSERT_FALSE (init); ASSERT_FALSE (init);
nano::account account (1000); nano::account account (1000);
ASSERT_EQ (wallet.end (), wallet.find (transaction, account)); ASSERT_EQ (wallet.end (transaction), wallet.find (transaction, account));
} }
TEST (wallet, find_existing) TEST (wallet, find_existing)
@ -283,9 +283,9 @@ TEST (wallet, find_existing)
wallet.insert_adhoc (transaction, key1.prv); wallet.insert_adhoc (transaction, key1.prv);
ASSERT_TRUE (wallet.exists (transaction, key1.pub)); ASSERT_TRUE (wallet.exists (transaction, key1.pub));
auto existing (wallet.find (transaction, key1.pub)); auto existing (wallet.find (transaction, key1.pub));
ASSERT_NE (wallet.end (), existing); ASSERT_NE (wallet.end (transaction), existing);
++existing; ++existing;
ASSERT_EQ (wallet.end (), existing); ASSERT_EQ (wallet.end (transaction), existing);
} }
TEST (wallet, rekey) TEST (wallet, rekey)
@ -487,8 +487,8 @@ TEST (wallet, serialize_json_empty)
ASSERT_EQ (wallet1.salt (transaction), wallet2.salt (transaction)); ASSERT_EQ (wallet1.salt (transaction), wallet2.salt (transaction));
ASSERT_EQ (wallet1.check (transaction), wallet2.check (transaction)); ASSERT_EQ (wallet1.check (transaction), wallet2.check (transaction));
ASSERT_EQ (wallet1.representative (transaction), wallet2.representative (transaction)); ASSERT_EQ (wallet1.representative (transaction), wallet2.representative (transaction));
ASSERT_EQ (wallet1.end (), wallet1.begin (transaction)); ASSERT_EQ (wallet1.end (transaction), wallet1.begin (transaction));
ASSERT_EQ (wallet2.end (), wallet2.begin (transaction)); ASSERT_EQ (wallet2.end (transaction), wallet2.begin (transaction));
} }
TEST (wallet, serialize_json_one) TEST (wallet, serialize_json_one)

View file

@ -12,6 +12,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <boost/format.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <chrono> #include <chrono>
@ -1005,7 +1006,7 @@ TEST (websocket, telemetry)
auto channel = node1->network.find_node_id (node2->get_node_id ()); auto channel = node1->network.find_node_id (node2->get_node_id ());
ASSERT_NE (channel, nullptr); ASSERT_NE (channel, nullptr);
ASSERT_TIMELY (5s, node1->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, node1->telemetry.get_telemetry (channel->get_remote_endpoint ()));
ASSERT_TIMELY_EQ (10s, future.wait_for (0s), std::future_status::ready); ASSERT_TIMELY_EQ (10s, future.wait_for (0s), std::future_status::ready);

View file

@ -94,7 +94,6 @@ add_library(
stats_sinks.hpp stats_sinks.hpp
stream.hpp stream.hpp
thread_pool.hpp thread_pool.hpp
thread_pool.cpp
thread_roles.hpp thread_roles.hpp
thread_roles.cpp thread_roles.cpp
thread_runner.hpp thread_runner.hpp

View file

@ -609,7 +609,7 @@ std::optional<nano::account> nano::send_block::destination_field () const
return hashables.destination; return hashables.destination;
} }
nano::root const & nano::send_block::root () const nano::root nano::send_block::root () const
{ {
return hashables.previous; return hashables.previous;
} }
@ -899,7 +899,7 @@ std::optional<nano::block_hash> nano::open_block::source_field () const
return hashables.source; return hashables.source;
} }
nano::root const & nano::open_block::root () const nano::root nano::open_block::root () const
{ {
return hashables.account; return hashables.account;
} }
@ -1165,7 +1165,7 @@ bool nano::change_block::valid_predecessor (nano::block const & block_a) const
return result; return result;
} }
nano::root const & nano::change_block::root () const nano::root nano::change_block::root () const
{ {
return hashables.previous; return hashables.previous;
} }
@ -1482,7 +1482,7 @@ bool nano::state_block::valid_predecessor (nano::block const & block_a) const
return true; return true;
} }
nano::root const & nano::state_block::root () const nano::root nano::state_block::root () const
{ {
if (!hashables.previous.is_zero ()) if (!hashables.previous.is_zero ())
{ {
@ -1836,7 +1836,7 @@ std::optional<nano::block_hash> nano::receive_block::source_field () const
return hashables.source; return hashables.source;
} }
nano::root const & nano::receive_block::root () const nano::root nano::receive_block::root () const
{ {
return hashables.previous; return hashables.previous;
} }

View file

@ -33,7 +33,7 @@ public:
virtual uint64_t block_work () const = 0; virtual uint64_t block_work () const = 0;
virtual void block_work_set (uint64_t) = 0; virtual void block_work_set (uint64_t) = 0;
// Previous block or account number for open blocks // Previous block or account number for open blocks
virtual nano::root const & root () const = 0; virtual nano::root root () const = 0;
// Qualified root value based on previous() and root() // Qualified root value based on previous() and root()
virtual nano::qualified_root qualified_root () const; virtual nano::qualified_root qualified_root () const;
virtual void serialize (nano::stream &) const = 0; virtual void serialize (nano::stream &) const = 0;
@ -123,7 +123,7 @@ public:
virtual ~send_block () = default; virtual ~send_block () = default;
uint64_t block_work () const override; uint64_t block_work () const override;
void block_work_set (uint64_t) override; void block_work_set (uint64_t) override;
nano::root const & root () const override; nano::root root () const override;
void serialize (nano::stream &) const override; void serialize (nano::stream &) const override;
bool deserialize (nano::stream &); bool deserialize (nano::stream &);
void serialize_json (std::string &, bool = false) const override; void serialize_json (std::string &, bool = false) const override;
@ -177,7 +177,7 @@ public:
virtual ~receive_block () = default; virtual ~receive_block () = default;
uint64_t block_work () const override; uint64_t block_work () const override;
void block_work_set (uint64_t) override; void block_work_set (uint64_t) override;
nano::root const & root () const override; nano::root root () const override;
void serialize (nano::stream &) const override; void serialize (nano::stream &) const override;
bool deserialize (nano::stream &); bool deserialize (nano::stream &);
void serialize_json (std::string &, bool = false) const override; void serialize_json (std::string &, bool = false) const override;
@ -232,7 +232,7 @@ public:
virtual ~open_block () = default; virtual ~open_block () = default;
uint64_t block_work () const override; uint64_t block_work () const override;
void block_work_set (uint64_t) override; void block_work_set (uint64_t) override;
nano::root const & root () const override; nano::root root () const override;
void serialize (nano::stream &) const override; void serialize (nano::stream &) const override;
bool deserialize (nano::stream &); bool deserialize (nano::stream &);
void serialize_json (std::string &, bool = false) const override; void serialize_json (std::string &, bool = false) const override;
@ -287,7 +287,7 @@ public:
virtual ~change_block () = default; virtual ~change_block () = default;
uint64_t block_work () const override; uint64_t block_work () const override;
void block_work_set (uint64_t) override; void block_work_set (uint64_t) override;
nano::root const & root () const override; nano::root root () const override;
void serialize (nano::stream &) const override; void serialize (nano::stream &) const override;
bool deserialize (nano::stream &); bool deserialize (nano::stream &);
void serialize_json (std::string &, bool = false) const override; void serialize_json (std::string &, bool = false) const override;
@ -353,7 +353,7 @@ public:
virtual ~state_block () = default; virtual ~state_block () = default;
uint64_t block_work () const override; uint64_t block_work () const override;
void block_work_set (uint64_t) override; void block_work_set (uint64_t) override;
nano::root const & root () const override; nano::root root () const override;
void serialize (nano::stream &) const override; void serialize (nano::stream &) const override;
bool deserialize (nano::stream &); bool deserialize (nano::stream &);
void serialize_json (std::string &, bool = false) const override; void serialize_json (std::string &, bool = false) const override;

View file

@ -6,6 +6,7 @@
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <valgrind/valgrind.h> #include <valgrind/valgrind.h>

View file

@ -61,11 +61,6 @@ std::string nano::public_key::to_account () const
return result; return result;
} }
nano::public_key::public_key () :
uint256_union{ 0 }
{
}
nano::public_key const & nano::public_key::null () nano::public_key const & nano::public_key::null ()
{ {
return nano::hardened_constants::get ().not_an_account; return nano::hardened_constants::get ().not_an_account;
@ -143,12 +138,6 @@ bool nano::public_key::decode_account (std::string const & source_a)
return error; return error;
} }
nano::uint256_union::uint256_union (nano::uint256_t const & number_a)
{
bytes.fill (0);
boost::multiprecision::export_bits (number_a, bytes.rbegin (), 8, false);
}
// Construct a uint256_union = AES_ENC_CTR (cleartext, key, iv) // Construct a uint256_union = AES_ENC_CTR (cleartext, key, iv)
void nano::uint256_union::encrypt (nano::raw_key const & cleartext, nano::raw_key const & key, uint128_union const & iv) void nano::uint256_union::encrypt (nano::raw_key const & cleartext, nano::raw_key const & key, uint128_union const & iv)
{ {
@ -157,11 +146,6 @@ void nano::uint256_union::encrypt (nano::raw_key const & cleartext, nano::raw_ke
enc.ProcessData (bytes.data (), cleartext.bytes.data (), sizeof (cleartext.bytes)); enc.ProcessData (bytes.data (), cleartext.bytes.data (), sizeof (cleartext.bytes));
} }
bool nano::uint256_union::is_zero () const
{
return qwords[0] == 0 && qwords[1] == 0 && qwords[2] == 0 && qwords[3] == 0;
}
std::string nano::uint256_union::to_string () const std::string nano::uint256_union::to_string () const
{ {
std::string result; std::string result;
@ -193,22 +177,9 @@ nano::uint256_union nano::uint256_union::operator^ (nano::uint256_union const &
nano::uint256_union::uint256_union (std::string const & hex_a) nano::uint256_union::uint256_union (std::string const & hex_a)
{ {
auto error (decode_hex (hex_a)); auto error (decode_hex (hex_a));
release_assert (!error); release_assert (!error);
} }
void nano::uint256_union::clear ()
{
qwords.fill (0);
}
nano::uint256_t nano::uint256_union::number () const
{
nano::uint256_t result;
boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ());
return result;
}
void nano::uint256_union::encode_hex (std::string & text) const void nano::uint256_union::encode_hex (std::string & text) const
{ {
debug_assert (text.empty ()); debug_assert (text.empty ());
@ -281,46 +252,6 @@ bool nano::uint256_union::decode_dec (std::string const & text)
return error; return error;
} }
nano::uint256_union::uint256_union (uint64_t value0)
{
*this = nano::uint256_t (value0);
}
bool nano::uint512_union::operator== (nano::uint512_union const & other_a) const
{
return bytes == other_a.bytes;
}
nano::uint512_union::uint512_union (nano::uint256_union const & upper, nano::uint256_union const & lower)
{
uint256s[0] = upper;
uint256s[1] = lower;
}
nano::uint512_union::uint512_union (nano::uint512_t const & number_a)
{
bytes.fill (0);
boost::multiprecision::export_bits (number_a, bytes.rbegin (), 8, false);
}
bool nano::uint512_union::is_zero () const
{
return qwords[0] == 0 && qwords[1] == 0 && qwords[2] == 0 && qwords[3] == 0
&& qwords[4] == 0 && qwords[5] == 0 && qwords[6] == 0 && qwords[7] == 0;
}
void nano::uint512_union::clear ()
{
bytes.fill (0);
}
nano::uint512_t nano::uint512_union::number () const
{
nano::uint512_t result;
boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ());
return result;
}
void nano::uint512_union::encode_hex (std::string & text) const void nano::uint512_union::encode_hex (std::string & text) const
{ {
debug_assert (text.empty ()); debug_assert (text.empty ());
@ -355,18 +286,6 @@ bool nano::uint512_union::decode_hex (std::string const & text)
return error; return error;
} }
bool nano::uint512_union::operator!= (nano::uint512_union const & other_a) const
{
return !(*this == other_a);
}
nano::uint512_union & nano::uint512_union::operator^= (nano::uint512_union const & other_a)
{
uint256s[0] ^= other_a.uint256s[0];
uint256s[1] ^= other_a.uint256s[1];
return *this;
}
std::string nano::uint512_union::to_string () const std::string nano::uint512_union::to_string () const
{ {
std::string result; std::string result;
@ -431,48 +350,9 @@ bool nano::validate_message (nano::public_key const & public_key, nano::uint256_
nano::uint128_union::uint128_union (std::string const & string_a) nano::uint128_union::uint128_union (std::string const & string_a)
{ {
auto error (decode_hex (string_a)); auto error (decode_hex (string_a));
release_assert (!error); release_assert (!error);
} }
nano::uint128_union::uint128_union (uint64_t value_a)
{
*this = nano::uint128_t (value_a);
}
nano::uint128_union::uint128_union (nano::uint128_t const & number_a)
{
bytes.fill (0);
boost::multiprecision::export_bits (number_a, bytes.rbegin (), 8, false);
}
bool nano::uint128_union::operator== (nano::uint128_union const & other_a) const
{
return qwords[0] == other_a.qwords[0] && qwords[1] == other_a.qwords[1];
}
bool nano::uint128_union::operator!= (nano::uint128_union const & other_a) const
{
return !(*this == other_a);
}
bool nano::uint128_union::operator< (nano::uint128_union const & other_a) const
{
return std::memcmp (bytes.data (), other_a.bytes.data (), 16) < 0;
}
bool nano::uint128_union::operator> (nano::uint128_union const & other_a) const
{
return std::memcmp (bytes.data (), other_a.bytes.data (), 16) > 0;
}
nano::uint128_t nano::uint128_union::number () const
{
nano::uint128_t result;
boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ());
return result;
}
void nano::uint128_union::encode_hex (std::string & text) const void nano::uint128_union::encode_hex (std::string & text) const
{ {
debug_assert (text.empty ()); debug_assert (text.empty ());
@ -747,16 +627,6 @@ std::string nano::uint128_union::format_balance (nano::uint128_t scale, int prec
return ::format_balance (number (), scale, precision, group_digits, thousands_sep, decimal_point, grouping); return ::format_balance (number (), scale, precision, group_digits, thousands_sep, decimal_point, grouping);
} }
void nano::uint128_union::clear ()
{
qwords.fill (0);
}
bool nano::uint128_union::is_zero () const
{
return qwords[0] == 0 && qwords[1] == 0;
}
std::string nano::uint128_union::to_string () const std::string nano::uint128_union::to_string () const
{ {
std::string result; std::string result;
@ -771,26 +641,6 @@ std::string nano::uint128_union::to_string_dec () const
return result; return result;
} }
nano::hash_or_account::hash_or_account () :
account{}
{
}
nano::hash_or_account::hash_or_account (uint64_t value_a) :
raw (value_a)
{
}
bool nano::hash_or_account::is_zero () const
{
return raw.is_zero ();
}
void nano::hash_or_account::clear ()
{
raw.clear ();
}
bool nano::hash_or_account::decode_hex (std::string const & text_a) bool nano::hash_or_account::decode_hex (std::string const & text_a)
{ {
return raw.decode_hex (text_a); return raw.decode_hex (text_a);
@ -811,36 +661,6 @@ std::string nano::hash_or_account::to_account () const
return account.to_account (); return account.to_account ();
} }
nano::block_hash const & nano::hash_or_account::as_block_hash () const
{
return hash;
}
nano::account const & nano::hash_or_account::as_account () const
{
return account;
}
nano::hash_or_account::operator nano::uint256_union const & () const
{
return raw;
}
nano::block_hash const & nano::root::previous () const
{
return hash;
}
bool nano::hash_or_account::operator== (nano::hash_or_account const & hash_or_account_a) const
{
return bytes == hash_or_account_a.bytes;
}
bool nano::hash_or_account::operator!= (nano::hash_or_account const & hash_or_account_a) const
{
return !(*this == hash_or_account_a);
}
std::string nano::to_string_hex (uint64_t const value_a) std::string nano::to_string_hex (uint64_t const value_a)
{ {
std::stringstream stream; std::stringstream stream;
@ -915,6 +735,13 @@ std::ostream & nano::operator<< (std::ostream & os, const uint512_union & val)
return os; return os;
} }
std::ostream & nano::operator<< (std::ostream & os, const hash_or_account & val)
{
// TODO: Replace with streaming implementation
os << val.to_string ();
return os;
}
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned #pragma warning(disable : 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned
@ -947,43 +774,3 @@ double nano::difficulty::to_multiplier (uint64_t const difficulty_a, uint64_t co
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(pop) #pragma warning(pop)
#endif #endif
nano::public_key::operator nano::link const & () const
{
return reinterpret_cast<nano::link const &> (*this);
}
nano::public_key::operator nano::root const & () const
{
return reinterpret_cast<nano::root const &> (*this);
}
nano::public_key::operator nano::hash_or_account const & () const
{
return reinterpret_cast<nano::hash_or_account const &> (*this);
}
bool nano::public_key::operator== (std::nullptr_t) const
{
return bytes == null ().bytes;
}
bool nano::public_key::operator!= (std::nullptr_t) const
{
return !(*this == nullptr);
}
nano::block_hash::operator nano::link const & () const
{
return reinterpret_cast<nano::link const &> (*this);
}
nano::block_hash::operator nano::root const & () const
{
return reinterpret_cast<nano::root const &> (*this);
}
nano::block_hash::operator nano::hash_or_account const & () const
{
return reinterpret_cast<nano::hash_or_account const &> (*this);
}

View file

@ -4,6 +4,8 @@
#include <boost/multiprecision/cpp_int.hpp> #include <boost/multiprecision/cpp_int.hpp>
#include <array> #include <array>
#include <compare>
#include <limits>
#include <ostream> #include <ostream>
#include <fmt/ostream.h> #include <fmt/ostream.h>
@ -13,6 +15,7 @@ namespace nano
using uint128_t = boost::multiprecision::uint128_t; using uint128_t = boost::multiprecision::uint128_t;
using uint256_t = boost::multiprecision::uint256_t; using uint256_t = boost::multiprecision::uint256_t;
using uint512_t = boost::multiprecision::uint512_t; using uint512_t = boost::multiprecision::uint512_t;
// SI dividers // SI dividers
nano::uint128_t const Knano_ratio = nano::uint128_t ("1000000000000000000000000000000000"); // 10^33 = 1000 nano nano::uint128_t const Knano_ratio = nano::uint128_t ("1000000000000000000000000000000000"); // 10^33 = 1000 nano
nano::uint128_t const nano_ratio = nano::uint128_t ("1000000000000000000000000000000"); // 10^30 = 1 nano nano::uint128_t const nano_ratio = nano::uint128_t ("1000000000000000000000000000000"); // 10^30 = 1 nano
@ -20,31 +23,55 @@ nano::uint128_t const raw_ratio = nano::uint128_t ("1"); // 10^0
class uint128_union class uint128_union
{ {
public:
// Type that is implicitly convertible to this union
using underlying_type = nano::uint128_t;
public: public:
uint128_union () = default; uint128_union () = default;
uint128_union (uint64_t value) :
uint128_union (nano::uint128_t{ value }){};
uint128_union (nano::uint128_t const & value)
{
bytes.fill (0);
boost::multiprecision::export_bits (value, bytes.rbegin (), 8, false);
}
/** /**
* Decode from hex string * Decode from hex string
* @warning Aborts at runtime if the input is invalid * @warning Aborts at runtime if the input is invalid
*/ */
uint128_union (std::string const &); explicit uint128_union (std::string const &);
uint128_union (uint64_t);
uint128_union (nano::uint128_t const &);
bool operator== (nano::uint128_union const &) const;
bool operator!= (nano::uint128_union const &) const;
bool operator< (nano::uint128_union const &) const;
bool operator> (nano::uint128_union const &) const;
void encode_hex (std::string &) const; void encode_hex (std::string &) const;
bool decode_hex (std::string const &); bool decode_hex (std::string const &);
void encode_dec (std::string &) const; void encode_dec (std::string &) const;
bool decode_dec (std::string const &, bool = false); bool decode_dec (std::string const &, bool = false);
bool decode_dec (std::string const &, nano::uint128_t); bool decode_dec (std::string const &, nano::uint128_t);
std::string format_balance (nano::uint128_t scale, int precision, bool group_digits) const; std::string format_balance (nano::uint128_t scale, int precision, bool group_digits) const;
std::string format_balance (nano::uint128_t scale, int precision, bool group_digits, std::locale const & locale) const; std::string format_balance (nano::uint128_t scale, int precision, bool group_digits, std::locale const & locale) const;
nano::uint128_t number () const;
void clear (); void clear ()
bool is_zero () const; {
qwords.fill (0);
}
bool is_zero () const
{
return qwords[0] == 0 && qwords[1] == 0;
}
nano::uint128_t number () const
{
nano::uint128_t result;
boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ());
return result;
}
std::string to_string () const; std::string to_string () const;
std::string to_string_dec () const; std::string to_string_dec () const;
public:
union union
{ {
std::array<uint8_t, 16> bytes; std::array<uint8_t, 16> bytes;
@ -52,6 +79,24 @@ public:
std::array<uint32_t, 4> dwords; std::array<uint32_t, 4> dwords;
std::array<uint64_t, 2> qwords; std::array<uint64_t, 2> qwords;
}; };
public: // Keep operators inlined
std::strong_ordering operator<=> (nano::uint128_union const & other) const
{
return std::memcmp (bytes.data (), other.bytes.data (), 16) <=> 0;
};
bool operator== (nano::uint128_union const & other) const
{
return *this <=> other == 0;
}
operator nano::uint128_t () const
{
return number ();
}
uint128_union const & as_union () const
{
return *this;
}
}; };
static_assert (std::is_nothrow_move_constructible<uint128_union>::value, "uint128_union should be noexcept MoveConstructible"); static_assert (std::is_nothrow_move_constructible<uint128_union>::value, "uint128_union should be noexcept MoveConstructible");
@ -61,37 +106,69 @@ class amount : public uint128_union
public: public:
using uint128_union::uint128_union; using uint128_union::uint128_union;
auto operator<=> (nano::amount const & other) const
{
return uint128_union::operator<=> (other);
}
operator nano::uint128_t () const operator nano::uint128_t () const
{ {
return number (); return number ();
} }
}; };
class raw_key; class raw_key;
class uint256_union class uint256_union
{ {
public:
// Type that is implicitly convertible to this union
using underlying_type = nano::uint256_t;
public: public:
uint256_union () = default; uint256_union () = default;
uint256_union (uint64_t value) :
uint256_union (nano::uint256_t{ value }){};
uint256_union (nano::uint256_t const & value)
{
bytes.fill (0);
boost::multiprecision::export_bits (value, bytes.rbegin (), 8, false);
}
/** /**
* Decode from hex string * Decode from hex string
* @warning Aborts at runtime if the input is invalid * @warning Aborts at runtime if the input is invalid
*/ */
explicit uint256_union (std::string const &); explicit uint256_union (std::string const &);
uint256_union (uint64_t);
uint256_union (nano::uint256_t const &);
void encrypt (nano::raw_key const &, nano::raw_key const &, uint128_union const &); void encrypt (nano::raw_key const &, nano::raw_key const &, uint128_union const &);
uint256_union & operator^= (nano::uint256_union const &);
uint256_union operator^ (nano::uint256_union const &) const; uint256_union & operator^= (uint256_union const &);
uint256_union operator^ (uint256_union const &) const;
void encode_hex (std::string &) const; void encode_hex (std::string &) const;
bool decode_hex (std::string const &); bool decode_hex (std::string const &);
void encode_dec (std::string &) const; void encode_dec (std::string &) const;
bool decode_dec (std::string const &); bool decode_dec (std::string const &);
void clear (); void clear ()
bool is_zero () const; {
std::string to_string () const; qwords.fill (0);
nano::uint256_t number () const; }
bool is_zero () const
{
return owords[0].is_zero () && owords[1].is_zero ();
}
nano::uint256_t number () const
{
nano::uint256_t result;
boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ());
return result;
}
std::string to_string () const;
public:
union union
{ {
std::array<uint8_t, 32> bytes; std::array<uint8_t, 32> bytes;
@ -100,33 +177,46 @@ public:
std::array<uint64_t, 4> qwords; std::array<uint64_t, 4> qwords;
std::array<uint128_union, 2> owords; std::array<uint128_union, 2> owords;
}; };
};
inline bool operator== (nano::uint256_union const & lhs, nano::uint256_union const & rhs)
{
return lhs.bytes == rhs.bytes;
}
inline bool operator!= (nano::uint256_union const & lhs, nano::uint256_union const & rhs)
{
return !(lhs == rhs);
}
inline bool operator< (nano::uint256_union const & lhs, nano::uint256_union const & rhs)
{
return std::memcmp (lhs.bytes.data (), rhs.bytes.data (), 32) < 0;
}
static_assert (std::is_nothrow_move_constructible<uint256_union>::value, "uint256_union should be noexcept MoveConstructible");
class link; public: // Keep operators inlined
class root; std::strong_ordering operator<=> (nano::uint256_union const & other) const
class hash_or_account; {
return std::memcmp (bytes.data (), other.bytes.data (), 32) <=> 0;
};
bool operator== (nano::uint256_union const & other) const
{
return *this <=> other == 0;
}
operator nano::uint256_t () const
{
return number ();
}
uint256_union const & as_union () const
{
return *this;
}
};
static_assert (std::is_nothrow_move_constructible<uint256_union>::value, "uint256_union should be noexcept MoveConstructible");
// All keys and hashes are 256 bit. // All keys and hashes are 256 bit.
class block_hash final : public uint256_union class block_hash final : public uint256_union
{ {
public: public:
using uint256_union::uint256_union; using uint256_union::uint256_union;
operator nano::link const & () const;
operator nano::root const & () const; public: // Keep operators inlined
operator nano::hash_or_account const & () const; auto operator<=> (nano::block_hash const & other) const
{
return uint256_union::operator<=> (other);
}
bool operator== (nano::block_hash const & other) const
{
return *this <=> other == 0;
}
operator nano::uint256_t () const
{
return number ();
}
}; };
class public_key final : public uint256_union class public_key final : public uint256_union
@ -134,21 +224,35 @@ class public_key final : public uint256_union
public: public:
using uint256_union::uint256_union; using uint256_union::uint256_union;
public_key (); public_key () :
uint256_union{ 0 } {};
static const public_key & null (); static const public_key & null ();
std::string to_node_id () const; bool decode_node_id (std::string const &);
bool decode_node_id (std::string const & source_a);
void encode_account (std::string &) const; void encode_account (std::string &) const;
std::string to_account () const;
bool decode_account (std::string const &); bool decode_account (std::string const &);
operator nano::link const & () const; std::string to_node_id () const;
operator nano::root const & () const; std::string to_account () const;
operator nano::hash_or_account const & () const;
bool operator== (std::nullptr_t) const; public: // Keep operators inlined
bool operator!= (std::nullptr_t) const; auto operator<=> (nano::public_key const & other) const
{
return uint256_union::operator<=> (other);
}
bool operator== (nano::public_key const & other) const
{
return *this <=> other == 0;
}
bool operator== (std::nullptr_t) const
{
return *this == null ();
}
operator nano::uint256_t () const
{
return number ();
}
}; };
class wallet_id : public uint256_union class wallet_id : public uint256_union
@ -162,24 +266,33 @@ using account = public_key;
class hash_or_account class hash_or_account
{ {
public: public:
hash_or_account (); // Type that is implicitly convertible to this union
hash_or_account (uint64_t value_a); using underlying_type = nano::uint256_t;
public:
hash_or_account () :
account{} {};
hash_or_account (uint64_t value) :
raw{ value } {};
hash_or_account (uint256_union const & value) :
raw{ value } {};
void clear ()
{
raw.clear ();
}
bool is_zero () const
{
return raw.is_zero ();
}
bool is_zero () const;
void clear ();
std::string to_string () const;
bool decode_hex (std::string const &); bool decode_hex (std::string const &);
bool decode_account (std::string const &); bool decode_account (std::string const &);
std::string to_string () const;
std::string to_account () const; std::string to_account () const;
nano::account const & as_account () const; public:
nano::block_hash const & as_block_hash () const;
operator nano::uint256_union const & () const;
bool operator== (nano::hash_or_account const &) const;
bool operator!= (nano::hash_or_account const &) const;
union union
{ {
std::array<uint8_t, 32> bytes; std::array<uint8_t, 32> bytes;
@ -187,6 +300,36 @@ public:
nano::account account; nano::account account;
nano::block_hash hash; nano::block_hash hash;
}; };
public: // Keep operators inlined
auto operator<=> (nano::hash_or_account const & other) const
{
return raw <=> other.raw;
};
bool operator== (nano::hash_or_account const & other) const
{
return *this <=> other == 0;
}
explicit operator nano::uint256_t () const
{
return raw.number ();
}
explicit operator nano::uint256_union () const
{
return raw;
}
nano::account const & as_account () const
{
return account;
}
nano::block_hash const & as_block_hash () const
{
return hash;
}
nano::uint256_union const & as_union () const
{
return raw;
}
}; };
// A link can either be a destination account or source hash // A link can either be a destination account or source hash
@ -194,6 +337,16 @@ class link final : public hash_or_account
{ {
public: public:
using hash_or_account::hash_or_account; using hash_or_account::hash_or_account;
public: // Keep operators inlined
auto operator<=> (nano::link const & other) const
{
return hash_or_account::operator<=> (other);
}
bool operator== (nano::link const & other) const
{
return *this <=> other == 0;
}
}; };
// A root can either be an open block hash or a previous hash // A root can either be an open block hash or a previous hash
@ -202,7 +355,20 @@ class root final : public hash_or_account
public: public:
using hash_or_account::hash_or_account; using hash_or_account::hash_or_account;
nano::block_hash const & previous () const; nano::block_hash const & previous () const
{
return hash;
}
public: // Keep operators inlined
auto operator<=> (nano::root const & other) const
{
return hash_or_account::operator<=> (other);
}
bool operator== (nano::root const & other) const
{
return *this <=> other == 0;
}
}; };
// The seed or private key // The seed or private key
@ -213,22 +379,52 @@ public:
~raw_key (); ~raw_key ();
void decrypt (nano::uint256_union const &, nano::raw_key const &, uint128_union const &); void decrypt (nano::uint256_union const &, nano::raw_key const &, uint128_union const &);
}; };
class uint512_union class uint512_union
{ {
public:
// Type that is implicitly convertible to this union
using underlying_type = nano::uint512_t;
public: public:
uint512_union () = default; uint512_union () = default;
uint512_union (nano::uint256_union const &, nano::uint256_union const &); uint512_union (nano::uint512_t const & value)
uint512_union (nano::uint512_t const &); {
bool operator== (nano::uint512_union const &) const; bytes.fill (0);
bool operator!= (nano::uint512_union const &) const; boost::multiprecision::export_bits (value, bytes.rbegin (), 8, false);
nano::uint512_union & operator^= (nano::uint512_union const &); }
uint512_union (nano::uint256_union const & upper, nano::uint256_union const & lower) :
uint256s{ upper, lower } {};
nano::uint512_union & operator^= (nano::uint512_union const & other)
{
uint256s[0] ^= other.uint256s[0];
uint256s[1] ^= other.uint256s[1];
return *this;
}
void encode_hex (std::string &) const; void encode_hex (std::string &) const;
bool decode_hex (std::string const &); bool decode_hex (std::string const &);
void clear ();
bool is_zero () const; void clear ()
nano::uint512_t number () const; {
bytes.fill (0);
}
bool is_zero () const
{
return uint256s[0].is_zero () && uint256s[1].is_zero ();
}
nano::uint512_t number () const
{
nano::uint512_t result;
boost::multiprecision::import_bits (result, bytes.begin (), bytes.end ());
return result;
}
std::string to_string () const; std::string to_string () const;
public:
union union
{ {
std::array<uint8_t, 64> bytes; std::array<uint8_t, 64> bytes;
@ -236,6 +432,24 @@ public:
std::array<uint64_t, 8> qwords; std::array<uint64_t, 8> qwords;
std::array<uint256_union, 2> uint256s; std::array<uint256_union, 2> uint256s;
}; };
public: // Keep operators inlined
std::strong_ordering operator<=> (nano::uint512_union const & other) const
{
return std::memcmp (bytes.data (), other.bytes.data (), 64) <=> 0;
};
bool operator== (nano::uint512_union const & other) const
{
return *this <=> other == 0;
}
operator nano::uint512_t () const
{
return number ();
}
uint512_union const & as_union () const
{
return *this;
}
}; };
static_assert (std::is_nothrow_move_constructible<uint512_union>::value, "uint512_union should be noexcept MoveConstructible"); static_assert (std::is_nothrow_move_constructible<uint512_union>::value, "uint512_union should be noexcept MoveConstructible");
@ -248,15 +462,19 @@ public:
class qualified_root : public uint512_union class qualified_root : public uint512_union
{ {
public: public:
using uint512_union::uint512_union; qualified_root () = default;
qualified_root (nano::root const & root, nano::block_hash const & previous) :
uint512_union{ root.as_union (), previous.as_union () } {};
qualified_root (nano::uint512_t const & value) :
uint512_union{ value } {};
nano::root const & root () const nano::root root () const
{ {
return reinterpret_cast<nano::root const &> (uint256s[0]); return nano::root{ uint256s[0] };
} }
nano::block_hash const & previous () const nano::block_hash previous () const
{ {
return reinterpret_cast<nano::block_hash const &> (uint256s[1]); return nano::block_hash{ uint256s[1] };
} }
}; };
@ -276,6 +494,7 @@ bool from_string_hex (std::string const &, uint64_t &);
std::ostream & operator<< (std::ostream &, const uint128_union &); std::ostream & operator<< (std::ostream &, const uint128_union &);
std::ostream & operator<< (std::ostream &, const uint256_union &); std::ostream & operator<< (std::ostream &, const uint256_union &);
std::ostream & operator<< (std::ostream &, const uint512_union &); std::ostream & operator<< (std::ostream &, const uint512_union &);
std::ostream & operator<< (std::ostream &, const hash_or_account &);
/** /**
* Convert a double to string in fixed format * Convert a double to string in fixed format
@ -297,92 +516,91 @@ namespace difficulty
namespace std namespace std
{ {
template <> template <>
struct hash<::nano::uint256_union> struct hash<::nano::uint128_union>
{ {
size_t operator() (::nano::uint256_union const & data_a) const size_t operator() (::nano::uint128_union const & value) const noexcept
{ {
return data_a.qwords[0] + data_a.qwords[1] + data_a.qwords[2] + data_a.qwords[3]; return value.qwords[0] + value.qwords[1];
} }
}; };
template <> template <>
struct hash<::nano::account> struct hash<::nano::uint256_union>
{ {
size_t operator() (::nano::account const & data_a) const size_t operator() (::nano::uint256_union const & value) const noexcept
{ {
return hash<::nano::uint256_union> () (data_a); return value.qwords[0] + value.qwords[1] + value.qwords[2] + value.qwords[3];
}
};
template <>
struct hash<::nano::public_key>
{
size_t operator() (::nano::public_key const & value) const noexcept
{
return hash<::nano::uint256_union>{}(value);
} }
}; };
template <> template <>
struct hash<::nano::block_hash> struct hash<::nano::block_hash>
{ {
size_t operator() (::nano::block_hash const & data_a) const size_t operator() (::nano::block_hash const & value) const noexcept
{ {
return hash<::nano::uint256_union> () (data_a); return hash<::nano::uint256_union>{}(value);
} }
}; };
template <> template <>
struct hash<::nano::hash_or_account> struct hash<::nano::hash_or_account>
{ {
size_t operator() (::nano::hash_or_account const & data_a) const size_t operator() (::nano::hash_or_account const & value) const noexcept
{ {
return hash<::nano::block_hash> () (data_a.as_block_hash ()); return hash<::nano::block_hash>{}(value.as_block_hash ());
}
};
template <>
struct hash<::nano::raw_key>
{
size_t operator() (::nano::raw_key const & data_a) const
{
return hash<::nano::uint256_union> () (data_a);
} }
}; };
template <> template <>
struct hash<::nano::root> struct hash<::nano::root>
{ {
size_t operator() (::nano::root const & data_a) const size_t operator() (::nano::root const & value) const noexcept
{ {
return hash<::nano::uint256_union> () (data_a); return hash<::nano::hash_or_account>{}(value);
}
};
template <>
struct hash<::nano::link>
{
size_t operator() (::nano::link const & value) const noexcept
{
return hash<::nano::hash_or_account>{}(value);
}
};
template <>
struct hash<::nano::raw_key>
{
size_t operator() (::nano::raw_key const & value) const noexcept
{
return hash<::nano::uint256_union>{}(value);
} }
}; };
template <> template <>
struct hash<::nano::wallet_id> struct hash<::nano::wallet_id>
{ {
size_t operator() (::nano::wallet_id const & data_a) const size_t operator() (::nano::wallet_id const & value) const noexcept
{ {
return hash<::nano::uint256_union> () (data_a); return hash<::nano::uint256_union>{}(value);
}
};
template <>
struct hash<::nano::uint256_t>
{
size_t operator() (::nano::uint256_t const & number_a) const
{
return number_a.convert_to<size_t> ();
} }
}; };
template <> template <>
struct hash<::nano::uint512_union> struct hash<::nano::uint512_union>
{ {
size_t operator() (::nano::uint512_union const & data_a) const size_t operator() (::nano::uint512_union const & value) const noexcept
{ {
return hash<::nano::uint256_union> () (data_a.uint256s[0]) + hash<::nano::uint256_union> () (data_a.uint256s[1]); return hash<::nano::uint256_union>{}(value.uint256s[0]) + hash<::nano::uint256_union> () (value.uint256s[1]);
} }
}; };
template <> template <>
struct hash<::nano::qualified_root> struct hash<::nano::qualified_root>
{ {
size_t operator() (::nano::qualified_root const & data_a) const size_t operator() (::nano::qualified_root const & value) const noexcept
{ {
return hash<::nano::uint512_union> () (data_a); return hash<::nano::uint512_union>{}(value);
}
};
template <>
struct equal_to<std::reference_wrapper<::nano::block_hash const>>
{
bool operator() (std::reference_wrapper<::nano::block_hash const> const & lhs, std::reference_wrapper<::nano::block_hash const> const & rhs) const
{
return lhs.get () == rhs.get ();
} }
}; };
} }
@ -390,20 +608,91 @@ struct equal_to<std::reference_wrapper<::nano::block_hash const>>
namespace boost namespace boost
{ {
template <> template <>
struct hash<std::reference_wrapper<::nano::block_hash const>> struct hash<::nano::uint128_union>
{ {
size_t operator() (std::reference_wrapper<::nano::block_hash const> const & hash_a) const size_t operator() (::nano::uint128_union const & value) const noexcept
{ {
std::hash<::nano::block_hash> hash; return std::hash<::nano::uint128_union> () (value);
return hash (hash_a); }
};
template <>
struct hash<::nano::uint256_union>
{
size_t operator() (::nano::uint256_union const & value) const noexcept
{
return std::hash<::nano::uint256_union> () (value);
}
};
template <>
struct hash<::nano::public_key>
{
size_t operator() (::nano::public_key const & value) const noexcept
{
return std::hash<::nano::public_key> () (value);
}
};
template <>
struct hash<::nano::block_hash>
{
size_t operator() (::nano::block_hash const & value) const noexcept
{
return std::hash<::nano::block_hash> () (value);
}
};
template <>
struct hash<::nano::hash_or_account>
{
size_t operator() (::nano::hash_or_account const & value) const noexcept
{
return std::hash<::nano::hash_or_account> () (value);
} }
}; };
template <> template <>
struct hash<::nano::root> struct hash<::nano::root>
{ {
size_t operator() (::nano::root const & value_a) const size_t operator() (::nano::root const & value) const noexcept
{ {
return std::hash<::nano::root> () (value_a); return std::hash<::nano::root> () (value);
}
};
template <>
struct hash<::nano::link>
{
size_t operator() (::nano::link const & value) const noexcept
{
return std::hash<::nano::link> () (value);
}
};
template <>
struct hash<::nano::raw_key>
{
size_t operator() (::nano::raw_key const & value) const noexcept
{
return std::hash<::nano::raw_key> () (value);
}
};
template <>
struct hash<::nano::wallet_id>
{
size_t operator() (::nano::wallet_id const & value) const noexcept
{
return std::hash<::nano::wallet_id> () (value);
}
};
template <>
struct hash<::nano::uint512_union>
{
size_t operator() (::nano::uint512_union const & value) const noexcept
{
return std::hash<::nano::uint512_union> () (value);
}
};
template <>
struct hash<::nano::qualified_root>
{
size_t operator() (::nano::qualified_root const & value) const noexcept
{
return std::hash<::nano::qualified_root> () (value);
} }
}; };
} }
@ -427,6 +716,11 @@ struct fmt::formatter<nano::uint512_union> : fmt::ostream_formatter
{ {
}; };
template <>
struct fmt::formatter<nano::hash_or_account> : fmt::ostream_formatter
{
};
template <> template <>
struct fmt::formatter<nano::block_hash> : fmt::formatter<nano::uint256_union> struct fmt::formatter<nano::block_hash> : fmt::formatter<nano::uint256_union>
{ {
@ -440,4 +734,4 @@ struct fmt::formatter<nano::public_key> : fmt::formatter<nano::uint256_union>
template <> template <>
struct fmt::formatter<nano::qualified_root> : fmt::formatter<nano::uint512_union> struct fmt::formatter<nano::qualified_root> : fmt::formatter<nano::uint512_union>
{ {
}; };

View file

@ -12,21 +12,25 @@ template <typename... T>
class observer_set final class observer_set final
{ {
public: public:
void add (std::function<void (T...)> const & observer_a) using observer_type = std::function<void (T const &...)>;
public:
void add (observer_type observer)
{ {
nano::lock_guard<nano::mutex> lock{ mutex }; nano::lock_guard<nano::mutex> lock{ mutex };
observers.push_back (observer_a); observers.push_back (observer);
} }
void notify (T... args) const void notify (T const &... args) const
{ {
// Make observers copy to allow parallel notifications
nano::unique_lock<nano::mutex> lock{ mutex }; nano::unique_lock<nano::mutex> lock{ mutex };
auto observers_copy = observers; auto observers_copy = observers;
lock.unlock (); lock.unlock ();
for (auto & i : observers_copy) for (auto const & observer : observers_copy)
{ {
i (args...); observer (args...);
} }
} }
@ -53,7 +57,7 @@ public:
private: private:
mutable nano::mutex mutex{ mutex_identifier (mutexes::observer_set) }; mutable nano::mutex mutex{ mutex_identifier (mutexes::observer_set) };
std::vector<std::function<void (T...)>> observers; std::vector<observer_type> observers;
}; };
} }

View file

@ -1,97 +0,0 @@
#include <nano/lib/thread_pool.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/thread_pool.hpp>
/*
* thread_pool
*/
nano::thread_pool::thread_pool (unsigned num_threads, nano::thread_role::name thread_name) :
num_threads (num_threads),
thread_pool_m (std::make_unique<boost::asio::thread_pool> (num_threads)),
thread_names_latch{ num_threads }
{
set_thread_names (thread_name);
}
nano::thread_pool::~thread_pool ()
{
stop ();
}
void nano::thread_pool::stop ()
{
nano::unique_lock<nano::mutex> lk (mutex);
if (!stopped)
{
stopped = true;
#if defined(BOOST_ASIO_HAS_IOCP)
// A hack needed for Windows to prevent deadlock during destruction, described here: https://github.com/chriskohlhoff/asio/issues/431
boost::asio::use_service<boost::asio::detail::win_iocp_io_context> (*thread_pool_m).stop ();
#endif
lk.unlock ();
thread_pool_m->stop ();
thread_pool_m->join ();
lk.lock ();
thread_pool_m = nullptr;
}
}
void nano::thread_pool::push_task (std::function<void ()> task)
{
++num_tasks;
nano::lock_guard<nano::mutex> guard (mutex);
if (!stopped)
{
boost::asio::post (*thread_pool_m, [this, task] () {
task ();
--num_tasks;
});
}
}
void nano::thread_pool::add_timed_task (std::chrono::steady_clock::time_point const & expiry_time, std::function<void ()> task)
{
nano::lock_guard<nano::mutex> guard (mutex);
if (!stopped && thread_pool_m)
{
auto timer = std::make_shared<boost::asio::steady_timer> (thread_pool_m->get_executor (), expiry_time);
timer->async_wait ([this, task, timer] (boost::system::error_code const & ec) {
if (!ec)
{
push_task (task);
}
});
}
}
unsigned nano::thread_pool::get_num_threads () const
{
return num_threads;
}
uint64_t nano::thread_pool::num_queued_tasks () const
{
return num_tasks;
}
void nano::thread_pool::set_thread_names (nano::thread_role::name thread_name)
{
for (auto i = 0u; i < num_threads; ++i)
{
boost::asio::post (*thread_pool_m, [this, thread_name] () {
nano::thread_role::set (thread_name);
thread_names_latch.arrive_and_wait ();
});
}
thread_names_latch.wait ();
}
nano::container_info nano::thread_pool::container_info () const
{
nano::container_info info;
info.put ("count", num_queued_tasks ());
return info;
}

View file

@ -4,50 +4,151 @@
#include <nano/lib/thread_roles.hpp> #include <nano/lib/thread_roles.hpp>
#include <nano/lib/threading.hpp> #include <nano/lib/threading.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/thread_pool.hpp>
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <functional>
#include <latch> #include <latch>
#include <memory>
namespace boost::asio #include <type_traits>
{
class thread_pool;
}
namespace nano namespace nano
{ {
class thread_pool final class thread_pool final
{ {
public: public:
explicit thread_pool (unsigned num_threads, nano::thread_role::name); // TODO: Auto start should be removed once the node is refactored to start the thread pool explicitly
~thread_pool (); thread_pool (unsigned num_threads, nano::thread_role::name thread_name, bool auto_start = false) :
num_threads{ num_threads },
thread_name{ thread_name },
thread_names_latch{ num_threads }
{
if (auto_start)
{
start ();
}
}
/** This will run when there is an available thread for execution */ ~thread_pool ()
void push_task (std::function<void ()>); {
// Must be stopped before destruction to avoid running takss when node components are being destroyed
debug_assert (!thread_pool_impl);
}
/** Run a task at a certain point in time */ void start ()
void add_timed_task (std::chrono::steady_clock::time_point const & expiry_time, std::function<void ()> task); {
debug_assert (!stopped);
debug_assert (!thread_pool_impl);
thread_pool_impl = std::make_unique<boost::asio::thread_pool> (num_threads);
set_thread_names ();
}
/** Stops any further pushed tasks from executing */ void stop ()
void stop (); {
nano::unique_lock<nano::mutex> lock{ mutex };
if (!stopped && thread_pool_impl)
{
stopped = true;
/** Number of threads in the thread pool */ // TODO: Is this still needed?
unsigned get_num_threads () const; #if defined(BOOST_ASIO_HAS_IOCP)
// A hack needed for Windows to prevent deadlock during destruction, described here: https://github.com/chriskohlhoff/asio/issues/431
boost::asio::use_service<boost::asio::detail::win_iocp_io_context> (*thread_pool_impl).stop ();
#endif
/** Returns the number of tasks which are awaiting execution by the thread pool **/ lock.unlock ();
uint64_t num_queued_tasks () const;
nano::container_info container_info () const; thread_pool_impl->stop ();
thread_pool_impl->join ();
lock.lock ();
thread_pool_impl = nullptr;
}
}
template <typename F>
void post (F && task)
{
nano::lock_guard<nano::mutex> guard{ mutex };
if (!stopped)
{
++num_tasks;
release_assert (thread_pool_impl);
boost::asio::post (*thread_pool_impl, [this, t = std::forward<F> (task)] () mutable {
t ();
--num_tasks;
});
}
}
template <typename F>
void post_delayed (std::chrono::steady_clock::duration const & delay, F && task)
{
nano::lock_guard<nano::mutex> guard{ mutex };
if (!stopped)
{
++num_delayed;
release_assert (thread_pool_impl);
auto timer = std::make_shared<boost::asio::steady_timer> (thread_pool_impl->get_executor ());
timer->expires_after (delay);
timer->async_wait ([this, t = std::forward<F> (task), /* preserve lifetime */ timer] (boost::system::error_code const & ec) mutable {
if (!ec)
{
--num_delayed;
post (std::move (t));
}
});
}
}
bool alive () const
{
nano::lock_guard<nano::mutex> guard{ mutex };
return thread_pool_impl != nullptr;
}
uint64_t queued_tasks () const
{
return num_tasks;
}
uint64_t delayed_tasks () const
{
return num_delayed;
}
nano::container_info container_info () const
{
nano::container_info info;
info.put ("tasks", num_tasks);
info.put ("delayed", num_delayed);
return info;
}
private: private:
nano::mutex mutex; void set_thread_names ()
std::atomic<bool> stopped{ false }; {
unsigned num_threads; for (auto i = 0u; i < num_threads; ++i)
std::unique_ptr<boost::asio::thread_pool> thread_pool_m; {
nano::relaxed_atomic_integral<uint64_t> num_tasks{ 0 }; boost::asio::post (*thread_pool_impl, [this] () {
nano::thread_role::set (thread_name);
thread_names_latch.arrive_and_wait ();
});
}
thread_names_latch.wait ();
}
private:
unsigned const num_threads;
nano::thread_role::name const thread_name;
/** Set the names of all the threads in the thread pool for easier identification */
std::latch thread_names_latch; std::latch thread_names_latch;
void set_thread_names (nano::thread_role::name thread_name); mutable nano::mutex mutex;
std::atomic<bool> stopped{ false };
std::unique_ptr<boost::asio::thread_pool> thread_pool_impl;
std::atomic<uint64_t> num_tasks{ 0 };
std::atomic<uint64_t> num_delayed{ 0 };
}; };
} // namespace nano }

View file

@ -37,6 +37,9 @@ std::string nano::thread_role::get_string (nano::thread_role::name role)
case nano::thread_role::name::block_processing: case nano::thread_role::name::block_processing:
thread_role_name_string = "Blck processing"; thread_role_name_string = "Blck processing";
break; break;
case nano::thread_role::name::block_processing_notifications:
thread_role_name_string = "Blck proc notif";
break;
case nano::thread_role::name::request_loop: case nano::thread_role::name::request_loop:
thread_role_name_string = "Request loop"; thread_role_name_string = "Request loop";
break; break;

View file

@ -17,6 +17,7 @@ enum class name
vote_processing, vote_processing,
vote_cache_processing, vote_cache_processing,
block_processing, block_processing,
block_processing_notifications,
request_loop, request_loop,
wallet_actions, wallet_actions,
bootstrap_initiator, bootstrap_initiator,

View file

@ -353,7 +353,7 @@ int main (int argc, char * const * argv)
auto inactive_node = nano::default_inactive_node (data_path, vm); auto inactive_node = nano::default_inactive_node (data_path, vm);
auto transaction = inactive_node->node->store.tx_begin_read (); auto transaction = inactive_node->node->store.tx_begin_read ();
auto i = inactive_node->node->store.block.begin (transaction); auto i = inactive_node->node->store.block.begin (transaction);
auto end = inactive_node->node->store.block.end (); auto end = inactive_node->node->store.block.end (transaction);
for (; i != end; ++i) for (; i != end; ++i)
{ {
nano::block_hash hash = i->first; nano::block_hash hash = i->first;
@ -435,7 +435,7 @@ int main (int argc, char * const * argv)
auto current (node->online_reps.trended ()); auto current (node->online_reps.trended ());
std::cout << boost::str (boost::format ("Trended Weight %1%\n") % current); std::cout << boost::str (boost::format ("Trended Weight %1%\n") % current);
auto transaction (node->store.tx_begin_read ()); auto transaction (node->store.tx_begin_read ());
for (auto i (node->store.online_weight.begin (transaction)), n (node->store.online_weight.end ()); i != n; ++i) for (auto i (node->store.online_weight.begin (transaction)), n (node->store.online_weight.end (transaction)); i != n; ++i)
{ {
using time_point = std::chrono::system_clock::time_point; using time_point = std::chrono::system_clock::time_point;
time_point ts (std::chrono::duration_cast<time_point::duration> (std::chrono::nanoseconds (i->first))); time_point ts (std::chrono::duration_cast<time_point::duration> (std::chrono::nanoseconds (i->first)));
@ -471,7 +471,7 @@ int main (int argc, char * const * argv)
// Cache the account heads to make searching quicker against unchecked keys. // Cache the account heads to make searching quicker against unchecked keys.
auto transaction (node->store.tx_begin_read ()); auto transaction (node->store.tx_begin_read ());
std::unordered_set<nano::block_hash> frontier_hashes; std::unordered_set<nano::block_hash> frontier_hashes;
for (auto i (node->store.account.begin (transaction)), n (node->store.account.end ()); i != n; ++i) for (auto i (node->store.account.begin (transaction)), n (node->store.account.end (transaction)); i != n; ++i)
{ {
frontier_hashes.insert (i->second.head); frontier_hashes.insert (i->second.head);
} }
@ -1669,7 +1669,7 @@ int main (int argc, char * const * argv)
} }
size_t const accounts_deque_overflow (32 * 1024); size_t const accounts_deque_overflow (32 * 1024);
auto transaction = node->ledger.tx_begin_read (); auto transaction = node->ledger.tx_begin_read ();
for (auto i (node->store.account.begin (transaction)), n (node->store.account.end ()); i != n; ++i) for (auto i (node->store.account.begin (transaction)), n (node->store.account.end (transaction)); i != n; ++i)
{ {
{ {
nano::unique_lock<nano::mutex> lock{ mutex }; nano::unique_lock<nano::mutex> lock{ mutex };
@ -1780,7 +1780,7 @@ int main (int argc, char * const * argv)
start_threads (check_pending, pending); start_threads (check_pending, pending);
size_t const pending_deque_overflow (64 * 1024); size_t const pending_deque_overflow (64 * 1024);
for (auto i (node->store.pending.begin (transaction)), n (node->store.pending.end ()); i != n; ++i) for (auto i (node->store.pending.begin (transaction)), n (node->store.pending.end (transaction)); i != n; ++i)
{ {
{ {
nano::unique_lock<nano::mutex> lock{ mutex }; nano::unique_lock<nano::mutex> lock{ mutex };
@ -1837,7 +1837,7 @@ int main (int argc, char * const * argv)
auto transaction = source_node->ledger.tx_begin_read (); auto transaction = source_node->ledger.tx_begin_read ();
block_count = source_node->ledger.block_count (); block_count = source_node->ledger.block_count ();
std::cout << boost::str (boost::format ("Performing bootstrap emulation, %1% blocks in ledger...") % block_count) << std::endl; std::cout << boost::str (boost::format ("Performing bootstrap emulation, %1% blocks in ledger...") % block_count) << std::endl;
for (auto i (source_node->store.account.begin (transaction)), n (source_node->store.account.end ()); i != n; ++i) for (auto i (source_node->store.account.begin (transaction)), n (source_node->store.account.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
@ -1942,7 +1942,7 @@ int main (int argc, char * const * argv)
nano::locked<std::vector<boost::unordered_set<nano::account>>> opened_account_versions_shared (epoch_count); nano::locked<std::vector<boost::unordered_set<nano::account>>> opened_account_versions_shared (epoch_count);
using opened_account_versions_t = decltype (opened_account_versions_shared)::value_type; using opened_account_versions_t = decltype (opened_account_versions_shared)::value_type;
node->store.account.for_each_par ( node->store.account.for_each_par (
[&opened_account_versions_shared, epoch_count] (nano::store::read_transaction const & /*unused*/, nano::store::iterator<nano::account, nano::account_info> i, nano::store::iterator<nano::account, nano::account_info> n) { [&opened_account_versions_shared, epoch_count] (nano::store::read_transaction const & /*unused*/, auto i, auto n) {
// First cache locally // First cache locally
opened_account_versions_t opened_account_versions_l (epoch_count); opened_account_versions_t opened_account_versions_l (epoch_count);
for (; i != n; ++i) for (; i != n; ++i)
@ -1979,7 +1979,7 @@ int main (int argc, char * const * argv)
nano::locked<boost::unordered_map<nano::account, std::underlying_type_t<nano::epoch>>> unopened_highest_pending_shared; nano::locked<boost::unordered_map<nano::account, std::underlying_type_t<nano::epoch>>> unopened_highest_pending_shared;
using unopened_highest_pending_t = decltype (unopened_highest_pending_shared)::value_type; using unopened_highest_pending_t = decltype (unopened_highest_pending_shared)::value_type;
node->store.pending.for_each_par ( node->store.pending.for_each_par (
[&unopened_highest_pending_shared, &opened_accounts] (nano::store::read_transaction const & /*unused*/, nano::store::iterator<nano::pending_key, nano::pending_info> i, nano::store::iterator<nano::pending_key, nano::pending_info> n) { [&unopened_highest_pending_shared, &opened_accounts] (nano::store::read_transaction const & /*unused*/, auto i, auto n) {
// First cache locally // First cache locally
unopened_highest_pending_t unopened_highest_pending_l; unopened_highest_pending_t unopened_highest_pending_l;
for (; i != n; ++i) for (; i != n; ++i)

View file

@ -18,6 +18,7 @@
#include <nano/rpc/rpc.hpp> #include <nano/rpc/rpc.hpp>
#include <nano/secure/working.hpp> #include <nano/secure/working.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
@ -147,7 +148,7 @@ public:
{ {
auto transaction (wallet->wallets.tx_begin_write ()); auto transaction (wallet->wallets.tx_begin_write ());
auto existing (wallet->store.begin (transaction)); auto existing (wallet->store.begin (transaction));
if (existing != wallet->store.end ()) if (existing != wallet->store.end (transaction))
{ {
wallet_config.account = existing->first; wallet_config.account = existing->first;
} }

View file

@ -29,20 +29,37 @@ nano::active_elections::active_elections (nano::node & node_a, nano::confirming_
{ {
count_by_behavior.fill (0); // Zero initialize array count_by_behavior.fill (0); // Zero initialize array
// Cementing blocks might implicitly confirm dependent elections
confirming_set.batch_cemented.add ([this] (auto const & cemented) { confirming_set.batch_cemented.add ([this] (auto const & cemented) {
auto transaction = node.ledger.tx_begin_read (); std::deque<block_cemented_result> results;
for (auto const & [block, confirmation_root, source_election] : cemented)
{ {
transaction.refresh_if_needed (); // Process all cemented blocks while holding the lock to avoid races where an election for a block that is already cemented is inserted
block_cemented (transaction, block, confirmation_root, source_election); nano::lock_guard<nano::mutex> guard{ mutex };
for (auto const & [block, confirmation_root, source_election] : cemented)
{
auto result = block_cemented (block, confirmation_root, source_election);
results.push_back (result);
}
}
{
// TODO: This could be offloaded to a separate notification worker, profiling is needed
auto transaction = node.ledger.tx_begin_read ();
for (auto const & [status, votes] : results)
{
transaction.refresh_if_needed ();
notify_observers (transaction, status, votes);
}
} }
}); });
// Notify elections about alternative (forked) blocks // Notify elections about alternative (forked) blocks
block_processor.block_processed.add ([this] (auto const & result, auto const & context) { block_processor.batch_processed.add ([this] (auto const & batch) {
if (result == nano::block_status::fork) for (auto const & [result, context] : batch)
{ {
publish (context.block); if (result == nano::block_status::fork)
{
publish (context.block);
}
} }
}); });
@ -87,16 +104,17 @@ void nano::active_elections::stop ()
clear (); clear ();
} }
void nano::active_elections::block_cemented (nano::secure::transaction const & transaction, std::shared_ptr<nano::block> const & block, nano::block_hash const & confirmation_root, std::shared_ptr<nano::election> const & source_election) auto nano::active_elections::block_cemented (std::shared_ptr<nano::block> const & block, nano::block_hash const & confirmation_root, std::shared_ptr<nano::election> const & source_election) -> block_cemented_result
{ {
debug_assert (!mutex.try_lock ());
debug_assert (node.block_confirmed (block->hash ())); debug_assert (node.block_confirmed (block->hash ()));
// Dependent elections are implicitly confirmed when their block is cemented // Dependent elections are implicitly confirmed when their block is cemented
auto dependend_election = election (block->qualified_root ()); auto dependend_election = election_impl (block->qualified_root ());
if (dependend_election) if (dependend_election)
{ {
node.stats.inc (nano::stat::type::active_elections, nano::stat::detail::confirm_dependent); node.stats.inc (nano::stat::type::active_elections, nano::stat::detail::confirm_dependent);
dependend_election->try_confirm (block->hash ()); dependend_election->try_confirm (block->hash ()); // TODO: This should either confirm or cancel the election
} }
nano::election_status status; nano::election_status status;
@ -130,16 +148,7 @@ void nano::active_elections::block_cemented (nano::secure::transaction const & t
nano::log::arg{ "confirmation_root", confirmation_root }, nano::log::arg{ "confirmation_root", confirmation_root },
nano::log::arg{ "source_election", source_election }); nano::log::arg{ "source_election", source_election });
notify_observers (transaction, status, votes); return { status, votes };
bool cemented_bootstrap_count_reached = node.ledger.cemented_count () >= node.ledger.bootstrap_weight_max_blocks;
bool was_active = status.type == nano::election_status_type::active_confirmed_quorum || status.type == nano::election_status_type::active_confirmation_height;
// Next-block activations are only done for blocks with previously active elections
if (cemented_bootstrap_count_reached && was_active && !node.flags.disable_activate_successors)
{
activate_successors (transaction, block);
}
} }
void nano::active_elections::notify_observers (nano::secure::transaction const & transaction, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes) const void nano::active_elections::notify_observers (nano::secure::transaction const & transaction, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes) const
@ -177,17 +186,6 @@ void nano::active_elections::notify_observers (nano::secure::transaction const &
} }
} }
void nano::active_elections::activate_successors (nano::secure::transaction const & transaction, std::shared_ptr<nano::block> const & block)
{
node.scheduler.priority.activate (transaction, block->account ());
// Start or vote for the next unconfirmed block in the destination account
if (block->is_send () && !block->destination ().is_zero () && block->destination () != block->account ())
{
node.scheduler.priority.activate (transaction, block->destination ());
}
}
int64_t nano::active_elections::limit (nano::election_behavior behavior) const int64_t nano::active_elections::limit (nano::election_behavior behavior) const
{ {
switch (behavior) switch (behavior)
@ -320,7 +318,7 @@ void nano::active_elections::cleanup_election (nano::unique_lock<nano::mutex> &
entry.erased_callback (election); entry.erased_callback (election);
} }
vacancy_update (); vacancy_updated.notify ();
for (auto const & [hash, block] : blocks_l) for (auto const & [hash, block] : blocks_l)
{ {
@ -443,7 +441,7 @@ nano::election_insertion_result nano::active_elections::insert (std::shared_ptr<
node.vote_cache_processor.trigger (hash); node.vote_cache_processor.trigger (hash);
node.observers.active_started.notify (hash); node.observers.active_started.notify (hash);
vacancy_update (); vacancy_updated.notify ();
} }
// Votes are generated for inserted or ongoing elections // Votes are generated for inserted or ongoing elections
@ -467,11 +465,17 @@ bool nano::active_elections::active (nano::block const & block_a) const
return roots.get<tag_root> ().find (block_a.qualified_root ()) != roots.get<tag_root> ().end (); return roots.get<tag_root> ().find (block_a.qualified_root ()) != roots.get<tag_root> ().end ();
} }
std::shared_ptr<nano::election> nano::active_elections::election (nano::qualified_root const & root_a) const std::shared_ptr<nano::election> nano::active_elections::election (nano::qualified_root const & root) const
{ {
std::shared_ptr<nano::election> result;
nano::lock_guard<nano::mutex> lock{ mutex }; nano::lock_guard<nano::mutex> lock{ mutex };
auto existing = roots.get<tag_root> ().find (root_a); return election_impl (root);
}
std::shared_ptr<nano::election> nano::active_elections::election_impl (nano::qualified_root const & root) const
{
debug_assert (!mutex.try_lock ());
std::shared_ptr<nano::election> result;
auto existing = roots.get<tag_root> ().find (root);
if (existing != roots.get<tag_root> ().end ()) if (existing != roots.get<tag_root> ().end ())
{ {
result = existing->election; result = existing->election;
@ -549,8 +553,7 @@ void nano::active_elections::clear ()
nano::lock_guard<nano::mutex> guard{ mutex }; nano::lock_guard<nano::mutex> guard{ mutex };
roots.clear (); roots.clear ();
} }
vacancy_updated.notify ();
vacancy_update ();
} }
nano::container_info nano::active_elections::container_info () const nano::container_info nano::active_elections::container_info () const

View file

@ -2,6 +2,7 @@
#include <nano/lib/enum_util.hpp> #include <nano/lib/enum_util.hpp>
#include <nano/lib/numbers.hpp> #include <nano/lib/numbers.hpp>
#include <nano/lib/observer_set.hpp>
#include <nano/node/election_behavior.hpp> #include <nano/node/election_behavior.hpp>
#include <nano/node/election_insertion_result.hpp> #include <nano/node/election_insertion_result.hpp>
#include <nano/node/election_status.hpp> #include <nano/node/election_status.hpp>
@ -104,7 +105,7 @@ public:
bool active (nano::qualified_root const &) const; bool active (nano::qualified_root const &) const;
std::shared_ptr<nano::election> election (nano::qualified_root const &) const; std::shared_ptr<nano::election> election (nano::qualified_root const &) const;
// Returns a list of elections sorted by difficulty // Returns a list of elections sorted by difficulty
std::vector<std::shared_ptr<nano::election>> list_active (std::size_t = std::numeric_limits<std::size_t>::max ()); std::vector<std::shared_ptr<nano::election>> list_active (std::size_t max_count = std::numeric_limits<std::size_t>::max ());
bool erase (nano::block const &); bool erase (nano::block const &);
bool erase (nano::qualified_root const &); bool erase (nano::qualified_root const &);
bool empty () const; bool empty () const;
@ -121,21 +122,24 @@ public:
* How many election slots are available for specified election type * How many election slots are available for specified election type
*/ */
int64_t vacancy (nano::election_behavior behavior) const; int64_t vacancy (nano::election_behavior behavior) const;
std::function<void ()> vacancy_update{ [] () {} };
nano::container_info container_info () const; nano::container_info container_info () const;
public: // Events
nano::observer_set<> vacancy_updated;
private: private:
void request_loop (); void request_loop ();
void request_confirm (nano::unique_lock<nano::mutex> &); void request_confirm (nano::unique_lock<nano::mutex> &);
// Erase all blocks from active and, if not confirmed, clear digests from network filters // Erase all blocks from active and, if not confirmed, clear digests from network filters
void cleanup_election (nano::unique_lock<nano::mutex> & lock_a, std::shared_ptr<nano::election>); void cleanup_election (nano::unique_lock<nano::mutex> & lock_a, std::shared_ptr<nano::election>);
nano::stat::type completion_type (nano::election const & election) const;
// Returns a list of elections sorted by difficulty, mutex must be locked using block_cemented_result = std::pair<nano::election_status, std::vector<nano::vote_with_weight_info>>;
std::vector<std::shared_ptr<nano::election>> list_active_impl (std::size_t) const; block_cemented_result block_cemented (std::shared_ptr<nano::block> const & block, nano::block_hash const & confirmation_root, std::shared_ptr<nano::election> const & source_election);
void activate_successors (nano::secure::transaction const &, std::shared_ptr<nano::block> const & block);
void notify_observers (nano::secure::transaction const &, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes) const; void notify_observers (nano::secure::transaction const &, nano::election_status const & status, std::vector<nano::vote_with_weight_info> const & votes) const;
void block_cemented (nano::secure::transaction const &, std::shared_ptr<nano::block> const & block, nano::block_hash const & confirmation_root, std::shared_ptr<nano::election> const & source_election);
std::shared_ptr<nano::election> election_impl (nano::qualified_root const &) const;
std::vector<std::shared_ptr<nano::election>> list_active_impl (std::size_t max_count) const;
private: // Dependencies private: // Dependencies
active_elections_config const & config; active_elections_config const & config;

View file

@ -96,7 +96,7 @@ void nano::backlog_population::populate_backlog (nano::unique_lock<nano::mutex>
auto transaction = ledger.tx_begin_read (); auto transaction = ledger.tx_begin_read ();
auto it = ledger.store.account.begin (transaction, next); auto it = ledger.store.account.begin (transaction, next);
auto const end = ledger.store.account.end (); auto const end = ledger.store.account.end (transaction);
auto should_refresh = [&transaction] () { auto should_refresh = [&transaction] () {
auto cutoff = std::chrono::steady_clock::now () - 100ms; // TODO: Make this configurable auto cutoff = std::chrono::steady_clock::now () - 100ms; // TODO: Make this configurable

View file

@ -13,28 +13,6 @@
#include <utility> #include <utility>
/*
* block_processor::context
*/
nano::block_processor::context::context (std::shared_ptr<nano::block> block, nano::block_source source_a, callback_t callback_a) :
block{ std::move (block) },
source{ source_a },
callback{ std::move (callback_a) }
{
debug_assert (source != nano::block_source::unknown);
}
auto nano::block_processor::context::get_future () -> std::future<result_t>
{
return promise.get_future ();
}
void nano::block_processor::context::set_result (result_t const & result)
{
promise.set_value (result);
}
/* /*
* block_processor * block_processor
*/ */
@ -45,7 +23,8 @@ nano::block_processor::block_processor (nano::node_config const & node_config, n
ledger{ ledger_a }, ledger{ ledger_a },
unchecked{ unchecked_a }, unchecked{ unchecked_a },
stats{ stats_a }, stats{ stats_a },
logger{ logger_a } logger{ logger_a },
workers{ 1, nano::thread_role::name::block_processing_notifications }
{ {
batch_processed.add ([this] (auto const & items) { batch_processed.add ([this] (auto const & items) {
// For every batch item: notify the 'processed' observer. // For every batch item: notify the 'processed' observer.
@ -93,12 +72,15 @@ nano::block_processor::~block_processor ()
{ {
// Thread must be stopped before destruction // Thread must be stopped before destruction
debug_assert (!thread.joinable ()); debug_assert (!thread.joinable ());
debug_assert (!workers.alive ());
} }
void nano::block_processor::start () void nano::block_processor::start ()
{ {
debug_assert (!thread.joinable ()); debug_assert (!thread.joinable ());
workers.start ();
thread = std::thread ([this] () { thread = std::thread ([this] () {
nano::thread_role::set (nano::thread_role::name::block_processing); nano::thread_role::set (nano::thread_role::name::block_processing);
run (); run ();
@ -116,6 +98,7 @@ void nano::block_processor::stop ()
{ {
thread.join (); thread.join ();
} }
workers.stop ();
} }
// TODO: Remove and replace all checks with calls to size (block_source) // TODO: Remove and replace all checks with calls to size (block_source)
@ -231,13 +214,24 @@ void nano::block_processor::rollback_competitor (secure::write_transaction const
void nano::block_processor::run () void nano::block_processor::run ()
{ {
nano::interval log_interval;
nano::unique_lock<nano::mutex> lock{ mutex }; nano::unique_lock<nano::mutex> lock{ mutex };
while (!stopped) while (!stopped)
{ {
if (!queue.empty ()) if (!queue.empty ())
{ {
// TODO: Cleaner periodical logging // It's possible that ledger processing happens faster than the notifications can be processed by other components, cooldown here
if (should_log ()) while (workers.queued_tasks () >= config.max_queued_notifications)
{
stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::cooldown);
condition.wait_for (lock, 100ms, [this] { return stopped; });
if (stopped)
{
return;
}
}
if (log_interval.elapsed (15s))
{ {
logger.info (nano::log::type::blockprocessor, "{} blocks (+ {} forced) in processing queue", logger.info (nano::log::type::blockprocessor, "{} blocks (+ {} forced) in processing queue",
queue.size (), queue.size (),
@ -246,41 +240,32 @@ void nano::block_processor::run ()
auto processed = process_batch (lock); auto processed = process_batch (lock);
debug_assert (!lock.owns_lock ()); debug_assert (!lock.owns_lock ());
// Set results for futures when not holding the lock
for (auto & [result, context] : processed)
{
if (context.callback)
{
context.callback (result);
}
context.set_result (result);
}
batch_processed.notify (processed);
lock.lock (); lock.lock ();
// Queue notifications to be dispatched in the background
workers.post ([this, processed = std::move (processed)] () mutable {
stats.inc (nano::stat::type::blockprocessor, nano::stat::detail::notify);
// Set results for futures when not holding the lock
for (auto & [result, context] : processed)
{
if (context.callback)
{
context.callback (result);
}
context.set_result (result);
}
batch_processed.notify (processed);
});
} }
else else
{ {
condition.notify_one (); condition.wait (lock, [this] {
condition.wait (lock); return stopped || !queue.empty ();
});
} }
} }
} }
bool nano::block_processor::should_log ()
{
auto result (false);
auto now (std::chrono::steady_clock::now ());
if (next_log < now)
{
next_log = now + std::chrono::seconds (15);
result = true;
}
return result;
}
auto nano::block_processor::next () -> context auto nano::block_processor::next () -> context
{ {
debug_assert (!mutex.try_lock ()); debug_assert (!mutex.try_lock ());
@ -317,7 +302,7 @@ auto nano::block_processor::process_batch (nano::unique_lock<nano::mutex> & lock
debug_assert (!mutex.try_lock ()); debug_assert (!mutex.try_lock ());
debug_assert (!queue.empty ()); debug_assert (!queue.empty ());
auto batch = next_batch (256); auto batch = next_batch (config.batch_size);
lock.unlock (); lock.unlock ();
@ -464,9 +449,32 @@ nano::container_info nano::block_processor::container_info () const
info.put ("blocks", queue.size ()); info.put ("blocks", queue.size ());
info.put ("forced", queue.size ({ nano::block_source::forced })); info.put ("forced", queue.size ({ nano::block_source::forced }));
info.add ("queue", queue.container_info ()); info.add ("queue", queue.container_info ());
info.add ("workers", workers.container_info ());
return info; return info;
} }
/*
* block_processor::context
*/
nano::block_processor::context::context (std::shared_ptr<nano::block> block, nano::block_source source_a, callback_t callback_a) :
block{ std::move (block) },
source{ source_a },
callback{ std::move (callback_a) }
{
debug_assert (source != nano::block_source::unknown);
}
auto nano::block_processor::context::get_future () -> std::future<result_t>
{
return promise.get_future ();
}
void nano::block_processor::context::set_result (result_t const & result)
{
promise.set_value (result);
}
/* /*
* block_processor_config * block_processor_config
*/ */

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <nano/lib/logging.hpp> #include <nano/lib/logging.hpp>
#include <nano/lib/thread_pool.hpp>
#include <nano/node/fair_queue.hpp> #include <nano/node/fair_queue.hpp>
#include <nano/node/fwd.hpp> #include <nano/node/fwd.hpp>
#include <nano/secure/common.hpp> #include <nano/secure/common.hpp>
@ -46,6 +47,9 @@ public:
size_t priority_live{ 1 }; size_t priority_live{ 1 };
size_t priority_bootstrap{ 8 }; size_t priority_bootstrap{ 8 };
size_t priority_local{ 16 }; size_t priority_local{ 16 };
size_t batch_size{ 256 };
size_t max_queued_notifications{ 8 };
}; };
/** /**
@ -89,7 +93,6 @@ public:
bool add (std::shared_ptr<nano::block> const &, nano::block_source = nano::block_source::live, std::shared_ptr<nano::transport::channel> const & channel = nullptr, std::function<void (nano::block_status)> callback = {}); bool add (std::shared_ptr<nano::block> const &, nano::block_source = nano::block_source::live, std::shared_ptr<nano::transport::channel> const & channel = nullptr, std::function<void (nano::block_status)> callback = {});
std::optional<nano::block_status> add_blocking (std::shared_ptr<nano::block> const & block, nano::block_source); std::optional<nano::block_status> add_blocking (std::shared_ptr<nano::block> const & block, nano::block_source);
void force (std::shared_ptr<nano::block> const &); void force (std::shared_ptr<nano::block> const &);
bool should_log ();
nano::container_info container_info () const; nano::container_info container_info () const;
@ -127,11 +130,11 @@ private:
private: private:
nano::fair_queue<context, nano::block_source> queue; nano::fair_queue<context, nano::block_source> queue;
std::chrono::steady_clock::time_point next_log{ std::chrono::steady_clock::now () };
bool stopped{ false }; bool stopped{ false };
nano::condition_variable condition; nano::condition_variable condition;
mutable nano::mutex mutex{ mutex_identifier (mutexes::block_processor) }; mutable nano::mutex mutex{ mutex_identifier (mutexes::block_processor) };
std::thread thread; std::thread thread;
nano::thread_pool workers;
}; };
} }

View file

@ -313,7 +313,7 @@ void nano::pulls_cache::add (nano::pull_info const & pull_a)
cache.erase (cache.begin ()); cache.erase (cache.begin ());
} }
debug_assert (cache.size () <= cache_size_max); debug_assert (cache.size () <= cache_size_max);
nano::uint512_union head_512 (pull_a.account_or_head, pull_a.head_original); nano::uint512_union head_512 (pull_a.account_or_head.as_union (), pull_a.head_original);
auto existing (cache.get<account_head_tag> ().find (head_512)); auto existing (cache.get<account_head_tag> ().find (head_512));
if (existing == cache.get<account_head_tag> ().end ()) if (existing == cache.get<account_head_tag> ().end ())
{ {
@ -336,7 +336,7 @@ void nano::pulls_cache::add (nano::pull_info const & pull_a)
void nano::pulls_cache::update_pull (nano::pull_info & pull_a) void nano::pulls_cache::update_pull (nano::pull_info & pull_a)
{ {
nano::lock_guard<nano::mutex> guard{ pulls_cache_mutex }; nano::lock_guard<nano::mutex> guard{ pulls_cache_mutex };
nano::uint512_union head_512 (pull_a.account_or_head, pull_a.head_original); nano::uint512_union head_512 (pull_a.account_or_head.as_union (), pull_a.head_original);
auto existing (cache.get<account_head_tag> ().find (head_512)); auto existing (cache.get<account_head_tag> ().find (head_512));
if (existing != cache.get<account_head_tag> ().end ()) if (existing != cache.get<account_head_tag> ().end ())
{ {
@ -347,7 +347,7 @@ void nano::pulls_cache::update_pull (nano::pull_info & pull_a)
void nano::pulls_cache::remove (nano::pull_info const & pull_a) void nano::pulls_cache::remove (nano::pull_info const & pull_a)
{ {
nano::lock_guard<nano::mutex> guard{ pulls_cache_mutex }; nano::lock_guard<nano::mutex> guard{ pulls_cache_mutex };
nano::uint512_union head_512 (pull_a.account_or_head, pull_a.head_original); nano::uint512_union head_512 (pull_a.account_or_head.as_union (), pull_a.head_original);
cache.get<account_head_tag> ().erase (head_512); cache.get<account_head_tag> ().erase (head_512);
} }

View file

@ -127,7 +127,7 @@ void nano::bulk_pull_client::throttled_receive_block ()
else else
{ {
auto this_l (shared_from_this ()); auto this_l (shared_from_this ());
node->workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (1), [this_l] () { node->workers.post_delayed (std::chrono::seconds (1), [this_l] () {
if (!this_l->connection->pending_stop && !this_l->attempt->stopped) if (!this_l->connection->pending_stop && !this_l->attempt->stopped)
{ {
this_l->throttled_receive_block (); this_l->throttled_receive_block ();
@ -177,7 +177,7 @@ void nano::bulk_pull_client::received_block (boost::system::error_code ec, std::
// Is block expected? // Is block expected?
bool block_expected (false); bool block_expected (false);
// Unconfirmed head is used only for lazy destinations if legacy bootstrap is not available, see nano::bootstrap_attempt::lazy_destinations_increment (...) // Unconfirmed head is used only for lazy destinations if legacy bootstrap is not available, see nano::bootstrap_attempt::lazy_destinations_increment (...)
bool unconfirmed_account_head = node->flags.disable_legacy_bootstrap && pull_blocks == 0 && pull.retry_limit <= node->network_params.bootstrap.lazy_retry_limit && (expected == pull.account_or_head.as_block_hash ()) && (block->account_field () == pull.account_or_head.as_account ()); bool unconfirmed_account_head = node->flags.disable_legacy_bootstrap && pull_blocks == 0 && pull.retry_limit <= node->network_params.bootstrap.lazy_retry_limit && (expected == pull.account_or_head.as_block_hash ()) && (block->account_field ().value_or (0) == pull.account_or_head.as_account ());
if (hash == expected || unconfirmed_account_head) if (hash == expected || unconfirmed_account_head)
{ {
expected = block->previous (); expected = block->previous ();
@ -394,7 +394,7 @@ void nano::bulk_pull_server::set_current_end ()
if (!request->end.is_zero ()) if (!request->end.is_zero ())
{ {
auto account (node->ledger.any.block_account (transaction, request->end)); auto account (node->ledger.any.block_account (transaction, request->end));
if (account != request->start.as_account ()) if (account.value_or (0) != request->start.as_account ())
{ {
node->logger.debug (nano::log::type::bulk_pull_server, "Request for block that is not on account chain: {} not on {}", request->end.to_string (), request->start.to_account ()); node->logger.debug (nano::log::type::bulk_pull_server, "Request for block that is not on account chain: {} not on {}", request->end.to_string (), request->start.to_account ());
@ -530,7 +530,7 @@ void nano::bulk_pull_server::sent_action (boost::system::error_code const & ec,
} }
if (!ec) if (!ec)
{ {
node->bootstrap_workers.push_task ([this_l = shared_from_this ()] () { node->bootstrap_workers.post ([this_l = shared_from_this ()] () {
this_l->send_next (); this_l->send_next ();
}); });
} }
@ -816,7 +816,7 @@ void nano::bulk_pull_account_server::sent_action (boost::system::error_code cons
} }
if (!ec) if (!ec)
{ {
node->bootstrap_workers.push_task ([this_l = shared_from_this ()] () { node->bootstrap_workers.post ([this_l = shared_from_this ()] () {
this_l->send_next_block (); this_l->send_next_block ();
}); });
} }

View file

@ -144,7 +144,7 @@ void nano::bulk_push_server::throttled_receive ()
else else
{ {
auto this_l (shared_from_this ()); auto this_l (shared_from_this ());
node->workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (1), [this_l] () { node->workers.post_delayed (std::chrono::seconds (1), [this_l] () {
if (!this_l->connection->stopped) if (!this_l->connection->stopped)
{ {
this_l->throttled_receive (); this_l->throttled_receive ();

View file

@ -102,7 +102,7 @@ void nano::bootstrap_connections::pool_connection (std::shared_ptr<nano::bootstr
{ {
nano::unique_lock<nano::mutex> lock{ mutex }; nano::unique_lock<nano::mutex> lock{ mutex };
auto const & socket_l = client_a->socket; auto const & socket_l = client_a->socket;
if (!stopped && !client_a->pending_stop && !node.network.excluded_peers.check (client_a->channel->get_tcp_endpoint ())) if (!stopped && !client_a->pending_stop && !node.network.excluded_peers.check (client_a->channel->get_remote_endpoint ()))
{ {
socket_l->set_timeout (node.network_params.network.idle_timeout); socket_l->set_timeout (node.network_params.network.idle_timeout);
// Push into idle deque // Push into idle deque
@ -138,7 +138,7 @@ std::shared_ptr<nano::bootstrap_client> nano::bootstrap_connections::find_connec
std::shared_ptr<nano::bootstrap_client> result; std::shared_ptr<nano::bootstrap_client> result;
for (auto i (idle.begin ()), end (idle.end ()); i != end && !stopped; ++i) for (auto i (idle.begin ()), end (idle.end ()); i != end && !stopped; ++i)
{ {
if ((*i)->channel->get_tcp_endpoint () == endpoint_a) if ((*i)->channel->get_remote_endpoint () == endpoint_a)
{ {
result = *i; result = *i;
idle.erase (i); idle.erase (i);
@ -306,7 +306,7 @@ void nano::bootstrap_connections::populate_connections (bool repeat)
if (!stopped && repeat) if (!stopped && repeat)
{ {
std::weak_ptr<nano::bootstrap_connections> this_w (shared_from_this ()); std::weak_ptr<nano::bootstrap_connections> this_w (shared_from_this ());
node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (1), [this_w] () { node.workers.post_delayed (std::chrono::seconds (1), [this_w] () {
if (auto this_l = this_w.lock ()) if (auto this_l = this_w.lock ())
{ {
this_l->populate_connections (); this_l->populate_connections ();

View file

@ -22,7 +22,7 @@ void nano::frontier_req_client::run (nano::account const & start_account_a, uint
return; return;
} }
nano::frontier_req request{ node->network_params.network }; nano::frontier_req request{ node->network_params.network };
request.start = (start_account_a.is_zero () || start_account_a.number () == std::numeric_limits<nano::uint256_t>::max ()) ? start_account_a : start_account_a.number () + 1; request.start = (start_account_a.is_zero () || start_account_a.number () == std::numeric_limits<nano::uint256_t>::max ()) ? start_account_a.number () : start_account_a.number () + 1;
request.age = frontiers_age_a; request.age = frontiers_age_a;
request.count = count_a; request.count = count_a;
current = start_account_a; current = start_account_a;
@ -70,7 +70,7 @@ void nano::frontier_req_client::receive_frontier ()
// we simply get a size of 0. // we simply get a size of 0.
if (size_a == nano::frontier_req_client::size_frontier) if (size_a == nano::frontier_req_client::size_frontier)
{ {
node->bootstrap_workers.push_task ([this_l, ec, size_a] () { node->bootstrap_workers.post ([this_l, ec, size_a] () {
this_l->received_frontier (ec, size_a); this_l->received_frontier (ec, size_a);
}); });
} }
@ -239,7 +239,7 @@ void nano::frontier_req_client::next ()
{ {
std::size_t max_size (128); std::size_t max_size (128);
auto transaction (node->store.tx_begin_read ()); auto transaction (node->store.tx_begin_read ());
for (auto i (node->store.account.begin (transaction, current.number () + 1)), n (node->store.account.end ()); i != n && accounts.size () != max_size; ++i) for (auto i (node->store.account.begin (transaction, current.number () + 1)), n (node->store.account.end (transaction)); i != n && accounts.size () != max_size; ++i)
{ {
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
nano::account const & account (i->first); nano::account const & account (i->first);
@ -355,7 +355,7 @@ void nano::frontier_req_server::sent_action (boost::system::error_code const & e
{ {
count++; count++;
node->bootstrap_workers.push_task ([this_l = shared_from_this ()] () { node->bootstrap_workers.post ([this_l = shared_from_this ()] () {
this_l->send_next (); this_l->send_next ();
}); });
} }
@ -381,7 +381,7 @@ void nano::frontier_req_server::next ()
auto transaction (node->store.tx_begin_read ()); auto transaction (node->store.tx_begin_read ());
if (!send_confirmed ()) if (!send_confirmed ())
{ {
for (auto i (node->store.account.begin (transaction, current.number () + 1)), n (node->store.account.end ()); i != n && accounts.size () != max_size; ++i) for (auto i (node->store.account.begin (transaction, current.number () + 1)), n (node->store.account.end (transaction)); i != n && accounts.size () != max_size; ++i)
{ {
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
if (disable_age_filter || (now - info.modified) <= request->age) if (disable_age_filter || (now - info.modified) <= request->age)
@ -393,7 +393,7 @@ void nano::frontier_req_server::next ()
} }
else else
{ {
for (auto i (node->store.confirmation_height.begin (transaction, current.number () + 1)), n (node->store.confirmation_height.end ()); i != n && accounts.size () != max_size; ++i) for (auto i (node->store.confirmation_height.begin (transaction, current.number () + 1)), n (node->store.confirmation_height.end (transaction)); i != n && accounts.size () != max_size; ++i)
{ {
nano::confirmation_height_info const & info (i->second); nano::confirmation_height_info const & info (i->second);
nano::block_hash const & confirmed_frontier (info.frontier); nano::block_hash const & confirmed_frontier (info.frontier);

View file

@ -293,7 +293,7 @@ bool nano::bootstrap_attempt_lazy::process_block_lazy (std::shared_ptr<nano::blo
if (!lazy_blocks_processed (hash)) if (!lazy_blocks_processed (hash))
{ {
// Search for new dependencies // Search for new dependencies
if (block_a->source_field () && !node->block_or_pruned_exists (block_a->source_field ().value ()) && block_a->source_field ().value () != node->network_params.ledger.genesis->account ()) if (block_a->source_field () && !node->block_or_pruned_exists (block_a->source_field ().value ()) && block_a->source_field ().value () != node->network_params.ledger.genesis->account ().as_union ())
{ {
lazy_add (block_a->source_field ().value (), retry_limit); lazy_add (block_a->source_field ().value (), retry_limit);
} }

View file

@ -138,7 +138,7 @@ bool nano::bootstrap_attempt_legacy::request_frontier (nano::unique_lock<nano::m
lock_a.lock (); lock_a.lock ();
if (connection_l && !stopped) if (connection_l && !stopped)
{ {
endpoint_frontier_request = connection_l->channel->get_tcp_endpoint (); endpoint_frontier_request = connection_l->channel->get_remote_endpoint ();
std::future<bool> future; std::future<bool> future;
{ {
auto this_l = std::dynamic_pointer_cast<nano::bootstrap_attempt_legacy> (shared_from_this ()); auto this_l = std::dynamic_pointer_cast<nano::bootstrap_attempt_legacy> (shared_from_this ());

View file

@ -395,7 +395,7 @@ nano::asc_pull_ack nano::bootstrap_server::process (secure::transaction const &
response.type = nano::asc_pull_type::frontiers; response.type = nano::asc_pull_type::frontiers;
nano::asc_pull_ack::frontiers_payload response_payload{}; nano::asc_pull_ack::frontiers_payload response_payload{};
for (auto it = store.account.begin (transaction, request.start), end = store.account.end (); it != end && response_payload.frontiers.size () < request.count; ++it) for (auto it = store.account.begin (transaction, request.start), end = store.account.end (transaction); it != end && response_payload.frontiers.size () < request.count; ++it)
{ {
response_payload.frontiers.emplace_back (it->first, it->second.head); response_payload.frontiers.emplace_back (it->first, it->second.head);
} }

View file

@ -77,7 +77,7 @@ std::deque<nano::account> nano::bootstrap_ascending::account_database_iterator::
std::deque<nano::account> result; std::deque<nano::account> result;
auto it = ledger.store.account.begin (transaction, next); auto it = ledger.store.account.begin (transaction, next);
auto const end = ledger.store.account.end (); auto const end = ledger.store.account.end (transaction);
for (size_t count = 0; it != end && count < batch_size; ++it, ++count) for (size_t count = 0; it != end && count < batch_size; ++it, ++count)
{ {
@ -115,7 +115,7 @@ std::deque<nano::account> nano::bootstrap_ascending::pending_database_iterator::
std::deque<nano::account> result; std::deque<nano::account> result;
auto it = ledger.store.pending.begin (transaction, next); auto it = ledger.store.pending.begin (transaction, next);
auto const end = ledger.store.pending.end (); auto const end = ledger.store.pending.end (transaction);
// TODO: This pending iteration heuristic should be encapsulated in a pending_iterator class and reused across other components // TODO: This pending iteration heuristic should be encapsulated in a pending_iterator class and reused across other components
// The heuristic is to advance the iterator sequentially until we reach a new account or perform a fresh lookup if the account has too many pending blocks // The heuristic is to advance the iterator sequentially until we reach a new account or perform a fresh lookup if the account has too many pending blocks
@ -164,4 +164,4 @@ std::deque<nano::account> nano::bootstrap_ascending::pending_database_iterator::
bool nano::bootstrap_ascending::pending_database_iterator::warmed_up () const bool nano::bootstrap_ascending::pending_database_iterator::warmed_up () const
{ {
return completed > 0; return completed > 0;
} }

View file

@ -33,7 +33,6 @@ nano::bootstrap_ascending::service::service (nano::node_config const & node_conf
scoring{ config, node_config_a.network_params.network }, scoring{ config, node_config_a.network_params.network },
database_limiter{ config.database_rate_limit, 1.0 } database_limiter{ config.database_rate_limit, 1.0 }
{ {
// TODO: This is called from a very congested blockprocessor thread. Offload this work to a dedicated processing thread
block_processor.batch_processed.add ([this] (auto const & batch) { block_processor.batch_processed.add ([this] (auto const & batch) {
{ {
nano::lock_guard<nano::mutex> lock{ mutex }; nano::lock_guard<nano::mutex> lock{ mutex };
@ -217,11 +216,14 @@ void nano::bootstrap_ascending::service::inspect (secure::transaction const & tx
{ {
if (source == nano::block_source::bootstrap) if (source == nano::block_source::bootstrap)
{ {
const auto account = block.previous ().is_zero () ? block.account_field ().value () : ledger.any.block_account (tx, block.previous ()).value (); const auto account = block.previous ().is_zero () ? block.account_field ().value () : ledger.any.block_account (tx, block.previous ()).value_or (0);
const auto source_hash = block.source_field ().value_or (block.link_field ().value_or (0).as_block_hash ()); const auto source_hash = block.source_field ().value_or (block.link_field ().value_or (0).as_block_hash ());
// Mark account as blocked because it is missing the source block if (!account.is_zero () && !source_hash.is_zero ())
accounts.block (account, source_hash); {
// Mark account as blocked because it is missing the source block
accounts.block (account, source_hash);
}
} }
} }
break; break;
@ -789,7 +791,7 @@ nano::bootstrap_ascending::service::verify_result nano::bootstrap_ascending::ser
case query_type::blocks_by_account: case query_type::blocks_by_account:
{ {
// Open & state blocks always contain account field // Open & state blocks always contain account field
if (first->account_field () != tag.start.as_account ()) if (first->account_field ().value_or (0) != tag.start.as_account ())
{ {
// TODO: Stat & log // TODO: Stat & log
return verify_result::invalid; return verify_result::invalid;

View file

@ -1012,7 +1012,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
nano::raw_key seed; nano::raw_key seed;
existing->second->store.seed (seed, transaction); existing->second->store.seed (seed, transaction);
std::cout << boost::str (boost::format ("Seed: %1%\n") % seed.to_string ()); std::cout << boost::str (boost::format ("Seed: %1%\n") % seed.to_string ());
for (auto i (existing->second->store.begin (transaction)), m (existing->second->store.end ()); i != m; ++i) for (auto i (existing->second->store.begin (transaction)), m (existing->second->store.end (transaction)); i != m; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
nano::raw_key key; nano::raw_key key;
@ -1201,7 +1201,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
{ {
std::cout << boost::str (boost::format ("Wallet ID: %1%\n") % i->first.to_string ()); std::cout << boost::str (boost::format ("Wallet ID: %1%\n") % i->first.to_string ());
auto transaction (i->second->wallets.tx_begin_read ()); auto transaction (i->second->wallets.tx_begin_read ());
for (auto j (i->second->store.begin (transaction)), m (i->second->store.end ()); j != m; ++j) for (auto j (i->second->store.begin (transaction)), m (i->second->store.end (transaction)); j != m; ++j)
{ {
std::cout << nano::account (j->first).to_account () << '\n'; std::cout << nano::account (j->first).to_account () << '\n';
} }
@ -1224,7 +1224,7 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
{ {
auto transaction (wallet->second->wallets.tx_begin_write ()); auto transaction (wallet->second->wallets.tx_begin_write ());
auto account (wallet->second->store.find (transaction, account_id)); auto account (wallet->second->store.find (transaction, account_id));
if (account != wallet->second->store.end ()) if (account != wallet->second->store.end (transaction))
{ {
wallet->second->store.erase (transaction, account_id); wallet->second->store.erase (transaction, account_id);
} }

View file

@ -15,7 +15,7 @@ nano::confirming_set::confirming_set (confirming_set_config const & config_a, na
block_processor{ block_processor_a }, block_processor{ block_processor_a },
stats{ stats_a }, stats{ stats_a },
logger{ logger_a }, logger{ logger_a },
notification_workers{ 1, nano::thread_role::name::confirmation_height_notifications } workers{ 1, nano::thread_role::name::confirmation_height_notifications }
{ {
batch_cemented.add ([this] (auto const & cemented) { batch_cemented.add ([this] (auto const & cemented) {
for (auto const & context : cemented) for (auto const & context : cemented)
@ -80,6 +80,8 @@ void nano::confirming_set::start ()
return; return;
} }
workers.start ();
thread = std::thread{ [this] () { thread = std::thread{ [this] () {
nano::thread_role::set (nano::thread_role::name::confirmation_height); nano::thread_role::set (nano::thread_role::name::confirmation_height);
run (); run ();
@ -97,7 +99,7 @@ void nano::confirming_set::stop ()
{ {
thread.join (); thread.join ();
} }
notification_workers.stop (); workers.stop ();
} }
bool nano::confirming_set::contains (nano::block_hash const & hash) const bool nano::confirming_set::contains (nano::block_hash const & hash) const
@ -177,7 +179,7 @@ void nano::confirming_set::run_batch (std::unique_lock<std::mutex> & lock)
std::unique_lock lock{ mutex }; std::unique_lock lock{ mutex };
// It's possible that ledger cementing happens faster than the notifications can be processed by other components, cooldown here // It's possible that ledger cementing happens faster than the notifications can be processed by other components, cooldown here
while (notification_workers.num_queued_tasks () >= config.max_queued_notifications) while (workers.queued_tasks () >= config.max_queued_notifications)
{ {
stats.inc (nano::stat::type::confirming_set, nano::stat::detail::cooldown); stats.inc (nano::stat::type::confirming_set, nano::stat::detail::cooldown);
condition.wait_for (lock, 100ms, [this] { return stopped.load (); }); condition.wait_for (lock, 100ms, [this] { return stopped.load (); });
@ -187,7 +189,7 @@ void nano::confirming_set::run_batch (std::unique_lock<std::mutex> & lock)
} }
} }
notification_workers.push_task ([this, batch = std::move (batch)] () { workers.post ([this, batch = std::move (batch)] () {
stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify); stats.inc (nano::stat::type::confirming_set, nano::stat::detail::notify);
batch_cemented.notify (batch); batch_cemented.notify (batch);
}); });
@ -333,6 +335,6 @@ nano::container_info nano::confirming_set::container_info () const
nano::container_info info; nano::container_info info;
info.put ("set", set); info.put ("set", set);
info.put ("deferred", deferred); info.put ("deferred", deferred);
info.add ("notification_workers", notification_workers.container_info ()); info.add ("workers", workers.container_info ());
return info; return info;
} }

View file

@ -118,11 +118,11 @@ private:
// Blocks that are being cemented in the current batch // Blocks that are being cemented in the current batch
std::unordered_set<nano::block_hash> current; std::unordered_set<nano::block_hash> current;
nano::thread_pool notification_workers;
std::atomic<bool> stopped{ false }; std::atomic<bool> stopped{ false };
mutable std::mutex mutex; mutable std::mutex mutex;
std::condition_variable condition; std::condition_variable condition;
std::thread thread; std::thread thread;
nano::thread_pool workers;
}; };
} }

View file

@ -4,6 +4,7 @@
#include <nano/node/websocket.hpp> #include <nano/node/websocket.hpp>
#include <boost/algorithm/string/erase.hpp> #include <boost/algorithm/string/erase.hpp>
#include <boost/format.hpp>
std::shared_ptr<request_type> nano::distributed_work::peer_request::get_prepared_json_request (std::string const & request_string_a) const std::shared_ptr<request_type> nano::distributed_work::peer_request::get_prepared_json_request (std::string const & request_string_a) const
{ {
@ -400,10 +401,9 @@ void nano::distributed_work::handle_failure ()
status = work_generation_status::failure_peers; status = work_generation_status::failure_peers;
auto now (std::chrono::steady_clock::now ());
std::weak_ptr<nano::node> node_weak (node.shared ()); std::weak_ptr<nano::node> node_weak (node.shared ());
auto next_backoff (std::min (backoff * 2, std::chrono::seconds (5 * 60))); auto next_backoff (std::min (backoff * 2, std::chrono::seconds (5 * 60)));
node.workers.add_timed_task (now + std::chrono::seconds (backoff), [node_weak, request_l = request, next_backoff] { node.workers.post_delayed (std::chrono::seconds (backoff), [node_weak, request_l = request, next_backoff] {
bool error_l{ true }; bool error_l{ true };
if (auto node_l = node_weak.lock ()) if (auto node_l = node_weak.lock ())
{ {

View file

@ -75,7 +75,7 @@ void nano::election::confirm_once (nano::unique_lock<nano::mutex> & lock)
lock.unlock (); lock.unlock ();
node.election_workers.push_task ([status_l, confirmation_action_l = confirmation_action] () { node.election_workers.post ([status_l, confirmation_action_l = confirmation_action] () {
if (confirmation_action_l) if (confirmation_action_l)
{ {
confirmation_action_l (status_l.winner); confirmation_action_l (status_l.winner);

View file

@ -116,7 +116,7 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc
{ {
auto transaction (store.tx_begin_read ()); auto transaction (store.tx_begin_read ());
// Collect accounts to upgrade // Collect accounts to upgrade
for (auto i (store.account.begin (transaction)), n (store.account.end ()); i != n && accounts_list.size () < count_limit; ++i) for (auto i (store.account.begin (transaction)), n (store.account.end (transaction)); i != n && accounts_list.size () < count_limit; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
@ -161,7 +161,7 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc
upgrader_condition.wait (lock); upgrader_condition.wait (lock);
} }
} }
node.workers.push_task ([&upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_accounts, &workers, epoch, difficulty, signer, root, account] () { node.workers.post ([&upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_accounts, &workers, epoch, difficulty, signer, root, account] () {
upgrader_process (upgraded_accounts, epoch, difficulty, signer, root, account); upgrader_process (upgraded_accounts, epoch, difficulty, signer, root, account);
{ {
nano::lock_guard<nano::mutex> lock{ upgrader_mutex }; nano::lock_guard<nano::mutex> lock{ upgrader_mutex };
@ -241,7 +241,7 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc
upgrader_condition.wait (lock); upgrader_condition.wait (lock);
} }
} }
node.workers.push_task ([&upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_pending, &workers, epoch, difficulty, signer, root, account] () { node.workers.post ([&upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_pending, &workers, epoch, difficulty, signer, root, account] () {
upgrader_process (upgraded_pending, epoch, difficulty, signer, root, account); upgrader_process (upgraded_pending, epoch, difficulty, signer, root, account);
{ {
nano::lock_guard<nano::mutex> lock{ upgrader_mutex }; nano::lock_guard<nano::mutex> lock{ upgrader_mutex };

View file

@ -9,6 +9,7 @@ namespace nano
{ {
class block; class block;
class container_info; class container_info;
class thread_pool;
} }
namespace nano namespace nano

View file

@ -14,6 +14,7 @@
#include <nano/node/json_handler.hpp> #include <nano/node/json_handler.hpp>
#include <nano/node/node.hpp> #include <nano/node/node.hpp>
#include <boost/array.hpp>
#include <boost/endian/conversion.hpp> #include <boost/endian/conversion.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>

View file

@ -207,7 +207,7 @@ bool nano::json_handler::wallet_account_impl (store::transaction const & transac
bool result (false); bool result (false);
if (!ec) if (!ec)
{ {
if (wallet_a->store.find (transaction_a, account_a) != wallet_a->store.end ()) if (wallet_a->store.find (transaction_a, account_a) != wallet_a->store.end (transaction_a))
{ {
result = true; result = true;
} }
@ -541,7 +541,7 @@ void nano::json_handler::account_block_count ()
void nano::json_handler::account_create () void nano::json_handler::account_create ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -718,7 +718,7 @@ void nano::json_handler::account_list ()
{ {
boost::property_tree::ptree accounts; boost::property_tree::ptree accounts;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
for (auto i (wallet->store.begin (transaction)), j (wallet->store.end ()); i != j; ++i) for (auto i (wallet->store.begin (transaction)), j (wallet->store.end (transaction)); i != j; ++i)
{ {
boost::property_tree::ptree entry; boost::property_tree::ptree entry;
entry.put ("", nano::account (i->first).to_account ()); entry.put ("", nano::account (i->first).to_account ());
@ -731,7 +731,7 @@ void nano::json_handler::account_list ()
void nano::json_handler::account_move () void nano::json_handler::account_move ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -770,7 +770,7 @@ void nano::json_handler::account_move ()
void nano::json_handler::account_remove () void nano::json_handler::account_remove ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
auto account (rpc_l->account_impl ()); auto account (rpc_l->account_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
@ -805,7 +805,7 @@ void nano::json_handler::account_representative ()
void nano::json_handler::account_representative_set () void nano::json_handler::account_representative_set ()
{ {
node.workers.push_task (create_worker_task ([work_generation_enabled = node.work_generation_enabled ()] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([work_generation_enabled = node.work_generation_enabled ()] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
auto account (rpc_l->account_impl ()); auto account (rpc_l->account_impl ());
std::string representative_text (rpc_l->request.get<std::string> ("representative")); std::string representative_text (rpc_l->request.get<std::string> ("representative"));
@ -948,7 +948,7 @@ void nano::json_handler::accounts_representatives ()
void nano::json_handler::accounts_create () void nano::json_handler::accounts_create ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
auto count (rpc_l->count_impl ()); auto count (rpc_l->count_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
@ -1030,7 +1030,7 @@ void nano::json_handler::accounts_receivable ()
if (!ec) if (!ec)
{ {
boost::property_tree::ptree peers_l; boost::property_tree::ptree peers_l;
for (auto i (node.store.pending.begin (transaction, nano::pending_key (account, 0))), n (node.store.pending.end ()); i != n && nano::pending_key (i->first).account == account && peers_l.size () < count; ++i) for (auto i (node.store.pending.begin (transaction, nano::pending_key (account, 0))), n (node.store.pending.end (transaction)); i != n && nano::pending_key (i->first).account == account && peers_l.size () < count; ++i)
{ {
nano::pending_key const & key (i->first); nano::pending_key const & key (i->first);
if (block_confirmed (node, transaction, key.hash, include_active, include_only_confirmed)) if (block_confirmed (node, transaction, key.hash, include_active, include_only_confirmed))
@ -2240,7 +2240,7 @@ void nano::json_handler::delegators ()
{ {
auto transaction (node.ledger.tx_begin_read ()); auto transaction (node.ledger.tx_begin_read ());
boost::property_tree::ptree delegators; boost::property_tree::ptree delegators;
for (auto i (node.store.account.begin (transaction, start_account.number () + 1)), n (node.store.account.end ()); i != n && delegators.size () < count; ++i) for (auto i (node.store.account.begin (transaction, start_account.number () + 1)), n (node.store.account.end (transaction)); i != n && delegators.size () < count; ++i)
{ {
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
if (info.representative == representative) if (info.representative == representative)
@ -2266,7 +2266,7 @@ void nano::json_handler::delegators_count ()
{ {
uint64_t count (0); uint64_t count (0);
auto transaction (node.ledger.tx_begin_read ()); auto transaction (node.ledger.tx_begin_read ());
for (auto i (node.store.account.begin (transaction)), n (node.store.account.end ()); i != n; ++i) for (auto i (node.store.account.begin (transaction)), n (node.store.account.end (transaction)); i != n; ++i)
{ {
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
if (info.representative == account) if (info.representative == account)
@ -2377,7 +2377,7 @@ void nano::json_handler::frontiers ()
{ {
boost::property_tree::ptree frontiers; boost::property_tree::ptree frontiers;
auto transaction (node.ledger.tx_begin_read ()); auto transaction (node.ledger.tx_begin_read ());
for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end ()); i != n && frontiers.size () < count; ++i) for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end (transaction)); i != n && frontiers.size () < count; ++i)
{ {
frontiers.put (i->first.to_account (), i->second.head.to_string ()); frontiers.put (i->first.to_account (), i->second.head.to_string ());
} }
@ -2462,7 +2462,7 @@ public:
// Report opens as a receive // Report opens as a receive
tree.put ("type", "receive"); tree.put ("type", "receive");
} }
if (block_a.hashables.source != handler.node.ledger.constants.genesis->account ()) if (block_a.hashables.source != handler.node.ledger.constants.genesis->account ().as_union ())
{ {
bool error_or_pruned (false); bool error_or_pruned (false);
auto amount = handler.node.ledger.any.block_amount (transaction, hash); auto amount = handler.node.ledger.any.block_amount (transaction, hash);
@ -2780,7 +2780,7 @@ void nano::json_handler::ledger ()
auto transaction = node.ledger.tx_begin_read (); auto transaction = node.ledger.tx_begin_read ();
if (!ec && !sorting) // Simple if (!ec && !sorting) // Simple
{ {
for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end ()); i != n && accounts.size () < count; ++i) for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end (transaction)); i != n && accounts.size () < count; ++i)
{ {
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
if (info.modified >= modified_since && (receivable || info.balance.number () >= threshold.number ())) if (info.modified >= modified_since && (receivable || info.balance.number () >= threshold.number ()))
@ -2821,7 +2821,7 @@ void nano::json_handler::ledger ()
else if (!ec) // Sorting else if (!ec) // Sorting
{ {
std::vector<std::pair<nano::uint128_union, nano::account>> ledger_l; std::vector<std::pair<nano::uint128_union, nano::account>> ledger_l;
for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end ()); i != n; ++i) for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end (transaction)); i != n; ++i)
{ {
nano::account_info const & info (i->second); nano::account_info const & info (i->second);
nano::uint128_union balance (info.balance); nano::uint128_union balance (info.balance);
@ -2930,7 +2930,7 @@ void nano::json_handler::node_id_delete ()
void nano::json_handler::password_change () void nano::json_handler::password_change ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -2953,7 +2953,7 @@ void nano::json_handler::password_change ()
void nano::json_handler::password_enter () void nano::json_handler::password_enter ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -2991,7 +2991,7 @@ void nano::json_handler::peers ()
bool const peer_details = request.get<bool> ("peer_details", false); bool const peer_details = request.get<bool> ("peer_details", false);
auto peers_list (node.network.list (std::numeric_limits<std::size_t>::max ())); auto peers_list (node.network.list (std::numeric_limits<std::size_t>::max ()));
std::sort (peers_list.begin (), peers_list.end (), [] (auto const & lhs, auto const & rhs) { std::sort (peers_list.begin (), peers_list.end (), [] (auto const & lhs, auto const & rhs) {
return lhs->get_endpoint () < rhs->get_endpoint (); return lhs->get_remote_endpoint () < rhs->get_remote_endpoint ();
}); });
for (auto i (peers_list.begin ()), n (peers_list.end ()); i != n; ++i) for (auto i (peers_list.begin ()), n (peers_list.end ()); i != n; ++i)
{ {
@ -3003,9 +3003,9 @@ void nano::json_handler::peers ()
boost::property_tree::ptree pending_tree; boost::property_tree::ptree pending_tree;
pending_tree.put ("protocol_version", std::to_string (channel->get_network_version ())); pending_tree.put ("protocol_version", std::to_string (channel->get_network_version ()));
auto node_id_l (channel->get_node_id_optional ()); auto node_id_l (channel->get_node_id_optional ());
if (node_id_l.is_initialized ()) if (node_id_l.has_value ())
{ {
pending_tree.put ("node_id", node_id_l.get ().to_node_id ()); pending_tree.put ("node_id", node_id_l.value ().to_node_id ());
} }
else else
{ {
@ -3055,7 +3055,7 @@ void nano::json_handler::receivable ()
// The ptree container is used if there are any children nodes (e.g source/min_version) otherwise the amount container is used. // The ptree container is used if there are any children nodes (e.g source/min_version) otherwise the amount container is used.
std::vector<std::pair<std::string, boost::property_tree::ptree>> hash_ptree_pairs; std::vector<std::pair<std::string, boost::property_tree::ptree>> hash_ptree_pairs;
std::vector<std::pair<std::string, nano::uint128_t>> hash_amount_pairs; std::vector<std::pair<std::string, nano::uint128_t>> hash_amount_pairs;
for (auto i (node.store.pending.begin (transaction, nano::pending_key (account, 0))), n (node.store.pending.end ()); i != n && nano::pending_key (i->first).account == account && (should_sort || peers_l.size () < count); ++i) for (auto i (node.store.pending.begin (transaction, nano::pending_key (account, 0))), n (node.store.pending.end (transaction)); i != n && nano::pending_key (i->first).account == account && (should_sort || peers_l.size () < count); ++i)
{ {
nano::pending_key const & key (i->first); nano::pending_key const & key (i->first);
if (block_confirmed (node, transaction, key.hash, include_active, include_only_confirmed)) if (block_confirmed (node, transaction, key.hash, include_active, include_only_confirmed))
@ -3178,7 +3178,7 @@ void nano::json_handler::receivable_exists ()
void nano::json_handler::process () void nano::json_handler::process ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
bool const is_async = rpc_l->request.get<bool> ("async", false); bool const is_async = rpc_l->request.get<bool> ("async", false);
auto block (rpc_l->block_impl (true)); auto block (rpc_l->block_impl (true));
@ -4143,7 +4143,7 @@ void nano::json_handler::unchecked ()
void nano::json_handler::unchecked_clear () void nano::json_handler::unchecked_clear ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
rpc_l->node.unchecked.clear (); rpc_l->node.unchecked.clear ();
rpc_l->response_l.put ("success", ""); rpc_l->response_l.put ("success", "");
rpc_l->response_errors (); rpc_l->response_errors ();
@ -4240,7 +4240,7 @@ void nano::json_handler::unopened ()
{ {
auto transaction = node.store.tx_begin_read (); auto transaction = node.store.tx_begin_read ();
auto iterator = node.store.pending.begin (transaction, nano::pending_key (start, 0)); auto iterator = node.store.pending.begin (transaction, nano::pending_key (start, 0));
auto end = node.store.pending.end (); auto end = node.store.pending.end (transaction);
nano::account current_account = start; nano::account current_account = start;
nano::uint128_t current_account_sum{ 0 }; nano::uint128_t current_account_sum{ 0 };
boost::property_tree::ptree accounts; boost::property_tree::ptree accounts;
@ -4316,7 +4316,7 @@ void nano::json_handler::validate_account_number ()
void nano::json_handler::wallet_add () void nano::json_handler::wallet_add ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -4346,7 +4346,7 @@ void nano::json_handler::wallet_add ()
void nano::json_handler::wallet_add_watch () void nano::json_handler::wallet_add_watch ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -4392,7 +4392,7 @@ void nano::json_handler::wallet_info ()
uint64_t adhoc_count (0); uint64_t adhoc_count (0);
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
@ -4448,7 +4448,7 @@ void nano::json_handler::wallet_balances ()
boost::property_tree::ptree balances; boost::property_tree::ptree balances;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
nano::uint128_t balance = node.ledger.any.account_balance (block_transaction, account).value_or (0).number (); nano::uint128_t balance = node.ledger.any.account_balance (block_transaction, account).value_or (0).number ();
@ -4469,7 +4469,7 @@ void nano::json_handler::wallet_balances ()
void nano::json_handler::wallet_change_seed () void nano::json_handler::wallet_change_seed ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
if (!rpc_l->ec) if (!rpc_l->ec)
{ {
@ -4509,7 +4509,7 @@ void nano::json_handler::wallet_contains ()
if (!ec) if (!ec)
{ {
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto exists (wallet->store.find (transaction, account) != wallet->store.end ()); auto exists (wallet->store.find (transaction, account) != wallet->store.end (transaction));
response_l.put ("exists", exists ? "1" : "0"); response_l.put ("exists", exists ? "1" : "0");
} }
response_errors (); response_errors ();
@ -4517,7 +4517,7 @@ void nano::json_handler::wallet_contains ()
void nano::json_handler::wallet_create () void nano::json_handler::wallet_create ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
nano::raw_key seed; nano::raw_key seed;
auto seed_text (rpc_l->request.get_optional<std::string> ("seed")); auto seed_text (rpc_l->request.get_optional<std::string> ("seed"));
if (seed_text.is_initialized () && seed.decode_hex (seed_text.get ())) if (seed_text.is_initialized () && seed.decode_hex (seed_text.get ()))
@ -4553,7 +4553,7 @@ void nano::json_handler::wallet_create ()
void nano::json_handler::wallet_destroy () void nano::json_handler::wallet_destroy ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
std::string wallet_text (rpc_l->request.get<std::string> ("wallet")); std::string wallet_text (rpc_l->request.get<std::string> ("wallet"));
nano::wallet_id wallet; nano::wallet_id wallet;
if (!wallet.decode_hex (wallet_text)) if (!wallet.decode_hex (wallet_text))
@ -4599,7 +4599,7 @@ void nano::json_handler::wallet_frontiers ()
boost::property_tree::ptree frontiers; boost::property_tree::ptree frontiers;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
auto latest (node.ledger.any.account_head (block_transaction, account)); auto latest (node.ledger.any.account_head (block_transaction, account));
@ -4630,7 +4630,7 @@ void nano::json_handler::wallet_history ()
std::multimap<uint64_t, boost::property_tree::ptree, std::greater<uint64_t>> entries; std::multimap<uint64_t, boost::property_tree::ptree, std::greater<uint64_t>> entries;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
auto info = node.ledger.any.account_get (block_transaction, account); auto info = node.ledger.any.account_get (block_transaction, account);
@ -4704,7 +4704,7 @@ void nano::json_handler::wallet_ledger ()
boost::property_tree::ptree accounts; boost::property_tree::ptree accounts;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
auto info = node.ledger.any.account_get (block_transaction, account); auto info = node.ledger.any.account_get (block_transaction, account);
@ -4780,11 +4780,11 @@ void nano::json_handler::wallet_receivable ()
boost::property_tree::ptree pending; boost::property_tree::ptree pending;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
boost::property_tree::ptree peers_l; boost::property_tree::ptree peers_l;
for (auto ii (node.store.pending.begin (block_transaction, nano::pending_key (account, 0))), nn (node.store.pending.end ()); ii != nn && nano::pending_key (ii->first).account == account && peers_l.size () < count; ++ii) for (auto ii (node.store.pending.begin (block_transaction, nano::pending_key (account, 0))), nn (node.store.pending.end (block_transaction)); ii != nn && nano::pending_key (ii->first).account == account && peers_l.size () < count; ++ii)
{ {
nano::pending_key key (ii->first); nano::pending_key key (ii->first);
if (block_confirmed (node, block_transaction, key.hash, include_active, include_only_confirmed)) if (block_confirmed (node, block_transaction, key.hash, include_active, include_only_confirmed))
@ -4845,7 +4845,7 @@ void nano::json_handler::wallet_representative ()
void nano::json_handler::wallet_representative_set () void nano::json_handler::wallet_representative_set ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
std::string representative_text (rpc_l->request.get<std::string> ("representative")); std::string representative_text (rpc_l->request.get<std::string> ("representative"));
auto representative (rpc_l->account_impl (representative_text, nano::error_rpc::bad_representative_number)); auto representative (rpc_l->account_impl (representative_text, nano::error_rpc::bad_representative_number));
@ -4871,7 +4871,7 @@ void nano::json_handler::wallet_representative_set ()
{ {
auto transaction (rpc_l->node.wallets.tx_begin_read ()); auto transaction (rpc_l->node.wallets.tx_begin_read ());
auto block_transaction = rpc_l->node.ledger.tx_begin_read (); auto block_transaction = rpc_l->node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
auto info = rpc_l->node.ledger.any.account_get (block_transaction, account); auto info = rpc_l->node.ledger.any.account_get (block_transaction, account);
@ -4905,7 +4905,7 @@ void nano::json_handler::wallet_republish ()
std::deque<std::shared_ptr<nano::block>> republish_bundle; std::deque<std::shared_ptr<nano::block>> republish_bundle;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
auto block_transaction = node.ledger.tx_begin_read (); auto block_transaction = node.ledger.tx_begin_read ();
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
auto latest (node.ledger.any.account_head (block_transaction, account)); auto latest (node.ledger.any.account_head (block_transaction, account));
@ -4967,7 +4967,7 @@ void nano::json_handler::wallet_work_get ()
{ {
boost::property_tree::ptree works; boost::property_tree::ptree works;
auto transaction (node.wallets.tx_begin_read ()); auto transaction (node.wallets.tx_begin_read ());
for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) for (auto i (wallet->store.begin (transaction)), n (wallet->store.end (transaction)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
uint64_t work (0); uint64_t work (0);
@ -5132,7 +5132,7 @@ void nano::json_handler::work_get ()
void nano::json_handler::work_set () void nano::json_handler::work_set ()
{ {
node.workers.push_task (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) { node.workers.post (create_worker_task ([] (std::shared_ptr<nano::json_handler> const & rpc_l) {
auto wallet (rpc_l->wallet_impl ()); auto wallet (rpc_l->wallet_impl ());
auto account (rpc_l->account_impl ()); auto account (rpc_l->account_impl ());
auto work (rpc_l->work_optional_impl ()); auto work (rpc_l->work_optional_impl ());

View file

@ -175,7 +175,7 @@ public:
if (peer0.address () == boost::asio::ip::address_v6{} && peer0.port () != 0) if (peer0.address () == boost::asio::ip::address_v6{} && peer0.port () != 0)
{ {
// TODO: Remove this as we do not need to establish a second connection to the same peer // TODO: Remove this as we do not need to establish a second connection to the same peer
nano::endpoint new_endpoint (channel->get_tcp_endpoint ().address (), peer0.port ()); nano::endpoint new_endpoint (channel->get_remote_endpoint ().address (), peer0.port ());
node.network.merge_peer (new_endpoint); node.network.merge_peer (new_endpoint);
// Remember this for future forwarding to other peers // Remember this for future forwarding to other peers

View file

@ -281,6 +281,15 @@ void nano::network::flood_vote (std::shared_ptr<nano::vote> const & vote, float
} }
} }
void nano::network::flood_vote_non_pr (std::shared_ptr<nano::vote> const & vote, float scale, bool rebroadcasted)
{
nano::confirm_ack message{ node.network_params.network, vote, rebroadcasted };
for (auto & i : list_non_pr (fanout (scale)))
{
i->send (message, nullptr);
}
}
void nano::network::flood_vote_pr (std::shared_ptr<nano::vote> const & vote, bool rebroadcasted) void nano::network::flood_vote_pr (std::shared_ptr<nano::vote> const & vote, bool rebroadcasted)
{ {
nano::confirm_ack message{ node.network_params.network, vote, rebroadcasted }; nano::confirm_ack message{ node.network_params.network, vote, rebroadcasted };
@ -300,7 +309,7 @@ void nano::network::flood_block_many (std::deque<std::shared_ptr<nano::block>> b
if (!blocks_a.empty ()) if (!blocks_a.empty ())
{ {
std::weak_ptr<nano::node> node_w (node.shared ()); std::weak_ptr<nano::node> node_w (node.shared ());
node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (delay_a + std::rand () % delay_a), [node_w, blocks (std::move (blocks_a)), callback_a, delay_a] () { node.workers.post_delayed (std::chrono::milliseconds (delay_a + std::rand () % delay_a), [node_w, blocks (std::move (blocks_a)), callback_a, delay_a] () {
if (auto node_l = node_w.lock ()) if (auto node_l = node_w.lock ())
{ {
node_l->network.flood_block_many (std::move (blocks), callback_a, delay_a); node_l->network.flood_block_many (std::move (blocks), callback_a, delay_a);
@ -377,11 +386,13 @@ std::deque<std::shared_ptr<nano::transport::channel>> nano::network::list_non_pr
{ {
std::deque<std::shared_ptr<nano::transport::channel>> result; std::deque<std::shared_ptr<nano::transport::channel>> result;
tcp_channels.list (result); tcp_channels.list (result);
auto partition_point = std::partition (result.begin (), result.end (),
[this] (std::shared_ptr<nano::transport::channel> const & channel) {
return !node.rep_crawler.is_pr (channel);
});
result.resize (std::distance (result.begin (), partition_point));
nano::random_pool_shuffle (result.begin (), result.end ()); nano::random_pool_shuffle (result.begin (), result.end ());
result.erase (std::remove_if (result.begin (), result.end (), [this] (std::shared_ptr<nano::transport::channel> const & channel) {
return node.rep_crawler.is_pr (channel);
}),
result.end ());
if (result.size () > count_a) if (result.size () > count_a)
{ {
result.resize (count_a, nullptr); result.resize (count_a, nullptr);
@ -496,14 +507,14 @@ void nano::network::erase (nano::transport::channel const & channel_a)
auto const channel_type = channel_a.get_type (); auto const channel_type = channel_a.get_type ();
if (channel_type == nano::transport::transport_type::tcp) if (channel_type == nano::transport::transport_type::tcp)
{ {
tcp_channels.erase (channel_a.get_tcp_endpoint ()); tcp_channels.erase (channel_a.get_remote_endpoint ());
} }
} }
void nano::network::exclude (std::shared_ptr<nano::transport::channel> const & channel) void nano::network::exclude (std::shared_ptr<nano::transport::channel> const & channel)
{ {
// Add to peer exclusion list // Add to peer exclusion list
excluded_peers.add (channel->get_tcp_endpoint ()); excluded_peers.add (channel->get_remote_endpoint ());
// Disconnect // Disconnect
erase (*channel); erase (*channel);

View file

@ -95,6 +95,7 @@ public:
void flood_keepalive_self (float const scale_a = 0.5f); void flood_keepalive_self (float const scale_a = 0.5f);
void flood_vote (std::shared_ptr<nano::vote> const &, float scale, bool rebroadcasted = false); void flood_vote (std::shared_ptr<nano::vote> const &, float scale, bool rebroadcasted = false);
void flood_vote_pr (std::shared_ptr<nano::vote> const &, bool rebroadcasted = false); void flood_vote_pr (std::shared_ptr<nano::vote> const &, bool rebroadcasted = false);
void flood_vote_non_pr (std::shared_ptr<nano::vote> const &, float scale, bool rebroadcasted = false);
// Flood block to all PRs and a random selection of non-PRs // Flood block to all PRs and a random selection of non-PRs
void flood_block_initial (std::shared_ptr<nano::block> const &); void flood_block_initial (std::shared_ptr<nano::block> const &);
// Flood block to a random selection of peers // Flood block to a random selection of peers

View file

@ -1,5 +1,6 @@
#include <nano/lib/blocks.hpp> #include <nano/lib/blocks.hpp>
#include <nano/lib/stream.hpp> #include <nano/lib/stream.hpp>
#include <nano/lib/thread_pool.hpp>
#include <nano/lib/thread_runner.hpp> #include <nano/lib/thread_runner.hpp>
#include <nano/lib/tomlconfig.hpp> #include <nano/lib/tomlconfig.hpp>
#include <nano/lib/utility.hpp> #include <nano/lib/utility.hpp>
@ -37,6 +38,7 @@
#include <nano/store/component.hpp> #include <nano/store/component.hpp>
#include <nano/store/rocksdb/rocksdb.hpp> #include <nano/store/rocksdb/rocksdb.hpp>
#include <boost/format.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <algorithm> #include <algorithm>
@ -68,6 +70,7 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, uint16_t pe
nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesystem::path const & application_path_a, nano::node_config const & config_a, nano::work_pool & work_a, nano::node_flags flags_a, unsigned seq) : nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesystem::path const & application_path_a, nano::node_config const & config_a, nano::work_pool & work_a, nano::node_flags flags_a, unsigned seq) :
node_id{ load_or_create_node_id (application_path_a) }, node_id{ load_or_create_node_id (application_path_a) },
config{ config_a }, config{ config_a },
flags{ flags_a },
io_ctx_shared{ std::make_shared<boost::asio::io_context> () }, io_ctx_shared{ std::make_shared<boost::asio::io_context> () },
io_ctx{ *io_ctx_shared }, io_ctx{ *io_ctx_shared },
logger{ make_logger_identifier (node_id) }, logger{ make_logger_identifier (node_id) },
@ -76,11 +79,14 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
node_initialized_latch (1), node_initialized_latch (1),
network_params{ config.network_params }, network_params{ config.network_params },
stats{ logger, config.stats_config }, stats{ logger, config.stats_config },
workers{ config.background_threads, nano::thread_role::name::worker }, workers_impl{ std::make_unique<nano::thread_pool> (config.background_threads, nano::thread_role::name::worker, /* start immediately */ true) },
bootstrap_workers{ config.bootstrap_serving_threads, nano::thread_role::name::bootstrap_worker }, workers{ *workers_impl },
wallet_workers{ 1, nano::thread_role::name::wallet_worker }, bootstrap_workers_impl{ std::make_unique<nano::thread_pool> (config.bootstrap_serving_threads, nano::thread_role::name::bootstrap_worker, /* start immediately */ true) },
election_workers{ 1, nano::thread_role::name::election_worker }, bootstrap_workers{ *bootstrap_workers_impl },
flags (flags_a), wallet_workers_impl{ std::make_unique<nano::thread_pool> (1, nano::thread_role::name::wallet_worker, /* start immediately */ true) },
wallet_workers{ *wallet_workers_impl },
election_workers_impl{ std::make_unique<nano::thread_pool> (1, nano::thread_role::name::election_worker, /* start immediately */ true) },
election_workers{ *election_workers_impl },
work (work_a), work (work_a),
distributed_work (*this), distributed_work (*this),
store_impl (nano::make_store (logger, application_path_a, network_params.ledger, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, config_a.backup_before_upgrade)), store_impl (nano::make_store (logger, application_path_a, network_params.ledger, flags.read_only, true, config_a.rocksdb_config, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_config, config_a.backup_before_upgrade)),
@ -138,7 +144,7 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
generator{ *generator_impl }, generator{ *generator_impl },
final_generator_impl{ std::make_unique<nano::vote_generator> (config, *this, ledger, wallets, vote_processor, history, network, stats, logger, /* final */ true) }, final_generator_impl{ std::make_unique<nano::vote_generator> (config, *this, ledger, wallets, vote_processor, history, network, stats, logger, /* final */ true) },
final_generator{ *final_generator_impl }, final_generator{ *final_generator_impl },
scheduler_impl{ std::make_unique<nano::scheduler::component> (*this) }, scheduler_impl{ std::make_unique<nano::scheduler::component> (config, *this, ledger, block_processor, active, online_reps, vote_cache, confirming_set, stats, logger) },
scheduler{ *scheduler_impl }, scheduler{ *scheduler_impl },
aggregator_impl{ std::make_unique<nano::request_aggregator> (config.request_aggregator, *this, stats, generator, final_generator, history, ledger, wallets, vote_router) }, aggregator_impl{ std::make_unique<nano::request_aggregator> (config.request_aggregator, *this, stats, generator, final_generator, history, ledger, wallets, vote_router) },
aggregator{ *aggregator_impl }, aggregator{ *aggregator_impl },
@ -194,13 +200,6 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
if (!init_error ()) if (!init_error ())
{ {
// Notify election schedulers when AEC frees election slot
active.vacancy_update = [this] () {
scheduler.priority.notify ();
scheduler.hinted.notify ();
scheduler.optimistic.notify ();
};
wallets.observer = [this] (bool active) { wallets.observer = [this] (bool active) {
observers.wallet.notify (active); observers.wallet.notify (active);
}; };
@ -325,7 +324,7 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
auto is_initialized (false); auto is_initialized (false);
{ {
auto const transaction (store.tx_begin_read ()); auto const transaction (store.tx_begin_read ());
is_initialized = (store.account.begin (transaction) != store.account.end ()); is_initialized = (store.account.begin (transaction) != store.account.end (transaction));
} }
if (!is_initialized && !flags.read_only) if (!is_initialized && !flags.read_only)
@ -415,7 +414,7 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
// TODO: Is it neccessary to call this for all blocks? // TODO: Is it neccessary to call this for all blocks?
if (block->is_send ()) if (block->is_send ())
{ {
wallet_workers.push_task ([this, hash = block->hash (), destination = block->destination ()] () { wallet_workers.post ([this, hash = block->hash (), destination = block->destination ()] () {
wallets.receive_confirmed (hash, destination); wallets.receive_confirmed (hash, destination);
}); });
} }
@ -577,7 +576,7 @@ void nano::node::start ()
if (flags.enable_pruning) if (flags.enable_pruning)
{ {
auto this_l (shared ()); auto this_l (shared ());
workers.push_task ([this_l] () { workers.post ([this_l] () {
this_l->ongoing_ledger_pruning (); this_l->ongoing_ledger_pruning ();
}); });
} }
@ -618,7 +617,7 @@ void nano::node::start ()
{ {
// Delay to start wallet lazy bootstrap // Delay to start wallet lazy bootstrap
auto this_l (shared ()); auto this_l (shared ());
workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::minutes (1), [this_l] () { workers.post_delayed (std::chrono::minutes (1), [this_l] () {
this_l->bootstrap_wallet (); this_l->bootstrap_wallet ();
}); });
} }
@ -667,9 +666,7 @@ void nano::node::stop ()
logger.info (nano::log::type::node, "Node stopping..."); logger.info (nano::log::type::node, "Node stopping...");
tcp_listener.stop (); tcp_listener.stop ();
bootstrap_workers.stop ();
wallet_workers.stop ();
election_workers.stop ();
vote_router.stop (); vote_router.stop ();
peer_history.stop (); peer_history.stop ();
// Cancels ongoing work generation tasks, which may be blocking other threads // Cancels ongoing work generation tasks, which may be blocking other threads
@ -697,12 +694,16 @@ void nano::node::stop ()
wallets.stop (); wallets.stop ();
stats.stop (); stats.stop ();
epoch_upgrader.stop (); epoch_upgrader.stop ();
workers.stop ();
local_block_broadcaster.stop (); local_block_broadcaster.stop ();
message_processor.stop (); message_processor.stop ();
network.stop (); // Stop network last to avoid killing in-use sockets network.stop (); // Stop network last to avoid killing in-use sockets
monitor.stop (); monitor.stop ();
bootstrap_workers.stop ();
wallet_workers.stop ();
election_workers.stop ();
workers.stop ();
// work pool is not stopped on purpose due to testing setup // work pool is not stopped on purpose due to testing setup
// Stop the IO runner last // Stop the IO runner last
@ -768,7 +769,7 @@ void nano::node::long_inactivity_cleanup ()
if (store.online_weight.count (transaction) > 0) if (store.online_weight.count (transaction) > 0)
{ {
auto sample (store.online_weight.rbegin (transaction)); auto sample (store.online_weight.rbegin (transaction));
auto n (store.online_weight.end ()); auto n (store.online_weight.rend (transaction));
debug_assert (sample != n); debug_assert (sample != n);
auto const one_week_ago = static_cast<std::size_t> ((std::chrono::system_clock::now () - std::chrono::hours (7 * 24)).time_since_epoch ().count ()); auto const one_week_ago = static_cast<std::size_t> ((std::chrono::system_clock::now () - std::chrono::hours (7 * 24)).time_since_epoch ().count ());
perform_cleanup = sample->first < one_week_ago; perform_cleanup = sample->first < one_week_ago;
@ -817,7 +818,7 @@ void nano::node::ongoing_bootstrap ()
{ {
auto transaction = store.tx_begin_read (); auto transaction = store.tx_begin_read ();
auto last_record = store.online_weight.rbegin (transaction); auto last_record = store.online_weight.rbegin (transaction);
if (last_record != store.online_weight.end ()) if (last_record != store.online_weight.end (transaction))
{ {
last_sample_time = last_record->first; last_sample_time = last_record->first;
} }
@ -836,7 +837,7 @@ void nano::node::ongoing_bootstrap ()
// Bootstrap and schedule for next attempt // Bootstrap and schedule for next attempt
bootstrap_initiator.bootstrap (false, boost::str (boost::format ("auto_bootstrap_%1%") % previous_bootstrap_count), frontiers_age); bootstrap_initiator.bootstrap (false, boost::str (boost::format ("auto_bootstrap_%1%") % previous_bootstrap_count), frontiers_age);
std::weak_ptr<nano::node> node_w (shared_from_this ()); std::weak_ptr<nano::node> node_w (shared_from_this ());
workers.add_timed_task (std::chrono::steady_clock::now () + next_wakeup, [node_w] () { workers.post_delayed (next_wakeup, [node_w] () {
if (auto node_l = node_w.lock ()) if (auto node_l = node_w.lock ())
{ {
node_l->ongoing_bootstrap (); node_l->ongoing_bootstrap ();
@ -857,7 +858,7 @@ void nano::node::backup_wallet ()
i->second->store.write_backup (transaction, backup_path / (i->first.to_string () + ".json")); i->second->store.write_backup (transaction, backup_path / (i->first.to_string () + ".json"));
} }
auto this_l (shared ()); auto this_l (shared ());
workers.add_timed_task (std::chrono::steady_clock::now () + network_params.node.backup_interval, [this_l] () { workers.post_delayed (network_params.node.backup_interval, [this_l] () {
this_l->backup_wallet (); this_l->backup_wallet ();
}); });
} }
@ -869,7 +870,7 @@ void nano::node::search_receivable_all ()
// Search pending // Search pending
wallets.search_receivable_all (); wallets.search_receivable_all ();
auto this_l (shared ()); auto this_l (shared ());
workers.add_timed_task (std::chrono::steady_clock::now () + network_params.node.search_pending_interval, [this_l] () { workers.post_delayed (network_params.node.search_pending_interval, [this_l] () {
this_l->search_receivable_all (); this_l->search_receivable_all ();
}); });
} }
@ -884,7 +885,7 @@ void nano::node::bootstrap_wallet ()
{ {
auto & wallet (*i->second); auto & wallet (*i->second);
nano::lock_guard<std::recursive_mutex> wallet_lock{ wallet.store.mutex }; nano::lock_guard<std::recursive_mutex> wallet_lock{ wallet.store.mutex };
for (auto j (wallet.store.begin (transaction)), m (wallet.store.end ()); j != m && accounts.size () < 128; ++j) for (auto j (wallet.store.begin (transaction)), m (wallet.store.end (transaction)); j != m && accounts.size () < 128; ++j)
{ {
nano::account account (j->first); nano::account account (j->first);
accounts.push_back (account); accounts.push_back (account);
@ -902,7 +903,7 @@ bool nano::node::collect_ledger_pruning_targets (std::deque<nano::block_hash> &
uint64_t read_operations (0); uint64_t read_operations (0);
bool finish_transaction (false); bool finish_transaction (false);
auto transaction = ledger.tx_begin_read (); auto transaction = ledger.tx_begin_read ();
for (auto i (store.confirmation_height.begin (transaction, last_account_a)), n (store.confirmation_height.end ()); i != n && !finish_transaction;) for (auto i (store.confirmation_height.begin (transaction, last_account_a)), n (store.confirmation_height.end (transaction)); i != n && !finish_transaction;)
{ {
++read_operations; ++read_operations;
auto const & account (i->first); auto const & account (i->first);
@ -994,8 +995,8 @@ void nano::node::ongoing_ledger_pruning ()
ledger_pruning (flags.block_processor_batch_size != 0 ? flags.block_processor_batch_size : 2 * 1024, bootstrap_weight_reached); ledger_pruning (flags.block_processor_batch_size != 0 ? flags.block_processor_batch_size : 2 * 1024, bootstrap_weight_reached);
auto const ledger_pruning_interval (bootstrap_weight_reached ? config.max_pruning_age : std::min (config.max_pruning_age, std::chrono::seconds (15 * 60))); auto const ledger_pruning_interval (bootstrap_weight_reached ? config.max_pruning_age : std::min (config.max_pruning_age, std::chrono::seconds (15 * 60)));
auto this_l (shared ()); auto this_l (shared ());
workers.add_timed_task (std::chrono::steady_clock::now () + ledger_pruning_interval, [this_l] () { workers.post_delayed (ledger_pruning_interval, [this_l] () {
this_l->workers.push_task ([this_l] () { this_l->workers.post ([this_l] () {
this_l->ongoing_ledger_pruning (); this_l->ongoing_ledger_pruning ();
}); });
}); });
@ -1139,7 +1140,7 @@ bool nano::node::block_confirmed_or_being_confirmed (nano::block_hash const & ha
void nano::node::ongoing_online_weight_calculation_queue () void nano::node::ongoing_online_weight_calculation_queue ()
{ {
std::weak_ptr<nano::node> node_w (shared_from_this ()); std::weak_ptr<nano::node> node_w (shared_from_this ());
workers.add_timed_task (std::chrono::steady_clock::now () + (std::chrono::seconds (network_params.node.weight_period)), [node_w] () { workers.post_delayed ((std::chrono::seconds (network_params.node.weight_period)), [node_w] () {
if (auto node_l = node_w.lock ()) if (auto node_l = node_w.lock ())
{ {
node_l->ongoing_online_weight_calculation (); node_l->ongoing_online_weight_calculation ();

View file

@ -4,7 +4,6 @@
#include <nano/lib/config.hpp> #include <nano/lib/config.hpp>
#include <nano/lib/logging.hpp> #include <nano/lib/logging.hpp>
#include <nano/lib/stats.hpp> #include <nano/lib/stats.hpp>
#include <nano/lib/thread_pool.hpp>
#include <nano/lib/work.hpp> #include <nano/lib/work.hpp>
#include <nano/node/bootstrap/bootstrap.hpp> #include <nano/node/bootstrap/bootstrap.hpp>
#include <nano/node/bootstrap/bootstrap_attempt.hpp> #include <nano/node/bootstrap/bootstrap_attempt.hpp>
@ -146,6 +145,7 @@ public:
public: public:
const nano::keypair node_id; const nano::keypair node_id;
nano::node_config config; nano::node_config config;
nano::node_flags flags;
std::shared_ptr<boost::asio::io_context> io_ctx_shared; std::shared_ptr<boost::asio::io_context> io_ctx_shared;
boost::asio::io_context & io_ctx; boost::asio::io_context & io_ctx;
nano::logger logger; nano::logger logger;
@ -154,11 +154,14 @@ public:
boost::latch node_initialized_latch; boost::latch node_initialized_latch;
nano::network_params & network_params; nano::network_params & network_params;
nano::stats stats; nano::stats stats;
nano::thread_pool workers; std::unique_ptr<nano::thread_pool> workers_impl;
nano::thread_pool bootstrap_workers; nano::thread_pool & workers;
nano::thread_pool wallet_workers; std::unique_ptr<nano::thread_pool> bootstrap_workers_impl;
nano::thread_pool election_workers; nano::thread_pool & bootstrap_workers;
nano::node_flags flags; std::unique_ptr<nano::thread_pool> wallet_workers_impl;
nano::thread_pool & wallet_workers;
std::unique_ptr<nano::thread_pool> election_workers_impl;
nano::thread_pool & election_workers;
nano::work_pool & work; nano::work_pool & work;
nano::distributed_work_factory distributed_work; nano::distributed_work_factory distributed_work;
std::unique_ptr<nano::store::component> store_impl; std::unique_ptr<nano::store::component> store_impl;

View file

@ -120,7 +120,6 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const
toml.put ("allow_local_peers", allow_local_peers, "Enable or disable local host peering.\ntype:bool"); toml.put ("allow_local_peers", allow_local_peers, "Enable or disable local host peering.\ntype:bool");
toml.put ("vote_minimum", vote_minimum.to_string_dec (), "Local representatives do not vote if the delegated weight is under this threshold. Saves on system resources.\ntype:string,amount,raw"); toml.put ("vote_minimum", vote_minimum.to_string_dec (), "Local representatives do not vote if the delegated weight is under this threshold. Saves on system resources.\ntype:string,amount,raw");
toml.put ("vote_generator_delay", vote_generator_delay.count (), "Delay before votes are sent to allow for efficient bundling of hashes in votes.\ntype:milliseconds"); toml.put ("vote_generator_delay", vote_generator_delay.count (), "Delay before votes are sent to allow for efficient bundling of hashes in votes.\ntype:milliseconds");
toml.put ("vote_generator_threshold", vote_generator_threshold, "Number of bundled hashes required for an additional generator delay.\ntype:uint64,[1..11]");
toml.put ("unchecked_cutoff_time", unchecked_cutoff_time.count (), "Number of seconds before deleting an unchecked entry.\nWarning: lower values (e.g., 3600 seconds, or 1 hour) may result in unsuccessful bootstraps, especially a bootstrap from scratch.\ntype:seconds"); toml.put ("unchecked_cutoff_time", unchecked_cutoff_time.count (), "Number of seconds before deleting an unchecked entry.\nWarning: lower values (e.g., 3600 seconds, or 1 hour) may result in unsuccessful bootstraps, especially a bootstrap from scratch.\ntype:seconds");
toml.put ("tcp_io_timeout", tcp_io_timeout.count (), "Timeout for TCP connect-, read- and write operations.\nWarning: a low value (e.g., below 5 seconds) may result in TCP connections failing.\ntype:seconds"); toml.put ("tcp_io_timeout", tcp_io_timeout.count (), "Timeout for TCP connect-, read- and write operations.\nWarning: a low value (e.g., below 5 seconds) may result in TCP connections failing.\ntype:seconds");
toml.put ("pow_sleep_interval", pow_sleep_interval.count (), "Time to sleep between batch work generation attempts. Reduces max CPU usage at the expense of a longer generation time.\ntype:nanoseconds"); toml.put ("pow_sleep_interval", pow_sleep_interval.count (), "Time to sleep between batch work generation attempts. Reduces max CPU usage at the expense of a longer generation time.\ntype:nanoseconds");
@ -484,8 +483,6 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml)
toml.get ("vote_generator_delay", delay_l); toml.get ("vote_generator_delay", delay_l);
vote_generator_delay = std::chrono::milliseconds (delay_l); vote_generator_delay = std::chrono::milliseconds (delay_l);
toml.get<unsigned> ("vote_generator_threshold", vote_generator_threshold);
auto block_processor_batch_max_time_l = block_processor_batch_max_time.count (); auto block_processor_batch_max_time_l = block_processor_batch_max_time.count ();
toml.get ("block_processor_batch_max_time", block_processor_batch_max_time_l); toml.get ("block_processor_batch_max_time", block_processor_batch_max_time_l);
block_processor_batch_max_time = std::chrono::milliseconds (block_processor_batch_max_time_l); block_processor_batch_max_time = std::chrono::milliseconds (block_processor_batch_max_time_l);
@ -600,10 +597,6 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml)
{ {
toml.get_error ().set ("bandwidth_limit unbounded = 0, default = 10485760, max = 18446744073709551615"); toml.get_error ().set ("bandwidth_limit unbounded = 0, default = 10485760, max = 18446744073709551615");
} }
if (vote_generator_threshold < 1 || vote_generator_threshold > 11)
{
toml.get_error ().set ("vote_generator_threshold must be a number between 1 and 11");
}
if (max_work_generate_multiplier < 1) if (max_work_generate_multiplier < 1)
{ {
toml.get_error ().set ("max_work_generate_multiplier must be greater than or equal to 1"); toml.get_error ().set ("max_work_generate_multiplier must be greater than or equal to 1");

View file

@ -73,7 +73,6 @@ public:
nano::amount vote_minimum{ nano::Knano_ratio }; // 1000 nano nano::amount vote_minimum{ nano::Knano_ratio }; // 1000 nano
nano::amount rep_crawler_weight_minimum{ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" }; nano::amount rep_crawler_weight_minimum{ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" };
std::chrono::milliseconds vote_generator_delay{ std::chrono::milliseconds (100) }; std::chrono::milliseconds vote_generator_delay{ std::chrono::milliseconds (100) };
unsigned vote_generator_threshold{ 3 };
nano::amount online_weight_minimum{ 60000 * nano::Knano_ratio }; // 60 million nano nano::amount online_weight_minimum{ 60000 * nano::Knano_ratio }; // 60 million nano
/* /*
* The minimum vote weight that a representative must have for its vote to be counted. * The minimum vote weight that a representative must have for its vote to be counted.

View file

@ -45,7 +45,7 @@ void nano::online_reps::sample ()
while (ledger.store.online_weight.count (transaction) >= config.network_params.node.max_weight_samples) while (ledger.store.online_weight.count (transaction) >= config.network_params.node.max_weight_samples)
{ {
auto oldest (ledger.store.online_weight.begin (transaction)); auto oldest (ledger.store.online_weight.begin (transaction));
debug_assert (oldest != ledger.store.online_weight.end ()); debug_assert (oldest != ledger.store.online_weight.end (transaction));
ledger.store.online_weight.del (transaction, oldest->first); ledger.store.online_weight.del (transaction, oldest->first);
} }
ledger.store.online_weight.put (transaction, std::chrono::system_clock::now ().time_since_epoch ().count (), online_l); ledger.store.online_weight.put (transaction, std::chrono::system_clock::now ().time_since_epoch ().count (), online_l);
@ -70,7 +70,7 @@ nano::uint128_t nano::online_reps::calculate_trend (store::transaction & transac
std::vector<nano::uint128_t> items; std::vector<nano::uint128_t> items;
items.reserve (config.network_params.node.max_weight_samples + 1); items.reserve (config.network_params.node.max_weight_samples + 1);
items.push_back (config.online_weight_minimum.number ()); items.push_back (config.online_weight_minimum.number ());
for (auto i (ledger.store.online_weight.begin (transaction_a)), n (ledger.store.online_weight.end ()); i != n; ++i) for (auto i (ledger.store.online_weight.begin (transaction_a)), n (ledger.store.online_weight.end (transaction_a)); i != n; ++i)
{ {
items.push_back (i->second.number ()); items.push_back (i->second.number ());
} }

View file

@ -104,7 +104,7 @@ void nano::peer_history::run_one ()
auto const now = std::chrono::system_clock::now (); auto const now = std::chrono::system_clock::now ();
auto const cutoff = now - config.erase_cutoff; auto const cutoff = now - config.erase_cutoff;
for (auto it = store.peer.begin (transaction); it != store.peer.end (); ++it) for (auto it = store.peer.begin (transaction); it != store.peer.end (transaction); ++it)
{ {
auto const [endpoint, timestamp_millis] = *it; auto const [endpoint, timestamp_millis] = *it;
auto timestamp = nano::from_milliseconds_since_epoch (timestamp_millis); auto timestamp = nano::from_milliseconds_since_epoch (timestamp_millis);
@ -124,7 +124,7 @@ std::vector<nano::endpoint> nano::peer_history::peers () const
{ {
auto transaction = store.tx_begin_read (); auto transaction = store.tx_begin_read ();
std::vector<nano::endpoint> peers; std::vector<nano::endpoint> peers;
for (auto it = store.peer.begin (transaction); it != store.peer.end (); ++it) for (auto it = store.peer.begin (transaction); it != store.peer.end (transaction); ++it)
{ {
auto const [endpoint, timestamp_millis] = *it; auto const [endpoint, timestamp_millis] = *it;
peers.push_back (endpoint.endpoint ()); peers.push_back (endpoint.endpoint ());

View file

@ -43,12 +43,6 @@ void nano::process_live_dispatcher::inspect (nano::block_status const & result,
void nano::process_live_dispatcher::process_live (nano::block const & block, secure::transaction const & transaction) void nano::process_live_dispatcher::process_live (nano::block const & block, secure::transaction const & transaction)
{ {
// Start collecting quorum on block
if (ledger.dependents_confirmed (transaction, block))
{
scheduler.activate (transaction, block.account ());
}
if (websocket.server && websocket.server->any_subscriber (nano::websocket::topic::new_unconfirmed_block)) if (websocket.server && websocket.server->any_subscriber (nano::websocket::topic::new_unconfirmed_block))
{ {
websocket.server->broadcast (nano::websocket::message_builder ().new_block_arrived (block)); websocket.server->broadcast (nano::websocket::message_builder ().new_block_arrived (block));

View file

@ -102,7 +102,7 @@ void nano::rep_crawler::validate_and_process (nano::unique_lock<nano::mutex> & l
rep.last_response = std::chrono::steady_clock::now (); rep.last_response = std::chrono::steady_clock::now ();
// Update if representative channel was changed // Update if representative channel was changed
if (rep.channel->get_endpoint () != channel->get_endpoint ()) if (rep.channel->get_remote_endpoint () != channel->get_remote_endpoint ())
{ {
debug_assert (rep.account == vote->account); debug_assert (rep.account == vote->account);
updated = true; updated = true;

View file

@ -5,16 +5,22 @@
#include <nano/node/scheduler/optimistic.hpp> #include <nano/node/scheduler/optimistic.hpp>
#include <nano/node/scheduler/priority.hpp> #include <nano/node/scheduler/priority.hpp>
nano::scheduler::component::component (nano::node & node) : nano::scheduler::component::component (nano::node_config & node_config, nano::node & node, nano::ledger & ledger, nano::block_processor & block_processor, nano::active_elections & active, nano::online_reps & online_reps, nano::vote_cache & vote_cache, nano::confirming_set & confirming_set, nano::stats & stats, nano::logger & logger) :
hinted_impl{ std::make_unique<nano::scheduler::hinted> (node.config.hinted_scheduler, node, node.vote_cache, node.active, node.online_reps, node.stats) }, hinted_impl{ std::make_unique<nano::scheduler::hinted> (node_config.hinted_scheduler, node, vote_cache, active, online_reps, stats) },
manual_impl{ std::make_unique<nano::scheduler::manual> (node) }, manual_impl{ std::make_unique<nano::scheduler::manual> (node) },
optimistic_impl{ std::make_unique<nano::scheduler::optimistic> (node.config.optimistic_scheduler, node, node.ledger, node.active, node.network_params.network, node.stats) }, optimistic_impl{ std::make_unique<nano::scheduler::optimistic> (node_config.optimistic_scheduler, node, ledger, active, node_config.network_params.network, stats) },
priority_impl{ std::make_unique<nano::scheduler::priority> (node, node.stats) }, priority_impl{ std::make_unique<nano::scheduler::priority> (node_config, node, ledger, block_processor, active, confirming_set, stats, logger) },
hinted{ *hinted_impl }, hinted{ *hinted_impl },
manual{ *manual_impl }, manual{ *manual_impl },
optimistic{ *optimistic_impl }, optimistic{ *optimistic_impl },
priority{ *priority_impl } priority{ *priority_impl }
{ {
// Notify election schedulers when AEC frees election slot
active.vacancy_updated.add ([this] () {
priority.notify ();
hinted.notify ();
optimistic.notify ();
});
} }
nano::scheduler::component::~component () nano::scheduler::component::~component ()

View file

@ -10,12 +10,10 @@ namespace nano::scheduler
class component final class component final
{ {
public: public:
explicit component (nano::node & node); component (nano::node_config &, nano::node &, nano::ledger &, nano::block_processor &, nano::active_elections &, nano::online_reps &, nano::vote_cache &, nano::confirming_set &, nano::stats &, nano::logger &);
~component (); ~component ();
// Starts all schedulers
void start (); void start ();
// Stops all schedulers
void stop (); void stop ();
nano::container_info container_info () const; nano::container_info container_info () const;

View file

@ -7,10 +7,15 @@
#include <nano/secure/ledger_set_any.hpp> #include <nano/secure/ledger_set_any.hpp>
#include <nano/secure/ledger_set_confirmed.hpp> #include <nano/secure/ledger_set_confirmed.hpp>
nano::scheduler::priority::priority (nano::node & node_a, nano::stats & stats_a) : nano::scheduler::priority::priority (nano::node_config & node_config, nano::node & node_a, nano::ledger & ledger_a, nano::block_processor & block_processor_a, nano::active_elections & active_a, nano::confirming_set & confirming_set_a, nano::stats & stats_a, nano::logger & logger_a) :
config{ node_a.config.priority_scheduler }, config{ node_config.priority_scheduler },
node{ node_a }, node{ node_a },
stats{ stats_a } ledger{ ledger_a },
block_processor{ block_processor_a },
active{ active_a },
confirming_set{ confirming_set_a },
stats{ stats_a },
logger{ logger_a }
{ {
std::vector<nano::uint128_t> minimums; std::vector<nano::uint128_t> minimums;
@ -34,13 +39,41 @@ nano::scheduler::priority::priority (nano::node & node_a, nano::stats & stats_a)
build_region (uint128_t{ 1 } << 116, uint128_t{ 1 } << 120, 2); build_region (uint128_t{ 1 } << 116, uint128_t{ 1 } << 120, 2);
minimums.push_back (uint128_t{ 1 } << 120); minimums.push_back (uint128_t{ 1 } << 120);
node.logger.debug (nano::log::type::election_scheduler, "Number of buckets: {}", minimums.size ()); logger.debug (nano::log::type::election_scheduler, "Number of buckets: {}", minimums.size ());
for (size_t i = 0u, n = minimums.size (); i < n; ++i) for (size_t i = 0u, n = minimums.size (); i < n; ++i)
{ {
auto bucket = std::make_unique<scheduler::bucket> (minimums[i], node.config.priority_bucket, node.active, stats); auto bucket = std::make_unique<scheduler::bucket> (minimums[i], node_config.priority_bucket, active, stats);
buckets.emplace_back (std::move (bucket)); buckets.emplace_back (std::move (bucket));
} }
// Activate accounts with fresh blocks
block_processor.batch_processed.add ([this] (auto const & batch) {
auto transaction = ledger.tx_begin_read ();
for (auto const & [result, context] : batch)
{
if (result == nano::block_status::progress)
{
release_assert (context.block != nullptr);
activate (transaction, context.block->account ());
}
}
});
// Activate successors of cemented blocks
confirming_set.batch_cemented.add ([this] (auto const & batch) {
if (node.flags.disable_activate_successors)
{
return;
}
auto transaction = ledger.tx_begin_read ();
for (auto const & context : batch)
{
release_assert (context.block != nullptr);
activate_successors (transaction, *context.block);
}
});
} }
nano::scheduler::priority::~priority () nano::scheduler::priority::~priority ()
@ -85,11 +118,10 @@ void nano::scheduler::priority::stop ()
bool nano::scheduler::priority::activate (secure::transaction const & transaction, nano::account const & account) bool nano::scheduler::priority::activate (secure::transaction const & transaction, nano::account const & account)
{ {
debug_assert (!account.is_zero ()); debug_assert (!account.is_zero ());
auto info = node.ledger.any.account_get (transaction, account); if (auto info = ledger.any.account_get (transaction, account))
if (info)
{ {
nano::confirmation_height_info conf_info; nano::confirmation_height_info conf_info;
node.store.confirmation_height.get (transaction, account, conf_info); ledger.store.confirmation_height.get (transaction, account, conf_info);
if (conf_info.height < info->block_count) if (conf_info.height < info->block_count)
{ {
return activate (transaction, account, *info, conf_info); return activate (transaction, account, *info, conf_info);
@ -103,14 +135,14 @@ bool nano::scheduler::priority::activate (secure::transaction const & transactio
{ {
debug_assert (conf_info.frontier != account_info.head); debug_assert (conf_info.frontier != account_info.head);
auto hash = conf_info.height == 0 ? account_info.open_block : node.ledger.any.block_successor (transaction, conf_info.frontier).value (); auto hash = conf_info.height == 0 ? account_info.open_block : ledger.any.block_successor (transaction, conf_info.frontier).value ();
auto block = node.ledger.any.block_get (transaction, hash); auto block = ledger.any.block_get (transaction, hash);
release_assert (block != nullptr); release_assert (block != nullptr);
if (node.ledger.dependents_confirmed (transaction, *block)) if (ledger.dependents_confirmed (transaction, *block))
{ {
auto const balance = block->balance (); auto const balance = block->balance ();
auto const previous_balance = node.ledger.any.block_balance (transaction, conf_info.frontier).value_or (0); auto const previous_balance = ledger.any.block_balance (transaction, conf_info.frontier).value_or (0);
auto const balance_priority = std::max (balance, previous_balance); auto const balance_priority = std::max (balance, previous_balance);
bool added = false; bool added = false;
@ -120,8 +152,8 @@ bool nano::scheduler::priority::activate (secure::transaction const & transactio
} }
if (added) if (added)
{ {
node.stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activated); stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activated);
node.logger.trace (nano::log::type::election_scheduler, nano::log::detail::block_activated, logger.trace (nano::log::type::election_scheduler, nano::log::detail::block_activated,
nano::log::arg{ "account", account.to_account () }, // TODO: Convert to lazy eval nano::log::arg{ "account", account.to_account () }, // TODO: Convert to lazy eval
nano::log::arg{ "block", block }, nano::log::arg{ "block", block },
nano::log::arg{ "time", account_info.modified }, nano::log::arg{ "time", account_info.modified },
@ -131,7 +163,7 @@ bool nano::scheduler::priority::activate (secure::transaction const & transactio
} }
else else
{ {
node.stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activate_full); stats.inc (nano::stat::type::election_scheduler, nano::stat::detail::activate_full);
} }
return true; // Activated return true; // Activated
@ -141,6 +173,17 @@ bool nano::scheduler::priority::activate (secure::transaction const & transactio
return false; // Not activated return false; // Not activated
} }
bool nano::scheduler::priority::activate_successors (secure::transaction const & transaction, nano::block const & block)
{
bool result = activate (transaction, block.account ());
// Start or vote for the next unconfirmed block in the destination account
if (block.is_send () && !block.destination ().is_zero () && block.destination () != block.account ())
{
result |= activate (transaction, block.destination ());
}
return result;
}
void nano::scheduler::priority::notify () void nano::scheduler::priority::notify ()
{ {
condition.notify_all (); condition.notify_all ();

View file

@ -26,7 +26,7 @@ public:
class priority final class priority final
{ {
public: public:
priority (nano::node &, nano::stats &); priority (nano::node_config &, nano::node &, nano::ledger &, nano::block_processor &, nano::active_elections &, nano::confirming_set &, nano::stats &, nano::logger &);
~priority (); ~priority ();
void start (); void start ();
@ -36,8 +36,9 @@ public:
* Activates the first unconfirmed block of \p account_a * Activates the first unconfirmed block of \p account_a
* @return true if account was activated * @return true if account was activated
*/ */
bool activate (secure::transaction const &, nano::account const &); bool activate (nano::secure::transaction const &, nano::account const &);
bool activate (secure::transaction const &, nano::account const &, nano::account_info const &, nano::confirmation_height_info const &); bool activate (nano::secure::transaction const &, nano::account const &, nano::account_info const &, nano::confirmation_height_info const &);
bool activate_successors (nano::secure::transaction const &, nano::block const &);
void notify (); void notify ();
std::size_t size () const; std::size_t size () const;
@ -48,7 +49,12 @@ public:
private: // Dependencies private: // Dependencies
priority_config const & config; priority_config const & config;
nano::node & node; nano::node & node;
nano::ledger & ledger;
nano::block_processor & block_processor;
nano::active_elections & active;
nano::confirming_set & confirming_set;
nano::stats & stats; nano::stats & stats;
nano::logger & logger;
private: private:
void run (); void run ();

View file

@ -209,7 +209,7 @@ void nano::telemetry::run_requests ()
} }
} }
void nano::telemetry::request (std::shared_ptr<nano::transport::channel> & channel) void nano::telemetry::request (std::shared_ptr<nano::transport::channel> const & channel)
{ {
stats.inc (nano::stat::type::telemetry, nano::stat::detail::request); stats.inc (nano::stat::type::telemetry, nano::stat::detail::request);
@ -228,7 +228,7 @@ void nano::telemetry::run_broadcasts ()
} }
} }
void nano::telemetry::broadcast (std::shared_ptr<nano::transport::channel> & channel, const nano::telemetry_data & telemetry) void nano::telemetry::broadcast (std::shared_ptr<nano::transport::channel> const & channel, const nano::telemetry_data & telemetry)
{ {
stats.inc (nano::stat::type::telemetry, nano::stat::detail::broadcast); stats.inc (nano::stat::type::telemetry, nano::stat::detail::broadcast);

View file

@ -92,7 +92,7 @@ private:
nano::endpoint endpoint () const nano::endpoint endpoint () const
{ {
return channel->get_endpoint (); return channel->get_remote_endpoint ();
} }
}; };
@ -105,8 +105,8 @@ private:
void run_broadcasts (); void run_broadcasts ();
void cleanup (); void cleanup ();
void request (std::shared_ptr<nano::transport::channel> &); void request (std::shared_ptr<nano::transport::channel> const &);
void broadcast (std::shared_ptr<nano::transport::channel> &, nano::telemetry_data const &); void broadcast (std::shared_ptr<nano::transport::channel> const &, nano::telemetry_data const &);
bool verify (nano::telemetry_ack const &, std::shared_ptr<nano::transport::channel> const &) const; bool verify (nano::telemetry_ack const &, std::shared_ptr<nano::transport::channel> const &) const;
bool check_timeout (entry const &) const; bool check_timeout (entry const &) const;

View file

@ -45,22 +45,20 @@ void nano::transport::channel::send (nano::message & message_a, std::function<vo
void nano::transport::channel::set_peering_endpoint (nano::endpoint endpoint) void nano::transport::channel::set_peering_endpoint (nano::endpoint endpoint)
{ {
nano::lock_guard<nano::mutex> lock{ channel_mutex }; nano::lock_guard<nano::mutex> lock{ mutex };
peering_endpoint = endpoint; peering_endpoint = endpoint;
} }
nano::endpoint nano::transport::channel::get_peering_endpoint () const nano::endpoint nano::transport::channel::get_peering_endpoint () const
{ {
nano::unique_lock<nano::mutex> lock{ channel_mutex };
if (peering_endpoint)
{ {
return *peering_endpoint; nano::lock_guard<nano::mutex> lock{ mutex };
} if (peering_endpoint)
else {
{ return *peering_endpoint;
lock.unlock (); }
return get_endpoint ();
} }
return get_remote_endpoint ();
} }
std::shared_ptr<nano::node> nano::transport::channel::owner () const std::shared_ptr<nano::node> nano::transport::channel::owner () const
@ -70,7 +68,8 @@ std::shared_ptr<nano::node> nano::transport::channel::owner () const
void nano::transport::channel::operator() (nano::object_stream & obs) const void nano::transport::channel::operator() (nano::object_stream & obs) const
{ {
obs.write ("endpoint", get_endpoint ()); obs.write ("remote_endpoint", get_remote_endpoint ());
obs.write ("local_endpoint", get_local_endpoint ());
obs.write ("peering_endpoint", get_peering_endpoint ()); obs.write ("peering_endpoint", get_peering_endpoint ());
obs.write ("node_id", get_node_id ().to_node_id ()); obs.write ("node_id", get_node_id ().to_node_id ());
} }

View file

@ -40,10 +40,10 @@ public:
virtual void close () = 0; virtual void close () = 0;
virtual std::string to_string () const = 0; virtual nano::endpoint get_remote_endpoint () const = 0;
virtual nano::endpoint get_endpoint () const = 0;
virtual nano::tcp_endpoint get_tcp_endpoint () const = 0;
virtual nano::endpoint get_local_endpoint () const = 0; virtual nano::endpoint get_local_endpoint () const = 0;
virtual std::string to_string () const = 0;
virtual nano::transport::transport_type get_type () const = 0; virtual nano::transport::transport_type get_type () const = 0;
virtual bool max (nano::transport::traffic_type = nano::transport::traffic_type::generic) virtual bool max (nano::transport::traffic_type = nano::transport::traffic_type::generic)
@ -58,62 +58,55 @@ public:
std::chrono::steady_clock::time_point get_last_bootstrap_attempt () const std::chrono::steady_clock::time_point get_last_bootstrap_attempt () const
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
return last_bootstrap_attempt; return last_bootstrap_attempt;
} }
void set_last_bootstrap_attempt (std::chrono::steady_clock::time_point const time_a) void set_last_bootstrap_attempt (std::chrono::steady_clock::time_point const time_a)
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
last_bootstrap_attempt = time_a; last_bootstrap_attempt = time_a;
} }
std::chrono::steady_clock::time_point get_last_packet_received () const std::chrono::steady_clock::time_point get_last_packet_received () const
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
return last_packet_received; return last_packet_received;
} }
void set_last_packet_received (std::chrono::steady_clock::time_point const time_a) void set_last_packet_received (std::chrono::steady_clock::time_point const time_a)
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
last_packet_received = time_a; last_packet_received = time_a;
} }
std::chrono::steady_clock::time_point get_last_packet_sent () const std::chrono::steady_clock::time_point get_last_packet_sent () const
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
return last_packet_sent; return last_packet_sent;
} }
void set_last_packet_sent (std::chrono::steady_clock::time_point const time_a) void set_last_packet_sent (std::chrono::steady_clock::time_point const time_a)
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
last_packet_sent = time_a; last_packet_sent = time_a;
} }
boost::optional<nano::account> get_node_id_optional () const std::optional<nano::account> get_node_id_optional () const
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
return node_id; return node_id;
} }
nano::account get_node_id () const nano::account get_node_id () const
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
if (node_id.is_initialized ()) return node_id.value_or (0);
{
return node_id.get ();
}
else
{
return 0;
}
} }
void set_node_id (nano::account node_id_a) void set_node_id (nano::account node_id_a)
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
node_id = node_id_a; node_id = node_id_a;
} }
@ -132,19 +125,18 @@ public:
std::shared_ptr<nano::node> owner () const; std::shared_ptr<nano::node> owner () const;
mutable nano::mutex channel_mutex; protected:
nano::node & node;
mutable nano::mutex mutex;
private: private:
std::chrono::steady_clock::time_point last_bootstrap_attempt{ std::chrono::steady_clock::time_point () }; std::chrono::steady_clock::time_point last_bootstrap_attempt{ std::chrono::steady_clock::time_point () };
std::chrono::steady_clock::time_point last_packet_received{ std::chrono::steady_clock::now () }; std::chrono::steady_clock::time_point last_packet_received{ std::chrono::steady_clock::now () };
std::chrono::steady_clock::time_point last_packet_sent{ std::chrono::steady_clock::now () }; std::chrono::steady_clock::time_point last_packet_sent{ std::chrono::steady_clock::now () };
boost::optional<nano::account> node_id{ boost::none }; std::optional<nano::account> node_id{};
std::atomic<uint8_t> network_version{ 0 }; std::atomic<uint8_t> network_version{ 0 };
std::optional<nano::endpoint> peering_endpoint{}; std::optional<nano::endpoint> peering_endpoint{};
protected:
nano::node & node;
public: // Logging public: // Logging
virtual void operator() (nano::object_stream &) const; virtual void operator() (nano::object_stream &) const;
}; };

View file

@ -30,16 +30,11 @@ namespace transport
endpoint = endpoint_a; endpoint = endpoint_a;
} }
nano::endpoint get_endpoint () const override nano::endpoint get_remote_endpoint () const override
{ {
return endpoint; return endpoint;
} }
nano::tcp_endpoint get_tcp_endpoint () const override
{
return nano::transport::map_endpoint_to_tcp (endpoint);
}
nano::endpoint get_local_endpoint () const override nano::endpoint get_local_endpoint () const override
{ {
return endpoint; return endpoint;

View file

@ -22,16 +22,11 @@ namespace transport
std::string to_string () const override; std::string to_string () const override;
nano::endpoint get_endpoint () const override nano::endpoint get_remote_endpoint () const override
{ {
return endpoint; return endpoint;
} }
nano::tcp_endpoint get_tcp_endpoint () const override
{
return nano::transport::map_endpoint_to_tcp (endpoint);
}
nano::endpoint get_local_endpoint () const override nano::endpoint get_local_endpoint () const override
{ {
return endpoint; return endpoint;

View file

@ -16,8 +16,6 @@ nano::transport::tcp_channel::tcp_channel (nano::node & node_a, std::weak_ptr<na
nano::transport::tcp_channel::~tcp_channel () nano::transport::tcp_channel::~tcp_channel ()
{ {
nano::lock_guard<nano::mutex> lk{ channel_mutex };
// Close socket. Exception: socket is used by tcp_server
if (auto socket_l = socket.lock ()) if (auto socket_l = socket.lock ())
{ {
socket_l->close (); socket_l->close ();
@ -26,14 +24,14 @@ nano::transport::tcp_channel::~tcp_channel ()
void nano::transport::tcp_channel::update_endpoints () void nano::transport::tcp_channel::update_endpoints ()
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
debug_assert (endpoint == nano::endpoint{}); // Not initialized endpoint value debug_assert (remote_endpoint == nano::endpoint{}); // Not initialized endpoint value
debug_assert (local_endpoint == nano::endpoint{}); // Not initialized endpoint value debug_assert (local_endpoint == nano::endpoint{}); // Not initialized endpoint value
if (auto socket_l = socket.lock ()) if (auto socket_l = socket.lock ())
{ {
endpoint = socket_l->remote_endpoint (); remote_endpoint = socket_l->remote_endpoint ();
local_endpoint = socket_l->local_endpoint (); local_endpoint = socket_l->local_endpoint ();
} }
} }
@ -90,7 +88,7 @@ void nano::transport::tcp_channel::send_buffer (nano::shared_const_buffer const
std::string nano::transport::tcp_channel::to_string () const std::string nano::transport::tcp_channel::to_string () const
{ {
return nano::util::to_str (get_tcp_endpoint ()); return nano::util::to_str (get_remote_endpoint ());
} }
void nano::transport::tcp_channel::operator() (nano::object_stream & obs) const void nano::transport::tcp_channel::operator() (nano::object_stream & obs) const

View file

@ -24,20 +24,15 @@ public:
std::string to_string () const override; std::string to_string () const override;
nano::endpoint get_endpoint () const override nano::endpoint get_remote_endpoint () const override
{ {
return nano::transport::map_tcp_to_endpoint (get_tcp_endpoint ()); nano::lock_guard<nano::mutex> lock{ mutex };
} return remote_endpoint;
nano::tcp_endpoint get_tcp_endpoint () const override
{
nano::lock_guard<nano::mutex> lk (channel_mutex);
return endpoint;
} }
nano::endpoint get_local_endpoint () const override nano::endpoint get_local_endpoint () const override
{ {
nano::lock_guard<nano::mutex> lk (channel_mutex); nano::lock_guard<nano::mutex> lock{ mutex };
return local_endpoint; return local_endpoint;
} }
@ -77,7 +72,7 @@ public:
std::weak_ptr<nano::transport::tcp_socket> socket; std::weak_ptr<nano::transport::tcp_socket> socket;
private: private:
nano::endpoint endpoint; nano::endpoint remote_endpoint;
nano::endpoint local_endpoint; nano::endpoint local_endpoint;
public: // Logging public: // Logging

View file

@ -196,9 +196,9 @@ void nano::transport::tcp_channels::random_fill (std::array<nano::endpoint, 8> &
auto j (target_a.begin ()); auto j (target_a.begin ());
for (auto i (peers.begin ()), n (peers.end ()); i != n; ++i, ++j) for (auto i (peers.begin ()), n (peers.end ()); i != n; ++i, ++j)
{ {
debug_assert ((*i)->get_endpoint ().address ().is_v6 ()); debug_assert ((*i)->get_remote_endpoint ().address ().is_v6 ());
debug_assert (j < target_a.end ()); debug_assert (j < target_a.end ());
*j = (*i)->get_endpoint (); *j = (*i)->get_remote_endpoint ();
} }
} }
@ -417,18 +417,6 @@ void nano::transport::tcp_channels::list (std::deque<std::shared_ptr<nano::trans
// clang-format on // clang-format on
} }
void nano::transport::tcp_channels::modify (std::shared_ptr<nano::transport::tcp_channel> const & channel_a, std::function<void (std::shared_ptr<nano::transport::tcp_channel> const &)> modify_callback_a)
{
nano::lock_guard<nano::mutex> lock{ mutex };
auto existing (channels.get<endpoint_tag> ().find (channel_a->get_tcp_endpoint ()));
if (existing != channels.get<endpoint_tag> ().end ())
{
channels.get<endpoint_tag> ().modify (existing, [modify_callback = std::move (modify_callback_a)] (channel_entry & wrapper_a) {
modify_callback (wrapper_a.channel);
});
}
}
void nano::transport::tcp_channels::start_tcp (nano::endpoint const & endpoint) void nano::transport::tcp_channels::start_tcp (nano::endpoint const & endpoint)
{ {
node.tcp_listener.connect (endpoint.address (), endpoint.port ()); node.tcp_listener.connect (endpoint.address (), endpoint.port ());

View file

@ -50,7 +50,6 @@ public:
bool track_reachout (nano::endpoint const &); bool track_reachout (nano::endpoint const &);
void purge (std::chrono::steady_clock::time_point cutoff_deadline); void purge (std::chrono::steady_clock::time_point cutoff_deadline);
void list (std::deque<std::shared_ptr<nano::transport::channel>> &, uint8_t = 0, bool = true); void list (std::deque<std::shared_ptr<nano::transport::channel>> &, uint8_t = 0, bool = true);
void modify (std::shared_ptr<nano::transport::tcp_channel> const &, std::function<void (std::shared_ptr<nano::transport::tcp_channel> const &)>);
void keepalive (); void keepalive ();
std::optional<nano::keepalive> sample_keepalive (); std::optional<nano::keepalive> sample_keepalive ();
@ -81,7 +80,7 @@ private:
} }
nano::tcp_endpoint endpoint () const nano::tcp_endpoint endpoint () const
{ {
return channel->get_tcp_endpoint (); return channel->get_remote_endpoint ();
} }
std::chrono::steady_clock::time_point last_bootstrap_attempt () const std::chrono::steady_clock::time_point last_bootstrap_attempt () const
{ {

View file

@ -526,7 +526,7 @@ void nano::transport::tcp_server::bootstrap_message_visitor::bulk_pull (const na
return; return;
} }
node->bootstrap_workers.push_task ([server = server, message = message] () { node->bootstrap_workers.post ([server = server, message = message] () {
// TODO: Add completion callback to bulk pull server // TODO: Add completion callback to bulk pull server
// TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers // TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers
auto bulk_pull_server = std::make_shared<nano::bulk_pull_server> (server, std::make_unique<nano::bulk_pull> (message)); auto bulk_pull_server = std::make_shared<nano::bulk_pull_server> (server, std::make_unique<nano::bulk_pull> (message));
@ -548,7 +548,7 @@ void nano::transport::tcp_server::bootstrap_message_visitor::bulk_pull_account (
return; return;
} }
node->bootstrap_workers.push_task ([server = server, message = message] () { node->bootstrap_workers.post ([server = server, message = message] () {
// TODO: Add completion callback to bulk pull server // TODO: Add completion callback to bulk pull server
// TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers // TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers
auto bulk_pull_account_server = std::make_shared<nano::bulk_pull_account_server> (server, std::make_unique<nano::bulk_pull_account> (message)); auto bulk_pull_account_server = std::make_shared<nano::bulk_pull_account_server> (server, std::make_unique<nano::bulk_pull_account> (message));
@ -565,7 +565,7 @@ void nano::transport::tcp_server::bootstrap_message_visitor::bulk_push (const na
{ {
return; return;
} }
node->bootstrap_workers.push_task ([server = server] () { node->bootstrap_workers.post ([server = server] () {
// TODO: Add completion callback to bulk pull server // TODO: Add completion callback to bulk pull server
auto bulk_push_server = std::make_shared<nano::bulk_push_server> (server); auto bulk_push_server = std::make_shared<nano::bulk_push_server> (server);
bulk_push_server->throttled_receive (); bulk_push_server->throttled_receive ();
@ -582,7 +582,7 @@ void nano::transport::tcp_server::bootstrap_message_visitor::frontier_req (const
return; return;
} }
node->bootstrap_workers.push_task ([server = server, message = message] () { node->bootstrap_workers.post ([server = server, message = message] () {
// TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers // TODO: There should be no need to re-copy message as unique pointer, refactor those bulk/frontier pull/push servers
auto response = std::make_shared<nano::frontier_req_server> (server, std::make_unique<nano::frontier_req> (message)); auto response = std::make_shared<nano::frontier_req_server> (server, std::make_unique<nano::frontier_req> (message));
response->send_next (); response->send_next ();

View file

@ -274,7 +274,7 @@ void nano::transport::tcp_socket::ongoing_checkup ()
return; return;
} }
node_l->workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (node_l->network_params.network.is_dev_network () ? 1 : 5), [this_w = weak_from_this ()] () { node_l->workers.post_delayed (std::chrono::seconds (node_l->network_params.network.is_dev_network () ? 1 : 5), [this_w = weak_from_this ()] () {
auto this_l = this_w.lock (); auto this_l = this_w.lock ();
if (!this_l) if (!this_l)
{ {

View file

@ -277,7 +277,7 @@ void nano::vote_generator::vote (std::vector<nano::block_hash> const & hashes_a,
void nano::vote_generator::broadcast_action (std::shared_ptr<nano::vote> const & vote_a) const void nano::vote_generator::broadcast_action (std::shared_ptr<nano::vote> const & vote_a) const
{ {
network.flood_vote_pr (vote_a); network.flood_vote_pr (vote_a);
network.flood_vote (vote_a, 2.0f); network.flood_vote_non_pr (vote_a, 2.0f);
vote_processor.vote (vote_a, inproc_channel); vote_processor.vote (vote_a, inproc_channel);
} }
@ -287,31 +287,36 @@ void nano::vote_generator::run ()
nano::unique_lock<nano::mutex> lock{ mutex }; nano::unique_lock<nano::mutex> lock{ mutex };
while (!stopped) while (!stopped)
{ {
if (candidates.size () >= nano::network::confirm_ack_hashes_max) condition.wait_for (lock, config.vote_generator_delay, [this] () { return broadcast_predicate () || !requests.empty (); });
if (broadcast_predicate ())
{ {
broadcast (lock); broadcast (lock);
next_broadcast = std::chrono::steady_clock::now () + std::chrono::milliseconds (config.vote_generator_delay);
} }
else if (!requests.empty ())
if (!requests.empty ())
{ {
auto request (requests.front ()); auto request (requests.front ());
requests.pop_front (); requests.pop_front ();
reply (lock, std::move (request)); reply (lock, std::move (request));
} }
else
{
condition.wait_for (lock, config.vote_generator_delay, [this] () { return this->candidates.size () >= nano::network::confirm_ack_hashes_max; });
if (candidates.size () >= config.vote_generator_threshold && candidates.size () < nano::network::confirm_ack_hashes_max)
{
condition.wait_for (lock, config.vote_generator_delay, [this] () { return this->candidates.size () >= nano::network::confirm_ack_hashes_max; });
}
if (!candidates.empty ())
{
broadcast (lock);
}
}
} }
} }
bool nano::vote_generator::broadcast_predicate () const
{
if (candidates.size () >= nano::network::confirm_ack_hashes_max)
{
return true;
}
if (candidates.size () > 0 && std::chrono::steady_clock::now () > next_broadcast)
{
return true;
}
return false;
}
nano::container_info nano::vote_generator::container_info () const nano::container_info nano::vote_generator::container_info () const
{ {
nano::lock_guard<nano::mutex> guard{ mutex }; nano::lock_guard<nano::mutex> guard{ mutex };

View file

@ -30,6 +30,7 @@ private:
using candidate_t = std::pair<nano::root, nano::block_hash>; using candidate_t = std::pair<nano::root, nano::block_hash>;
using request_t = std::pair<std::vector<candidate_t>, std::shared_ptr<nano::transport::channel>>; using request_t = std::pair<std::vector<candidate_t>, std::shared_ptr<nano::transport::channel>>;
using queue_entry_t = std::pair<nano::root, nano::block_hash>; using queue_entry_t = std::pair<nano::root, nano::block_hash>;
std::chrono::steady_clock::time_point next_broadcast = { std::chrono::steady_clock::now () };
public: public:
vote_generator (nano::node_config const &, nano::node &, nano::ledger &, nano::wallets &, nano::vote_processor &, nano::local_vote_history &, nano::network &, nano::stats &, nano::logger &, bool is_final); vote_generator (nano::node_config const &, nano::node &, nano::ledger &, nano::wallets &, nano::vote_processor &, nano::local_vote_history &, nano::network &, nano::stats &, nano::logger &, bool is_final);
@ -56,6 +57,7 @@ private:
void broadcast_action (std::shared_ptr<nano::vote> const &) const; void broadcast_action (std::shared_ptr<nano::vote> const &) const;
void process_batch (std::deque<queue_entry_t> & batch); void process_batch (std::deque<queue_entry_t> & batch);
bool should_vote (transaction_variant_t const &, nano::root const &, nano::block_hash const &) const; bool should_vote (transaction_variant_t const &, nano::root const &, nano::block_hash const &) const;
bool broadcast_predicate () const;
private: private:
std::function<void (std::shared_ptr<nano::vote> const &, std::shared_ptr<nano::transport::channel> &)> reply_action; // must be set only during initialization by using set_reply_action std::function<void (std::shared_ptr<nano::vote> const &, std::shared_ptr<nano::transport::channel> &)> reply_action; // must be set only during initialization by using set_reply_action

View file

@ -10,6 +10,7 @@
#include <nano/secure/ledger_set_any.hpp> #include <nano/secure/ledger_set_any.hpp>
#include <nano/secure/ledger_set_confirmed.hpp> #include <nano/secure/ledger_set_confirmed.hpp>
#include <nano/store/lmdb/iterator.hpp> #include <nano/store/lmdb/iterator.hpp>
#include <nano/store/typed_iterator_templ.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/polymorphic_cast.hpp> #include <boost/polymorphic_cast.hpp>
@ -19,6 +20,8 @@
#include <argon2.h> #include <argon2.h>
template class nano::store::typed_iterator<nano::account, nano::wallet_value>;
nano::uint256_union nano::wallet_store::check (store::transaction const & transaction_a) nano::uint256_union nano::wallet_store::check (store::transaction const & transaction_a)
{ {
nano::wallet_value value (entry_get_raw (transaction_a, nano::wallet_store::check_special)); nano::wallet_value value (entry_get_raw (transaction_a, nano::wallet_store::check_special));
@ -114,7 +117,7 @@ void nano::wallet_store::deterministic_index_set (store::transaction const & tra
void nano::wallet_store::deterministic_clear (store::transaction const & transaction_a) void nano::wallet_store::deterministic_clear (store::transaction const & transaction_a)
{ {
nano::uint256_union key (0); nano::uint256_union key (0);
for (auto i (begin (transaction_a)), n (end ()); i != n;) for (auto i (begin (transaction_a)), n (end (transaction_a)); i != n;)
{ {
switch (key_type (nano::wallet_value (i->second))) switch (key_type (nano::wallet_value (i->second)))
{ {
@ -370,7 +373,7 @@ nano::wallet_store::wallet_store (bool & init_a, nano::kdf & kdf_a, store::trans
std::vector<nano::account> nano::wallet_store::accounts (store::transaction const & transaction_a) std::vector<nano::account> nano::wallet_store::accounts (store::transaction const & transaction_a)
{ {
std::vector<nano::account> result; std::vector<nano::account> result;
for (auto i (begin (transaction_a)), n (end ()); i != n; ++i) for (auto i (begin (transaction_a)), n (end (transaction_a)); i != n; ++i)
{ {
nano::account const & account (i->first); nano::account const & account (i->first);
result.push_back (account); result.push_back (account);
@ -542,13 +545,14 @@ bool nano::wallet_store::valid_public_key (nano::public_key const & pub)
bool nano::wallet_store::exists (store::transaction const & transaction_a, nano::public_key const & pub) bool nano::wallet_store::exists (store::transaction const & transaction_a, nano::public_key const & pub)
{ {
return valid_public_key (pub) && find (transaction_a, pub) != end (); return valid_public_key (pub) && find (transaction_a, pub) != end (transaction_a);
} }
void nano::wallet_store::serialize_json (store::transaction const & transaction_a, std::string & string_a) void nano::wallet_store::serialize_json (store::transaction const & transaction_a, std::string & string_a)
{ {
boost::property_tree::ptree tree; boost::property_tree::ptree tree;
for (store::iterator<nano::uint256_union, nano::wallet_value> i (std::make_unique<nano::store::lmdb::iterator<nano::uint256_union, nano::wallet_value>> (transaction_a, env, handle)), n (nullptr); i != n; ++i) using iterator = store::typed_iterator<nano::uint256_union, nano::wallet_value>;
for (iterator i{ store::iterator{ store::lmdb::iterator::begin (env.tx (transaction_a), handle) } }, n{ store::iterator{ store::lmdb::iterator::end (env.tx (transaction_a), handle) } }; i != n; ++i)
{ {
tree.put (i->first.to_string (), i->second.key.to_string ()); tree.put (i->first.to_string (), i->second.key.to_string ());
} }
@ -597,7 +601,7 @@ bool nano::wallet_store::import (store::transaction const & transaction_a, nano:
debug_assert (valid_password (transaction_a)); debug_assert (valid_password (transaction_a));
debug_assert (other_a.valid_password (transaction_a)); debug_assert (other_a.valid_password (transaction_a));
auto result (false); auto result (false);
for (auto i (other_a.begin (transaction_a)), n (end ()); i != n; ++i) for (auto i (other_a.begin (transaction_a)), n (end (transaction_a)); i != n; ++i)
{ {
nano::raw_key prv; nano::raw_key prv;
auto error (other_a.fetch (transaction_a, i->first, prv)); auto error (other_a.fetch (transaction_a, i->first, prv));
@ -910,7 +914,7 @@ std::shared_ptr<nano::block> nano::wallet::change_action (nano::account const &
if (store.valid_password (transaction)) if (store.valid_password (transaction))
{ {
auto existing (store.find (transaction, source_a)); auto existing (store.find (transaction, source_a));
if (existing != store.end () && !wallets.node.ledger.any.account_head (block_transaction, source_a).is_zero ()) if (existing != store.end (transaction) && !wallets.node.ledger.any.account_head (block_transaction, source_a).is_zero ())
{ {
auto info = wallets.node.ledger.any.account_get (block_transaction, source_a); auto info = wallets.node.ledger.any.account_get (block_transaction, source_a);
debug_assert (info); debug_assert (info);
@ -977,7 +981,7 @@ std::shared_ptr<nano::block> nano::wallet::send_action (nano::account const & so
if (store.valid_password (transaction)) if (store.valid_password (transaction))
{ {
auto existing (store.find (transaction, source_a)); auto existing (store.find (transaction, source_a));
if (existing != store.end ()) if (existing != store.end (transaction))
{ {
auto balance (wallets.node.ledger.any.account_balance (block_transaction, source_a)); auto balance (wallets.node.ledger.any.account_balance (block_transaction, source_a));
if (balance && balance.value ().number () >= amount_a) if (balance && balance.value ().number () >= amount_a)
@ -1158,7 +1162,7 @@ void nano::wallet::work_ensure (nano::account const & account_a, nano::root cons
wallets.delayed_work->operator[] (account_a) = root_a; wallets.delayed_work->operator[] (account_a) = root_a;
wallets.node.workers.add_timed_task (std::chrono::steady_clock::now () + precache_delay, [this_l = shared_from_this (), account_a, root_a] { wallets.node.workers.post_delayed (precache_delay, [this_l = shared_from_this (), account_a, root_a] {
auto delayed_work = this_l->wallets.delayed_work.lock (); auto delayed_work = this_l->wallets.delayed_work.lock ();
auto existing (delayed_work->find (account_a)); auto existing (delayed_work->find (account_a));
if (existing != delayed_work->end () && existing->second == root_a) if (existing != delayed_work->end () && existing->second == root_a)
@ -1178,14 +1182,14 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact
{ {
wallets.node.logger.info (nano::log::type::wallet, "Beginning receivable block search"); wallets.node.logger.info (nano::log::type::wallet, "Beginning receivable block search");
for (auto i (store.begin (wallet_transaction_a)), n (store.end ()); i != n; ++i) for (auto i (store.begin (wallet_transaction_a)), n (store.end (wallet_transaction_a)); i != n; ++i)
{ {
auto block_transaction = wallets.node.ledger.tx_begin_read (); auto block_transaction = wallets.node.ledger.tx_begin_read ();
nano::account const & account (i->first); nano::account const & account (i->first);
// Don't search pending for watch-only accounts // Don't search pending for watch-only accounts
if (!nano::wallet_value (i->second).key.is_zero ()) if (!nano::wallet_value (i->second).key.is_zero ())
{ {
for (auto j (wallets.node.store.pending.begin (block_transaction, nano::pending_key (account, 0))), k (wallets.node.store.pending.end ()); j != k && nano::pending_key (j->first).account == account; ++j) for (auto j (wallets.node.store.pending.begin (block_transaction, nano::pending_key (account, 0))), k (wallets.node.store.pending.end (block_transaction)); j != k && nano::pending_key (j->first).account == account; ++j)
{ {
nano::pending_key key (j->first); nano::pending_key key (j->first);
auto hash (key.hash); auto hash (key.hash);
@ -1227,7 +1231,7 @@ bool nano::wallet::search_receivable (store::transaction const & wallet_transact
void nano::wallet::init_free_accounts (store::transaction const & transaction_a) void nano::wallet::init_free_accounts (store::transaction const & transaction_a)
{ {
free_accounts.clear (); free_accounts.clear ();
for (auto i (store.begin (transaction_a)), n (store.end ()); i != n; ++i) for (auto i (store.begin (transaction_a)), n (store.end (transaction_a)); i != n; ++i)
{ {
free_accounts.insert (i->first); free_accounts.insert (i->first);
} }
@ -1359,13 +1363,15 @@ nano::wallets::wallets (bool error_a, nano::node & node_a) :
status |= mdb_dbi_open (env.tx (transaction), "send_action_ids", MDB_CREATE, &send_action_ids); status |= mdb_dbi_open (env.tx (transaction), "send_action_ids", MDB_CREATE, &send_action_ids);
release_assert (status == 0); release_assert (status == 0);
std::string beginning (nano::uint256_union (0).to_string ()); std::string beginning (nano::uint256_union (0).to_string ());
nano::store::lmdb::db_val beginning_val{ beginning.size (), const_cast<char *> (beginning.c_str ()) };
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ()); std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ())))); nano::store::lmdb::db_val end_val{ end.size (), const_cast<char *> (end.c_str ()) };
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (end.size (), const_cast<char *> (end.c_str ())))); store::iterator i{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, beginning_val) };
store::iterator n{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, end_val) };
for (; i != n; ++i) for (; i != n; ++i)
{ {
nano::wallet_id id; nano::wallet_id id;
std::string text (i->first.data (), i->first.size ()); std::string text (reinterpret_cast<char const *> (i->first.data ()), i->first.size ());
auto error (id.decode_hex (text)); auto error (id.decode_hex (text));
release_assert (!error); release_assert (!error);
release_assert (items.find (id) == items.end ()); release_assert (items.find (id) == items.end ());
@ -1488,13 +1494,15 @@ void nano::wallets::reload ()
auto transaction (tx_begin_write ()); auto transaction (tx_begin_write ());
std::unordered_set<nano::uint256_union> stored_items; std::unordered_set<nano::uint256_union> stored_items;
std::string beginning (nano::uint256_union (0).to_string ()); std::string beginning (nano::uint256_union (0).to_string ());
nano::store::lmdb::db_val beginning_val{ beginning.size (), const_cast<char *> (beginning.c_str ()) };
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ()); std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
store::iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (beginning.size (), const_cast<char *> (beginning.c_str ())))); nano::store::lmdb::db_val end_val{ end.size (), const_cast<char *> (end.c_str ()) };
store::iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::store::lmdb::iterator<std::array<char, 64>, nano::no_value>> (transaction, env, handle, nano::store::lmdb::db_val (end.size (), const_cast<char *> (end.c_str ())))); store::iterator i{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, beginning_val) };
store::iterator n{ store::lmdb::iterator::lower_bound (env.tx (transaction), handle, end_val) };
for (; i != n; ++i) for (; i != n; ++i)
{ {
nano::wallet_id id; nano::wallet_id id;
std::string text (i->first.data (), i->first.size ()); std::string text (reinterpret_cast<char const *> (i->first.data ()), i->first.size ());
auto error (id.decode_hex (text)); auto error (id.decode_hex (text));
debug_assert (!error); debug_assert (!error);
// New wallet // New wallet
@ -1686,7 +1694,7 @@ void nano::wallets::compute_reps ()
{ {
auto & wallet (*i->second); auto & wallet (*i->second);
decltype (wallet.representatives) representatives_l; decltype (wallet.representatives) representatives_l;
for (auto ii (wallet.store.begin (transaction)), nn (wallet.store.end ()); ii != nn; ++ii) for (auto ii (wallet.store.begin (transaction)), nn (wallet.store.end (transaction)); ii != nn; ++ii)
{ {
auto account (ii->first); auto account (ii->first);
if (check_rep (account, half_principal_weight, false)) if (check_rep (account, half_principal_weight, false))
@ -1705,7 +1713,7 @@ void nano::wallets::ongoing_compute_reps ()
auto & node_l (node); auto & node_l (node);
// Representation drifts quickly on the test network but very slowly on the live network // Representation drifts quickly on the test network but very slowly on the live network
auto compute_delay = network_params.network.is_dev_network () ? std::chrono::milliseconds (10) : (network_params.network.is_test_network () ? std::chrono::milliseconds (nano::test_scan_wallet_reps_delay ()) : std::chrono::minutes (15)); auto compute_delay = network_params.network.is_dev_network () ? std::chrono::milliseconds (10) : (network_params.network.is_test_network () ? std::chrono::milliseconds (nano::test_scan_wallet_reps_delay ()) : std::chrono::minutes (15));
node.workers.add_timed_task (std::chrono::steady_clock::now () + compute_delay, [&node_l] () { node.workers.post_delayed (compute_delay, [&node_l] () {
node_l.wallets.ongoing_compute_reps (); node_l.wallets.ongoing_compute_reps ();
}); });
} }
@ -1753,22 +1761,24 @@ std::unordered_map<nano::wallet_id, std::shared_ptr<nano::wallet>> nano::wallets
nano::uint128_t const nano::wallets::generate_priority = std::numeric_limits<nano::uint128_t>::max (); nano::uint128_t const nano::wallets::generate_priority = std::numeric_limits<nano::uint128_t>::max ();
nano::uint128_t const nano::wallets::high_priority = std::numeric_limits<nano::uint128_t>::max () - 1; nano::uint128_t const nano::wallets::high_priority = std::numeric_limits<nano::uint128_t>::max () - 1;
nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::begin (store::transaction const & transaction_a) auto nano::wallet_store::begin (store::transaction const & transaction_a) -> iterator
{ {
store::iterator<nano::account, nano::wallet_value> result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, env, handle, nano::store::lmdb::db_val (nano::account (special_count)))); nano::account account{ special_count };
return result; nano::store::lmdb::db_val val{ account };
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, val) } };
} }
nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::begin (store::transaction const & transaction_a, nano::account const & key) auto nano::wallet_store::begin (store::transaction const & transaction_a, nano::account const & key) -> iterator
{ {
store::iterator<nano::account, nano::wallet_value> result (std::make_unique<nano::store::lmdb::iterator<nano::account, nano::wallet_value>> (transaction_a, env, handle, nano::store::lmdb::db_val (key))); nano::account account (key);
return result; nano::store::lmdb::db_val val{ account };
return iterator{ store::iterator{ store::lmdb::iterator::lower_bound (env.tx (transaction_a), handle, val) } };
} }
nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::find (store::transaction const & transaction_a, nano::account const & key) auto nano::wallet_store::find (store::transaction const & transaction_a, nano::account const & key) -> iterator
{ {
auto result (begin (transaction_a, key)); auto result = begin (transaction_a, key);
store::iterator<nano::account, nano::wallet_value> end (nullptr); auto end = this->end (transaction_a);
if (result != end) if (result != end)
{ {
if (result->first == key) if (result->first == key)
@ -1787,10 +1797,11 @@ nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::fin
return result; return result;
} }
nano::store::iterator<nano::account, nano::wallet_value> nano::wallet_store::end () auto nano::wallet_store::end (store::transaction const & transaction_a) -> iterator
{ {
return store::iterator<nano::account, nano::wallet_value> (nullptr); return iterator{ store::iterator{ store::lmdb::iterator::end (env.tx (transaction_a), handle) } };
} }
nano::mdb_wallets_store::mdb_wallets_store (std::filesystem::path const & path_a, nano::lmdb_config const & lmdb_config_a) : nano::mdb_wallets_store::mdb_wallets_store (std::filesystem::path const & path_a, nano::lmdb_config const & lmdb_config_a) :
environment (error, path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).override_config_sync (nano::lmdb_config::sync_strategy::always).override_config_map_size (1ULL * 1024 * 1024 * 1024)) environment (error, path_a, nano::store::lmdb::env::options::make ().set_config (lmdb_config_a).override_config_sync (nano::lmdb_config::sync_strategy::always).override_config_map_size (1ULL * 1024 * 1024 * 1024))
{ {

View file

@ -9,6 +9,7 @@
#include <nano/store/component.hpp> #include <nano/store/component.hpp>
#include <nano/store/lmdb/lmdb.hpp> #include <nano/store/lmdb/lmdb.hpp>
#include <nano/store/lmdb/wallet_value.hpp> #include <nano/store/lmdb/wallet_value.hpp>
#include <nano/store/typed_iterator.hpp>
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
@ -57,6 +58,9 @@ enum class key_type
class wallet_store final class wallet_store final
{ {
public:
using iterator = store::typed_iterator<nano::account, nano::wallet_value>;
public: public:
wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &); wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &);
wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &, std::string const &); wallet_store (bool &, nano::kdf &, store::transaction &, store::lmdb::env &, nano::account, unsigned, std::string const &, std::string const &);
@ -89,10 +93,10 @@ public:
bool fetch (store::transaction const &, nano::account const &, nano::raw_key &); bool fetch (store::transaction const &, nano::account const &, nano::raw_key &);
bool exists (store::transaction const &, nano::account const &); bool exists (store::transaction const &, nano::account const &);
void destroy (store::transaction const &); void destroy (store::transaction const &);
store::iterator<nano::account, nano::wallet_value> find (store::transaction const &, nano::account const &); iterator find (store::transaction const &, nano::account const &);
store::iterator<nano::account, nano::wallet_value> begin (store::transaction const &, nano::account const &); iterator begin (store::transaction const &, nano::account const &);
store::iterator<nano::account, nano::wallet_value> begin (store::transaction const &); iterator begin (store::transaction const &);
store::iterator<nano::account, nano::wallet_value> end (); iterator end (store::transaction const &);
void derive_key (nano::raw_key &, store::transaction const &, std::string const &); void derive_key (nano::raw_key &, store::transaction const &, std::string const &);
void serialize_json (store::transaction const &, std::string &); void serialize_json (store::transaction const &, std::string &);
void write_backup (store::transaction const &, std::filesystem::path const &); void write_backup (store::transaction const &, std::filesystem::path const &);

View file

@ -1050,7 +1050,7 @@ nano::websocket_server::websocket_server (nano::websocket::config & config_a, na
if (server->any_subscriber (nano::websocket::topic::telemetry)) if (server->any_subscriber (nano::websocket::topic::telemetry))
{ {
nano::websocket::message_builder builder; nano::websocket::message_builder builder;
server->broadcast (builder.telemetry_received (telemetry_data, channel->get_endpoint ())); server->broadcast (builder.telemetry_received (telemetry_data, channel->get_remote_endpoint ()));
} }
}); });

View file

@ -107,7 +107,7 @@ nano_qt::self_pane::self_pane (nano_qt::wallet & wallet_a, nano::account const &
QObject::connect (copy_button, &QPushButton::clicked, [this] () { QObject::connect (copy_button, &QPushButton::clicked, [this] () {
this->wallet.application.clipboard ()->setText (QString (this->wallet.account.to_account ().c_str ())); this->wallet.application.clipboard ()->setText (QString (this->wallet.account.to_account ().c_str ()));
copy_button->setText ("Copied!"); copy_button->setText ("Copied!");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (2), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (2), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
copy_button->setText ("Copy"); copy_button->setText ("Copy");
})); }));
@ -201,7 +201,7 @@ nano_qt::accounts::accounts (nano_qt::wallet & wallet_a) :
this->wallet.wallet_m->deterministic_insert (transaction); this->wallet.wallet_m->deterministic_insert (transaction);
show_button_success (*create_account); show_button_success (*create_account);
create_account->setText ("New account was created"); create_account->setText ("New account was created");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*create_account); show_button_ok (*create_account);
create_account->setText ("Create account"); create_account->setText ("Create account");
@ -212,7 +212,7 @@ nano_qt::accounts::accounts (nano_qt::wallet & wallet_a) :
{ {
show_button_error (*create_account); show_button_error (*create_account);
create_account->setText ("Wallet is locked, unlock it to create account"); create_account->setText ("Wallet is locked, unlock it to create account");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*create_account); show_button_ok (*create_account);
create_account->setText ("Create account"); create_account->setText ("Create account");
@ -234,7 +234,7 @@ nano_qt::accounts::accounts (nano_qt::wallet & wallet_a) :
this->wallet.application.clipboard ()->setText (QString (seed.to_string ().c_str ())); this->wallet.application.clipboard ()->setText (QString (seed.to_string ().c_str ()));
show_button_success (*backup_seed); show_button_success (*backup_seed);
backup_seed->setText ("Seed was copied to clipboard"); backup_seed->setText ("Seed was copied to clipboard");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*backup_seed); show_button_ok (*backup_seed);
backup_seed->setText ("Copy wallet seed to clipboard"); backup_seed->setText ("Copy wallet seed to clipboard");
@ -246,7 +246,7 @@ nano_qt::accounts::accounts (nano_qt::wallet & wallet_a) :
this->wallet.application.clipboard ()->setText (""); this->wallet.application.clipboard ()->setText ("");
show_button_error (*backup_seed); show_button_error (*backup_seed);
backup_seed->setText ("Wallet is locked, unlock it to enable the backup"); backup_seed->setText ("Wallet is locked, unlock it to enable the backup");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*backup_seed); show_button_ok (*backup_seed);
backup_seed->setText ("Copy wallet seed to clipboard"); backup_seed->setText ("Copy wallet seed to clipboard");
@ -268,7 +268,7 @@ void nano_qt::accounts::refresh_wallet_balance ()
auto block_transaction = this->wallet.node.ledger.tx_begin_read (); auto block_transaction = this->wallet.node.ledger.tx_begin_read ();
nano::uint128_t balance (0); nano::uint128_t balance (0);
nano::uint128_t pending (0); nano::uint128_t pending (0);
for (auto i (this->wallet.wallet_m->store.begin (transaction)), j (this->wallet.wallet_m->store.end ()); i != j; ++i) for (auto i (this->wallet.wallet_m->store.begin (transaction)), j (this->wallet.wallet_m->store.end (transaction)); i != j; ++i)
{ {
nano::public_key const & key (i->first); nano::public_key const & key (i->first);
balance = balance + this->wallet.node.ledger.any.account_balance (block_transaction, key).value_or (0).number (); balance = balance + this->wallet.node.ledger.any.account_balance (block_transaction, key).value_or (0).number ();
@ -280,7 +280,7 @@ void nano_qt::accounts::refresh_wallet_balance ()
final_text += "\nReady to receive: " + wallet.format_balance (pending); final_text += "\nReady to receive: " + wallet.format_balance (pending);
} }
wallet_balance_label->setText (QString (final_text.c_str ())); wallet_balance_label->setText (QString (final_text.c_str ()));
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (60), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (60), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
refresh_wallet_balance (); refresh_wallet_balance ();
})); }));
@ -293,7 +293,7 @@ void nano_qt::accounts::refresh ()
auto transaction (wallet.wallet_m->wallets.tx_begin_read ()); auto transaction (wallet.wallet_m->wallets.tx_begin_read ());
auto block_transaction = this->wallet.node.ledger.tx_begin_read (); auto block_transaction = this->wallet.node.ledger.tx_begin_read ();
QBrush brush; QBrush brush;
for (auto i (wallet.wallet_m->store.begin (transaction)), j (wallet.wallet_m->store.end ()); i != j; ++i) for (auto i (wallet.wallet_m->store.begin (transaction)), j (wallet.wallet_m->store.end (transaction)); i != j; ++i)
{ {
nano::public_key key (i->first); nano::public_key key (i->first);
auto balance_amount = wallet.node.ledger.any.account_balance (block_transaction, key).value_or (0).number (); auto balance_amount = wallet.node.ledger.any.account_balance (block_transaction, key).value_or (0).number ();
@ -410,7 +410,7 @@ nano_qt::import::import (nano_qt::wallet & wallet_a) :
show_line_error (*seed); show_line_error (*seed);
show_button_error (*import_seed); show_button_error (*import_seed);
import_seed->setText ("Wallet is locked, unlock it to enable the import"); import_seed->setText ("Wallet is locked, unlock it to enable the import");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (10), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (10), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_line_ok (*seed); show_line_ok (*seed);
show_button_ok (*import_seed); show_button_ok (*import_seed);
@ -427,7 +427,7 @@ nano_qt::import::import (nano_qt::wallet & wallet_a) :
show_button_success (*import_seed); show_button_success (*import_seed);
import_seed->setText ("Successful import of seed"); import_seed->setText ("Successful import of seed");
this->wallet.refresh (); this->wallet.refresh ();
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*import_seed); show_button_ok (*import_seed);
import_seed->setText ("Import seed"); import_seed->setText ("Import seed");
@ -447,7 +447,7 @@ nano_qt::import::import (nano_qt::wallet & wallet_a) :
{ {
import_seed->setText ("Incorrect seed. Only HEX characters allowed"); import_seed->setText ("Incorrect seed. Only HEX characters allowed");
} }
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*import_seed); show_button_ok (*import_seed);
import_seed->setText ("Import seed"); import_seed->setText ("Import seed");
@ -460,7 +460,7 @@ nano_qt::import::import (nano_qt::wallet & wallet_a) :
show_line_error (*clear_line); show_line_error (*clear_line);
show_button_error (*import_seed); show_button_error (*import_seed);
import_seed->setText ("Type words 'clear keys'"); import_seed->setText ("Type words 'clear keys'");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*import_seed); show_button_ok (*import_seed);
import_seed->setText ("Import seed"); import_seed->setText ("Import seed");
@ -555,7 +555,7 @@ public:
void open_block (nano::open_block const & block_a) void open_block (nano::open_block const & block_a)
{ {
type = "Receive"; type = "Receive";
if (block_a.hashables.source != ledger.constants.genesis->account ()) if (block_a.hashables.source != ledger.constants.genesis->account ().as_union ())
{ {
auto account_l = ledger.any.block_account (transaction, block_a.hashables.source); auto account_l = ledger.any.block_account (transaction, block_a.hashables.source);
auto amount_l = ledger.any.block_amount (transaction, block_a.hash ()); auto amount_l = ledger.any.block_amount (transaction, block_a.hash ());
@ -745,7 +745,7 @@ void nano_qt::block_viewer::rebroadcast_action (nano::block_hash const & hash_a)
if (successor) if (successor)
{ {
done = false; done = false;
wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (1), [this, successor] () { wallet.node.workers.post_delayed (std::chrono::seconds (1), [this, successor] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this, successor] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this, successor] () {
rebroadcast_action (successor.value ()); rebroadcast_action (successor.value ());
})); }));
@ -1147,7 +1147,7 @@ void nano_qt::wallet::ongoing_refresh ()
} }
})); }));
node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [wallet_w] () { node.workers.post_delayed (std::chrono::seconds (5), [wallet_w] () {
if (auto wallet_l = wallet_w.lock ()) if (auto wallet_l = wallet_w.lock ())
{ {
wallet_l->ongoing_refresh (); wallet_l->ongoing_refresh ();
@ -1231,7 +1231,7 @@ void nano_qt::wallet::start ()
{ {
show_button_error (*this_l->send_blocks_send); show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Wallet is locked, unlock it to send"); this_l->send_blocks_send->setText ("Wallet is locked, unlock it to send");
this_l->node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this_w] () { this_l->node.workers.post_delayed (std::chrono::seconds (5), [this_w] () {
if (auto this_l = this_w.lock ()) if (auto this_l = this_w.lock ())
{ {
this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () { this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () {
@ -1250,7 +1250,7 @@ void nano_qt::wallet::start ()
show_line_error (*this_l->send_count); show_line_error (*this_l->send_count);
show_button_error (*this_l->send_blocks_send); show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Not enough balance"); this_l->send_blocks_send->setText ("Not enough balance");
this_l->node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this_w] () { this_l->node.workers.post_delayed (std::chrono::seconds (5), [this_w] () {
if (auto this_l = this_w.lock ()) if (auto this_l = this_w.lock ())
{ {
this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () { this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () {
@ -1269,7 +1269,7 @@ void nano_qt::wallet::start ()
show_line_error (*this_l->send_account); show_line_error (*this_l->send_account);
show_button_error (*this_l->send_blocks_send); show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Bad destination account"); this_l->send_blocks_send->setText ("Bad destination account");
this_l->node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this_w] () { this_l->node.workers.post_delayed (std::chrono::seconds (5), [this_w] () {
if (auto this_l = this_w.lock ()) if (auto this_l = this_w.lock ())
{ {
this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () { this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () {
@ -1288,7 +1288,7 @@ void nano_qt::wallet::start ()
show_line_error (*this_l->send_count); show_line_error (*this_l->send_count);
show_button_error (*this_l->send_blocks_send); show_button_error (*this_l->send_blocks_send);
this_l->send_blocks_send->setText ("Bad amount number"); this_l->send_blocks_send->setText ("Bad amount number");
this_l->node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this_w] () { this_l->node.workers.post_delayed (std::chrono::seconds (5), [this_w] () {
if (auto this_l = this_w.lock ()) if (auto this_l = this_w.lock ())
{ {
this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () { this_l->application.postEvent (&this_l->processor, new eventloop_event ([this_w] () {
@ -1464,7 +1464,7 @@ void nano_qt::wallet::update_connected ()
void nano_qt::wallet::empty_password () void nano_qt::wallet::empty_password ()
{ {
this->node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (3), [this] () { this->node.workers.post_delayed (std::chrono::seconds (3), [this] () {
auto transaction (wallet_m->wallets.tx_begin_write ()); auto transaction (wallet_m->wallets.tx_begin_write ());
wallet_m->enter_password (transaction, std::string ("")); wallet_m->enter_password (transaction, std::string (""));
}); });
@ -1568,7 +1568,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) :
change->setText ("Password was changed"); change->setText ("Password was changed");
this->wallet.node.logger.warn (nano::log::type::qt, "Wallet password changed"); this->wallet.node.logger.warn (nano::log::type::qt, "Wallet password changed");
update_locked (false, false); update_locked (false, false);
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*change); show_button_ok (*change);
change->setText ("Set/Change password"); change->setText ("Set/Change password");
@ -1586,7 +1586,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) :
{ {
show_button_error (*change); show_button_error (*change);
change->setText ("Wallet is locked, unlock it"); change->setText ("Wallet is locked, unlock it");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*change); show_button_ok (*change);
change->setText ("Set/Change password"); change->setText ("Set/Change password");
@ -1612,7 +1612,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) :
change_rep->setText ("Representative was changed"); change_rep->setText ("Representative was changed");
current_representative->setText (QString (representative_l.to_account ().c_str ())); current_representative->setText (QString (representative_l.to_account ().c_str ()));
new_representative->clear (); new_representative->clear ();
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*change_rep); show_button_ok (*change_rep);
change_rep->setText ("Change representative"); change_rep->setText ("Change representative");
@ -1623,7 +1623,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) :
{ {
show_button_error (*change_rep); show_button_error (*change_rep);
change_rep->setText ("Wallet is locked, unlock it"); change_rep->setText ("Wallet is locked, unlock it");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_button_ok (*change_rep); show_button_ok (*change_rep);
change_rep->setText ("Change representative"); change_rep->setText ("Change representative");
@ -1636,7 +1636,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) :
show_line_error (*new_representative); show_line_error (*new_representative);
show_button_error (*change_rep); show_button_error (*change_rep);
change_rep->setText ("Invalid account"); change_rep->setText ("Invalid account");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_line_ok (*new_representative); show_line_ok (*new_representative);
show_button_ok (*change_rep); show_button_ok (*change_rep);
@ -1676,7 +1676,7 @@ nano_qt::settings::settings (nano_qt::wallet & wallet_a) :
show_line_error (*password); show_line_error (*password);
show_button_error (*lock_toggle); show_button_error (*lock_toggle);
lock_toggle->setText ("Invalid password"); lock_toggle->setText ("Invalid password");
this->wallet.node.workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::seconds (5), [this] () { this->wallet.node.workers.post_delayed (std::chrono::seconds (5), [this] () {
this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () { this->wallet.application.postEvent (&this->wallet.processor, new eventloop_event ([this] () {
show_line_ok (*password); show_line_ok (*password);
show_button_ok (*lock_toggle); show_button_ok (*lock_toggle);
@ -1944,7 +1944,7 @@ void nano_qt::advanced_actions::refresh_peers ()
peers_model->removeRows (0, peers_model->rowCount ()); peers_model->removeRows (0, peers_model->rowCount ());
auto list (wallet.node.network.list (std::numeric_limits<size_t>::max ())); auto list (wallet.node.network.list (std::numeric_limits<size_t>::max ()));
std::sort (list.begin (), list.end (), [] (auto const & lhs, auto const & rhs) { std::sort (list.begin (), list.end (), [] (auto const & lhs, auto const & rhs) {
return lhs->get_endpoint () < rhs->get_endpoint (); return lhs->get_remote_endpoint () < rhs->get_remote_endpoint ();
}); });
for (auto i (list.begin ()), n (list.end ()); i != n; ++i) for (auto i (list.begin ()), n (list.end ()); i != n; ++i)
{ {
@ -1959,9 +1959,9 @@ void nano_qt::advanced_actions::refresh_peers ()
items.push_back (version); items.push_back (version);
QString node_id (""); QString node_id ("");
auto node_id_l (channel->get_node_id_optional ()); auto node_id_l (channel->get_node_id_optional ());
if (node_id_l.is_initialized ()) if (node_id_l.has_value ())
{ {
node_id = node_id_l.get ().to_account ().c_str (); node_id = node_id_l.value ().to_account ().c_str ();
} }
items.push_back (new QStandardItem (node_id)); items.push_back (new QStandardItem (node_id));
peers_model->appendRow (items); peers_model->appendRow (items);
@ -1973,7 +1973,7 @@ void nano_qt::advanced_actions::refresh_ledger ()
{ {
ledger_model->removeRows (0, ledger_model->rowCount ()); ledger_model->removeRows (0, ledger_model->rowCount ());
auto transaction (wallet.node.ledger.tx_begin_read ()); auto transaction (wallet.node.ledger.tx_begin_read ());
for (auto i (wallet.node.ledger.store.account.begin (transaction)), j (wallet.node.ledger.store.account.end ()); i != j; ++i) for (auto i (wallet.node.ledger.store.account.begin (transaction)), j (wallet.node.ledger.store.account.end (transaction)); i != j; ++i)
{ {
QList<QStandardItem *> items; QList<QStandardItem *> items;
items.push_back (new QStandardItem (QString (i->first.to_account ().c_str ()))); items.push_back (new QStandardItem (QString (i->first.to_account ().c_str ())));

View file

@ -30,6 +30,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <boost/format.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <algorithm> #include <algorithm>
@ -67,7 +68,7 @@ TEST (rpc, wrapped_task)
// Exception should get caught // Exception should get caught
throw std::runtime_error (""); throw std::runtime_error ("");
})); }));
system.nodes[0]->workers.push_task (task); system.nodes[0]->workers.post (task);
ASSERT_TIMELY_EQ (5s, response, true); ASSERT_TIMELY_EQ (5s, response, true);
} }
@ -721,7 +722,7 @@ TEST (rpc, account_move)
ASSERT_TRUE (destination->exists (key.pub)); ASSERT_TRUE (destination->exists (key.pub));
ASSERT_TRUE (destination->exists (nano::dev::genesis_key.pub)); ASSERT_TRUE (destination->exists (nano::dev::genesis_key.pub));
auto transaction (node->wallets.tx_begin_read ()); auto transaction (node->wallets.tx_begin_read ());
ASSERT_EQ (source->store.end (), source->store.begin (transaction)); ASSERT_EQ (source->store.end (transaction), source->store.begin (transaction));
} }
TEST (rpc, block) TEST (rpc, block)
@ -2627,7 +2628,7 @@ TEST (rpc, wallet_frontiers)
frontiers.push_back (nano::account (i->second.get<std::string> (""))); frontiers.push_back (nano::account (i->second.get<std::string> ("")));
} }
ASSERT_EQ (1, frontiers.size ()); ASSERT_EQ (1, frontiers.size ());
ASSERT_EQ (node->latest (nano::dev::genesis_key.pub), frontiers[0]); ASSERT_EQ (node->latest (nano::dev::genesis_key.pub), frontiers[0].as_union ());
} }
TEST (rpc, work_validate) TEST (rpc, work_validate)
@ -6212,7 +6213,7 @@ TEST (rpc, epoch_upgrade)
{ {
auto transaction (node->ledger.tx_begin_read ()); auto transaction (node->ledger.tx_begin_read ());
ASSERT_EQ (2, node->store.account.count (transaction)); ASSERT_EQ (2, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i) for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_0); ASSERT_EQ (info.epoch (), nano::epoch::epoch_0);
@ -6230,7 +6231,7 @@ TEST (rpc, epoch_upgrade)
{ {
auto transaction (node->ledger.tx_begin_read ()); auto transaction (node->ledger.tx_begin_read ());
ASSERT_EQ (4, node->store.account.count (transaction)); ASSERT_EQ (4, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i) for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); ASSERT_EQ (info.epoch (), nano::epoch::epoch_1);
@ -6293,7 +6294,7 @@ TEST (rpc, epoch_upgrade)
{ {
auto transaction (node->ledger.tx_begin_read ()); auto transaction (node->ledger.tx_begin_read ());
ASSERT_EQ (5, node->store.account.count (transaction)); ASSERT_EQ (5, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i) for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_2); ASSERT_EQ (info.epoch (), nano::epoch::epoch_2);
@ -6375,7 +6376,7 @@ TEST (rpc, epoch_upgrade_multithreaded)
{ {
auto transaction (node->ledger.tx_begin_read ()); auto transaction (node->ledger.tx_begin_read ());
ASSERT_EQ (2, node->store.account.count (transaction)); ASSERT_EQ (2, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i) for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_0); ASSERT_EQ (info.epoch (), nano::epoch::epoch_0);
@ -6394,7 +6395,7 @@ TEST (rpc, epoch_upgrade_multithreaded)
{ {
auto transaction (node->ledger.tx_begin_read ()); auto transaction (node->ledger.tx_begin_read ());
ASSERT_EQ (4, node->store.account.count (transaction)); ASSERT_EQ (4, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i) for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); ASSERT_EQ (info.epoch (), nano::epoch::epoch_1);
@ -6457,7 +6458,7 @@ TEST (rpc, epoch_upgrade_multithreaded)
{ {
auto transaction (node->ledger.tx_begin_read ()); auto transaction (node->ledger.tx_begin_read ());
ASSERT_EQ (5, node->store.account.count (transaction)); ASSERT_EQ (5, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i) for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_2); ASSERT_EQ (info.epoch (), nano::epoch::epoch_2);
@ -6786,7 +6787,7 @@ TEST (rpc, telemetry_all)
auto channel = node1->network.find_node_id (node->get_node_id ()); auto channel = node1->network.find_node_id (node->get_node_id ());
ASSERT_TRUE (channel); ASSERT_TRUE (channel);
ASSERT_TIMELY (10s, node1->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (10s, node1->telemetry.get_telemetry (channel->get_remote_endpoint ()));
boost::property_tree::ptree request; boost::property_tree::ptree request;
request.put ("action", "telemetry"); request.put ("action", "telemetry");

View file

@ -21,61 +21,6 @@
#include <array> #include <array>
#include <unordered_map> #include <unordered_map>
namespace boost
{
template <>
struct hash<::nano::uint256_union>
{
size_t operator() (::nano::uint256_union const & value_a) const
{
return std::hash<::nano::uint256_union> () (value_a);
}
};
template <>
struct hash<::nano::block_hash>
{
size_t operator() (::nano::block_hash const & value_a) const
{
return std::hash<::nano::block_hash> () (value_a);
}
};
template <>
struct hash<::nano::hash_or_account>
{
size_t operator() (::nano::hash_or_account const & data_a) const
{
return std::hash<::nano::hash_or_account> () (data_a);
}
};
template <>
struct hash<::nano::public_key>
{
size_t operator() (::nano::public_key const & value_a) const
{
return std::hash<::nano::public_key> () (value_a);
}
};
template <>
struct hash<::nano::uint512_union>
{
size_t operator() (::nano::uint512_union const & value_a) const
{
return std::hash<::nano::uint512_union> () (value_a);
}
};
template <>
struct hash<::nano::qualified_root>
{
size_t operator() (::nano::qualified_root const & value_a) const
{
return std::hash<::nano::qualified_root> () (value_a);
}
};
}
namespace nano namespace nano
{ {
/** /**

View file

@ -14,7 +14,7 @@
#include <nano/store/block.hpp> #include <nano/store/block.hpp>
#include <nano/store/component.hpp> #include <nano/store/component.hpp>
#include <nano/store/confirmation_height.hpp> #include <nano/store/confirmation_height.hpp>
#include <nano/store/final.hpp> #include <nano/store/final_vote.hpp>
#include <nano/store/online_weight.hpp> #include <nano/store/online_weight.hpp>
#include <nano/store/peer.hpp> #include <nano/store/peer.hpp>
#include <nano/store/pending.hpp> #include <nano/store/pending.hpp>
@ -749,7 +749,7 @@ void nano::ledger::initialize (nano::generate_cache_flags const & generate_cache
if (generate_cache_flags_a.reps || generate_cache_flags_a.account_count || generate_cache_flags_a.block_count) if (generate_cache_flags_a.reps || generate_cache_flags_a.account_count || generate_cache_flags_a.block_count)
{ {
store.account.for_each_par ( store.account.for_each_par (
[this] (store::read_transaction const & /*unused*/, store::iterator<nano::account, nano::account_info> i, store::iterator<nano::account, nano::account_info> n) { [this] (store::read_transaction const & /*unused*/, auto i, auto n) {
uint64_t block_count_l{ 0 }; uint64_t block_count_l{ 0 };
uint64_t account_count_l{ 0 }; uint64_t account_count_l{ 0 };
for (; i != n; ++i) for (; i != n; ++i)
@ -763,7 +763,7 @@ void nano::ledger::initialize (nano::generate_cache_flags const & generate_cache
}); });
store.rep_weight.for_each_par ( store.rep_weight.for_each_par (
[this] (store::read_transaction const & /*unused*/, store::iterator<nano::account, nano::uint128_union> i, store::iterator<nano::account, nano::uint128_union> n) { [this] (store::read_transaction const & /*unused*/, auto i, auto n) {
nano::rep_weights rep_weights_l{ this->store.rep_weight }; nano::rep_weights rep_weights_l{ this->store.rep_weight };
for (; i != n; ++i) for (; i != n; ++i)
{ {
@ -776,7 +776,7 @@ void nano::ledger::initialize (nano::generate_cache_flags const & generate_cache
if (generate_cache_flags_a.cemented_count) if (generate_cache_flags_a.cemented_count)
{ {
store.confirmation_height.for_each_par ( store.confirmation_height.for_each_par (
[this] (store::read_transaction const & /*unused*/, store::iterator<nano::account, nano::confirmation_height_info> i, store::iterator<nano::account, nano::confirmation_height_info> n) { [this] (store::read_transaction const & /*unused*/, auto i, auto n) {
uint64_t cemented_count_l (0); uint64_t cemented_count_l (0);
for (; i != n; ++i) for (; i != n; ++i)
{ {
@ -1093,7 +1093,7 @@ public:
} }
void open_block (nano::open_block const & block_a) override void open_block (nano::open_block const & block_a) override
{ {
if (block_a.source_field ().value () != ledger.constants.genesis->account ()) if (block_a.source_field ().value () != ledger.constants.genesis->account ().as_union ())
{ {
result[0] = block_a.source_field ().value (); result[0] = block_a.source_field ().value ();
} }
@ -1429,12 +1429,12 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p
auto rocksdb_transaction (rocksdb_store->tx_begin_write ()); auto rocksdb_transaction (rocksdb_store->tx_begin_write ());
rocksdb_store->version.put (rocksdb_transaction, version); rocksdb_store->version.put (rocksdb_transaction, version);
for (auto i (store.online_weight.begin (lmdb_transaction)), n (store.online_weight.end ()); i != n; ++i) for (auto i (store.online_weight.begin (lmdb_transaction)), n (store.online_weight.end (lmdb_transaction)); i != n; ++i)
{ {
rocksdb_store->online_weight.put (rocksdb_transaction, i->first, i->second); rocksdb_store->online_weight.put (rocksdb_transaction, i->first, i->second);
} }
for (auto i (store.peer.begin (lmdb_transaction)), n (store.peer.end ()); i != n; ++i) for (auto i (store.peer.begin (lmdb_transaction)), n (store.peer.end (lmdb_transaction)); i != n; ++i)
{ {
rocksdb_store->peer.put (rocksdb_transaction, i->first, i->second); rocksdb_store->peer.put (rocksdb_transaction, i->first, i->second);
} }
@ -1523,4 +1523,4 @@ nano::container_info nano::ledger::container_info () const
info.put ("bootstrap_weights", bootstrap_weights); info.put ("bootstrap_weights", bootstrap_weights);
info.add ("rep_weights", cache.rep_weights.container_info ()); info.add ("rep_weights", cache.rep_weights.container_info ());
return info; return info;
} }

View file

@ -60,7 +60,7 @@ uint64_t nano::ledger_set_any::account_height (secure::transaction const & trans
auto nano::ledger_set_any::account_lower_bound (secure::transaction const & transaction, nano::account const & account) const -> account_iterator auto nano::ledger_set_any::account_lower_bound (secure::transaction const & transaction, nano::account const & account) const -> account_iterator
{ {
auto disk = ledger.store.account.begin (transaction, account); auto disk = ledger.store.account.begin (transaction, account);
if (disk == ledger.store.account.end ()) if (disk == ledger.store.account.end (transaction))
{ {
return account_iterator{}; return account_iterator{};
} }
@ -153,7 +153,7 @@ uint64_t nano::ledger_set_any::block_height (secure::transaction const & transac
std::optional<std::pair<nano::pending_key, nano::pending_info>> nano::ledger_set_any::receivable_lower_bound (secure::transaction const & transaction, nano::account const & account, nano::block_hash const & hash) const std::optional<std::pair<nano::pending_key, nano::pending_info>> nano::ledger_set_any::receivable_lower_bound (secure::transaction const & transaction, nano::account const & account, nano::block_hash const & hash) const
{ {
auto result = ledger.store.pending.begin (transaction, { account, hash }); auto result = ledger.store.pending.begin (transaction, { account, hash });
if (result == ledger.store.pending.end ()) if (result == ledger.store.pending.end (transaction))
{ {
return std::nullopt; return std::nullopt;
} }

View file

@ -108,11 +108,11 @@ auto nano::ledger_set_confirmed::receivable_upper_bound (secure::transaction con
std::optional<std::pair<nano::pending_key, nano::pending_info>> nano::ledger_set_confirmed::receivable_lower_bound (secure::transaction const & transaction, nano::account const & account, nano::block_hash const & hash) const std::optional<std::pair<nano::pending_key, nano::pending_info>> nano::ledger_set_confirmed::receivable_lower_bound (secure::transaction const & transaction, nano::account const & account, nano::block_hash const & hash) const
{ {
auto result = ledger.store.pending.begin (transaction, { account, hash }); auto result = ledger.store.pending.begin (transaction, { account, hash });
while (result != ledger.store.pending.end () && !block_exists (transaction, result->first.hash)) while (result != ledger.store.pending.end (transaction) && !block_exists (transaction, result->first.hash))
{ {
++result; ++result;
} }
if (result == ledger.store.pending.end ()) if (result == ledger.store.pending.end (transaction))
{ {
return std::nullopt; return std::nullopt;
} }

View file

@ -67,9 +67,9 @@ namespace std
template <> template <>
struct hash<::nano::pending_key> struct hash<::nano::pending_key>
{ {
size_t operator() (::nano::pending_key const & data_a) const size_t operator() (::nano::pending_key const & value) const
{ {
return hash<::nano::uint512_union>{}({ ::nano::uint256_union{ data_a.account.number () }, data_a.hash }); return hash<::nano::uint512_union>{}({ ::nano::uint256_union{ value.account.number () }, value.hash });
} }
}; };
} }

View file

@ -37,7 +37,7 @@ size_t manually_count_pruned_blocks (nano::store::component & store)
size_t count = 0; size_t count = 0;
auto transaction = store.tx_begin_read (); auto transaction = store.tx_begin_read ();
auto i = store.pruned.begin (transaction); auto i = store.pruned.begin (transaction);
for (; i != store.pruned.end (); ++i) for (; i != store.pruned.end (transaction); ++i)
{ {
++count; ++count;
} }
@ -54,7 +54,7 @@ TEST (system, generate_mass_activity)
uint32_t count (20); uint32_t count (20);
system.generate_mass_activity (count, *system.nodes[0]); system.generate_mass_activity (count, *system.nodes[0]);
auto transaction (system.nodes[0]->store.tx_begin_read ()); auto transaction (system.nodes[0]->store.tx_begin_read ());
for (auto i (system.nodes[0]->store.account.begin (transaction)), n (system.nodes[0]->store.account.end ()); i != n; ++i) for (auto i (system.nodes[0]->store.account.begin (transaction)), n (system.nodes[0]->store.account.end (transaction)); i != n; ++i)
{ {
} }
} }
@ -76,7 +76,7 @@ TEST (system, generate_mass_activity_long)
} }
system.generate_mass_activity (count, *system.nodes[0]); system.generate_mass_activity (count, *system.nodes[0]);
auto transaction (system.nodes[0]->store.tx_begin_read ()); auto transaction (system.nodes[0]->store.tx_begin_read ());
for (auto i (system.nodes[0]->store.account.begin (transaction)), n (system.nodes[0]->store.account.end ()); i != n; ++i) for (auto i (system.nodes[0]->store.account.begin (transaction)), n (system.nodes[0]->store.account.end (transaction)); i != n; ++i)
{ {
} }
system.stop (); system.stop ();
@ -104,7 +104,7 @@ TEST (system, receive_while_synchronizing)
node1->start (); node1->start ();
system.nodes.push_back (node1); system.nodes.push_back (node1);
ASSERT_NE (nullptr, nano::test::establish_tcp (system, *node1, node->network.endpoint ())); ASSERT_NE (nullptr, nano::test::establish_tcp (system, *node1, node->network.endpoint ()));
node1->workers.add_timed_task (std::chrono::steady_clock::now () + std::chrono::milliseconds (200), ([&system, &key] () { node1->workers.post_delayed (std::chrono::milliseconds (200), ([&system, &key] () {
auto hash (system.wallet (0)->send_sync (nano::dev::genesis_key.pub, key.pub, system.nodes[0]->config.receive_minimum.number ())); auto hash (system.wallet (0)->send_sync (nano::dev::genesis_key.pub, key.pub, system.nodes[0]->config.receive_minimum.number ()));
auto transaction = system.nodes[0]->ledger.tx_begin_read (); auto transaction = system.nodes[0]->ledger.tx_begin_read ();
auto block = system.nodes[0]->ledger.any.block_get (transaction, hash); auto block = system.nodes[0]->ledger.any.block_get (transaction, hash);
@ -694,7 +694,7 @@ TEST (confirmation_height, many_accounts_single_confirmation)
// All frontiers (except last) should have 2 blocks and both should be confirmed // All frontiers (except last) should have 2 blocks and both should be confirmed
auto transaction = node->store.tx_begin_read (); auto transaction = node->store.tx_begin_read ();
for (auto i (node->store.account.begin (transaction)), n (node->store.account.end ()); i != n; ++i) for (auto i (node->store.account.begin (transaction)), n (node->store.account.end (transaction)); i != n; ++i)
{ {
auto & account = i->first; auto & account = i->first;
auto & account_info = i->second; auto & account_info = i->second;
@ -706,7 +706,7 @@ TEST (confirmation_height, many_accounts_single_confirmation)
} }
size_t cemented_count = 0; size_t cemented_count = 0;
for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end ()); i != n; ++i) for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end (transaction)); i != n; ++i)
{ {
cemented_count += i->second.height; cemented_count += i->second.height;
} }
@ -782,7 +782,7 @@ TEST (confirmation_height, many_accounts_many_confirmations)
auto transaction = node->store.tx_begin_read (); auto transaction = node->store.tx_begin_read ();
size_t cemented_count = 0; size_t cemented_count = 0;
for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end ()); i != n; ++i) for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end (transaction)); i != n; ++i)
{ {
cemented_count += i->second.height; cemented_count += i->second.height;
} }
@ -925,7 +925,7 @@ TEST (confirmation_height, long_chains)
ASSERT_EQ (num_blocks + 1, info->block_count); ASSERT_EQ (num_blocks + 1, info->block_count);
size_t cemented_count = 0; size_t cemented_count = 0;
for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end ()); i != n; ++i) for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end (transaction)); i != n; ++i)
{ {
cemented_count += i->second.height; cemented_count += i->second.height;
} }
@ -1098,7 +1098,7 @@ TEST (confirmation_height, many_accounts_send_receive_self)
auto transaction = node->store.tx_begin_read (); auto transaction = node->store.tx_begin_read ();
size_t cemented_count = 0; size_t cemented_count = 0;
for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end ()); i != n; ++i) for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end (transaction)); i != n; ++i)
{ {
cemented_count += i->second.height; cemented_count += i->second.height;
} }
@ -1256,7 +1256,7 @@ TEST (confirmation_height, many_accounts_send_receive_self_no_elections)
auto transaction = store->tx_begin_read (); auto transaction = store->tx_begin_read ();
size_t cemented_count = 0; size_t cemented_count = 0;
for (auto i (store->confirmation_height.begin (transaction)), n (store->confirmation_height.end ()); i != n; ++i) for (auto i (store->confirmation_height.begin (transaction)), n (store->confirmation_height.end (transaction)); i != n; ++i)
{ {
cemented_count += i->second.height; cemented_count += i->second.height;
} }
@ -1378,7 +1378,7 @@ namespace transport
// Pick first peer to be consistent // Pick first peer to be consistent
auto peer = data.node->network.tcp_channels.channels[0].channel; auto peer = data.node->network.tcp_channels.channels[0].channel;
auto maybe_telemetry = data.node->telemetry.get_telemetry (peer->get_endpoint ()); auto maybe_telemetry = data.node->telemetry.get_telemetry (peer->get_remote_endpoint ());
if (maybe_telemetry) if (maybe_telemetry)
{ {
callback_process (shared_data, data, node_data, maybe_telemetry->timestamp); callback_process (shared_data, data, node_data, maybe_telemetry->timestamp);
@ -1508,7 +1508,7 @@ TEST (telemetry, cache_read_and_timeout)
ASSERT_NE (channel, nullptr); ASSERT_NE (channel, nullptr);
node_client->telemetry.trigger (); node_client->telemetry.trigger ();
ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
auto responses = node_client->telemetry.get_all_telemetries (); auto responses = node_client->telemetry.get_all_telemetries ();
ASSERT_TRUE (!responses.empty ()); ASSERT_TRUE (!responses.empty ());
@ -1531,7 +1531,7 @@ TEST (telemetry, cache_read_and_timeout)
// Request telemetry metrics again // Request telemetry metrics again
node_client->telemetry.trigger (); node_client->telemetry.trigger ();
ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (channel->get_remote_endpoint ()));
responses = node_client->telemetry.get_all_telemetries (); responses = node_client->telemetry.get_all_telemetries ();
ASSERT_TRUE (!responses.empty ()); ASSERT_TRUE (!responses.empty ());
@ -1606,7 +1606,7 @@ TEST (telemetry, many_nodes)
for (auto const & peer : peers) for (auto const & peer : peers)
{ {
std::optional<nano::telemetry_data> telemetry_data; std::optional<nano::telemetry_data> telemetry_data;
ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (peer->get_endpoint ())); ASSERT_TIMELY (5s, telemetry_data = node_client->telemetry.get_telemetry (peer->get_remote_endpoint ()));
telemetry_datas.push_back (*telemetry_data); telemetry_datas.push_back (*telemetry_data);
} }
@ -1750,7 +1750,7 @@ TEST (node, mass_epoch_upgrader)
{ {
auto transaction (node.store.tx_begin_read ()); auto transaction (node.store.tx_begin_read ());
size_t block_count_sum = 0; size_t block_count_sum = 0;
for (auto i (node.store.account.begin (transaction)); i != node.store.account.end (); ++i) for (auto i (node.store.account.begin (transaction)); i != node.store.account.end (transaction); ++i)
{ {
nano::account_info info (i->second); nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); ASSERT_EQ (info.epoch (), nano::epoch::epoch_1);

View file

@ -8,8 +8,7 @@ add_library(
db_val.hpp db_val.hpp
db_val_impl.hpp db_val_impl.hpp
iterator.hpp iterator.hpp
iterator_impl.hpp final_vote.hpp
final.hpp
lmdb/account.hpp lmdb/account.hpp
lmdb/block.hpp lmdb/block.hpp
lmdb/confirmation_height.hpp lmdb/confirmation_height.hpp
@ -32,6 +31,9 @@ add_library(
peer.hpp peer.hpp
pending.hpp pending.hpp
pruned.hpp pruned.hpp
rep_weight.hpp
reverse_iterator.hpp
reverse_iterator_templ.hpp
rocksdb/account.hpp rocksdb/account.hpp
rocksdb/block.hpp rocksdb/block.hpp
rocksdb/confirmation_height.hpp rocksdb/confirmation_height.hpp
@ -46,9 +48,12 @@ add_library(
rocksdb/rocksdb.hpp rocksdb/rocksdb.hpp
rocksdb/iterator.hpp rocksdb/iterator.hpp
rocksdb/transaction_impl.hpp rocksdb/transaction_impl.hpp
rocksdb/utility.hpp
rocksdb/version.hpp rocksdb/version.hpp
tables.hpp tables.hpp
transaction.hpp transaction.hpp
typed_iterator.hpp
typed_iterator_templ.hpp
version.hpp version.hpp
versioning.hpp versioning.hpp
account.cpp account.cpp
@ -57,13 +62,13 @@ add_library(
confirmation_height.cpp confirmation_height.cpp
db_val.cpp db_val.cpp
iterator.cpp iterator.cpp
iterator_impl.cpp final_vote.cpp
final.cpp
lmdb/account.cpp lmdb/account.cpp
lmdb/block.cpp lmdb/block.cpp
lmdb/confirmation_height.cpp lmdb/confirmation_height.cpp
lmdb/db_val.cpp lmdb/db_val.cpp
lmdb/final_vote.cpp lmdb/final_vote.cpp
lmdb/iterator.cpp
lmdb/lmdb.cpp lmdb/lmdb.cpp
lmdb/lmdb_env.cpp lmdb/lmdb_env.cpp
lmdb/transaction.cpp lmdb/transaction.cpp
@ -78,11 +83,13 @@ add_library(
peer.cpp peer.cpp
pending.cpp pending.cpp
pruned.cpp pruned.cpp
rep_weight.cpp
rocksdb/account.cpp rocksdb/account.cpp
rocksdb/block.cpp rocksdb/block.cpp
rocksdb/confirmation_height.cpp rocksdb/confirmation_height.cpp
rocksdb/db_val.cpp rocksdb/db_val.cpp
rocksdb/final_vote.cpp rocksdb/final_vote.cpp
rocksdb/iterator.cpp
rocksdb/online_weight.cpp rocksdb/online_weight.cpp
rocksdb/peer.cpp rocksdb/peer.cpp
rocksdb/pending.cpp rocksdb/pending.cpp
@ -90,8 +97,10 @@ add_library(
rocksdb/rep_weight.cpp rocksdb/rep_weight.cpp
rocksdb/rocksdb.cpp rocksdb/rocksdb.cpp
rocksdb/transaction.cpp rocksdb/transaction.cpp
rocksdb/utility.cpp
rocksdb/version.cpp rocksdb/version.cpp
transaction.cpp transaction.cpp
typed_iterator.cpp
version.cpp version.cpp
versioning.cpp versioning.cpp
write_queue.hpp write_queue.hpp

Some files were not shown because too many files have changed in this diff Show more