diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 737fd17f..bfb70c41 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -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 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 ()); +} diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index b4fe93bf..0034b27b 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -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 (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) diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index e5988f65..03e90734 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -18,14 +18,14 @@ using stream = std::basic_streambuf; template bool read (nano::stream & stream_a, T & value) { - static_assert (std::is_pod::value, "Can't stream read non-standard layout types"); + static_assert (std::is_standard_layout::value, "Can't stream read non-standard layout types"); auto amount_read (stream_a.sgetn (reinterpret_cast (&value), sizeof (value))); return amount_read != sizeof (value); } template void write (nano::stream & stream_a, T const & value) { - static_assert (std::is_pod::value, "Can't stream write non-standard layout types"); + static_assert (std::is_standard_layout::value, "Can't stream write non-standard layout types"); auto amount_written (stream_a.sputn (reinterpret_cast (&value), sizeof (value))); assert (amount_written == sizeof (value)); } diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 0ec6c703..ca35dbff 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -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 (), "Defines the for OpenCL commands") ("device", boost::program_options::value (), "Defines for OpenCL command") ("threads", boost::program_options::value (), "Defines 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; diff --git a/nano/node/lmdb.cpp b/nano/node/lmdb.cpp index 03f917d0..b3e1425d 100644 --- a/nano/node/lmdb.cpp +++ b/nano/node/lmdb.cpp @@ -115,6 +115,11 @@ mdb_val (sizeof (val_a), const_cast (&val_a)) { } +nano::mdb_val::mdb_val (nano::endpoint_key const & val_a) : +mdb_val (sizeof (val_a), const_cast (&val_a)) +{ +} + nano::mdb_val::mdb_val (std::shared_ptr const & val_a) : buffer (std::make_shared> ()) { @@ -194,7 +199,14 @@ nano::mdb_val::operator std::array () 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 (value.mv_data), reinterpret_cast (value.mv_data) + sizeof (result), reinterpret_cast (&result)); + return result; +} + +nano::mdb_val::operator nano::no_value () const { return no_value::dummy; } @@ -657,7 +669,7 @@ template class nano::mdb_iterator; template class nano::mdb_iterator>; template class nano::mdb_iterator>; template class nano::mdb_iterator; -template class nano::mdb_iterator, nano::mdb_val::no_value>; +template class nano::mdb_iterator, nano::no_value>; nano::store_iterator nano::mdb_store::representation_begin (nano::transaction const & transaction_a) { @@ -701,24 +713,7 @@ nano::store_iterator> 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::mdb_store::peers_begin (nano::transaction const & transaction_a) +{ + nano::store_iterator result (std::make_unique> (transaction_a, peers)); + return result; +} + +nano::store_iterator nano::mdb_store::peers_end () +{ + nano::store_iterator result (nano::store_iterator (nullptr)); + return result; +} + void nano::mdb_store::do_upgrades (nano::transaction const & transaction_a, bool & slow_upgrade) { switch (version_get (transaction_a)) diff --git a/nano/node/lmdb.hpp b/nano/node/lmdb.hpp index a279319d..caaefa34 100644 --- a/nano/node/lmdb.hpp +++ b/nano/node/lmdb.hpp @@ -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 const &); mdb_val (std::shared_ptr 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 () const; - explicit operator no_value () const; + explicit operator nano::endpoint_key () const; + explicit operator nano::no_value () const; explicit operator std::shared_ptr () const; explicit operator std::shared_ptr () const; explicit operator std::shared_ptr () 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 peers_begin (nano::transaction const & transaction_a); + nano::store_iterator 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 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 diff --git a/nano/node/node.cpp b/nano/node/node.cpp index c0d2d1ed..c531fc6a 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -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 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 block_a) diff --git a/nano/node/node.hpp b/nano/node/node.hpp index dab13a93..85573551 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -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 { diff --git a/nano/node/peers.cpp b/nano/node/peers.cpp index 404fd877..7df34fdf 100644 --- a/nano/node/peers.cpp +++ b/nano/node/peers.cpp @@ -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) { } diff --git a/nano/node/peers.hpp b/nano/node/peers.hpp index 2108c5ba..d9e76268 100644 --- a/nano/node/peers.hpp +++ b/nano/node/peers.hpp @@ -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 node_id; bool operator< (nano::peer_information const &) const; }; diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index 22e06a07..00cce8d3 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -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, nano::mdb_val::no_value> i (std::make_unique, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast (beginning.c_str ())))); - nano::store_iterator, nano::mdb_val::no_value> n (std::make_unique, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast (end.c_str ())))); + nano::store_iterator, nano::no_value> i (std::make_unique, nano::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast (beginning.c_str ())))); + nano::store_iterator, nano::no_value> n (std::make_unique, nano::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast (end.c_str ())))); for (; i != n; ++i) { nano::uint256_union id; @@ -1427,8 +1427,8 @@ void nano::wallets::reload () std::unordered_set 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, nano::mdb_val::no_value> i (std::make_unique, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast (beginning.c_str ())))); - nano::store_iterator, nano::mdb_val::no_value> n (std::make_unique, nano::mdb_val::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast (end.c_str ())))); + nano::store_iterator, nano::no_value> i (std::make_unique, nano::no_value>> (transaction, handle, nano::mdb_val (beginning.size (), const_cast (beginning.c_str ())))); + nano::store_iterator, nano::no_value> n (std::make_unique, nano::no_value>> (transaction, handle, nano::mdb_val (end.size (), const_cast (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 (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, nano::mdb_val::no_value> i (std::make_unique, nano::mdb_val::no_value>> (transaction_source, handle, nano::mdb_val (beginning.size (), const_cast (beginning.c_str ())))); - nano::store_iterator, nano::mdb_val::no_value> n (std::make_unique, nano::mdb_val::no_value>> (transaction_source, handle, nano::mdb_val (end.size (), const_cast (end.c_str ())))); + nano::store_iterator, nano::no_value> i (std::make_unique, nano::no_value>> (transaction_source, handle, nano::mdb_val (beginning.size (), const_cast (beginning.c_str ())))); + nano::store_iterator, nano::no_value> n (std::make_unique, nano::no_value>> (transaction_source, handle, nano::mdb_val (end.size (), const_cast (end.c_str ())))); for (; i != n; ++i) { nano::uint256_union id; diff --git a/nano/secure/blockstore.hpp b/nano/secure/blockstore.hpp index 731cd64a..fa078a64 100644 --- a/nano/secure/blockstore.hpp +++ b/nano/secure/blockstore.hpp @@ -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 peers_begin (nano::transaction const & transaction_a) = 0; + virtual nano::store_iterator peers_end () = 0; + // Requires a write transaction virtual nano::raw_key get_node_id (nano::transaction const &) = 0; diff --git a/nano/secure/common.cpp b/nano/secure/common.cpp index 1f089044..7b21e642 100644 --- a/nano/secure/common.cpp +++ b/nano/secure/common.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -304,6 +305,21 @@ nano::block_hash nano::pending_key::key () const return account; } +nano::endpoint_key::endpoint_key (const std::array & address_a, uint16_t port_a) : +address (address_a), network_port (boost::endian::native_to_big (port_a)) +{ +} + +const std::array & 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) diff --git a/nano/secure/common.hpp b/nano/secure/common.hpp index fbae5a29..4137c2ed 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -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 & address_a, uint16_t port_a); + + /* + * @return The ipv6 address in network byte order + */ + const std::array & address_bytes () const; + + /* + * @return The port in host byte order + */ + uint16_t port () const; + +private: + // Both stored internally in network byte order + std::array 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;