Cache peers in database (#1608)
* Cache peers implementation * Add --debug_peers CLI command * Fix test and formartting * Store port in network byte order. Added an appropriate interface similar to boost's endpoint for nano::endpoint_key * Formatting * Fix rebase * Update stopped (removed in merge) * Formatting
This commit is contained in:
parent
28a10823c6
commit
ea192aa708
14 changed files with 346 additions and 68 deletions
|
@ -1417,3 +1417,74 @@ TEST (block_store, upgrade_sideband_epoch)
|
|||
ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block2).code);
|
||||
ASSERT_EQ (nano::epoch::epoch_1, store.block_version (transaction, block2.hash ()));
|
||||
}
|
||||
|
||||
TEST (block_store, peers)
|
||||
{
|
||||
nano::logging logging;
|
||||
auto init (false);
|
||||
nano::mdb_store store (init, logging, nano::unique_path ());
|
||||
ASSERT_TRUE (!init);
|
||||
|
||||
auto transaction (store.tx_begin_write ());
|
||||
nano::endpoint_key endpoint (boost::asio::ip::address_v6::any ().to_bytes (), 100);
|
||||
|
||||
// Confirm that the store is empty
|
||||
ASSERT_FALSE (store.peer_exists (transaction, endpoint));
|
||||
ASSERT_EQ (store.peer_count (transaction), 0);
|
||||
|
||||
// Add one, confirm that it can be found
|
||||
store.peer_put (transaction, endpoint);
|
||||
ASSERT_TRUE (store.peer_exists (transaction, endpoint));
|
||||
ASSERT_EQ (store.peer_count (transaction), 1);
|
||||
|
||||
// Add another one and check that it (and the existing one) can be found
|
||||
nano::endpoint_key endpoint1 (boost::asio::ip::address_v6::any ().to_bytes (), 101);
|
||||
store.peer_put (transaction, endpoint1);
|
||||
ASSERT_TRUE (store.peer_exists (transaction, endpoint1)); // Check new peer is here
|
||||
ASSERT_TRUE (store.peer_exists (transaction, endpoint)); // Check first peer is still here
|
||||
ASSERT_EQ (store.peer_count (transaction), 2);
|
||||
|
||||
// Delete the first one
|
||||
store.peer_del (transaction, endpoint1);
|
||||
ASSERT_FALSE (store.peer_exists (transaction, endpoint1)); // Confirm it no longer exists
|
||||
ASSERT_TRUE (store.peer_exists (transaction, endpoint)); // Check first peer is still here
|
||||
ASSERT_EQ (store.peer_count (transaction), 1);
|
||||
|
||||
// Delete original one
|
||||
store.peer_del (transaction, endpoint);
|
||||
ASSERT_EQ (store.peer_count (transaction), 0);
|
||||
ASSERT_FALSE (store.peer_exists (transaction, endpoint));
|
||||
}
|
||||
|
||||
TEST (block_store, endpoint_key_byte_order)
|
||||
{
|
||||
boost::asio::ip::address_v6 address (boost::asio::ip::address_v6::from_string ("::ffff:127.0.0.1"));
|
||||
auto port = 100;
|
||||
nano::endpoint_key endpoint_key (address.to_bytes (), port);
|
||||
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
nano::vectorstream stream (bytes);
|
||||
nano::write (stream, endpoint_key);
|
||||
}
|
||||
|
||||
// This checks that the endpoint is serialized as expected, with a size
|
||||
// of 18 bytes (16 for ipv6 address and 2 for port), both in network byte order.
|
||||
ASSERT_EQ (bytes.size (), 18);
|
||||
ASSERT_EQ (bytes[10], 0xff);
|
||||
ASSERT_EQ (bytes[11], 0xff);
|
||||
ASSERT_EQ (bytes[12], 127);
|
||||
ASSERT_EQ (bytes[bytes.size () - 2], 0);
|
||||
ASSERT_EQ (bytes.back (), 100);
|
||||
|
||||
// Deserialize the same stream bytes
|
||||
nano::bufferstream stream1 (bytes.data (), bytes.size ());
|
||||
nano::endpoint_key endpoint_key1;
|
||||
nano::read (stream1, endpoint_key1);
|
||||
|
||||
// This should be in network bytes order
|
||||
ASSERT_EQ (address.to_bytes (), endpoint_key1.address_bytes ());
|
||||
|
||||
// This should be in host byte order
|
||||
ASSERT_EQ (port, endpoint_key1.port ());
|
||||
}
|
||||
|
|
|
@ -2128,6 +2128,60 @@ TEST (node, confirm_back)
|
|||
}
|
||||
}
|
||||
|
||||
TEST (node, peers)
|
||||
{
|
||||
nano::system system (24000, 1);
|
||||
auto list (system.nodes.front ()->peers.list ());
|
||||
ASSERT_TRUE (list.empty ());
|
||||
|
||||
nano::node_init init;
|
||||
auto node (std::make_shared<nano::node> (init, system.io_ctx, 24001, nano::unique_path (), system.alarm, system.logging, system.work));
|
||||
system.nodes.push_back (node);
|
||||
|
||||
auto endpoint = system.nodes.front ()->network.endpoint ();
|
||||
nano::endpoint_key endpoint_key{ endpoint.address ().to_v6 ().to_bytes (), endpoint.port () };
|
||||
auto & store = system.nodes.back ()->store;
|
||||
{
|
||||
// Add a peer to the database
|
||||
auto transaction (store.tx_begin_write ());
|
||||
store.peer_put (transaction, endpoint_key);
|
||||
|
||||
// Add a peer which is not contactable
|
||||
store.peer_put (transaction, nano::endpoint_key{ boost::asio::ip::address_v6::any ().to_bytes (), 55555 });
|
||||
}
|
||||
|
||||
node->start ();
|
||||
system.deadline_set (10s);
|
||||
while (system.nodes.back ()->peers.empty ())
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
|
||||
// Confirm that the peers match with the endpoints we are expecting
|
||||
ASSERT_EQ (1, system.nodes.front ()->peers.list ().size ());
|
||||
ASSERT_EQ (system.nodes.front ()->peers.list ().front (), system.nodes.back ()->network.endpoint ());
|
||||
ASSERT_EQ (1, node->peers.list ().size ());
|
||||
ASSERT_EQ (system.nodes.back ()->peers.list ().front (), system.nodes.front ()->network.endpoint ());
|
||||
|
||||
// Stop the peer node and check that it is removed from the store
|
||||
system.nodes.front ()->stop ();
|
||||
|
||||
system.deadline_set (10s);
|
||||
while (system.nodes.back ()->peers.size () == 1)
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
|
||||
ASSERT_TRUE (system.nodes.back ()->peers.empty ());
|
||||
|
||||
// Uncontactable peer should not be stored
|
||||
auto transaction (store.tx_begin_read ());
|
||||
ASSERT_EQ (store.peer_count (transaction), 1);
|
||||
ASSERT_TRUE (store.peer_exists (transaction, endpoint_key));
|
||||
|
||||
node->stop ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void add_required_children_node_config_tree (nano::jsonconfig & tree)
|
||||
|
|
|
@ -18,14 +18,14 @@ using stream = std::basic_streambuf<uint8_t>;
|
|||
template <typename T>
|
||||
bool read (nano::stream & stream_a, T & value)
|
||||
{
|
||||
static_assert (std::is_pod<T>::value, "Can't stream read non-standard layout types");
|
||||
static_assert (std::is_standard_layout<T>::value, "Can't stream read non-standard layout types");
|
||||
auto amount_read (stream_a.sgetn (reinterpret_cast<uint8_t *> (&value), sizeof (value)));
|
||||
return amount_read != sizeof (value);
|
||||
}
|
||||
template <typename T>
|
||||
void write (nano::stream & stream_a, T const & value)
|
||||
{
|
||||
static_assert (std::is_pod<T>::value, "Can't stream write non-standard layout types");
|
||||
static_assert (std::is_standard_layout<T>::value, "Can't stream write non-standard layout types");
|
||||
auto amount_written (stream_a.sputn (reinterpret_cast<uint8_t const *> (&value), sizeof (value)));
|
||||
assert (amount_written == sizeof (value));
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ int main (int argc, char * const * argv)
|
|||
("debug_profile_votes", "Profile votes processing (only for nano_test_network)")
|
||||
("debug_rpc", "Read an RPC command from stdin and invoke it. Network operations will have no effect.")
|
||||
("debug_validate_blocks", "Check all blocks for correct hash, signature, work value")
|
||||
("debug_peers", "Display peer IPv6:port connections")
|
||||
("platform", boost::program_options::value<std::string> (), "Defines the <platform> for OpenCL commands")
|
||||
("device", boost::program_options::value<std::string> (), "Defines <device> for OpenCL command")
|
||||
("threads", boost::program_options::value<std::string> (), "Defines <threads> count for OpenCL command");
|
||||
|
@ -813,6 +814,16 @@ int main (int argc, char * const * argv)
|
|||
nano::remove_temporary_directories ();
|
||||
std::cout << boost::str (boost::format ("%|1$ 12d| seconds \n%2% blocks per second") % seconds % (block_count / seconds)) << std::endl;
|
||||
}
|
||||
else if (vm.count ("debug_peers"))
|
||||
{
|
||||
nano::inactive_node node (data_path);
|
||||
auto transaction (node.node->store.tx_begin ());
|
||||
|
||||
for (auto i (node.node->store.peers_begin (transaction)), n (node.node->store.peers_end ()); i != n; ++i)
|
||||
{
|
||||
std::cout << boost::str (boost::format ("%1%\n") % nano::endpoint (boost::asio::ip::address_v6 (i->first.address_bytes ()), i->first.port ()));
|
||||
}
|
||||
}
|
||||
else if (vm.count ("version"))
|
||||
{
|
||||
std::cout << "Version " << NANO_VERSION_MAJOR << "." << NANO_VERSION_MINOR << std::endl;
|
||||
|
|
|
@ -115,6 +115,11 @@ mdb_val (sizeof (val_a), const_cast<nano::block_info *> (&val_a))
|
|||
{
|
||||
}
|
||||
|
||||
nano::mdb_val::mdb_val (nano::endpoint_key const & val_a) :
|
||||
mdb_val (sizeof (val_a), const_cast<nano::endpoint_key *> (&val_a))
|
||||
{
|
||||
}
|
||||
|
||||
nano::mdb_val::mdb_val (std::shared_ptr<nano::block> const & val_a) :
|
||||
buffer (std::make_shared<std::vector<uint8_t>> ())
|
||||
{
|
||||
|
@ -194,7 +199,14 @@ nano::mdb_val::operator std::array<char, 64> () const
|
|||
return result;
|
||||
}
|
||||
|
||||
nano::mdb_val::operator no_value () const
|
||||
nano::mdb_val::operator nano::endpoint_key () const
|
||||
{
|
||||
nano::endpoint_key result;
|
||||
std::copy (reinterpret_cast<uint8_t const *> (value.mv_data), reinterpret_cast<uint8_t const *> (value.mv_data) + sizeof (result), reinterpret_cast<uint8_t *> (&result));
|
||||
return result;
|
||||
}
|
||||
|
||||
nano::mdb_val::operator nano::no_value () const
|
||||
{
|
||||
return no_value::dummy;
|
||||
}
|
||||
|
@ -657,7 +669,7 @@ template class nano::mdb_iterator<nano::uint256_union, nano::uint256_union>;
|
|||
template class nano::mdb_iterator<nano::uint256_union, std::shared_ptr<nano::block>>;
|
||||
template class nano::mdb_iterator<nano::uint256_union, std::shared_ptr<nano::vote>>;
|
||||
template class nano::mdb_iterator<nano::uint256_union, nano::wallet_value>;
|
||||
template class nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>;
|
||||
template class nano::mdb_iterator<std::array<char, 64>, nano::no_value>;
|
||||
|
||||
nano::store_iterator<nano::account, nano::uint128_union> nano::mdb_store::representation_begin (nano::transaction const & transaction_a)
|
||||
{
|
||||
|
@ -701,24 +713,7 @@ nano::store_iterator<nano::account, std::shared_ptr<nano::vote>> nano::mdb_store
|
|||
|
||||
nano::mdb_store::mdb_store (bool & error_a, nano::logging & logging_a, boost::filesystem::path const & path_a, int lmdb_max_dbs) :
|
||||
logging (logging_a),
|
||||
env (error_a, path_a, lmdb_max_dbs),
|
||||
frontiers (0),
|
||||
accounts_v0 (0),
|
||||
accounts_v1 (0),
|
||||
send_blocks (0),
|
||||
receive_blocks (0),
|
||||
open_blocks (0),
|
||||
change_blocks (0),
|
||||
state_blocks_v0 (0),
|
||||
state_blocks_v1 (0),
|
||||
pending_v0 (0),
|
||||
pending_v1 (0),
|
||||
blocks_info (0),
|
||||
representation (0),
|
||||
unchecked (0),
|
||||
vote (0),
|
||||
meta (0),
|
||||
stopped (false)
|
||||
env (error_a, path_a, lmdb_max_dbs)
|
||||
{
|
||||
auto slow_upgrade (false);
|
||||
if (!error_a)
|
||||
|
@ -739,6 +734,7 @@ stopped (false)
|
|||
error_a |= mdb_dbi_open (env.tx (transaction), "unchecked", MDB_CREATE, &unchecked) != 0;
|
||||
error_a |= mdb_dbi_open (env.tx (transaction), "vote", MDB_CREATE, &vote) != 0;
|
||||
error_a |= mdb_dbi_open (env.tx (transaction), "meta", MDB_CREATE, &meta) != 0;
|
||||
error_a |= mdb_dbi_open (env.tx (transaction), "peers", MDB_CREATE, &peers) != 0;
|
||||
if (!full_sideband (transaction))
|
||||
{
|
||||
error_a |= mdb_dbi_open (env.tx (transaction), "blocks_info", MDB_CREATE, &blocks_info) != 0;
|
||||
|
@ -859,6 +855,53 @@ void nano::mdb_store::delete_node_id (nano::transaction const & transaction_a)
|
|||
assert (!error || error == MDB_NOTFOUND);
|
||||
}
|
||||
|
||||
void nano::mdb_store::peer_put (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a)
|
||||
{
|
||||
nano::mdb_val junk;
|
||||
auto status (mdb_put (env.tx (transaction_a), peers, nano::mdb_val (endpoint_a), junk, 0));
|
||||
release_assert (status == 0);
|
||||
}
|
||||
|
||||
void nano::mdb_store::peer_del (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a)
|
||||
{
|
||||
auto status (mdb_del (env.tx (transaction_a), peers, nano::mdb_val (endpoint_a), nullptr));
|
||||
release_assert (status == 0);
|
||||
}
|
||||
|
||||
bool nano::mdb_store::peer_exists (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a) const
|
||||
{
|
||||
nano::mdb_val junk;
|
||||
auto status (mdb_get (env.tx (transaction_a), peers, nano::mdb_val (endpoint_a), junk));
|
||||
release_assert (status == 0 || status == MDB_NOTFOUND);
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
size_t nano::mdb_store::peer_count (nano::transaction const & transaction_a) const
|
||||
{
|
||||
MDB_stat stats;
|
||||
auto status (mdb_stat (env.tx (transaction_a), peers, &stats));
|
||||
release_assert (status == 0);
|
||||
return stats.ms_entries;
|
||||
}
|
||||
|
||||
void nano::mdb_store::peer_clear (nano::transaction const & transaction_a)
|
||||
{
|
||||
auto status (mdb_drop (env.tx (transaction_a), peers, 0));
|
||||
release_assert (status == 0);
|
||||
}
|
||||
|
||||
nano::store_iterator<nano::endpoint_key, nano::no_value> nano::mdb_store::peers_begin (nano::transaction const & transaction_a)
|
||||
{
|
||||
nano::store_iterator<nano::endpoint_key, nano::no_value> result (std::make_unique<nano::mdb_iterator<nano::endpoint_key, nano::no_value>> (transaction_a, peers));
|
||||
return result;
|
||||
}
|
||||
|
||||
nano::store_iterator<nano::endpoint_key, nano::no_value> nano::mdb_store::peers_end ()
|
||||
{
|
||||
nano::store_iterator<nano::endpoint_key, nano::no_value> result (nano::store_iterator<nano::endpoint_key, nano::no_value> (nullptr));
|
||||
return result;
|
||||
}
|
||||
|
||||
void nano::mdb_store::do_upgrades (nano::transaction const & transaction_a, bool & slow_upgrade)
|
||||
{
|
||||
switch (version_get (transaction_a))
|
||||
|
|
|
@ -46,10 +46,6 @@ public:
|
|||
class mdb_val
|
||||
{
|
||||
public:
|
||||
enum class no_value
|
||||
{
|
||||
dummy
|
||||
};
|
||||
mdb_val (nano::epoch = nano::epoch::unspecified);
|
||||
mdb_val (nano::account_info const &);
|
||||
mdb_val (nano::block_info const &);
|
||||
|
@ -59,6 +55,7 @@ public:
|
|||
mdb_val (size_t, void *);
|
||||
mdb_val (nano::uint128_union const &);
|
||||
mdb_val (nano::uint256_union const &);
|
||||
mdb_val (nano::endpoint_key const &);
|
||||
mdb_val (std::shared_ptr<nano::block> const &);
|
||||
mdb_val (std::shared_ptr<nano::vote> const &);
|
||||
void * data () const;
|
||||
|
@ -70,7 +67,8 @@ public:
|
|||
explicit operator nano::uint128_union () const;
|
||||
explicit operator nano::uint256_union () const;
|
||||
explicit operator std::array<char, 64> () const;
|
||||
explicit operator no_value () const;
|
||||
explicit operator nano::endpoint_key () const;
|
||||
explicit operator nano::no_value () const;
|
||||
explicit operator std::shared_ptr<nano::block> () const;
|
||||
explicit operator std::shared_ptr<nano::send_block> () const;
|
||||
explicit operator std::shared_ptr<nano::receive_block> () const;
|
||||
|
@ -264,6 +262,15 @@ public:
|
|||
/** Deletes the node ID from the store */
|
||||
void delete_node_id (nano::transaction const &) override;
|
||||
|
||||
void peer_put (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a);
|
||||
bool peer_exists (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a) const;
|
||||
void peer_del (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a);
|
||||
size_t peer_count (nano::transaction const & transaction_a) const;
|
||||
void peer_clear (nano::transaction const & transaction_a);
|
||||
|
||||
nano::store_iterator<nano::endpoint_key, nano::no_value> peers_begin (nano::transaction const & transaction_a);
|
||||
nano::store_iterator<nano::endpoint_key, nano::no_value> peers_end ();
|
||||
|
||||
void stop ();
|
||||
|
||||
nano::logging & logging;
|
||||
|
@ -274,97 +281,103 @@ public:
|
|||
* Maps head block to owning account
|
||||
* nano::block_hash -> nano::account
|
||||
*/
|
||||
MDB_dbi frontiers;
|
||||
MDB_dbi frontiers{ 0 };
|
||||
|
||||
/**
|
||||
* Maps account v1 to account information, head, rep, open, balance, timestamp and block count.
|
||||
* nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t
|
||||
*/
|
||||
MDB_dbi accounts_v0;
|
||||
MDB_dbi accounts_v0{ 0 };
|
||||
|
||||
/**
|
||||
* Maps account v0 to account information, head, rep, open, balance, timestamp and block count.
|
||||
* nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t
|
||||
*/
|
||||
MDB_dbi accounts_v1;
|
||||
MDB_dbi accounts_v1{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to send block.
|
||||
* nano::block_hash -> nano::send_block
|
||||
*/
|
||||
MDB_dbi send_blocks;
|
||||
MDB_dbi send_blocks{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to receive block.
|
||||
* nano::block_hash -> nano::receive_block
|
||||
*/
|
||||
MDB_dbi receive_blocks;
|
||||
MDB_dbi receive_blocks{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to open block.
|
||||
* nano::block_hash -> nano::open_block
|
||||
*/
|
||||
MDB_dbi open_blocks;
|
||||
MDB_dbi open_blocks{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to change block.
|
||||
* nano::block_hash -> nano::change_block
|
||||
*/
|
||||
MDB_dbi change_blocks;
|
||||
MDB_dbi change_blocks{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to v0 state block.
|
||||
* nano::block_hash -> nano::state_block
|
||||
*/
|
||||
MDB_dbi state_blocks_v0;
|
||||
MDB_dbi state_blocks_v0{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to v1 state block.
|
||||
* nano::block_hash -> nano::state_block
|
||||
*/
|
||||
MDB_dbi state_blocks_v1;
|
||||
MDB_dbi state_blocks_v1{ 0 };
|
||||
|
||||
/**
|
||||
* Maps min_version 0 (destination account, pending block) to (source account, amount).
|
||||
* nano::account, nano::block_hash -> nano::account, nano::amount
|
||||
*/
|
||||
MDB_dbi pending_v0;
|
||||
MDB_dbi pending_v0{ 0 };
|
||||
|
||||
/**
|
||||
* Maps min_version 1 (destination account, pending block) to (source account, amount).
|
||||
* nano::account, nano::block_hash -> nano::account, nano::amount
|
||||
*/
|
||||
MDB_dbi pending_v1;
|
||||
MDB_dbi pending_v1{ 0 };
|
||||
|
||||
/**
|
||||
* Maps block hash to account and balance.
|
||||
* block_hash -> nano::account, nano::amount
|
||||
*/
|
||||
MDB_dbi blocks_info;
|
||||
MDB_dbi blocks_info{ 0 };
|
||||
|
||||
/**
|
||||
* Representative weights.
|
||||
* nano::account -> nano::uint128_t
|
||||
*/
|
||||
MDB_dbi representation;
|
||||
MDB_dbi representation{ 0 };
|
||||
|
||||
/**
|
||||
* Unchecked bootstrap blocks.
|
||||
* nano::block_hash -> nano::block
|
||||
*/
|
||||
MDB_dbi unchecked;
|
||||
MDB_dbi unchecked{ 0 };
|
||||
|
||||
/**
|
||||
* Highest vote observed for account.
|
||||
* nano::account -> uint64_t
|
||||
*/
|
||||
MDB_dbi vote;
|
||||
MDB_dbi vote{ 0 };
|
||||
|
||||
/**
|
||||
* Meta information about block store, such as versions.
|
||||
* nano::uint256_union (arbitrary key) -> blob
|
||||
*/
|
||||
MDB_dbi meta;
|
||||
MDB_dbi meta{ 0 };
|
||||
|
||||
/*
|
||||
* Endpoints for peers
|
||||
* nano::endpoint_key -> no_value
|
||||
*/
|
||||
MDB_dbi peers{ 0 };
|
||||
|
||||
private:
|
||||
bool entry_has_sideband (MDB_val, nano::block_type);
|
||||
|
@ -377,7 +390,7 @@ private:
|
|||
boost::optional<MDB_val> block_raw_get_by_type (nano::transaction const &, nano::block_hash const &, nano::block_type &);
|
||||
void block_raw_put (nano::transaction const &, MDB_dbi, nano::block_hash const &, MDB_val);
|
||||
void clear (MDB_dbi);
|
||||
bool stopped;
|
||||
bool stopped{ false };
|
||||
std::thread upgrades;
|
||||
};
|
||||
class wallet_value
|
||||
|
|
|
@ -21,6 +21,8 @@ std::chrono::seconds constexpr nano::node::cutoff;
|
|||
std::chrono::seconds constexpr nano::node::syn_cookie_cutoff;
|
||||
std::chrono::minutes constexpr nano::node::backup_interval;
|
||||
std::chrono::seconds constexpr nano::node::search_pending_interval;
|
||||
std::chrono::seconds constexpr nano::node::peer_interval;
|
||||
|
||||
int constexpr nano::port_mapping::mapping_timeout;
|
||||
int constexpr nano::port_mapping::check_timeout;
|
||||
unsigned constexpr nano::active_transactions::request_interval_ms;
|
||||
|
@ -2279,6 +2281,7 @@ nano::process_return nano::node::process (nano::block const & block_a)
|
|||
void nano::node::start ()
|
||||
{
|
||||
network.start ();
|
||||
add_initial_peers ();
|
||||
ongoing_keepalive ();
|
||||
ongoing_syn_cookie_cleanup ();
|
||||
if (!flags.disable_legacy_bootstrap)
|
||||
|
@ -2288,6 +2291,7 @@ void nano::node::start ()
|
|||
ongoing_store_flush ();
|
||||
ongoing_rep_crawl ();
|
||||
ongoing_rep_calculation ();
|
||||
ongoing_peer_store ();
|
||||
if (!flags.disable_bootstrap_listener)
|
||||
{
|
||||
bootstrap.start ();
|
||||
|
@ -2307,7 +2311,6 @@ void nano::node::start ()
|
|||
}
|
||||
online_reps.recalculate_stake ();
|
||||
port_mapping.start ();
|
||||
add_initial_peers ();
|
||||
}
|
||||
|
||||
void nano::node::stop ()
|
||||
|
@ -2477,6 +2480,30 @@ void nano::node::ongoing_store_flush ()
|
|||
});
|
||||
}
|
||||
|
||||
void nano::node::ongoing_peer_store ()
|
||||
{
|
||||
auto endpoint_peers = peers.list ();
|
||||
if (!endpoint_peers.empty ())
|
||||
{
|
||||
// Clear all peers then refresh with the current list of peers
|
||||
auto transaction (store.tx_begin_write ());
|
||||
store.peer_clear (transaction);
|
||||
for (const auto & endpoint : endpoint_peers)
|
||||
{
|
||||
nano::endpoint_key endpoint_key (endpoint.address ().to_v6 ().to_bytes (), endpoint.port ());
|
||||
store.peer_put (transaction, std::move (endpoint_key));
|
||||
}
|
||||
}
|
||||
|
||||
std::weak_ptr<nano::node> node_w (shared_from_this ());
|
||||
alarm.add (std::chrono::steady_clock::now () + peer_interval, [node_w]() {
|
||||
if (auto node_l = node_w.lock ())
|
||||
{
|
||||
node_l->ongoing_peer_store ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void nano::node::backup_wallet ()
|
||||
{
|
||||
auto transaction (wallets.tx_begin_read ());
|
||||
|
@ -2847,6 +2874,15 @@ uint64_t nano::node::work_generate_blocking (nano::uint256_union const & hash_a,
|
|||
|
||||
void nano::node::add_initial_peers ()
|
||||
{
|
||||
auto transaction (store.tx_begin_read ());
|
||||
for (auto i (store.peers_begin (transaction)), n (store.peers_end ()); i != n; ++i)
|
||||
{
|
||||
nano::endpoint endpoint (boost::asio::ip::address_v6 (i->first.address_bytes ()), i->first.port ());
|
||||
if (!peers.reachout (endpoint))
|
||||
{
|
||||
send_keepalive (endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nano::node::block_confirm (std::shared_ptr<nano::block> block_a)
|
||||
|
|
|
@ -521,6 +521,7 @@ public:
|
|||
void ongoing_rep_calculation ();
|
||||
void ongoing_bootstrap ();
|
||||
void ongoing_store_flush ();
|
||||
void ongoing_peer_store ();
|
||||
void backup_wallet ();
|
||||
void search_pending ();
|
||||
void bootstrap_wallet ();
|
||||
|
@ -570,11 +571,12 @@ public:
|
|||
const std::chrono::steady_clock::time_point startup_time;
|
||||
static double constexpr price_max = 16.0;
|
||||
static double constexpr free_cutoff = 1024.0;
|
||||
static std::chrono::seconds constexpr period = std::chrono::seconds (60);
|
||||
static std::chrono::seconds constexpr period = (nano::nano_network == nano::nano_networks::nano_test_network) ? std::chrono::seconds (1) : std::chrono::seconds (60);
|
||||
static std::chrono::seconds constexpr cutoff = period * 5;
|
||||
static std::chrono::seconds constexpr syn_cookie_cutoff = std::chrono::seconds (5);
|
||||
static std::chrono::minutes constexpr backup_interval = std::chrono::minutes (5);
|
||||
static std::chrono::seconds constexpr search_pending_interval = (nano::nano_network == nano::nano_networks::nano_test_network) ? std::chrono::seconds (1) : std::chrono::seconds (5 * 60);
|
||||
static std::chrono::seconds constexpr peer_interval = search_pending_interval;
|
||||
};
|
||||
class thread_runner
|
||||
{
|
||||
|
|
|
@ -15,10 +15,7 @@ endpoint (endpoint_a),
|
|||
ip_address (endpoint_a.address ()),
|
||||
last_contact (std::chrono::steady_clock::now ()),
|
||||
last_attempt (last_contact),
|
||||
last_bootstrap_attempt (std::chrono::steady_clock::time_point ()),
|
||||
last_rep_request (std::chrono::steady_clock::time_point ()),
|
||||
last_rep_response (std::chrono::steady_clock::time_point ()),
|
||||
rep_weight (0),
|
||||
|
||||
network_version (network_version_a),
|
||||
node_id (node_id_a)
|
||||
{
|
||||
|
@ -28,13 +25,7 @@ nano::peer_information::peer_information (nano::endpoint const & endpoint_a, std
|
|||
endpoint (endpoint_a),
|
||||
ip_address (endpoint_a.address ()),
|
||||
last_contact (last_contact_a),
|
||||
last_attempt (last_attempt_a),
|
||||
last_bootstrap_attempt (std::chrono::steady_clock::time_point ()),
|
||||
last_rep_request (std::chrono::steady_clock::time_point ()),
|
||||
last_rep_response (std::chrono::steady_clock::time_point ()),
|
||||
rep_weight (0),
|
||||
network_version (nano::protocol_version),
|
||||
node_id ()
|
||||
last_attempt (last_attempt_a)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -50,12 +50,12 @@ public:
|
|||
boost::asio::ip::address ip_address;
|
||||
std::chrono::steady_clock::time_point last_contact;
|
||||
std::chrono::steady_clock::time_point last_attempt;
|
||||
std::chrono::steady_clock::time_point last_bootstrap_attempt;
|
||||
std::chrono::steady_clock::time_point last_rep_request;
|
||||
std::chrono::steady_clock::time_point last_rep_response;
|
||||
nano::amount rep_weight;
|
||||
std::chrono::steady_clock::time_point last_bootstrap_attempt{ std::chrono::steady_clock::time_point () };
|
||||
std::chrono::steady_clock::time_point last_rep_request{ std::chrono::steady_clock::time_point () };
|
||||
std::chrono::steady_clock::time_point last_rep_response{ std::chrono::steady_clock::time_point () };
|
||||
nano::amount rep_weight{ 0 };
|
||||
nano::account probable_rep_account;
|
||||
unsigned network_version;
|
||||
unsigned network_version{ nano::protocol_version };
|
||||
boost::optional<nano::account> node_id;
|
||||
bool operator< (nano::peer_information const &) const;
|
||||
};
|
||||
|
|
|
@ -1325,8 +1325,8 @@ thread ([this]() {
|
|||
assert (status == 0);
|
||||
std::string beginning (nano::uint256_union (0).to_string ());
|
||||
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||
nano::store_iterator<std::array<char, 64>, nano::mdb_val::no_value> i (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::mdb_val::no_value> n (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
for (; i != n; ++i)
|
||||
{
|
||||
nano::uint256_union id;
|
||||
|
@ -1427,8 +1427,8 @@ void nano::wallets::reload ()
|
|||
std::unordered_set<nano::uint256_union> stored_items;
|
||||
std::string beginning (nano::uint256_union (0).to_string ());
|
||||
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||
nano::store_iterator<std::array<char, 64>, nano::mdb_val::no_value> i (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::mdb_val::no_value> n (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
for (; i != n; ++i)
|
||||
{
|
||||
nano::uint256_union id;
|
||||
|
@ -1591,8 +1591,8 @@ void nano::wallets::split_if_needed (nano::transaction & transaction_destination
|
|||
MDB_txn * tx_destination (*boost::polymorphic_downcast<nano::mdb_txn *> (transaction_destination.impl.get ()));
|
||||
std::string beginning (nano::uint256_union (0).to_string ());
|
||||
std::string end ((nano::uint256_union (nano::uint256_t (0) - nano::uint256_t (1))).to_string ());
|
||||
nano::store_iterator<std::array<char, 64>, nano::mdb_val::no_value> i (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>> (transaction_source, handle, nano::mdb_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::mdb_val::no_value> n (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::mdb_val::no_value>> (transaction_source, handle, nano::mdb_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::no_value> i (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::no_value>> (transaction_source, handle, nano::mdb_val (beginning.size (), const_cast<char *> (beginning.c_str ()))));
|
||||
nano::store_iterator<std::array<char, 64>, nano::no_value> n (std::make_unique<nano::mdb_iterator<std::array<char, 64>, nano::no_value>> (transaction_source, handle, nano::mdb_val (end.size (), const_cast<char *> (end.c_str ()))));
|
||||
for (; i != n; ++i)
|
||||
{
|
||||
nano::uint256_union id;
|
||||
|
|
|
@ -290,6 +290,14 @@ public:
|
|||
virtual void version_put (nano::transaction const &, int) = 0;
|
||||
virtual int version_get (nano::transaction const &) = 0;
|
||||
|
||||
virtual void peer_put (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a) = 0;
|
||||
virtual void peer_del (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a) = 0;
|
||||
virtual bool peer_exists (nano::transaction const & transaction_a, nano::endpoint_key const & endpoint_a) const = 0;
|
||||
virtual size_t peer_count (nano::transaction const & transaction_a) const = 0;
|
||||
virtual void peer_clear (nano::transaction const & transaction_a) = 0;
|
||||
virtual nano::store_iterator<nano::endpoint_key, nano::no_value> peers_begin (nano::transaction const & transaction_a) = 0;
|
||||
virtual nano::store_iterator<nano::endpoint_key, nano::no_value> peers_end () = 0;
|
||||
|
||||
// Requires a write transaction
|
||||
virtual nano::raw_key get_node_id (nano::transaction const &) = 0;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <nano/secure/blockstore.hpp>
|
||||
#include <nano/secure/versioning.hpp>
|
||||
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include <queue>
|
||||
|
@ -304,6 +305,21 @@ nano::block_hash nano::pending_key::key () const
|
|||
return account;
|
||||
}
|
||||
|
||||
nano::endpoint_key::endpoint_key (const std::array<uint8_t, 16> & address_a, uint16_t port_a) :
|
||||
address (address_a), network_port (boost::endian::native_to_big (port_a))
|
||||
{
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 16> & nano::endpoint_key::address_bytes () const
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
uint16_t nano::endpoint_key::port () const
|
||||
{
|
||||
return boost::endian::big_to_native (network_port);
|
||||
}
|
||||
|
||||
nano::block_info::block_info () :
|
||||
account (0),
|
||||
balance (0)
|
||||
|
|
|
@ -122,6 +122,39 @@ public:
|
|||
nano::block_hash hash;
|
||||
nano::block_hash key () const;
|
||||
};
|
||||
|
||||
class endpoint_key
|
||||
{
|
||||
public:
|
||||
endpoint_key () = default;
|
||||
|
||||
/*
|
||||
* @param address_a This should be in network byte order
|
||||
* @param port_a This should be in host byte order
|
||||
*/
|
||||
endpoint_key (const std::array<uint8_t, 16> & address_a, uint16_t port_a);
|
||||
|
||||
/*
|
||||
* @return The ipv6 address in network byte order
|
||||
*/
|
||||
const std::array<uint8_t, 16> & address_bytes () const;
|
||||
|
||||
/*
|
||||
* @return The port in host byte order
|
||||
*/
|
||||
uint16_t port () const;
|
||||
|
||||
private:
|
||||
// Both stored internally in network byte order
|
||||
std::array<uint8_t, 16> address;
|
||||
uint16_t network_port{ 0 };
|
||||
};
|
||||
|
||||
enum class no_value
|
||||
{
|
||||
dummy
|
||||
};
|
||||
|
||||
// Internally unchecked_key is equal to pending_key (2x uint256_union)
|
||||
using unchecked_key = pending_key;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue