diff --git a/rai/core/core.cpp b/rai/core/core.cpp index 37f6e9cb..29b61f6e 100644 --- a/rai/core/core.cpp +++ b/rai/core/core.cpp @@ -194,8 +194,7 @@ void rai::network::publish_block (boost::asio::ip::udp::endpoint const & endpoin void rai::network::send_confirm_req (boost::asio::ip::udp::endpoint const & endpoint_a, rai::block const & block) { - rai::confirm_req message; - message.block = block.clone (); + rai::confirm_req message (block.clone ()); rai::work work; message.work = work.create (message.block->hash ()); std::shared_ptr > bytes (new std::vector ); @@ -405,15 +404,11 @@ rai::publish::publish (std::unique_ptr block_a) : message (rai::message_type::publish), block (std::move (block_a)) { + block_type_set (block->type ()); } bool rai::publish::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (type == rai::message_type::publish); @@ -422,7 +417,7 @@ bool rai::publish::deserialize (rai::stream & stream_a) result = read (stream_a, work); if (!result) { - block = rai::deserialize_block (stream_a); + block = rai::deserialize_block (stream_a, block_type ()); result = block == nullptr; } } @@ -431,9 +426,10 @@ bool rai::publish::deserialize (rai::stream & stream_a) void rai::publish::serialize (rai::stream & stream_a) { + assert (block != nullptr); write_header (stream_a); write (stream_a, work); - rai::serialize_block (stream_a, *block); + block->serialize (stream_a); } namespace @@ -1337,11 +1333,6 @@ void rai::keepalive::serialize (rai::stream & stream_a) bool rai::keepalive::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (type == rai::message_type::keepalive); @@ -1465,11 +1456,6 @@ message (rai::message_type::confirm_ack) bool rai::confirm_ack::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (type == rai::message_type::confirm_ack); @@ -1518,13 +1504,15 @@ message (rai::message_type::confirm_req) { } +rai::confirm_req::confirm_req (std::unique_ptr block_a) : +message (rai::message_type::confirm_req), +block (std::move (block_a)) +{ + block_type_set (block->type ()); +} + bool rai::confirm_req::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (type == rai::message_type::confirm_req); @@ -1533,7 +1521,7 @@ bool rai::confirm_req::deserialize (rai::stream & stream_a) result = read (stream_a, work); if (!result) { - block = rai::deserialize_block (stream_a); + block = rai::deserialize_block (stream_a, block_type ()); result = block == nullptr; } } @@ -1547,11 +1535,6 @@ message (rai::message_type::confirm_unk) bool rai::confirm_unk::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (type == rai::message_type::confirm_unk); @@ -1577,7 +1560,7 @@ void rai::confirm_req::serialize (rai::stream & stream_a) assert (block != nullptr); write_header (stream_a); write (stream_a, work); - rai::serialize_block (stream_a, *block); + block->serialize (stream_a); } rai::rpc::rpc (boost::shared_ptr service_a, boost::shared_ptr pool_a, uint16_t port_a, rai::client & client_a, bool enable_control_a) : @@ -2028,11 +2011,6 @@ void rai::bulk_req::visit (rai::message_visitor & visitor_a) const bool rai::bulk_req::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (rai::message_type::bulk_req == type); @@ -3066,8 +3044,8 @@ request (std::move (request_a)) } rai::frontier_req_response::frontier_req_response (std::shared_ptr const & connection_a, std::unique_ptr request_a) : -iterator (connection_a->client->store.latest_begin (request_a->start)), connection (connection_a), +iterator (connection_a->client->store.latest_begin (request_a->start)), request (std::move (request_a)) { skip_old (); @@ -3181,11 +3159,6 @@ message (rai::message_type::frontier_req) bool rai::frontier_req::deserialize (rai::stream & stream_a) { - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <64> extensions; auto result (read_header (stream_a, version_max, version_using, version_min, type, extensions)); assert (!result); assert (rai::message_type::frontier_req == type); @@ -4025,9 +3998,11 @@ void rai::fan::value_set (rai::uint256_union const & value_a) *(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; +uint32_t constexpr rai::message::magic_number; +size_t constexpr rai::message::test_network_position; +size_t constexpr rai::message::ipv4_only_position; +size_t constexpr rai::message::bootstrap_receiver_position; +std::bitset <64> constexpr rai::message::block_type_mask; rai::message::message (rai::message_type type_a) : version_max (0x01), @@ -4037,6 +4012,27 @@ type (type_a) { } +rai::block_type rai::message::block_type () const +{ + return static_cast (((extensions & block_type_mask) >> 8).to_ullong ()); +} + +void rai::message::block_type_set (rai::block_type type_a) +{ + extensions &= ~rai::message::block_type_mask; + extensions |= std::bitset <64> (static_cast (type_a) << 8); +} + +bool rai::message::ipv4_only () +{ + return extensions.test (ipv4_only_position); +} + +void rai::message::ipv4_only_set (bool value_a) +{ + extensions.set (ipv4_only_position, value_a); +} + void rai::message::write_header (rai::stream & stream_a) { rai::write (stream_a, rai::message::magic_number); diff --git a/rai/core/core.hpp b/rai/core/core.hpp index da7fa657..913c43c9 100644 --- a/rai/core/core.hpp +++ b/rai/core/core.hpp @@ -145,14 +145,20 @@ namespace rai { 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; + rai::block_type block_type () const; + void block_type_set (rai::block_type); + bool ipv4_only (); + void ipv4_only_set (bool); + static uint32_t constexpr 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); + static size_t constexpr test_network_position = 0; + static size_t constexpr ipv4_only_position = 1; + static size_t constexpr bootstrap_receiver_position = 2; + static std::bitset <64> constexpr block_type_mask = std::bitset <64> (0x0000000000000f00); }; class keepalive : public message { @@ -180,6 +186,7 @@ namespace rai { { public: confirm_req (); + confirm_req (std::unique_ptr ); bool deserialize (rai::stream &); void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; diff --git a/rai/secure.cpp b/rai/secure.cpp index a013215b..5cd8e21f 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -725,6 +725,57 @@ void rai::serialize_block (rai::stream & stream_a, rai::block const & block_a) block_a.serialize (stream_a); } +std::unique_ptr rai::deserialize_block (rai::stream & stream_a, rai::block_type type_a) +{ + std::unique_ptr result; + switch (type_a) + { + case rai::block_type::receive: + { + std::unique_ptr obj (new rai::receive_block); + auto error (obj->deserialize (stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + case rai::block_type::send: + { + std::unique_ptr obj (new rai::send_block); + auto error (obj->deserialize (stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + case rai::block_type::open: + { + std::unique_ptr obj (new rai::open_block); + auto error (obj->deserialize (stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + case rai::block_type::change: + { + bool error; + std::unique_ptr obj (new rai::change_block (error, stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + default: + break; + } + return result; +} + std::unique_ptr rai::deserialize_block (rai::stream & stream_a) { rai::block_type type; @@ -732,51 +783,7 @@ std::unique_ptr rai::deserialize_block (rai::stream & stream_a) std::unique_ptr result; if (!error) { - switch (type) - { - case rai::block_type::receive: - { - std::unique_ptr obj (new rai::receive_block); - auto error (obj->deserialize (stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - case rai::block_type::send: - { - std::unique_ptr obj (new rai::send_block); - auto error (obj->deserialize (stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - case rai::block_type::open: - { - std::unique_ptr obj (new rai::open_block); - auto error (obj->deserialize (stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - case rai::block_type::change: - { - bool error; - std::unique_ptr obj (new rai::change_block (error, stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - default: - break; - } + result = rai::deserialize_block (stream_a, type); } return result; } diff --git a/rai/secure.hpp b/rai/secure.hpp index 5581fef8..02bb38d9 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -175,9 +175,10 @@ namespace rai virtual bool operator == (rai::block const &) const = 0; virtual std::unique_ptr clone () const = 0; virtual rai::block_type type () const = 0; - }; - std::unique_ptr deserialize_block (rai::stream &); - void serialize_block (rai::stream &, rai::block const &); + }; + std::unique_ptr deserialize_block (rai::stream &); + std::unique_ptr deserialize_block (rai::stream &, rai::block_type); + void serialize_block (rai::stream &, rai::block const &); class send_hashables { public: diff --git a/rai/test/message.cpp b/rai/test/message.cpp index 0730cf79..c04c4e6e 100644 --- a/rai/test/message.cpp +++ b/rai/test/message.cpp @@ -36,4 +36,44 @@ TEST (message, keepalive_deserialize) rai::bufferstream stream (bytes.data (), bytes.size ()); ASSERT_FALSE (message2.deserialize (stream)); ASSERT_EQ (message1.peers, message2.peers); +} + +TEST (message, publish_serialization) +{ + rai::publish publish (std::unique_ptr (new rai::send_block)); + ASSERT_EQ (rai::block_type::send, publish.block_type ()); + ASSERT_FALSE (publish.ipv4_only ()); + publish.ipv4_only_set (true); + ASSERT_TRUE (publish.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 (0x02, bytes [8]); + ASSERT_EQ (static_cast (rai::block_type::send), bytes [9]); + for (auto i (bytes.begin () + 10), 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; + std::bitset <64> extensions; + ASSERT_FALSE (rai::message::read_header (stream, version_max, version_using, version_min, type, extensions)); + ASSERT_EQ (0x01, version_min); + ASSERT_EQ (0x01, version_using); + ASSERT_EQ (0x01, version_max); + ASSERT_EQ (rai::message_type::publish, type); } \ No newline at end of file diff --git a/rai/test/network.cpp b/rai/test/network.cpp index ea4511cc..d91f62d5 100644 --- a/rai/test/network.cpp +++ b/rai/test/network.cpp @@ -4,42 +4,6 @@ #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; - std::bitset <64> extensions; - ASSERT_FALSE (rai::message::read_header (stream, version_max, version_using, version_min, type, extensions)); - 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; @@ -212,8 +176,7 @@ TEST (network, confirm_req) block->hashables.previous.clear (); block->hashables.balance = 200; block->hashables.destination = key2.pub; - rai::confirm_req req; - req.block = std::move (block); + rai::confirm_req req (std::move (block)); std::vector bytes; { rai::vectorstream stream (bytes); @@ -307,8 +270,7 @@ TEST (network, send_insufficient_work) block->hashables.previous.clear (); block->hashables.balance = 20; rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, block->hash (), block->signature); - rai::publish publish; - publish.block = std::move (block); + rai::publish publish (std::move (block)); std::shared_ptr > bytes (new std::vector ); { rai::vectorstream stream (*bytes);