diff --git a/nano/core_test/message.cpp b/nano/core_test/message.cpp index 60d2338218..e5c08adc20 100644 --- a/nano/core_test/message.cpp +++ b/nano/core_test/message.cpp @@ -441,7 +441,7 @@ TEST (message, confirm_req_hash_batch_serialization_v2) /** * Test that a confirm_ack can encode an empty hash set */ -TEST (confirm_ack, empty_vote_hashes) +TEST (message, confirm_ack_empty_vote_hashes) { nano::keypair key; auto vote = std::make_shared (key.pub, key.prv, 0, 0, std::vector{} /* empty */); @@ -833,7 +833,7 @@ TEST (message, node_id_handshake_response_v2_serialization) ASSERT_TRUE (nano::at_end (stream)); } -TEST (handshake, signature) +TEST (message, handshake_signature) { nano::keypair node_id{}; nano::keypair node_id_2{}; @@ -853,7 +853,7 @@ TEST (handshake, signature) ASSERT_FALSE (response.validate (cookie)); } -TEST (handshake, signature_v2) +TEST (message, handshake_signature_v2) { nano::keypair node_id{}; nano::keypair node_id_2{}; @@ -895,3 +895,69 @@ TEST (handshake, signature_v2) ASSERT_FALSE (message.validate (cookie)); } } + +TEST (message, telemetry_data_serialization) +{ + nano::telemetry_data original; + original.node_id = nano::account{ 11111 }; + original.account_count = 22222; + original.block_count = 33333; + original.cemented_count = 44444; + original.bandwidth_cap = 55555; + original.account_count = 66666; + original.bandwidth_cap = 77777; + original.uptime = 88888; + original.peer_count = 99999; + original.protocol_version = 1; + original.genesis_block = nano::block_hash{ 22222 }; + original.major_version = 4; + original.minor_version = 3; + original.patch_version = 2; + original.pre_release_version = 1; + original.maker = nano::telemetry_maker::nf_pruned_node; + original.timestamp = std::chrono::system_clock::time_point{ 123456789s }; + original.active_difficulty = 42; + original.database_backend = nano::telemetry_backend::rocksdb; + original.database_version_major = 3; + original.database_version_minor = 2; + original.database_version_patch = 1; + + // Serialize + std::vector bytes; + { + nano::vectorstream stream{ bytes }; + original.serialize (stream); + } + nano::bufferstream stream{ bytes.data (), bytes.size () }; + + nano::telemetry_data telemetry; + ASSERT_NO_THROW (telemetry.deserialize (stream, bytes.size ())); + + // Compare + ASSERT_EQ (original.node_id, telemetry.node_id); + ASSERT_EQ (original.account_count, telemetry.account_count); + ASSERT_EQ (original.block_count, telemetry.block_count); + ASSERT_EQ (original.cemented_count, telemetry.cemented_count); + ASSERT_EQ (original.bandwidth_cap, telemetry.bandwidth_cap); + ASSERT_EQ (original.account_count, telemetry.account_count); + ASSERT_EQ (original.bandwidth_cap, telemetry.bandwidth_cap); + ASSERT_EQ (original.uptime, telemetry.uptime); + ASSERT_EQ (original.peer_count, telemetry.peer_count); + ASSERT_EQ (original.protocol_version, telemetry.protocol_version); + ASSERT_EQ (original.genesis_block, telemetry.genesis_block); + ASSERT_EQ (original.major_version, telemetry.major_version); + ASSERT_EQ (original.minor_version, telemetry.minor_version); + ASSERT_EQ (original.patch_version, telemetry.patch_version); + ASSERT_EQ (original.pre_release_version, telemetry.pre_release_version); + ASSERT_EQ (original.maker, telemetry.maker); + ASSERT_EQ (original.timestamp, telemetry.timestamp); + ASSERT_EQ (original.active_difficulty, telemetry.active_difficulty); + ASSERT_EQ (original.database_backend, telemetry.database_backend); + ASSERT_EQ (original.database_version_major, telemetry.database_version_major); + ASSERT_EQ (original.database_version_minor, telemetry.database_version_minor); + ASSERT_EQ (original.database_version_patch, telemetry.database_version_patch); + ASSERT_EQ (original, telemetry); + + ASSERT_EQ (nano::telemetry_data::size, bytes.size ()); + ASSERT_TRUE (nano::at_end (stream)); +} \ No newline at end of file diff --git a/nano/core_test/telemetry.cpp b/nano/core_test/telemetry.cpp index aafb6dda71..142db6db99 100644 --- a/nano/core_test/telemetry.cpp +++ b/nano/core_test/telemetry.cpp @@ -19,13 +19,13 @@ TEST (telemetry, signatures) data.minor_version = 1; data.patch_version = 5; data.pre_release_version = 2; - data.maker = 1; + data.maker = nano::telemetry_maker::nf_pruned_node; data.timestamp = std::chrono::system_clock::time_point (100ms); data.sign (node_id); ASSERT_FALSE (data.validate_signature ()); auto signature = data.signature; // Check that the signature is different if changing a piece of data - data.maker = 2; + data.maker = nano::telemetry_maker::nf_node; data.sign (node_id); ASSERT_NE (data.signature, signature); } @@ -39,7 +39,6 @@ TEST (telemetry, unknown_data) data.minor_version = 1; data.patch_version = 5; data.pre_release_version = 2; - data.maker = 1; data.timestamp = std::chrono::system_clock::time_point (100ms); data.unknown_data.push_back (1); data.sign (node_id); @@ -209,7 +208,7 @@ TEST (telemetry, max_possible_size) auto node_server = system.add_node (node_flags); nano::telemetry_data data; - data.unknown_data.resize (nano::message_header::telemetry_size_mask.to_ulong () - nano::telemetry_data::latest_size); + data.unknown_data.resize (nano::message_header::telemetry_size_mask.to_ulong () - nano::telemetry_data::size); nano::telemetry_ack message{ nano::dev::network_params.network, data }; nano::test::wait_peer_connections (system); diff --git a/nano/node/messages.cpp b/nano/node/messages.cpp index 0143a62b2e..5ac44fca38 100644 --- a/nano/node/messages.cpp +++ b/nano/node/messages.cpp @@ -1036,14 +1036,13 @@ bool nano::telemetry_ack::deserialize (nano::stream & stream_a) { if (!is_empty_payload ()) { - data.deserialize (stream_a, nano::narrow_cast (header.extensions.to_ulong ())); + data.deserialize (stream_a, size ()); } } catch (std::runtime_error const &) { - error = true; + // Ignore deserialization errors for backwards compatibility } - return error; } @@ -1081,74 +1080,106 @@ void nano::telemetry_ack::operator() (nano::object_stream & obs) const * telemetry_data */ -void nano::telemetry_data::deserialize (nano::stream & stream_a, uint16_t payload_length_a) +void nano::telemetry_data::deserialize (nano::stream & stream, uint16_t payload_length) { - read (stream_a, signature); - read (stream_a, node_id); - read (stream_a, block_count); + version = version_t::unknown; + + read (stream, signature); + + read (stream, node_id); + read (stream, block_count); boost::endian::big_to_native_inplace (block_count); - read (stream_a, cemented_count); + read (stream, cemented_count); boost::endian::big_to_native_inplace (cemented_count); - read (stream_a, unchecked_count); + read (stream, unchecked_count); boost::endian::big_to_native_inplace (unchecked_count); - read (stream_a, account_count); + read (stream, account_count); boost::endian::big_to_native_inplace (account_count); - read (stream_a, bandwidth_cap); + read (stream, bandwidth_cap); boost::endian::big_to_native_inplace (bandwidth_cap); - read (stream_a, peer_count); + read (stream, peer_count); boost::endian::big_to_native_inplace (peer_count); - read (stream_a, protocol_version); - read (stream_a, uptime); + read (stream, protocol_version); + read (stream, uptime); boost::endian::big_to_native_inplace (uptime); - read (stream_a, genesis_block.bytes); - read (stream_a, major_version); - read (stream_a, minor_version); - read (stream_a, patch_version); - read (stream_a, pre_release_version); - read (stream_a, maker); + read (stream, genesis_block.bytes); + read (stream, major_version); + read (stream, minor_version); + read (stream, patch_version); + read (stream, pre_release_version); + + uint8_t maker_l; + read (stream, maker_l); + maker = static_cast (maker_l); uint64_t timestamp_l; - read (stream_a, timestamp_l); + read (stream, timestamp_l); boost::endian::big_to_native_inplace (timestamp_l); timestamp = std::chrono::system_clock::time_point (std::chrono::milliseconds (timestamp_l)); - read (stream_a, active_difficulty); + + read (stream, active_difficulty); boost::endian::big_to_native_inplace (active_difficulty); - if (payload_length_a > latest_size) + + version = version_t::v1; + + // Added in V27, will throw if not present + uint8_t database_backend_l; + read (stream, database_backend_l); + database_backend = static_cast (database_backend_l); + + read (stream, database_version_major); + read (stream, database_version_minor); + read (stream, database_version_patch); + + version = version_t::v2; + + if (payload_length > size) { - read (stream_a, unknown_data, payload_length_a - latest_size); + read (stream, unknown_data, payload_length - size); } } -void nano::telemetry_data::serialize_without_signature (nano::stream & stream_a) const +void nano::telemetry_data::serialize_without_signature (nano::stream & stream) const { // All values should be serialized in big endian - write (stream_a, node_id); - write (stream_a, boost::endian::native_to_big (block_count)); - write (stream_a, boost::endian::native_to_big (cemented_count)); - write (stream_a, boost::endian::native_to_big (unchecked_count)); - write (stream_a, boost::endian::native_to_big (account_count)); - write (stream_a, boost::endian::native_to_big (bandwidth_cap)); - write (stream_a, boost::endian::native_to_big (peer_count)); - write (stream_a, protocol_version); - write (stream_a, boost::endian::native_to_big (uptime)); - write (stream_a, genesis_block.bytes); - write (stream_a, major_version); - write (stream_a, minor_version); - write (stream_a, patch_version); - write (stream_a, pre_release_version); - write (stream_a, maker); - write (stream_a, boost::endian::native_to_big (std::chrono::duration_cast (timestamp.time_since_epoch ()).count ())); - write (stream_a, boost::endian::native_to_big (active_difficulty)); - write (stream_a, unknown_data); -} - -void nano::telemetry_data::serialize (nano::stream & stream_a) const -{ - write (stream_a, signature); - serialize_without_signature (stream_a); -} - -nano::error nano::telemetry_data::serialize_json (nano::jsonconfig & json, bool ignore_identification_metrics_a) const + write (stream, node_id); + write (stream, boost::endian::native_to_big (block_count)); + write (stream, boost::endian::native_to_big (cemented_count)); + write (stream, boost::endian::native_to_big (unchecked_count)); + write (stream, boost::endian::native_to_big (account_count)); + write (stream, boost::endian::native_to_big (bandwidth_cap)); + write (stream, boost::endian::native_to_big (peer_count)); + write (stream, protocol_version); + write (stream, boost::endian::native_to_big (uptime)); + write (stream, genesis_block.bytes); + write (stream, major_version); + write (stream, minor_version); + write (stream, patch_version); + write (stream, pre_release_version); + write (stream, static_cast> (maker)); + write (stream, boost::endian::native_to_big (std::chrono::duration_cast (timestamp.time_since_epoch ()).count ())); + write (stream, boost::endian::native_to_big (active_difficulty)); + + if (version == version_t::v1) + { + return; + } + + write (stream, static_cast> (database_backend)); + write (stream, database_version_major); + write (stream, database_version_minor); + write (stream, database_version_patch); + + write (stream, unknown_data); +} + +void nano::telemetry_data::serialize (nano::stream & stream) const +{ + write (stream, signature); + serialize_without_signature (stream); +} + +nano::error nano::telemetry_data::serialize_json (nano::jsonconfig & json, bool ignore_identification_metrics) const { json.put ("block_count", block_count); json.put ("cemented_count", cemented_count); @@ -1163,11 +1194,15 @@ nano::error nano::telemetry_data::serialize_json (nano::jsonconfig & json, bool json.put ("minor_version", minor_version); json.put ("patch_version", patch_version); json.put ("pre_release_version", pre_release_version); - json.put ("maker", maker); + json.put ("maker", to_string (maker)); json.put ("timestamp", std::chrono::duration_cast (timestamp.time_since_epoch ()).count ()); json.put ("active_difficulty", nano::to_string_hex (active_difficulty)); + json.put ("database_backend", to_string (database_backend)); + json.put ("database_version_major", database_version_major); + json.put ("database_version_minor", database_version_minor); + json.put ("database_version_patch", database_version_patch); // Keep these last for UI purposes - if (!ignore_identification_metrics_a) + if (!ignore_identification_metrics) { json.put ("node_id", node_id.to_node_id ()); json.put ("signature", signature.to_string ()); @@ -1175,9 +1210,9 @@ nano::error nano::telemetry_data::serialize_json (nano::jsonconfig & json, bool return json.get_error (); } -nano::error nano::telemetry_data::deserialize_json (nano::jsonconfig & json, bool ignore_identification_metrics_a) +nano::error nano::telemetry_data::deserialize_json (nano::jsonconfig & json, bool ignore_identification_metrics) { - if (!ignore_identification_metrics_a) + if (!ignore_identification_metrics) { std::string signature_l; json.get ("signature", signature_l); @@ -1208,6 +1243,7 @@ nano::error nano::telemetry_data::deserialize_json (nano::jsonconfig & json, boo json.get ("peer_count", peer_count); json.get ("protocol_version", protocol_version); json.get ("uptime", uptime); + std::string genesis_block_l; json.get ("genesis_block", genesis_block_l); if (!json.get_error ()) @@ -1217,27 +1253,31 @@ nano::error nano::telemetry_data::deserialize_json (nano::jsonconfig & json, boo json.get_error ().set ("Could not deserialize genesis block"); } } + json.get ("major_version", major_version); json.get ("minor_version", minor_version); json.get ("patch_version", patch_version); json.get ("pre_release_version", pre_release_version); - json.get ("maker", maker); + + std::string maker_text; + json.get ("maker", maker_text); + maker = to_telemetry_maker (maker_text); + auto timestamp_l = json.get ("timestamp"); timestamp = std::chrono::system_clock::time_point (std::chrono::milliseconds (timestamp_l)); + auto current_active_difficulty_text = json.get ("active_difficulty"); auto ec = nano::from_string_hex (current_active_difficulty_text, active_difficulty); debug_assert (!ec); - return json.get_error (); -} -bool nano::telemetry_data::operator== (nano::telemetry_data const & data_a) const -{ - return (signature == data_a.signature && node_id == data_a.node_id && block_count == data_a.block_count && cemented_count == data_a.cemented_count && unchecked_count == data_a.unchecked_count && account_count == data_a.account_count && bandwidth_cap == data_a.bandwidth_cap && uptime == data_a.uptime && peer_count == data_a.peer_count && protocol_version == data_a.protocol_version && genesis_block == data_a.genesis_block && major_version == data_a.major_version && minor_version == data_a.minor_version && patch_version == data_a.patch_version && pre_release_version == data_a.pre_release_version && maker == data_a.maker && timestamp == data_a.timestamp && active_difficulty == data_a.active_difficulty && unknown_data == data_a.unknown_data); -} + std::string database_backend_text; + json.get ("database_backend", database_backend_text); + database_backend = to_telemetry_backend (database_backend_text); -bool nano::telemetry_data::operator!= (nano::telemetry_data const & data_a) const -{ - return !(*this == data_a); + json.get ("database_version_major", database_version_major); + json.get ("database_version_minor", database_version_minor); + json.get ("database_version_patch", database_version_patch); + return json.get_error (); } void nano::telemetry_data::sign (nano::keypair const & node_id_a) @@ -1248,7 +1288,6 @@ void nano::telemetry_data::sign (nano::keypair const & node_id_a) nano::vectorstream stream (bytes); serialize_without_signature (stream); } - signature = nano::sign_message (node_id_a.prv, node_id_a.pub, bytes.data (), bytes.size ()); } @@ -1259,7 +1298,6 @@ bool nano::telemetry_data::validate_signature () const nano::vectorstream stream (bytes); serialize_without_signature (stream); } - return nano::validate_message (node_id, bytes.data (), bytes.size (), signature); } @@ -1268,6 +1306,64 @@ void nano::telemetry_data::operator() (nano::object_stream & obs) const // TODO: Telemetry data } +std::string nano::to_string (nano::telemetry_maker maker) +{ + switch (maker) + { + case nano::telemetry_maker::nf_node: + return "nf"; + case nano::telemetry_maker::nf_pruned_node: + return "nf-pruned"; + } + return "unknown (" + std::to_string (static_cast> (maker)) + ")"; +} + +nano::telemetry_maker nano::to_telemetry_maker (std::string str) +{ + // Convert to lowercase + std::transform (str.begin (), str.end (), str.begin (), ::tolower); + + if (str == "nf") + { + return nano::telemetry_maker::nf_node; + } + if (str == "nf-pruned") + { + return nano::telemetry_maker::nf_pruned_node; + } + return {}; // TODO: Enumeration should have a default "unknown" value, at this point it's probably too late to add it +} + +std::string nano::to_string (nano::telemetry_backend backend) +{ + switch (backend) + { + case nano::telemetry_backend::unknown: + return "Unknown"; + case nano::telemetry_backend::lmdb: + return "LMDB"; + case nano::telemetry_backend::rocksdb: + return "RocksDB"; + } + return "Unknown (" + std::to_string (static_cast> (backend)) + ")"; +} + +nano::telemetry_backend nano::to_telemetry_backend (std::string str) +{ + // Convert to lowercase + std::transform (str.begin (), str.end (), str.begin (), ::tolower); + + if (str == "lmdb") + { + return nano::telemetry_backend::lmdb; + } + if (str == "rocksdb") + { + return nano::telemetry_backend::rocksdb; + } + return nano::telemetry_backend::unknown; +} + /* * node_id_handshake */ diff --git a/nano/node/messages.hpp b/nano/node/messages.hpp index 7cba524971..bc74997339 100644 --- a/nano/node/messages.hpp +++ b/nano/node/messages.hpp @@ -304,15 +304,39 @@ class frontier_req final : public message void operator() (nano::object_stream &) const override; }; +// Indicates type of node enum class telemetry_maker : uint8_t { + // TODO: Default 0 value should be "unknown" nf_node = 0, nf_pruned_node = 1 }; +// Indicates type of database backend +enum class telemetry_backend : uint8_t +{ + unknown = 0, + lmdb = 1, + rocksdb = 2, +}; + +std::string to_string (telemetry_maker); +telemetry_maker to_telemetry_maker (std::string); + +std::string to_string (telemetry_backend); +telemetry_backend to_telemetry_backend (std::string); + class telemetry_data { public: + enum class version_t + { + unknown = 0, + v1, // Pre V27 + v2, // V27+ + }; + +public: // Payload nano::signature signature{ 0 }; nano::account node_id{}; uint64_t block_count{ 0 }; @@ -328,23 +352,37 @@ class telemetry_data uint8_t minor_version{ 0 }; uint8_t patch_version{ 0 }; uint8_t pre_release_version{ 0 }; - uint8_t maker{ static_cast> (telemetry_maker::nf_node) }; // Where this telemetry information originated + telemetry_maker maker{ telemetry_maker::nf_node }; std::chrono::system_clock::time_point timestamp; uint64_t active_difficulty{ 0 }; + telemetry_backend database_backend{ telemetry_backend::unknown }; + uint8_t database_version_major{ 0 }; + uint8_t database_version_minor{ 0 }; + uint8_t database_version_patch{ 0 }; + + // Remaining data that might be present in future telemetry versions, kept here so we can re-serialize it + // TODO: Is supporting re-serialization necessary? std::vector unknown_data; +private: + version_t version{ version_t::v2 }; + +public: void serialize (nano::stream &) const; - void deserialize (nano::stream &, uint16_t); - nano::error serialize_json (nano::jsonconfig &, bool) const; - nano::error deserialize_json (nano::jsonconfig &, bool); + void deserialize (nano::stream &, uint16_t payload_length); + + nano::error serialize_json (nano::jsonconfig &, bool ignore_identification_metrics) const; + nano::error deserialize_json (nano::jsonconfig &, bool ignore_identification_metrics); + void sign (nano::keypair const &); bool validate_signature () const; - bool operator== (nano::telemetry_data const &) const; - bool operator!= (nano::telemetry_data const &) const; + + bool operator== (nano::telemetry_data const &) const = default; + bool operator!= (nano::telemetry_data const &) const = default; // Size does not include unknown_data - static auto constexpr size = sizeof (signature) + sizeof (node_id) + sizeof (block_count) + sizeof (cemented_count) + sizeof (unchecked_count) + sizeof (account_count) + sizeof (bandwidth_cap) + sizeof (peer_count) + sizeof (protocol_version) + sizeof (uptime) + sizeof (genesis_block) + sizeof (major_version) + sizeof (minor_version) + sizeof (patch_version) + sizeof (pre_release_version) + sizeof (maker) + sizeof (uint64_t) + sizeof (active_difficulty); - static auto constexpr latest_size = size; // This needs to be updated for each new telemetry version + // This needs to be updated for each new telemetry version + static size_t constexpr size = sizeof (signature) + sizeof (node_id) + sizeof (block_count) + sizeof (cemented_count) + sizeof (unchecked_count) + sizeof (account_count) + sizeof (bandwidth_cap) + sizeof (peer_count) + sizeof (protocol_version) + sizeof (uptime) + sizeof (genesis_block) + sizeof (major_version) + sizeof (minor_version) + sizeof (patch_version) + sizeof (pre_release_version) + sizeof (maker) + sizeof (uint64_t) + sizeof (active_difficulty) + sizeof (database_backend) + sizeof (database_version_major) + sizeof (database_version_minor) + sizeof (database_version_patch); private: void serialize_without_signature (nano::stream &) const; @@ -378,6 +416,8 @@ class telemetry_ack final : public message uint16_t size () const; bool is_empty_payload () const; static uint16_t size (nano::message_header const &); + +public: // Payload nano::telemetry_data data; public: // Logging diff --git a/nano/node/node.cpp b/nano/node/node.cpp index f296ae5cca..9ea650a828 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -1335,6 +1335,52 @@ nano::account nano::node::get_node_id () const nano::telemetry_data nano::node::local_telemetry () const { + struct database_details_t + { + nano::telemetry_backend backend{ telemetry_backend::unknown }; + uint8_t version_major{ 0 }; + uint8_t version_minor{ 0 }; + uint8_t version_patch{ 0 }; + }; + + auto parse_backend_type = [] (std::string backend) -> telemetry_backend { + // Convert to lowercase + std::transform (backend.begin (), backend.end (), backend.begin (), ::tolower); + + if (backend == "lmdb") + { + return telemetry_backend::lmdb; + } + if (backend == "rocksdb") + { + return telemetry_backend::rocksdb; + } + debug_assert (false, "invalid database backend string"); + return telemetry_backend::unknown; + }; + + auto parse_backend_vendor = [&] (std::string vendor) -> database_details_t { + // Expected format: "DB_TYPE X.Y.Z" + auto type_version_split = nano::util::split (vendor, " "); + if (type_version_split.size () == 2) + { + auto version_split = nano::util::split (type_version_split[1], "."); + if (version_split.size () == 3) + { + return { + .backend = parse_backend_type (type_version_split[0]), + .version_major = static_cast (std::stoul (version_split[0])), + .version_minor = static_cast (std::stoul (version_split[1])), + .version_patch = static_cast (std::stoul (version_split[2])), + }; + } + } + debug_assert (false, "invalid database vendor string"); + return {}; + }; + + auto backend_details = parse_backend_vendor (store.vendor_get ()); + nano::telemetry_data telemetry_data; telemetry_data.node_id = node_id.pub; telemetry_data.block_count = ledger.block_count (); @@ -1350,9 +1396,14 @@ nano::telemetry_data nano::node::local_telemetry () const telemetry_data.minor_version = nano::get_minor_node_version (); telemetry_data.patch_version = nano::get_patch_node_version (); telemetry_data.pre_release_version = nano::get_pre_release_node_version (); - telemetry_data.maker = static_cast> (ledger.pruning ? telemetry_maker::nf_pruned_node : telemetry_maker::nf_node); + telemetry_data.maker = ledger.pruning ? telemetry_maker::nf_pruned_node : telemetry_maker::nf_node; telemetry_data.timestamp = std::chrono::system_clock::now (); telemetry_data.active_difficulty = default_difficulty (nano::work_version::work_1); + telemetry_data.database_backend = backend_details.backend; + telemetry_data.database_version_major = backend_details.version_major; + telemetry_data.database_version_minor = backend_details.version_minor; + telemetry_data.database_version_patch = backend_details.version_patch; + // Make sure this is the final operation! telemetry_data.sign (node_id); return telemetry_data; diff --git a/nano/node/telemetry.cpp b/nano/node/telemetry.cpp index 9016b73d1e..aa27ac4835 100644 --- a/nano/node/telemetry.cpp +++ b/nano/node/telemetry.cpp @@ -16,6 +16,8 @@ #include #include +#include + using namespace std::chrono_literals; nano::telemetry::telemetry (const config & config_a, nano::node & node_a, nano::network & network_a, nano::node_observers & observers_a, nano::network_params & network_params_a, nano::stats & stats_a) : @@ -296,4 +298,4 @@ std::unique_ptr nano::telemetry::collect_contain auto composite = std::make_unique (name); composite->add_component (std::make_unique (container_info{ "telemetries", telemetries.size (), sizeof (decltype (telemetries)::value_type) })); return composite; -} \ No newline at end of file +} diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 5ba2161d80..6d831e1522 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -6775,7 +6775,12 @@ TEST (rpc, telemetry_all) nano::telemetry_data telemetry_data; auto const should_ignore_identification_metrics = true; ASSERT_FALSE (telemetry_data.deserialize_json (config, should_ignore_identification_metrics)); - ASSERT_TRUE (nano::test::compare_telemetry_data (telemetry_data, node->local_telemetry ())); + auto local_telemetry = node->local_telemetry (); + // Ignore the identification metrics + local_telemetry.signature.clear (); + local_telemetry.node_id.clear (); + local_telemetry.timestamp = telemetry_data.timestamp = {}; + ASSERT_EQ (telemetry_data, local_telemetry); } request.put ("raw", "true"); diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index 1ea6065a40..8bf02f626a 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -1632,7 +1632,7 @@ TEST (telemetry, many_nodes) ASSERT_EQ (data.minor_version, nano::get_minor_node_version ()); ASSERT_EQ (data.patch_version, nano::get_patch_node_version ()); ASSERT_EQ (data.pre_release_version, nano::get_pre_release_node_version ()); - ASSERT_EQ (data.maker, 0); + ASSERT_EQ (data.maker, nano::telemetry_maker::nf_node); ASSERT_LT (data.uptime, 100); ASSERT_EQ (data.genesis_block, nano::dev::genesis->hash ()); ASSERT_LE (data.timestamp, std::chrono::system_clock::now ()); diff --git a/nano/test_common/telemetry.cpp b/nano/test_common/telemetry.cpp index db2465e074..af07b3ecdd 100644 --- a/nano/test_common/telemetry.cpp +++ b/nano/test_common/telemetry.cpp @@ -7,56 +7,34 @@ namespace { -void compare_telemetry_data_impl (const nano::telemetry_data & data_a, const nano::telemetry_data & data_b, bool & result) -{ - ASSERT_EQ (data_a.block_count, data_b.block_count); - ASSERT_EQ (data_a.cemented_count, data_b.cemented_count); - ASSERT_EQ (data_a.bandwidth_cap, data_b.bandwidth_cap); - ASSERT_EQ (data_a.peer_count, data_b.peer_count); - ASSERT_EQ (data_a.protocol_version, data_b.protocol_version); - ASSERT_EQ (data_a.unchecked_count, data_b.unchecked_count); - ASSERT_EQ (data_a.account_count, data_b.account_count); - ASSERT_LE (data_a.uptime, data_b.uptime); - ASSERT_EQ (data_a.genesis_block, data_b.genesis_block); - ASSERT_EQ (data_a.major_version, nano::get_major_node_version ()); - ASSERT_EQ (data_a.minor_version, nano::get_minor_node_version ()); - ASSERT_EQ (data_a.patch_version, nano::get_patch_node_version ()); - ASSERT_EQ (data_a.pre_release_version, nano::get_pre_release_node_version ()); - ASSERT_EQ (data_a.maker, static_cast> (nano::telemetry_maker::nf_node)); - ASSERT_GT (data_a.timestamp, std::chrono::system_clock::now () - std::chrono::seconds (100)); - ASSERT_EQ (data_a.active_difficulty, data_b.active_difficulty); - ASSERT_EQ (data_a.unknown_data, std::vector{}); - result = true; -} -} - -bool nano::test::compare_telemetry_data (const nano::telemetry_data & data_a, const nano::telemetry_data & data_b) -{ - bool result = false; - compare_telemetry_data_impl (data_a, data_b, result); - return result; -} - -namespace -{ -void compare_telemetry_impl (const nano::telemetry_data & data, nano::node const & node, bool & result) +void compare_telemetry_impl (nano::telemetry_data data, nano::node const & node, bool & result) { ASSERT_FALSE (data.validate_signature ()); ASSERT_EQ (data.node_id, node.node_id.pub); + auto data_node = node.local_telemetry (); + + // Ignore timestamps and uptime + data.timestamp = data_node.timestamp = {}; + data.uptime = data_node.uptime = {}; + // Signature should be different because uptime/timestamp will have changed. nano::telemetry_data data_l = data; data_l.signature.clear (); data_l.sign (node.node_id); ASSERT_NE (data.signature, data_l.signature); - ASSERT_TRUE (nano::test::compare_telemetry_data (data, node.local_telemetry ())); + // Clear signatures for comparison + data.signature.clear (); + data_node.signature.clear (); + + ASSERT_EQ (data, data_node); result = true; } } -bool nano::test::compare_telemetry (const nano::telemetry_data & data, const nano::node & node) +bool nano::test::compare_telemetry (nano::telemetry_data data, const nano::node & node) { bool result = false; compare_telemetry_impl (data, node, result); diff --git a/nano/test_common/telemetry.hpp b/nano/test_common/telemetry.hpp index 3efdd06cf6..35892b3db6 100644 --- a/nano/test_common/telemetry.hpp +++ b/nano/test_common/telemetry.hpp @@ -8,15 +8,9 @@ class telemetry_data; namespace nano::test { -/** - * Compares telemetry data without signatures - * @return true if comparison OK - */ -bool compare_telemetry_data (nano::telemetry_data const &, nano::telemetry_data const &); - /** * Compares telemetry data and checks signature matches node_id * @return true if comparison OK */ -bool compare_telemetry (nano::telemetry_data const &, nano::node const &); +bool compare_telemetry (nano::telemetry_data, nano::node const &); } \ No newline at end of file