From 1d2ae2138a85dd93bc8a0d2c55513c5b5ba4658f Mon Sep 17 00:00:00 2001 From: Jeetraj Date: Thu, 9 Apr 2026 11:05:47 +0530 Subject: [PATCH] p2p: isolate regtest from mainnet bootstrap state --- src/cryptonote_core/cryptonote_core.cpp | 14 ++-- src/cryptonote_core/cryptonote_core.h | 2 +- src/p2p/net_node.inl | 7 +- tests/unit_tests/node_server.cpp | 105 ++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 627f11450..4bada999f 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -97,16 +97,18 @@ namespace cryptonote , "Fixed difficulty used for testing." , 0 }; - const command_line::arg_descriptor arg_data_dir = { + const command_line::arg_descriptor arg_data_dir = { "data-dir" , "Specify data directory" , tools::get_default_data_dir() - , {{ &arg_testnet_on, &arg_stagenet_on }} - , [](std::array testnet_stagenet, bool defaulted, std::string val)->std::string { - if (testnet_stagenet[0]) + , {{ &arg_testnet_on, &arg_stagenet_on, &arg_regtest_on }} + , [](std::array nets, bool defaulted, std::string val)->std::string { + if (nets[0]) return (boost::filesystem::path(val) / "testnet").string(); - else if (testnet_stagenet[1]) + else if (nets[1]) return (boost::filesystem::path(val) / "stagenet").string(); + else if (nets[2]) + return (boost::filesystem::path(val) / "fake").string(); return val; } }; @@ -474,8 +476,6 @@ namespace cryptonote bool keep_fakechain = command_line::get_arg(vm, arg_keep_fakechain); boost::filesystem::path folder(m_config_folder); - if (m_nettype == FAKECHAIN) - folder /= "fake"; // make sure the data directory exists, and try to lock it CHECK_AND_ASSERT_MES (boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false, diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index f1339dbb9..7806fe495 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -63,7 +63,7 @@ namespace cryptonote const size_t long_term_block_weight_window; }; - extern const command_line::arg_descriptor arg_data_dir; + extern const command_line::arg_descriptor arg_data_dir; extern const command_line::arg_descriptor arg_testnet_on; extern const command_line::arg_descriptor arg_stagenet_on; extern const command_line::arg_descriptor arg_regtest_on; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 058bd457b..943061814 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -431,8 +431,9 @@ namespace nodetool { bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + bool regtest = command_line::get_arg(vm, cryptonote::arg_regtest_on); const bool pad_txs = command_line::get_arg(vm, arg_pad_transactions); - m_nettype = testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET; + m_nettype = testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : regtest ? cryptonote::FAKECHAIN : cryptonote::MAINNET; network_zone& public_zone = m_network_zones[epee::net_utils::zone::public_]; public_zone.m_connect = &public_connect; @@ -777,6 +778,10 @@ namespace nodetool { return get_ip_seed_nodes(); } + if (m_nettype == cryptonote::FAKECHAIN) + { + return {}; + } if (!m_enable_dns_seed_nodes) { // TODO: a domain can be set through socks, so that the remote side does the lookup for the DNS seed nodes. diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp index e55b43911..63665c4ea 100644 --- a/tests/unit_tests/node_server.cpp +++ b/tests/unit_tests/node_server.cpp @@ -132,6 +132,69 @@ static bool is_blocked(Server &server, const epee::net_utils::network_address &a return false; } +namespace +{ + using path_t = boost::filesystem::path; + using ec_t = boost::system::error_code; + + path_t create_temp_dir(const char* pattern) + { + ec_t ec; + path_t path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(pattern, ec); + if (ec) + return path_t{}; + + const bool success = boost::filesystem::create_directory(path, ec); + if (!ec && success) + return path; + + return path_t{}; + } + + void remove_tree(const path_t& path) + { + ec_t ec; + boost::filesystem::remove_all(path, ec); + } + + boost::program_options::variables_map make_regtest_options(const path_t& dir) + { + boost::program_options::options_description desc; + cryptonote::core::init_options(desc); + Server::init_options(desc); + + std::vector args{ + "--regtest", + "--p2p-bind-ip=127.0.0.1", + "--no-igd", + "--out-peers=0", + "--in-peers=0", + "--data-dir", + dir.string(), + "--check-updates=disabled", + "--disable-dns-checkpoints", + "--offline", + }; + + boost::program_options::variables_map vm; + boost::program_options::store( + boost::program_options::command_line_parser(args).options(desc).run(), + vm + ); + boost::program_options::notify(vm); + return vm; + } + + nodetool::peerlist_entry make_peer(const epee::net_utils::network_address& address, const nodetool::peerid_type id, const int64_t last_seen) + { + nodetool::peerlist_entry peer = AUTO_VAL_INIT(peer); + peer.adr = address; + peer.id = id; + peer.last_seen = last_seen; + return peer; + } +} + TEST(ban, add) { test_core pr_core; @@ -1269,5 +1332,47 @@ TEST(node_server, race_condition) remove_tree(dir); } +TEST(regtest, isolates_p2p_state_from_mainnet_data_dir) +{ + const path_t dir = create_temp_dir("regtest-%%%%%%%%%%%%%%%%"); + ASSERT_TRUE(!dir.empty()); + auto cleanup = epee::misc_utils::create_scope_leave_handler([&dir]{ + remove_tree(dir); + }); + + nodetool::peerlist_types peers{}; + peers.white.push_back(make_peer(MAKE_IPV4_ADDRESS_PORT(11, 22, 33, 44, 18080), 1, 100)); + peers.gray.push_back(make_peer(MAKE_IPV4_ADDRESS_PORT(55, 66, 77, 88, 18080), 2, 200)); + + const path_t mainnet_state = dir / P2P_NET_DATA_FILENAME; + ASSERT_TRUE(nodetool::peerlist_storage{}.store(mainnet_state.string(), peers)); + + test_core pr_core; + cryptonote::t_cryptonote_protocol_handler cprotocol(pr_core, NULL); + Server server(cprotocol); + cprotocol.set_p2p_endpoint(&server); + + const auto vm = make_regtest_options(dir); + ASSERT_TRUE(server.init(vm)); + ASSERT_EQ(0u, server.get_public_white_peers_count()); + ASSERT_EQ(0u, server.get_public_gray_peers_count()); + ASSERT_TRUE(server.deinit()); + + const path_t regtest_state = dir / "fake" / P2P_NET_DATA_FILENAME; + ASSERT_TRUE(boost::filesystem::exists(regtest_state)); + + auto base_storage = nodetool::peerlist_storage::open(mainnet_state.string()); + ASSERT_TRUE(bool(base_storage)); + nodetool::peerlist_types base_public = base_storage->take_zone(epee::net_utils::zone::public_); + EXPECT_EQ(1u, base_public.white.size()); + EXPECT_EQ(1u, base_public.gray.size()); + + auto regtest_storage = nodetool::peerlist_storage::open(regtest_state.string()); + ASSERT_TRUE(bool(regtest_storage)); + nodetool::peerlist_types regtest_public = regtest_storage->take_zone(epee::net_utils::zone::public_); + EXPECT_TRUE(regtest_public.white.empty()); + EXPECT_TRUE(regtest_public.gray.empty()); +} + namespace nodetool { template class node_server>; } namespace cryptonote { template class t_cryptonote_protocol_handler; }