From e6dd35475675aa0cd62cd20922fa9ffe3b4fa16c Mon Sep 17 00:00:00 2001 From: clemahieu Date: Thu, 30 Oct 2014 18:35:03 -0500 Subject: [PATCH] Changing header to be fixed 16 bits. --- CMakeLists.txt | 1 + rai/core/core.cpp | 102 ++++++++++++++++++++++++++++++++++++++++--- rai/core/core.hpp | 19 +++++++- rai/test/block.cpp | 14 ------ rai/test/client.cpp | 9 ++++ rai/test/ledger.cpp | 15 +++++-- rai/test/message.cpp | 39 +++++++++++++++++ rai/test/network.cpp | 91 ++++++++++++++++++++++++++++---------- 8 files changed, 242 insertions(+), 48 deletions(-) create mode 100644 rai/test/message.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 999158f4..b0a0bbfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ add_executable (test rai/test/daemon.cpp rai/test/entry.cpp rai/test/ledger.cpp + rai/test/message.cpp rai/test/processor_service.cpp rai/test/peer_container.cpp rai/test/network.cpp diff --git a/rai/core/core.cpp b/rai/core/core.cpp index a721326f..251bcc39 100644 --- a/rai/core/core.cpp +++ b/rai/core/core.cpp @@ -49,7 +49,7 @@ namespace } bool constexpr log_to_cerr () { - return false; + return true; } } @@ -227,14 +227,16 @@ void rai::network::receive_action (boost::system::error_code const & error, size { if (!rai::reserved_address (remote) && remote != endpoint ()) { - if (size_a >= sizeof (rai::message_type)) + rai::bufferstream header_stream (buffer.data (), size_a); + uint8_t version_max; + uint8_t version_using; + uint8_t version_min; + rai::message_type type; + if (!rai::message::read_header (header_stream, version_max, version_using, version_min, type)) { auto sender (remote); maintain_keepalive (sender); client.peers.incoming_from_peer (sender); - rai::bufferstream type_stream (buffer.data (), size_a); - rai::message_type type; - read (type_stream, type); switch (type) { case rai::message_type::keepalive: @@ -344,6 +346,13 @@ void rai::network::receive_action (boost::system::error_code const & error, size } } } + else + { + if (network_logging ()) + { + client.log.add ("Unable to parse message header"); + } + } } else { @@ -387,7 +396,13 @@ void rai::network::merge_peers (std::array const & peers_a) } } +rai::publish::publish () : +message (rai::message_type::publish) +{ +} + rai::publish::publish (std::unique_ptr block_a) : +message (rai::message_type::publish), block (std::move (block_a)) { } @@ -1288,7 +1303,8 @@ void rai::publish::visit (rai::message_visitor & visitor_a) const visitor_a.publish (*this); } -rai::keepalive::keepalive () +rai::keepalive::keepalive () : +message (rai::message_type::keepalive) { boost::asio::ip::udp::endpoint endpoint (boost::asio::ip::address_v6 {}, 0); for (auto i (peers.begin ()), n (peers.end ()); i != n; ++i) @@ -1434,6 +1450,11 @@ rai::key_entry * rai::key_entry::operator -> () return this; } +rai::confirm_ack::confirm_ack () : +message (rai::message_type::confirm_ack) +{ +} + bool rai::confirm_ack::deserialize (rai::stream & stream_a) { rai::message_type type; @@ -1479,6 +1500,11 @@ void rai::confirm_ack::visit (rai::message_visitor & visitor_a) const visitor_a.confirm_ack (*this); } +rai::confirm_req::confirm_req () : +message (rai::message_type::confirm_req) +{ +} + bool rai::confirm_req::deserialize (rai::stream & stream_a) { rai::message_type type; @@ -1493,6 +1519,11 @@ bool rai::confirm_req::deserialize (rai::stream & stream_a) return result; } +rai::confirm_unk::confirm_unk () : +message (rai::message_type::confirm_unk) +{ +} + bool rai::confirm_unk::deserialize (rai::stream & stream_a) { rai::message_type type; @@ -1955,6 +1986,11 @@ bool rai::parse_tcp_endpoint (std::string const & string, rai::tcp_endpoint & en return result; } +rai::bulk_req::bulk_req () : +message (rai::message_type::bulk_req) +{ +} + void rai::bulk_req::visit (rai::message_visitor & visitor_a) const { visitor_a.bulk_req (*this); @@ -3092,6 +3128,11 @@ std::pair rai::frontier_req_response::g return result; } +rai::frontier_req::frontier_req () : +message (rai::message_type::frontier_req) +{ +} + bool rai::frontier_req::deserialize (rai::stream & stream_a) { rai::message_type type; @@ -3927,4 +3968,53 @@ void rai::fan::value_set (rai::uint256_union const & value_a) auto value_l (value ()); *(values [0]) ^= value_l; *(values [0]) ^= value_a; +} + +uint32_t const rai::message::magic_number; +std::bitset <64> constexpr rai::message::ipv4_only; +std::bitset <64> constexpr rai::message::bootstrap_receiver; + +rai::message::message (rai::message_type type_a) : +version_max (0x01), +version_using (0x01), +version_min (0x01), +type (type_a) +{ +} + +void rai::message::write_header (rai::stream & stream_a) +{ + rai::write (stream_a, rai::message::magic_number); + rai::write (stream_a, version_max); + rai::write (stream_a, version_using); + rai::write (stream_a, version_min); + rai::write (stream_a, type); + rai::write (stream_a, extensions.to_ullong ()); +} + +bool rai::message::read_header (rai::stream & stream_a, uint8_t & version_max_a, uint8_t & version_using_a, uint8_t & version_min_a, rai::message_type & type_a) +{ + uint32_t magic_number_l; + auto result (rai::read (stream_a, magic_number_l)); + if (!result) + { + result = magic_number_l != magic_number; + if (!result) + { + result = rai::read (stream_a, version_max_a); + if (!result) + { + result = rai::read (stream_a, version_using_a); + if (!result) + { + result = rai::read (stream_a, version_min_a); + if (!result) + { + result = rai::read (stream_a, type_a); + } + } + } + } + } + return result; } \ No newline at end of file diff --git a/rai/core/core.hpp b/rai/core/core.hpp index 77ad1f2e..b35e3d11 100644 --- a/rai/core/core.hpp +++ b/rai/core/core.hpp @@ -138,9 +138,21 @@ namespace rai { class message { public: + message (rai::message_type); virtual ~message () = default; + void write_header (rai::stream &); + static bool read_header (rai::stream &, uint8_t &, uint8_t &, uint8_t &, rai::message_type &); virtual void serialize (rai::stream &) = 0; + virtual bool deserialize (rai::stream &) = 0; virtual void visit (rai::message_visitor &) const = 0; + static uint32_t const magic_number = 0x734152b5u; + uint8_t version_max; + uint8_t version_using; + uint8_t version_min; + rai::message_type type; + std::bitset <64> extensions; + constexpr static std::bitset <64> const ipv4_only = std::bitset <64> (1); + constexpr static std::bitset <64> const bootstrap_receiver = std::bitset <64> (2); }; class keepalive : public message { @@ -156,7 +168,7 @@ namespace rai { class publish : public message { public: - publish () = default; + publish (); publish (std::unique_ptr ); void visit (rai::message_visitor &) const override; bool deserialize (rai::stream &); @@ -168,6 +180,7 @@ namespace rai { class confirm_req : public message { public: + confirm_req (); bool deserialize (rai::stream &); void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; @@ -178,6 +191,7 @@ namespace rai { class confirm_ack : public message { public: + confirm_ack (); bool deserialize (rai::stream &); void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; @@ -188,6 +202,7 @@ namespace rai { class confirm_unk : public message { public: + confirm_unk (); bool deserialize (rai::stream &); void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; @@ -197,6 +212,7 @@ namespace rai { class frontier_req : public message { public: + frontier_req (); bool deserialize (rai::stream &); void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; @@ -208,6 +224,7 @@ namespace rai { class bulk_req : public message { public: + bulk_req (); bool deserialize (rai::stream &); void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; diff --git a/rai/test/block.cpp b/rai/test/block.cpp index 41b7b141..393b460d 100644 --- a/rai/test/block.cpp +++ b/rai/test/block.cpp @@ -438,20 +438,6 @@ TEST (frontier_req, serialization) ASSERT_EQ (request1, request2); } -TEST (keepalive_ack, serialization) -{ - rai::keepalive request1; - std::vector bytes; - { - rai::vectorstream stream (bytes); - request1.serialize (stream); - } - rai::keepalive request2; - rai::bufferstream buffer (bytes.data (), bytes.size ()); - ASSERT_FALSE (request2.deserialize (buffer)); - ASSERT_EQ (request1, request2); -} - TEST (salsa20_8, one) { rai::uint512_union value; diff --git a/rai/test/client.cpp b/rai/test/client.cpp index c96bda8e..4af7a0fa 100644 --- a/rai/test/client.cpp +++ b/rai/test/client.cpp @@ -42,10 +42,13 @@ TEST (client, send_self) system.clients [0]->wallet.insert (rai::test_genesis_key.prv); system.clients [0]->wallet.insert (key2.prv); ASSERT_FALSE (system.clients [0]->transactions.send (key2.pub, 1000)); + auto iterations (0); while (system.clients [0]->ledger.account_balance (key2.pub).is_zero ()) { system.service->poll_one (); system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } ASSERT_EQ (std::numeric_limits ::max () - 1000, system.clients [0]->ledger.account_balance (rai::test_genesis_key.pub)); } @@ -59,10 +62,13 @@ TEST (client, send_single) ASSERT_FALSE (system.clients [0]->transactions.send (key2.pub, 1000)); ASSERT_EQ (std::numeric_limits ::max () - 1000, system.clients [0]->ledger.account_balance (rai::test_genesis_key.pub)); ASSERT_TRUE (system.clients [0]->ledger.account_balance (key2.pub).is_zero ()); + auto iterations (0); while (system.clients [0]->ledger.account_balance (key2.pub).is_zero ()) { system.service->poll_one (); system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } } @@ -75,10 +81,13 @@ TEST (client, send_single_observing_peer) ASSERT_FALSE (system.clients [0]->transactions.send (key2.pub, 1000)); ASSERT_EQ (std::numeric_limits ::max () - 1000, system.clients [0]->ledger.account_balance (rai::test_genesis_key.pub)); ASSERT_TRUE (system.clients [0]->ledger.account_balance (key2.pub).is_zero ()); + auto iterations (0); while (std::any_of (system.clients.begin (), system.clients.end (), [&] (std::shared_ptr const & client_a) {return client_a->ledger.account_balance (key2.pub).is_zero();})) { system.service->poll_one (); system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } } diff --git a/rai/test/ledger.cpp b/rai/test/ledger.cpp index 7d21cd8b..050c30ba 100644 --- a/rai/test/ledger.cpp +++ b/rai/test/ledger.cpp @@ -1103,7 +1103,7 @@ TEST (fork, publish) ASSERT_TRUE (client0.expired ()); } -TEST (fork, keep) +TEST (ledger, fork_keep) { rai::system system (24000, 2); auto & client1 (*system.clients [0]); @@ -1142,10 +1142,13 @@ TEST (fork, keep) ASSERT_EQ (1, votes1->votes.rep_votes.size ()); ASSERT_TRUE (system.clients [0]->store.block_exists (publish1.block->hash ())); ASSERT_TRUE (system.clients [1]->store.block_exists (publish1.block->hash ())); + auto iterations (0); while (votes1->votes.rep_votes.size () == 1) { system.service->poll_one (); system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } auto winner (votes1->votes.winner ()); ASSERT_EQ (*publish1.block, *winner.first); @@ -1154,7 +1157,7 @@ TEST (fork, keep) ASSERT_TRUE (system.clients [1]->store.block_exists (publish1.block->hash ())); } -TEST (fork, flip) +TEST (ledger, fork_flip) { rai::system system (24000, 2); auto & client1 (*system.clients [0]); @@ -1193,10 +1196,13 @@ TEST (fork, flip) ASSERT_EQ (1, votes1->votes.rep_votes.size ()); ASSERT_TRUE (client1.store.block_exists (publish1.block->hash ())); ASSERT_TRUE (client2.store.block_exists (publish2.block->hash ())); + auto iterations (0); while (votes1->votes.rep_votes.size () == 1) { system.service->poll_one (); system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } auto winner (votes1->votes.winner ()); ASSERT_EQ (*publish1.block, *winner.first); @@ -1206,7 +1212,7 @@ TEST (fork, flip) ASSERT_FALSE (client2.store.block_exists (publish2.block->hash ())); } -TEST (fork, multi_flip) +TEST (ledger, fork_multi_flip) { rai::system system (24000, 2); auto & client1 (*system.clients [0]); @@ -1255,10 +1261,13 @@ TEST (fork, multi_flip) ASSERT_TRUE (client1.store.block_exists (publish1.block->hash ())); ASSERT_TRUE (client2.store.block_exists (publish2.block->hash ())); ASSERT_TRUE (client2.store.block_exists (publish3.block->hash ())); + auto iterations (0); while (votes1->votes.rep_votes.size () == 1) { system.service->poll_one (); system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } auto winner (votes1->votes.winner ()); ASSERT_EQ (*publish1.block, *winner.first); diff --git a/rai/test/message.cpp b/rai/test/message.cpp new file mode 100644 index 00000000..fbf739cf --- /dev/null +++ b/rai/test/message.cpp @@ -0,0 +1,39 @@ +#include +#include + +TEST (message, keepalive_serialization) +{ + rai::keepalive request1; + std::vector bytes; + { + rai::vectorstream stream (bytes); + request1.serialize (stream); + } + rai::keepalive request2; + rai::bufferstream buffer (bytes.data (), bytes.size ()); + ASSERT_FALSE (request2.deserialize (buffer)); + ASSERT_EQ (request1, request2); +} + +TEST (message, keepalive_deserialize) +{ + rai::keepalive message1; + message1.peers [0] = rai::endpoint (boost::asio::ip::address_v6::loopback (), 10000); + message1.checksum = 1; + std::vector bytes; + { + rai::vectorstream stream (bytes); + message1.serialize (stream); + } + uint8_t version_max; + uint8_t version_using; + uint8_t version_min; + rai::message_type type; + rai::bufferstream header_stream (bytes.data (), bytes.size ()); + ASSERT_FALSE (rai::message::read_header (header_stream, version_max, version_using, version_min, type)); + ASSERT_EQ (rai::message_type::keepalive, type); + rai::keepalive message2; + rai::bufferstream stream (bytes.data (), bytes.size ()); + ASSERT_FALSE (message2.deserialize (stream)); + ASSERT_EQ (message1.peers, message2.peers); +} \ No newline at end of file diff --git a/rai/test/network.cpp b/rai/test/network.cpp index 265a558f..597efbd3 100644 --- a/rai/test/network.cpp +++ b/rai/test/network.cpp @@ -4,6 +4,41 @@ #include #include +TEST (publish, serialization) +{ + rai::publish publish; + publish.extensions = rai::message::ipv4_only; + std::vector bytes; + { + rai::vectorstream stream (bytes); + publish.write_header (stream); + } + ASSERT_EQ (16, bytes.size ()); + ASSERT_EQ (0xb5, bytes [0]); + ASSERT_EQ (0x52, bytes [1]); + ASSERT_EQ (0x41, bytes [2]); + ASSERT_EQ (0x73, bytes [3]); + ASSERT_EQ (0x01, bytes [4]); + ASSERT_EQ (0x01, bytes [5]); + ASSERT_EQ (0x01, bytes [6]); + ASSERT_EQ (static_cast (rai::message_type::publish), bytes [7]); + ASSERT_EQ (0x01, bytes [8]); + for (auto i (bytes.begin () + 9), n (bytes.end ()); i != n; ++i) + { + ASSERT_EQ (0, *i); + } + rai::bufferstream stream (bytes.data (), bytes.size ()); + uint8_t version_max; + uint8_t version_using; + uint8_t version_min; + rai::message_type type; + ASSERT_FALSE (rai::message::read_header (stream, version_max, version_using, version_min, type)); + ASSERT_EQ (0x01, version_min); + ASSERT_EQ (0x01, version_using); + ASSERT_EQ (0x01, version_max); + ASSERT_EQ (rai::message_type::publish, type); +} + TEST (network, tcp_connection) { boost::asio::io_service service; @@ -63,22 +98,6 @@ TEST (network, self_discard) ASSERT_EQ (1, system.clients [0]->network.bad_sender_count); } -TEST (keepalive, deserialize) -{ - rai::keepalive message1; - message1.peers [0] = rai::endpoint (boost::asio::ip::address_v6::loopback (), 10000); - message1.checksum = 1; - std::vector bytes; - { - rai::vectorstream stream (bytes); - message1.serialize (stream); - } - rai::keepalive message2; - rai::bufferstream stream (bytes.data (), bytes.size ()); - ASSERT_FALSE (message2.deserialize (stream)); - ASSERT_EQ (message1.peers, message2.peers); -} - TEST (network, send_keepalive) { rai::system system (24000, 1); @@ -91,9 +110,12 @@ TEST (network, send_keepalive) auto initial (system.clients [0]->network.keepalive_count); ASSERT_EQ (1, system.clients [0]->peers.list ().size ()); ASSERT_EQ (0, client1->peers.list ().size ()); + auto iterations (0); while (system.clients [0]->network.keepalive_count == initial) { - system.service->run_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } auto peers1 (system.clients [0]->peers.list ()); auto peers2 (client1->peers.list ()); @@ -113,9 +135,12 @@ TEST (network, keepalive_ipv4) client1->start (); system.clients [0]->network.maintain_keepalive (rai::endpoint (boost::asio::ip::address_v4::loopback (), 24000)); auto initial (system.clients [0]->network.keepalive_count); + auto iterations (0); while (system.clients [0]->network.keepalive_count == initial) { - system.service->run_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } } @@ -132,18 +157,24 @@ TEST (network, multi_keepalive) client1->network.maintain_keepalive (system.clients [0]->network.endpoint ()); ASSERT_EQ (1, client1->peers.size ()); ASSERT_EQ (0, system.clients [0]->peers.size ()); + auto iterations1 (0); while (system.clients [0]->peers.size () != 1) { - system.service->run_one (); + system.service->poll_one (); + ++iterations1; + ASSERT_LT (iterations1, 200); } rai::client_init init2; auto client2 (std::make_shared (init2, system.service, 24002, system.processor, rai::test_genesis_key.pub)); ASSERT_FALSE (init2.error ()); client2->start (); client2->network.maintain_keepalive (system.clients [0]->network.endpoint ()); + auto iterations2 (0); while (client1->peers.size () != 2 || system.clients [0]->peers.size () != 2 || client2->peers.size () != 2) { - system.service->run_one (); + system.service->poll_one (); + ++iterations2; + ASSERT_LT (iterations2, 200); } client1->stop (); client2->stop (); @@ -204,9 +235,12 @@ TEST (network, send_discarded_publish) rai::genesis genesis; ASSERT_EQ (genesis.hash (), system.clients [0]->ledger.latest (rai::test_genesis_key.pub)); ASSERT_EQ (genesis.hash (), system.clients [1]->ledger.latest (rai::test_genesis_key.pub)); + auto iterations (0); while (system.clients [1]->network.publish_req_count == 0) { - system.service->run_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } ASSERT_EQ (genesis.hash (), system.clients [0]->ledger.latest (rai::test_genesis_key.pub)); ASSERT_EQ (genesis.hash (), system.clients [1]->ledger.latest (rai::test_genesis_key.pub)); @@ -223,9 +257,12 @@ TEST (network, send_invalid_publish) rai::genesis genesis; ASSERT_EQ (genesis.hash (), system.clients [0]->ledger.latest (rai::test_genesis_key.pub)); ASSERT_EQ (genesis.hash (), system.clients [1]->ledger.latest (rai::test_genesis_key.pub)); + auto iterations (0); while (system.clients [1]->network.publish_req_count == 0) { - system.service->run_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } ASSERT_EQ (genesis.hash (), system.clients [0]->ledger.latest (rai::test_genesis_key.pub)); ASSERT_EQ (genesis.hash (), system.clients [1]->ledger.latest (rai::test_genesis_key.pub)); @@ -248,9 +285,12 @@ TEST (network, send_valid_publish) rai::frontier frontier2; ASSERT_FALSE (system.clients [1]->store.latest_get (rai::test_genesis_key.pub, frontier2)); system.clients [0]->processor.process_receive_republish (std::unique_ptr (new rai::send_block (block2)), system.clients [0]->network.endpoint ()); + auto iterations (0); while (system.clients [1]->network.publish_req_count == 0) { - system.service->run_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } rai::frontier frontier3; ASSERT_FALSE (system.clients [1]->store.latest_get (rai::test_genesis_key.pub, frontier3)); @@ -276,9 +316,12 @@ TEST (network, send_insufficient_work) auto client (system.clients [1]->shared ()); system.clients [0]->network.send_buffer (bytes->data (), bytes->size (), system.clients [1]->network.endpoint (), [bytes, client] (boost::system::error_code const & ec, size_t size) {}); ASSERT_EQ (0, system.clients [0]->network.insufficient_work_count); + auto iterations (0); while (system.clients [1]->network.insufficient_work_count == 0) { - system.service->run_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); } ASSERT_EQ (1, system.clients [1]->network.insufficient_work_count); }