From 6f6506c259bb55cd68344be74bc73daa0667e903 Mon Sep 17 00:00:00 2001 From: Sergey Kroshnin Date: Mon, 28 Jan 2019 18:58:52 +0300 Subject: [PATCH] Node ID in RPC & QT wallet peers list (#946) * Add node_id field in RPC peers Breaking old style endpoint: version * Node ID in QT wallet peers list * Optonal "deprecated" RPC peers To return old style * Fix * fix merge artifacts * Add peer_information comparision operator * Optional node_id for peer_container::insert * Test rpc.peers_node_id * Fix * Rename version to protocol_version --- nano/core_test/rpc.cpp | 37 ++++++++++++++++++++++++++++++++++++- nano/node/node.cpp | 2 +- nano/node/peers.cpp | 30 ++++++++++++++---------------- nano/node/peers.hpp | 6 +++--- nano/node/rpc.cpp | 25 ++++++++++++++++++++++--- nano/qt/qt.cpp | 16 ++++++++++++---- 6 files changed, 88 insertions(+), 28 deletions(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index a860a740..2e896c0e 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -1533,7 +1533,34 @@ TEST (rpc, payment_wait) TEST (rpc, peers) { nano::system system (24000, 2); - system.nodes[0]->peers.insert (nano::endpoint (boost::asio::ip::address_v6::from_string ("::ffff:80.80.80.80"), 4000), nano::protocol_version); + nano::endpoint endpoint (boost::asio::ip::address_v6::from_string ("fc00::1"), 4000); + system.nodes[0]->peers.insert (endpoint, nano::protocol_version); + nano::rpc rpc (system.io_ctx, *system.nodes[0], nano::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + request.put ("action", "peers"); + request.put ("deprecated", true); + test_response response (request, rpc, system.io_ctx); + system.deadline_set (5s); + while (response.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + ASSERT_EQ (200, response.status); + auto & peers_node (response.json.get_child ("peers")); + ASSERT_EQ (2, peers_node.size ()); + ASSERT_EQ (std::to_string (nano::protocol_version), peers_node.get ("[::1]:24001")); + // Previously "[::ffff:80.80.80.80]:4000", but IPv4 address cause "No such node thrown in the test body" issue with peers_node.get + std::stringstream endpoint_text; + endpoint_text << endpoint; + ASSERT_EQ (std::to_string (nano::protocol_version), peers_node.get (endpoint_text.str ())); +} + +TEST (rpc, peers_node_id) +{ + nano::system system (24000, 2); + nano::endpoint endpoint (boost::asio::ip::address_v6::from_string ("fc00::1"), 4000); + system.nodes[0]->peers.insert (endpoint, nano::protocol_version); nano::rpc rpc (system.io_ctx, *system.nodes[0], nano::rpc_config (true)); rpc.start (); boost::property_tree::ptree request; @@ -1547,6 +1574,14 @@ TEST (rpc, peers) ASSERT_EQ (200, response.status); auto & peers_node (response.json.get_child ("peers")); ASSERT_EQ (2, peers_node.size ()); + auto tree1 (peers_node.get_child ("[::1]:24001")); + ASSERT_EQ (std::to_string (nano::protocol_version), tree1.get ("protocol_version")); + ASSERT_EQ (system.nodes[1]->node_id.pub.to_account (), tree1.get ("node_id")); + std::stringstream endpoint_text; + endpoint_text << endpoint; + auto tree2 (peers_node.get_child (endpoint_text.str ())); + ASSERT_EQ (std::to_string (nano::protocol_version), tree2.get ("protocol_version")); + ASSERT_EQ ("", tree2.get ("node_id")); } TEST (rpc, pending) diff --git a/nano/node/node.cpp b/nano/node/node.cpp index a3807c97..99acbdc6 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -590,7 +590,7 @@ public: validated_response = true; if (message_a.response->first != node.node_id.pub) { - node.peers.insert (endpoint_l, message_a.header.version_using); + node.peers.insert (endpoint_l, message_a.header.version_using, false, message_a.response->first); } } else if (node.config.logging.network_node_id_handshake_logging ()) diff --git a/nano/node/peers.cpp b/nano/node/peers.cpp index 84e20bd6..404fd877 100644 --- a/nano/node/peers.cpp +++ b/nano/node/peers.cpp @@ -10,7 +10,7 @@ nano::endpoint nano::map_endpoint_to_v6 (nano::endpoint const & endpoint_a) return endpoint_l; } -nano::peer_information::peer_information (nano::endpoint const & endpoint_a, unsigned network_version_a) : +nano::peer_information::peer_information (nano::endpoint const & endpoint_a, unsigned network_version_a, boost::optional node_id_a) : endpoint (endpoint_a), ip_address (endpoint_a.address ()), last_contact (std::chrono::steady_clock::now ()), @@ -20,7 +20,7 @@ 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 (node_id_a) { } @@ -38,6 +38,11 @@ node_id () { } +bool nano::peer_information::operator< (nano::peer_information const & peer_information_a) const +{ + return endpoint < peer_information_a.endpoint; +} + nano::peer_container::peer_container (nano::endpoint const & self_a) : self (self_a), peer_observer ([](nano::endpoint const &) {}), @@ -107,17 +112,6 @@ std::deque nano::peer_container::list () return result; } -std::map nano::peer_container::list_version () -{ - std::map result; - std::lock_guard lock (mutex); - for (auto i (peers.begin ()), j (peers.end ()); i != j; ++i) - { - result.insert (std::pair (i->endpoint, i->network_version)); - } - return result; -} - std::vector nano::peer_container::list_vector (size_t count_a) { std::vector result; @@ -443,7 +437,7 @@ bool nano::peer_container::reachout (nano::endpoint const & endpoint_a) return error; } -bool nano::peer_container::insert (nano::endpoint const & endpoint_a, unsigned version_a, bool preconfigured_a) +bool nano::peer_container::insert (nano::endpoint const & endpoint_a, unsigned version_a, bool preconfigured_a, boost::optional node_id_a) { assert (endpoint_a.address ().is_v6 ()); auto unknown (false); @@ -456,8 +450,12 @@ bool nano::peer_container::insert (nano::endpoint const & endpoint_a, unsigned v auto existing (peers.find (endpoint_a)); if (existing != peers.end ()) { - peers.modify (existing, [](nano::peer_information & info) { + peers.modify (existing, [node_id_a](nano::peer_information & info) { info.last_contact = std::chrono::steady_clock::now (); + if (node_id_a.is_initialized ()) + { + info.node_id = node_id_a; + } }); result = true; } @@ -474,7 +472,7 @@ bool nano::peer_container::insert (nano::endpoint const & endpoint_a, unsigned v } if (!result) { - peers.insert (nano::peer_information (endpoint_a, version_a)); + peers.insert (nano::peer_information (endpoint_a, version_a, node_id_a)); } } } diff --git a/nano/node/peers.hpp b/nano/node/peers.hpp index b2c2a657..2108c5ba 100644 --- a/nano/node/peers.hpp +++ b/nano/node/peers.hpp @@ -44,7 +44,7 @@ public: class peer_information { public: - peer_information (nano::endpoint const &, unsigned); + peer_information (nano::endpoint const &, unsigned, boost::optional = boost::none); peer_information (nano::endpoint const &, std::chrono::steady_clock::time_point const &, std::chrono::steady_clock::time_point const &); nano::endpoint endpoint; boost::asio::ip::address ip_address; @@ -57,6 +57,7 @@ public: nano::account probable_rep_account; unsigned network_version; boost::optional node_id; + bool operator< (nano::peer_information const &) const; }; /** Manages a set of disovered peers */ @@ -72,14 +73,13 @@ public: // Returns true if peer was already known bool known_peer (nano::endpoint const &); // Notify of peer we received from - bool insert (nano::endpoint const &, unsigned, bool = false); + bool insert (nano::endpoint const &, unsigned, bool = false, boost::optional = boost::none); std::unordered_set random_set (size_t); void random_fill (std::array &); // Request a list of the top known representatives std::vector representatives (size_t); // List of all peers std::deque list (); - std::map list_version (); std::vector list_vector (size_t); // A list of random peers sized for the configured rebroadcast fanout std::deque list_fanout (); diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index 3e997d38..543ddd83 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -2206,12 +2206,31 @@ void nano::rpc_handler::password_valid (bool wallet_locked) void nano::rpc_handler::peers () { boost::property_tree::ptree peers_l; - auto peers_list (node.peers.list_version ()); + const bool deprecated = request.get ("deprecated", false); + auto peers_list (node.peers.list_vector (std::numeric_limits::max ())); + std::sort (peers_list.begin (), peers_list.end ()); for (auto i (peers_list.begin ()), n (peers_list.end ()); i != n; ++i) { std::stringstream text; - text << i->first; - peers_l.push_back (boost::property_tree::ptree::value_type (text.str (), boost::property_tree::ptree (std::to_string (i->second)))); + text << i->endpoint; + if (!deprecated) + { + boost::property_tree::ptree pending_tree; + pending_tree.put ("protocol_version", std::to_string (i->network_version)); + if (i->node_id.is_initialized ()) + { + pending_tree.put ("node_id", i->node_id.get ().to_account ()); + } + else + { + pending_tree.put ("node_id", ""); + } + peers_l.push_back (boost::property_tree::ptree::value_type (text.str (), pending_tree)); + } + else + { + peers_l.push_back (boost::property_tree::ptree::value_type (text.str (), boost::property_tree::ptree (std::to_string (i->network_version)))); + } } response_l.add_child ("peers", peers_l); response_errors (); diff --git a/nano/qt/qt.cpp b/nano/qt/qt.cpp index 6611e316..3d640fc5 100644 --- a/nano/qt/qt.cpp +++ b/nano/qt/qt.cpp @@ -1789,6 +1789,7 @@ wallet (wallet_a) peers_model->setHorizontalHeaderItem (0, new QStandardItem ("IPv6 address:port")); peers_model->setHorizontalHeaderItem (1, new QStandardItem ("Net version")); + peers_model->setHorizontalHeaderItem (2, new QStandardItem ("Node ID")); peers_view->setEditTriggers (QAbstractItemView::NoEditTriggers); peers_view->verticalHeader ()->hide (); peers_view->setModel (peers_model); @@ -1927,19 +1928,26 @@ wallet (wallet_a) void nano_qt::advanced_actions::refresh_peers () { peers_model->removeRows (0, peers_model->rowCount ()); - auto list (wallet.node.peers.list_version ()); + auto list (wallet.node.peers.list_vector (std::numeric_limits::max ())); + std::sort (list.begin (), list.end ()); for (auto i (list.begin ()), n (list.end ()); i != n; ++i) { std::stringstream endpoint; - endpoint << i->first.address ().to_string (); + endpoint << i->endpoint.address ().to_string (); endpoint << ':'; - endpoint << i->first.port (); + endpoint << i->endpoint.port (); QString qendpoint (endpoint.str ().c_str ()); QList items; items.push_back (new QStandardItem (qendpoint)); auto version = new QStandardItem (); - version->setData (QVariant (i->second), Qt::DisplayRole); + version->setData (QVariant (i->network_version), Qt::DisplayRole); items.push_back (version); + QString node_id (""); + if (i->node_id.is_initialized ()) + { + node_id = i->node_id.get ().to_account ().c_str (); + } + items.push_back (new QStandardItem (node_id)); peers_model->appendRow (items); } peer_count_label->setText (QString ("%1 peers").arg (peers_model->rowCount ()));