diff --git a/nano/core_test/telemetry.cpp b/nano/core_test/telemetry.cpp index e49c623532..dc297f16fb 100644 --- a/nano/core_test/telemetry.cpp +++ b/nano/core_test/telemetry.cpp @@ -507,4 +507,27 @@ TEST (telemetry, ongoing_broadcasts) ASSERT_TIMELY (5s, node1.stats.count (nano::stat::type::telemetry, nano::stat::detail::process) >= 3); ASSERT_TIMELY (5s, node2.stats.count (nano::stat::type::telemetry, nano::stat::detail::process) >= 3) +} + +TEST (telemetry, mismatched_genesis) +{ + // Only second node will broadcast telemetry + nano::test::system system; + nano::node_flags node_flags; + node_flags.disable_ongoing_telemetry_requests = true; + node_flags.disable_providing_telemetry_metrics = true; + auto & node1 = *system.add_node (node_flags); + + // Set up a node with different genesis + nano::network_params network_params{ nano::networks::nano_dev_network }; + network_params.ledger.genesis = network_params.ledger.nano_live_genesis; + nano::node_config node_config{ network_params }; + node_flags.disable_providing_telemetry_metrics = false; + auto & node2 = *system.add_node (node_config, node_flags); + + ASSERT_TIMELY (5s, node1.stats.count (nano::stat::type::telemetry, nano::stat::detail::genesis_mismatch) > 0); + ASSERT_ALWAYS (1s, node1.stats.count (nano::stat::type::telemetry, nano::stat::detail::process) == 0) + + // Ensure node with different genesis gets disconnected + ASSERT_TIMELY (5s, !node1.network.find_node_id (node2.get_node_id ())); } \ No newline at end of file diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index 23a0c0b765..8d9d7c370c 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -226,6 +226,7 @@ enum class detail : uint8_t invalid_signature, different_genesis_hash, node_id_mismatch, + genesis_mismatch, request_within_protection_cache_zone, no_response_received, unsolicited_telemetry_ack, diff --git a/nano/node/network.cpp b/nano/node/network.cpp index d4a1975544..e5b697d3dd 100644 --- a/nano/node/network.cpp +++ b/nano/node/network.cpp @@ -7,6 +7,10 @@ #include +/* + * network + */ + nano::network::network (nano::node & node_a, uint16_t port_a) : id (nano::network_constants::active_network), syn_cookies (node_a.network_params.network.max_peers_per_ip), @@ -824,6 +828,19 @@ void nano::network::erase (nano::transport::channel const & channel_a) } } +void nano::network::exclude (std::shared_ptr const & channel) +{ + // Add to peer exclusion list + excluded_peers.add (channel->get_tcp_endpoint ()); + + // Disconnect + erase (*channel); +} + +/* + * message_buffer_manager + */ + nano::message_buffer_manager::message_buffer_manager (nano::stats & stats_a, std::size_t size, std::size_t count) : stats (stats_a), free (count), diff --git a/nano/node/network.hpp b/nano/node/network.hpp index fcfa32b254..a519611408 100644 --- a/nano/node/network.hpp +++ b/nano/node/network.hpp @@ -172,6 +172,9 @@ class network final float size_sqrt () const; bool empty () const; void erase (nano::transport::channel const &); + /** Disconnects and adds peer to exclusion list */ + void exclude (std::shared_ptr const & channel); + static std::string to_string (nano::networks); private: diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 6980872b32..43a403224f 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -36,11 +36,13 @@ class node_config public: node_config (nano::network_params & network_params = nano::dev::network_params); node_config (const std::optional &, nano::logging const &, nano::network_params & network_params = nano::dev::network_params); + nano::error serialize_toml (nano::tomlconfig &) const; nano::error deserialize_toml (nano::tomlconfig &); + bool upgrade_json (unsigned, nano::jsonconfig &); nano::account random_representative () const; - nano::network_params & network_params; + nano::network_params network_params; std::optional peering_port{}; nano::logging logging; std::vector> work_peers; diff --git a/nano/node/telemetry.cpp b/nano/node/telemetry.cpp index bf3459423f..5260fbfa0c 100644 --- a/nano/node/telemetry.cpp +++ b/nano/node/telemetry.cpp @@ -75,6 +75,14 @@ bool nano::telemetry::verify (const nano::telemetry_ack & telemetry, const std:: return false; } + if (telemetry.data.genesis_block != network_params.ledger.genesis->hash ()) + { + network.exclude (channel); + + stats.inc (nano::stat::type::telemetry, nano::stat::detail::genesis_mismatch); + return false; + } + return true; // Telemetry is OK }