Node ID persistence (#3816)
* Node ID persistence After this change, node IDs will persist on the disk file system and reused. The node ID will not be changing after every restart. This will help to more reliably track PRs. The node can be forced to generate a new ID by deleting the file: node_id_private.key Note that this change does not prevent the man in the middle attack. However, it makes it possible to detect telemetry spoofing. Sites like nanolooker and nanoticker can maintain associations between node ID and PR and only accept a telemetry packet, if the telemetry message is signed by the known Node ID. Co-authored-by: clemahieu <clemahieu@gmail.com>
This commit is contained in:
parent
32a3222849
commit
53154c0cf2
3 changed files with 58 additions and 1 deletions
|
@ -11,6 +11,7 @@
|
|||
#include <boost/make_shared.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
@ -4472,3 +4473,30 @@ TEST (node, pruning_depth)
|
|||
ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send1->hash ()));
|
||||
ASSERT_TRUE (node1.ledger.block_or_pruned_exists (send2->hash ()));
|
||||
}
|
||||
|
||||
TEST (node_config, node_id_private_key_persistence)
|
||||
{
|
||||
nano::logger_mt logger;
|
||||
|
||||
// create the directory and the file
|
||||
auto path = nano::unique_path ();
|
||||
ASSERT_TRUE (boost::filesystem::create_directories (path));
|
||||
auto priv_key_filename = path / "node_id_private.key";
|
||||
|
||||
// check that the key generated is random when the key does not exist
|
||||
nano::keypair kp1 = nano::load_or_create_node_id (path, logger);
|
||||
boost::filesystem::remove (priv_key_filename);
|
||||
nano::keypair kp2 = nano::load_or_create_node_id (path, logger);
|
||||
ASSERT_NE (kp1.prv, kp2.prv);
|
||||
|
||||
// check that the key persists
|
||||
nano::keypair kp3 = nano::load_or_create_node_id (path, logger);
|
||||
ASSERT_EQ (kp2.prv, kp3.prv);
|
||||
|
||||
// write the key file manually and check that right key is loaded
|
||||
std::ofstream ofs (priv_key_filename.string (), std::ofstream::out | std::ofstream::trunc);
|
||||
ofs << "3F28D035B8AA75EA53DF753BFD065CF6138E742971B2C99B84FD8FE328FED2D9" << std::flush;
|
||||
ofs.close ();
|
||||
nano::keypair kp4 = nano::load_or_create_node_id (path, logger);
|
||||
ASSERT_EQ (kp4.prv, nano::keypair ("3F28D035B8AA75EA53DF753BFD065CF6138E742971B2C99B84FD8FE328FED2D9").prv);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <future>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -74,6 +75,33 @@ std::unique_ptr<nano::container_info_component> nano::collect_container_info (re
|
|||
return composite;
|
||||
}
|
||||
|
||||
nano::keypair nano::load_or_create_node_id (boost::filesystem::path const & application_path, nano::logger_mt & logger)
|
||||
{
|
||||
auto node_private_key_path = application_path / "node_id_private.key";
|
||||
std::ifstream ifs (node_private_key_path.c_str ());
|
||||
if (ifs.good ())
|
||||
{
|
||||
logger.always_log (boost::str (boost::format ("%1% exists, reading node id from it") % node_private_key_path.string ()));
|
||||
std::string node_private_key;
|
||||
ifs >> node_private_key;
|
||||
release_assert (node_private_key.size () == 64);
|
||||
nano::keypair kp = nano::keypair (node_private_key);
|
||||
return kp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no node_id found, generate new one
|
||||
logger.always_log (boost::str (boost::format ("%1% does not exist, creating a new node_id") % node_private_key_path.string ()));
|
||||
nano::keypair kp;
|
||||
std::ofstream ofs (node_private_key_path.c_str (), std::ofstream::out | std::ofstream::trunc);
|
||||
ofs << kp.prv.to_string () << std::endl
|
||||
<< std::flush;
|
||||
ofs.close ();
|
||||
release_assert (!ofs.fail ());
|
||||
return kp;
|
||||
}
|
||||
}
|
||||
|
||||
nano::node::node (boost::asio::io_context & io_ctx_a, uint16_t peering_port_a, boost::filesystem::path const & application_path_a, nano::logging const & logging_a, nano::work_pool & work_a, nano::node_flags flags_a, unsigned seq) :
|
||||
node (io_ctx_a, application_path_a, nano::node_config (peering_port_a, logging_a), work_a, flags_a, seq)
|
||||
{
|
||||
|
@ -395,7 +423,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, boost::filesystem::path co
|
|||
logger.always_log (stream.str ());
|
||||
}
|
||||
|
||||
node_id = nano::keypair ();
|
||||
node_id = nano::load_or_create_node_id (application_path, logger);
|
||||
logger.always_log ("Node ID: ", node_id.pub.to_node_id ());
|
||||
|
||||
if ((network_params.network.is_live_network () || network_params.network.is_beta_network ()) && !flags.inactive_node)
|
||||
|
|
|
@ -219,6 +219,7 @@ private:
|
|||
nano::locked<std::future<void>> epoch_upgrading;
|
||||
};
|
||||
|
||||
nano::keypair load_or_create_node_id (boost::filesystem::path const & application_path, nano::logger_mt & logger);
|
||||
std::unique_ptr<container_info_component> collect_container_info (node & node, std::string const & name);
|
||||
|
||||
nano::node_flags const & inactive_node_flag_defaults ();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue