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:
commit
e0518c38e2
180 changed files with 2902 additions and 2305 deletions
2
.github/workflows/code_sanitizers.yml
vendored
2
.github/workflows/code_sanitizers.yml
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:-} \
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
129
nano/core_test/observer_set.cpp
Normal file
129
nano/core_test/observer_set.cpp
Normal 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));
|
||||||
|
}
|
||||||
|
|
@ -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 ());
|
||||||
|
|
||||||
|
|
|
||||||
48
nano/core_test/random_pool.cpp
Normal file
48
nano/core_test/random_pool.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -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 () } };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
96
nano/core_test/thread_pool.cpp
Normal file
96
nano/core_test/thread_pool.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ namespace nano
|
||||||
{
|
{
|
||||||
class block;
|
class block;
|
||||||
class container_info;
|
class container_info;
|
||||||
|
class thread_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace nano
|
namespace nano
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 ()
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ());
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 &);
|
||||||
|
|
|
||||||
|
|
@ -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 ()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 ())));
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue