diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 11721ee7..71592d5b 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -11,6 +11,7 @@ #include #include +#include #include 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); +} diff --git a/nano/node/node.cpp b/nano/node/node.cpp index edefe8e5..7a11e2fd 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -74,6 +75,33 @@ std::unique_ptr 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) diff --git a/nano/node/node.hpp b/nano/node/node.hpp index bf1c46dc..7e7dd66d 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -219,6 +219,7 @@ private: nano::locked> epoch_upgrading; }; +nano::keypair load_or_create_node_id (boost::filesystem::path const & application_path, nano::logger_mt & logger); std::unique_ptr collect_container_info (node & node, std::string const & name); nano::node_flags const & inactive_node_flag_defaults ();