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
This commit is contained in:
Sergey Kroshnin 2019-01-28 18:58:52 +03:00 committed by GitHub
commit 6f6506c259
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 28 deletions

View file

@ -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<std::string> ("[::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<std::string> (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<std::string> ("protocol_version"));
ASSERT_EQ (system.nodes[1]->node_id.pub.to_account (), tree1.get<std::string> ("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<std::string> ("protocol_version"));
ASSERT_EQ ("", tree2.get<std::string> ("node_id"));
}
TEST (rpc, pending)

View file

@ -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 ())

View file

@ -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<nano::account> 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::endpoint> nano::peer_container::list ()
return result;
}
std::map<nano::endpoint, unsigned> nano::peer_container::list_version ()
{
std::map<nano::endpoint, unsigned> result;
std::lock_guard<std::mutex> lock (mutex);
for (auto i (peers.begin ()), j (peers.end ()); i != j; ++i)
{
result.insert (std::pair<nano::endpoint, unsigned> (i->endpoint, i->network_version));
}
return result;
}
std::vector<nano::peer_information> nano::peer_container::list_vector (size_t count_a)
{
std::vector<peer_information> 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<nano::account> 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));
}
}
}

View file

@ -44,7 +44,7 @@ public:
class peer_information
{
public:
peer_information (nano::endpoint const &, unsigned);
peer_information (nano::endpoint const &, unsigned, boost::optional<nano::account> = 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<nano::account> 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<nano::account> = boost::none);
std::unordered_set<nano::endpoint> random_set (size_t);
void random_fill (std::array<nano::endpoint, 8> &);
// Request a list of the top known representatives
std::vector<peer_information> representatives (size_t);
// List of all peers
std::deque<nano::endpoint> list ();
std::map<nano::endpoint, unsigned> list_version ();
std::vector<peer_information> list_vector (size_t);
// A list of random peers sized for the configured rebroadcast fanout
std::deque<nano::endpoint> list_fanout ();

View file

@ -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<bool> ("deprecated", false);
auto peers_list (node.peers.list_vector (std::numeric_limits<size_t>::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 ();

View file

@ -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<size_t>::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<QStandardItem *> 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 ()));