Framing support for realtime network messages (#1972)
- Sizes addes for each message types & subtypes - New count field added to message header extensions (4 bit, max size 15) for confirm_req/confirm_ack by hash - Node ID handshake header flags functions moved to nano::message_header instead from nano::node_id_handshake - Tests expanded to check count extensions field
This commit is contained in:
parent
ecc571ca6d
commit
27289121c9
6 changed files with 380 additions and 131 deletions
|
|
@ -312,78 +312,6 @@ TEST (block, publish_req_serialization)
|
||||||
ASSERT_EQ (*req.block, *req2.block);
|
ASSERT_EQ (*req.block, *req2.block);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST (block, confirm_req_serialization)
|
|
||||||
{
|
|
||||||
nano::keypair key1;
|
|
||||||
nano::keypair key2;
|
|
||||||
auto block (std::make_shared<nano::send_block> (0, key2.pub, 200, nano::keypair ().prv, 2, 3));
|
|
||||||
nano::confirm_req req (block);
|
|
||||||
std::vector<uint8_t> bytes;
|
|
||||||
{
|
|
||||||
nano::vectorstream stream (bytes);
|
|
||||||
req.serialize (stream);
|
|
||||||
}
|
|
||||||
auto error (false);
|
|
||||||
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
|
||||||
nano::message_header header (error, stream2);
|
|
||||||
nano::confirm_req req2 (error, stream2, header);
|
|
||||||
ASSERT_FALSE (error);
|
|
||||||
ASSERT_EQ (req, req2);
|
|
||||||
ASSERT_EQ (*req.block, *req2.block);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST (block, confirm_req_hash_serialization)
|
|
||||||
{
|
|
||||||
nano::keypair key1;
|
|
||||||
nano::keypair key2;
|
|
||||||
nano::send_block block (1, key2.pub, 200, nano::keypair ().prv, 2, 3);
|
|
||||||
nano::confirm_req req (block.hash (), block.root ());
|
|
||||||
std::vector<uint8_t> bytes;
|
|
||||||
{
|
|
||||||
nano::vectorstream stream (bytes);
|
|
||||||
req.serialize (stream);
|
|
||||||
}
|
|
||||||
auto error (false);
|
|
||||||
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
|
||||||
nano::message_header header (error, stream2);
|
|
||||||
nano::confirm_req req2 (error, stream2, header);
|
|
||||||
ASSERT_FALSE (error);
|
|
||||||
ASSERT_EQ (req, req2);
|
|
||||||
ASSERT_EQ (req.roots_hashes, req2.roots_hashes);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST (block, confirm_req_hash_batch_serialization)
|
|
||||||
{
|
|
||||||
nano::keypair key;
|
|
||||||
nano::keypair representative;
|
|
||||||
std::vector<std::pair<nano::block_hash, nano::block_hash>> roots_hashes;
|
|
||||||
nano::state_block open (key.pub, 0, representative.pub, 2, 4, key.prv, key.pub, 5);
|
|
||||||
roots_hashes.push_back (std::make_pair (open.hash (), open.root ()));
|
|
||||||
for (auto i (roots_hashes.size ()); i < 7; i++)
|
|
||||||
{
|
|
||||||
nano::keypair key1;
|
|
||||||
nano::keypair previous;
|
|
||||||
nano::state_block block (key1.pub, previous.pub, representative.pub, 2, 4, key1.prv, key1.pub, 5);
|
|
||||||
roots_hashes.push_back (std::make_pair (block.hash (), block.root ()));
|
|
||||||
}
|
|
||||||
roots_hashes.push_back (std::make_pair (open.hash (), open.root ()));
|
|
||||||
nano::confirm_req req (roots_hashes);
|
|
||||||
std::vector<uint8_t> bytes;
|
|
||||||
{
|
|
||||||
nano::vectorstream stream (bytes);
|
|
||||||
req.serialize (stream);
|
|
||||||
}
|
|
||||||
auto error (false);
|
|
||||||
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
|
||||||
nano::message_header header (error, stream2);
|
|
||||||
nano::confirm_req req2 (error, stream2, header);
|
|
||||||
ASSERT_FALSE (error);
|
|
||||||
ASSERT_EQ (req, req2);
|
|
||||||
ASSERT_EQ (req.roots_hashes, req2.roots_hashes);
|
|
||||||
ASSERT_EQ (req.roots_hashes, roots_hashes);
|
|
||||||
ASSERT_EQ (req2.roots_hashes, roots_hashes);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST (state_block, serialization)
|
TEST (state_block, serialization)
|
||||||
{
|
{
|
||||||
nano::keypair key1;
|
nano::keypair key1;
|
||||||
|
|
|
||||||
|
|
@ -82,4 +82,116 @@ TEST (message, confirm_ack_serialization)
|
||||||
nano::confirm_ack con2 (error, stream2, header);
|
nano::confirm_ack con2 (error, stream2, header);
|
||||||
ASSERT_FALSE (error);
|
ASSERT_FALSE (error);
|
||||||
ASSERT_EQ (con1, con2);
|
ASSERT_EQ (con1, con2);
|
||||||
|
ASSERT_EQ (header.block_type (), nano::block_type::send);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST (message, confirm_ack_hash_serialization)
|
||||||
|
{
|
||||||
|
std::vector<nano::block_hash> hashes;
|
||||||
|
for (auto i (hashes.size ()); i < 12; i++)
|
||||||
|
{
|
||||||
|
nano::keypair key1;
|
||||||
|
nano::keypair previous;
|
||||||
|
nano::state_block block (key1.pub, previous.pub, key1.pub, 2, 4, key1.prv, key1.pub, 5);
|
||||||
|
hashes.push_back (block.hash ());
|
||||||
|
}
|
||||||
|
nano::keypair representative1;
|
||||||
|
auto vote (std::make_shared<nano::vote> (representative1.pub, representative1.prv, 0, hashes));
|
||||||
|
nano::confirm_ack con1 (vote);
|
||||||
|
std::vector<uint8_t> bytes;
|
||||||
|
{
|
||||||
|
nano::vectorstream stream1 (bytes);
|
||||||
|
con1.serialize (stream1);
|
||||||
|
}
|
||||||
|
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
||||||
|
bool error (false);
|
||||||
|
nano::message_header header (error, stream2);
|
||||||
|
nano::confirm_ack con2 (error, stream2, header);
|
||||||
|
ASSERT_FALSE (error);
|
||||||
|
ASSERT_EQ (con1, con2);
|
||||||
|
std::vector<nano::block_hash> vote_blocks;
|
||||||
|
for (auto block : con2.vote->blocks)
|
||||||
|
{
|
||||||
|
vote_blocks.push_back (boost::get<nano::block_hash> (block));
|
||||||
|
}
|
||||||
|
ASSERT_EQ (hashes, vote_blocks);
|
||||||
|
// Check overflow with 12 hashes
|
||||||
|
ASSERT_EQ (header.count_get (), hashes.size ());
|
||||||
|
ASSERT_EQ (header.block_type (), nano::block_type::not_a_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST (message, confirm_req_serialization)
|
||||||
|
{
|
||||||
|
nano::keypair key1;
|
||||||
|
nano::keypair key2;
|
||||||
|
auto block (std::make_shared<nano::send_block> (0, key2.pub, 200, nano::keypair ().prv, 2, 3));
|
||||||
|
nano::confirm_req req (block);
|
||||||
|
std::vector<uint8_t> bytes;
|
||||||
|
{
|
||||||
|
nano::vectorstream stream (bytes);
|
||||||
|
req.serialize (stream);
|
||||||
|
}
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
||||||
|
nano::message_header header (error, stream2);
|
||||||
|
nano::confirm_req req2 (error, stream2, header);
|
||||||
|
ASSERT_FALSE (error);
|
||||||
|
ASSERT_EQ (req, req2);
|
||||||
|
ASSERT_EQ (*req.block, *req2.block);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST (message, confirm_req_hash_serialization)
|
||||||
|
{
|
||||||
|
nano::keypair key1;
|
||||||
|
nano::keypair key2;
|
||||||
|
nano::send_block block (1, key2.pub, 200, nano::keypair ().prv, 2, 3);
|
||||||
|
nano::confirm_req req (block.hash (), block.root ());
|
||||||
|
std::vector<uint8_t> bytes;
|
||||||
|
{
|
||||||
|
nano::vectorstream stream (bytes);
|
||||||
|
req.serialize (stream);
|
||||||
|
}
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
||||||
|
nano::message_header header (error, stream2);
|
||||||
|
nano::confirm_req req2 (error, stream2, header);
|
||||||
|
ASSERT_FALSE (error);
|
||||||
|
ASSERT_EQ (req, req2);
|
||||||
|
ASSERT_EQ (req.roots_hashes, req2.roots_hashes);
|
||||||
|
ASSERT_EQ (header.block_type (), nano::block_type::not_a_block);
|
||||||
|
ASSERT_EQ (header.count_get (), req.roots_hashes.size ());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST (message, confirm_req_hash_batch_serialization)
|
||||||
|
{
|
||||||
|
nano::keypair key;
|
||||||
|
nano::keypair representative;
|
||||||
|
std::vector<std::pair<nano::block_hash, nano::block_hash>> roots_hashes;
|
||||||
|
nano::state_block open (key.pub, 0, representative.pub, 2, 4, key.prv, key.pub, 5);
|
||||||
|
roots_hashes.push_back (std::make_pair (open.hash (), open.root ()));
|
||||||
|
for (auto i (roots_hashes.size ()); i < 7; i++)
|
||||||
|
{
|
||||||
|
nano::keypair key1;
|
||||||
|
nano::keypair previous;
|
||||||
|
nano::state_block block (key1.pub, previous.pub, representative.pub, 2, 4, key1.prv, key1.pub, 5);
|
||||||
|
roots_hashes.push_back (std::make_pair (block.hash (), block.root ()));
|
||||||
|
}
|
||||||
|
roots_hashes.push_back (std::make_pair (open.hash (), open.root ()));
|
||||||
|
nano::confirm_req req (roots_hashes);
|
||||||
|
std::vector<uint8_t> bytes;
|
||||||
|
{
|
||||||
|
nano::vectorstream stream (bytes);
|
||||||
|
req.serialize (stream);
|
||||||
|
}
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream2 (bytes.data (), bytes.size ());
|
||||||
|
nano::message_header header (error, stream2);
|
||||||
|
nano::confirm_req req2 (error, stream2, header);
|
||||||
|
ASSERT_FALSE (error);
|
||||||
|
ASSERT_EQ (req, req2);
|
||||||
|
ASSERT_EQ (req.roots_hashes, req2.roots_hashes);
|
||||||
|
ASSERT_EQ (req.roots_hashes, roots_hashes);
|
||||||
|
ASSERT_EQ (req2.roots_hashes, roots_hashes);
|
||||||
|
ASSERT_EQ (header.block_type (), nano::block_type::not_a_block);
|
||||||
|
ASSERT_EQ (header.count_get (), req.roots_hashes.size ());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1966,6 +1966,38 @@ void nano::bootstrap_server::receive_header_action (boost::system::error_code co
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case nano::message_type::publish:
|
||||||
|
{
|
||||||
|
auto this_l (shared_from_this ());
|
||||||
|
socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) {
|
||||||
|
this_l->receive_publish_action (ec, size_a, header);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case nano::message_type::confirm_ack:
|
||||||
|
{
|
||||||
|
auto this_l (shared_from_this ());
|
||||||
|
socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) {
|
||||||
|
this_l->receive_confirm_ack_action (ec, size_a, header);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case nano::message_type::confirm_req:
|
||||||
|
{
|
||||||
|
auto this_l (shared_from_this ());
|
||||||
|
socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) {
|
||||||
|
this_l->receive_confirm_req_action (ec, size_a, header);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case nano::message_type::node_id_handshake:
|
||||||
|
{
|
||||||
|
auto this_l (shared_from_this ());
|
||||||
|
socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) {
|
||||||
|
this_l->receive_node_id_handshake_action (ec, size_a, header);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (node->config.logging.network_logging ())
|
if (node->config.logging.network_logging ())
|
||||||
|
|
@ -2025,34 +2057,12 @@ void nano::bootstrap_server::receive_bulk_pull_account_action (boost::system::er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::bootstrap_server::receive_keepalive_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
|
||||||
{
|
|
||||||
if (!ec)
|
|
||||||
{
|
|
||||||
auto error (false);
|
|
||||||
nano::bufferstream stream (receive_buffer->data (), header_a.payload_length_bytes ());
|
|
||||||
std::unique_ptr<nano::keepalive> request (new nano::keepalive (error, stream, header_a));
|
|
||||||
if (!error)
|
|
||||||
{
|
|
||||||
add_request (std::unique_ptr<nano::message> (request.release ()));
|
|
||||||
receive ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (node->config.logging.network_keepalive_logging ())
|
|
||||||
{
|
|
||||||
node->logger.try_log (boost::str (boost::format ("Error receiving keepalive from: %1%") % ec.message ()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void nano::bootstrap_server::receive_frontier_req_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
void nano::bootstrap_server::receive_frontier_req_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
||||||
{
|
{
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
auto error (false);
|
auto error (false);
|
||||||
nano::bufferstream stream (receive_buffer->data (), header_a.payload_length_bytes ());
|
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||||
std::unique_ptr<nano::frontier_req> request (new nano::frontier_req (error, stream, header_a));
|
std::unique_ptr<nano::frontier_req> request (new nano::frontier_req (error, stream, header_a));
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
|
|
@ -2073,6 +2083,107 @@ void nano::bootstrap_server::receive_frontier_req_action (boost::system::error_c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nano::bootstrap_server::receive_keepalive_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
||||||
|
{
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||||
|
std::unique_ptr<nano::keepalive> request (new nano::keepalive (error, stream, header_a));
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
add_request (std::unique_ptr<nano::message> (request.release ()));
|
||||||
|
receive ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node->config.logging.network_keepalive_logging ())
|
||||||
|
{
|
||||||
|
node->logger.try_log (boost::str (boost::format ("Error receiving keepalive: %1%") % ec.message ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nano::bootstrap_server::receive_publish_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
||||||
|
{
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||||
|
std::unique_ptr<nano::publish> request (new nano::publish (error, stream, header_a));
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
add_request (std::unique_ptr<nano::message> (request.release ()));
|
||||||
|
receive ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node->config.logging.network_message_logging ())
|
||||||
|
{
|
||||||
|
node->logger.try_log (boost::str (boost::format ("Error receiving publish: %1%") % ec.message ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nano::bootstrap_server::receive_confirm_req_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
||||||
|
{
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||||
|
std::unique_ptr<nano::confirm_req> request (new nano::confirm_req (error, stream, header_a));
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
add_request (std::unique_ptr<nano::message> (request.release ()));
|
||||||
|
receive ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node->config.logging.network_message_logging ())
|
||||||
|
{
|
||||||
|
node->logger.try_log (boost::str (boost::format ("Error receiving confirm_req: %1%") % ec.message ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nano::bootstrap_server::receive_confirm_ack_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
||||||
|
{
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||||
|
std::unique_ptr<nano::confirm_ack> request (new nano::confirm_ack (error, stream, header_a));
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
add_request (std::unique_ptr<nano::message> (request.release ()));
|
||||||
|
receive ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node->config.logging.network_message_logging ())
|
||||||
|
{
|
||||||
|
node->logger.try_log (boost::str (boost::format ("Error receiving confirm_ack: %1%") % ec.message ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nano::bootstrap_server::receive_node_id_handshake_action (boost::system::error_code const & ec, size_t size_a, nano::message_header const & header_a)
|
||||||
|
{
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
auto error (false);
|
||||||
|
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||||
|
std::unique_ptr<nano::node_id_handshake> request (new nano::node_id_handshake (error, stream, header_a));
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
add_request (std::unique_ptr<nano::message> (request.release ()));
|
||||||
|
receive ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node->config.logging.network_node_id_handshake_logging ())
|
||||||
|
{
|
||||||
|
node->logger.try_log (boost::str (boost::format ("Error receiving node_id_handshake: %1%") % ec.message ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nano::bootstrap_server::add_request (std::unique_ptr<nano::message> message_a)
|
void nano::bootstrap_server::add_request (std::unique_ptr<nano::message> message_a)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock (mutex);
|
std::lock_guard<std::mutex> lock (mutex);
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,10 @@ public:
|
||||||
void receive_bulk_pull_account_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
void receive_bulk_pull_account_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
void receive_frontier_req_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
void receive_frontier_req_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
void receive_keepalive_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
void receive_keepalive_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
|
void receive_publish_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
|
void receive_confirm_req_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
|
void receive_confirm_ack_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
|
void receive_node_id_handshake_action (boost::system::error_code const &, size_t, nano::message_header const &);
|
||||||
void add_request (std::unique_ptr<nano::message>);
|
void add_request (std::unique_ptr<nano::message>);
|
||||||
void finish_request ();
|
void finish_request ();
|
||||||
void run_next ();
|
void run_next ();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <boost/endian/conversion.hpp>
|
#include <boost/endian/conversion.hpp>
|
||||||
|
|
||||||
std::bitset<16> constexpr nano::message_header::block_type_mask;
|
std::bitset<16> constexpr nano::message_header::block_type_mask;
|
||||||
|
std::bitset<16> constexpr nano::message_header::count_mask;
|
||||||
|
|
||||||
nano::message_header::message_header (nano::message_type type_a) :
|
nano::message_header::message_header (nano::message_type type_a) :
|
||||||
version_max (nano::protocol_version),
|
version_max (nano::protocol_version),
|
||||||
|
|
@ -85,6 +86,25 @@ void nano::message_header::block_type_set (nano::block_type type_a)
|
||||||
extensions |= std::bitset<16> (static_cast<unsigned long long> (type_a) << 8);
|
extensions |= std::bitset<16> (static_cast<unsigned long long> (type_a) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t nano::message_header::count_get () const
|
||||||
|
{
|
||||||
|
return ((extensions & count_mask) >> 12).to_ullong ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nano::message_header::count_set (uint8_t count_a)
|
||||||
|
{
|
||||||
|
assert (count_a < 16);
|
||||||
|
extensions &= ~count_mask;
|
||||||
|
extensions |= std::bitset<16> (static_cast<unsigned long long> (count_a) << 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nano::message_header::flag_set (uint8_t flag_a)
|
||||||
|
{
|
||||||
|
// Flags from 8 are block_type & count
|
||||||
|
assert (flag_a < 8);
|
||||||
|
extensions.set (flag_a, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool nano::message_header::bulk_pull_is_count_present () const
|
bool nano::message_header::bulk_pull_is_count_present () const
|
||||||
{
|
{
|
||||||
auto result (false);
|
auto result (false);
|
||||||
|
|
@ -95,7 +115,32 @@ bool nano::message_header::bulk_pull_is_count_present () const
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nano::message_header::node_id_handshake_is_query () const
|
||||||
|
{
|
||||||
|
auto result (false);
|
||||||
|
if (type == nano::message_type::node_id_handshake)
|
||||||
|
{
|
||||||
|
if (extensions.test (node_id_handshake_query_flag))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nano::message_header::node_id_handshake_is_response () const
|
||||||
|
{
|
||||||
|
auto result (false);
|
||||||
|
if (type == nano::message_type::node_id_handshake)
|
||||||
|
{
|
||||||
|
if (extensions.test (node_id_handshake_response_flag))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,8 +169,22 @@ size_t nano::message_header::payload_length_bytes () const
|
||||||
{
|
{
|
||||||
return nano::keepalive::size;
|
return nano::keepalive::size;
|
||||||
}
|
}
|
||||||
// Add realtime network messages once they get framing support; currently the
|
case nano::message_type::publish:
|
||||||
// realtime messages all fit in a datagram from which they're deserialized.
|
{
|
||||||
|
return nano::block::size (block_type ());
|
||||||
|
}
|
||||||
|
case nano::message_type::confirm_ack:
|
||||||
|
{
|
||||||
|
return nano::confirm_ack::size (block_type (), count_get ());
|
||||||
|
}
|
||||||
|
case nano::message_type::confirm_req:
|
||||||
|
{
|
||||||
|
return nano::confirm_req::size (block_type (), count_get ());
|
||||||
|
}
|
||||||
|
case nano::message_type::node_id_handshake:
|
||||||
|
{
|
||||||
|
return nano::node_id_handshake::size (*this);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
assert (false);
|
assert (false);
|
||||||
|
|
@ -498,6 +557,8 @@ roots_hashes (roots_hashes_a)
|
||||||
{
|
{
|
||||||
// not_a_block (1) block type for hashes + roots request
|
// not_a_block (1) block type for hashes + roots request
|
||||||
header.block_type_set (nano::block_type::not_a_block);
|
header.block_type_set (nano::block_type::not_a_block);
|
||||||
|
assert (roots_hashes.size () < 16);
|
||||||
|
header.count_set (roots_hashes.size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
nano::confirm_req::confirm_req (nano::block_hash const & hash_a, nano::block_hash const & root_a) :
|
nano::confirm_req::confirm_req (nano::block_hash const & hash_a, nano::block_hash const & root_a) :
|
||||||
|
|
@ -507,6 +568,7 @@ roots_hashes (std::vector<std::pair<nano::block_hash, nano::block_hash>> (1, std
|
||||||
assert (!roots_hashes.empty ());
|
assert (!roots_hashes.empty ());
|
||||||
// not_a_block (1) block type for hashes + roots request
|
// not_a_block (1) block type for hashes + roots request
|
||||||
header.block_type_set (nano::block_type::not_a_block);
|
header.block_type_set (nano::block_type::not_a_block);
|
||||||
|
header.count_set (roots_hashes.size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void nano::confirm_req::visit (nano::message_visitor & visitor_a) const
|
void nano::confirm_req::visit (nano::message_visitor & visitor_a) const
|
||||||
|
|
@ -606,6 +668,20 @@ std::string nano::confirm_req::roots_string () const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t nano::confirm_req::size (nano::block_type type_a, size_t count)
|
||||||
|
{
|
||||||
|
size_t result (0);
|
||||||
|
if (type_a != nano::block_type::invalid && type_a != nano::block_type::not_a_block)
|
||||||
|
{
|
||||||
|
result = nano::block::size (type_a);
|
||||||
|
}
|
||||||
|
else if (type_a == nano::block_type::not_a_block)
|
||||||
|
{
|
||||||
|
result = sizeof (uint8_t) + count * (sizeof (nano::uint256_union) + sizeof (nano::block_hash));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nano::confirm_ack::confirm_ack (bool & error_a, nano::stream & stream_a, nano::message_header const & header_a, nano::vote_uniquer * uniquer_a) :
|
nano::confirm_ack::confirm_ack (bool & error_a, nano::stream & stream_a, nano::message_header const & header_a, nano::vote_uniquer * uniquer_a) :
|
||||||
message (header_a),
|
message (header_a),
|
||||||
vote (std::make_shared<nano::vote> (error_a, stream_a, header.block_type ()))
|
vote (std::make_shared<nano::vote> (error_a, stream_a, header.block_type ()))
|
||||||
|
|
@ -625,6 +701,8 @@ vote (vote_a)
|
||||||
if (first_vote_block.which ())
|
if (first_vote_block.which ())
|
||||||
{
|
{
|
||||||
header.block_type_set (nano::block_type::not_a_block);
|
header.block_type_set (nano::block_type::not_a_block);
|
||||||
|
assert (vote_a->blocks.size () < 16);
|
||||||
|
header.count_set (vote_a->blocks.size ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -650,6 +728,20 @@ void nano::confirm_ack::visit (nano::message_visitor & visitor_a) const
|
||||||
visitor_a.confirm_ack (*this);
|
visitor_a.confirm_ack (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t nano::confirm_ack::size (nano::block_type type_a, size_t count)
|
||||||
|
{
|
||||||
|
size_t result (sizeof (nano::account) + sizeof (nano::signature) + sizeof (uint64_t));
|
||||||
|
if (type_a != nano::block_type::invalid && type_a != nano::block_type::not_a_block)
|
||||||
|
{
|
||||||
|
result += nano::block::size (type_a);
|
||||||
|
}
|
||||||
|
else if (type_a == nano::block_type::not_a_block)
|
||||||
|
{
|
||||||
|
result += count * sizeof (nano::block_hash);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nano::frontier_req::frontier_req () :
|
nano::frontier_req::frontier_req () :
|
||||||
message (nano::message_type::frontier_req)
|
message (nano::message_type::frontier_req)
|
||||||
{
|
{
|
||||||
|
|
@ -869,9 +961,6 @@ void nano::bulk_push::visit (nano::message_visitor & visitor_a) const
|
||||||
visitor_a.bulk_push (*this);
|
visitor_a.bulk_push (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t constexpr nano::node_id_handshake::query_flag;
|
|
||||||
size_t constexpr nano::node_id_handshake::response_flag;
|
|
||||||
|
|
||||||
nano::node_id_handshake::node_id_handshake (bool & error_a, nano::stream & stream_a, nano::message_header const & header_a) :
|
nano::node_id_handshake::node_id_handshake (bool & error_a, nano::stream & stream_a, nano::message_header const & header_a) :
|
||||||
message (header_a),
|
message (header_a),
|
||||||
query (boost::none),
|
query (boost::none),
|
||||||
|
|
@ -887,11 +976,11 @@ response (response)
|
||||||
{
|
{
|
||||||
if (query)
|
if (query)
|
||||||
{
|
{
|
||||||
set_query_flag (true);
|
header.flag_set (nano::message_header::node_id_handshake_query_flag);
|
||||||
}
|
}
|
||||||
if (response)
|
if (response)
|
||||||
{
|
{
|
||||||
set_response_flag (true);
|
header.flag_set (nano::message_header::node_id_handshake_response_flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -915,14 +1004,14 @@ bool nano::node_id_handshake::deserialize (nano::stream & stream_a)
|
||||||
auto error (false);
|
auto error (false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (is_query_flag ())
|
if (header.node_id_handshake_is_query ())
|
||||||
{
|
{
|
||||||
nano::uint256_union query_hash;
|
nano::uint256_union query_hash;
|
||||||
read (stream_a, query_hash);
|
read (stream_a, query_hash);
|
||||||
query = query_hash;
|
query = query_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_response_flag ())
|
if (header.node_id_handshake_is_response ())
|
||||||
{
|
{
|
||||||
nano::account response_account;
|
nano::account response_account;
|
||||||
read (stream_a, response_account);
|
read (stream_a, response_account);
|
||||||
|
|
@ -945,31 +1034,30 @@ bool nano::node_id_handshake::operator== (nano::node_id_handshake const & other_
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nano::node_id_handshake::is_query_flag () const
|
|
||||||
{
|
|
||||||
return header.extensions.test (query_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nano::node_id_handshake::set_query_flag (bool value_a)
|
|
||||||
{
|
|
||||||
header.extensions.set (query_flag, value_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nano::node_id_handshake::is_response_flag () const
|
|
||||||
{
|
|
||||||
return header.extensions.test (response_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nano::node_id_handshake::set_response_flag (bool value_a)
|
|
||||||
{
|
|
||||||
header.extensions.set (response_flag, value_a);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nano::node_id_handshake::visit (nano::message_visitor & visitor_a) const
|
void nano::node_id_handshake::visit (nano::message_visitor & visitor_a) const
|
||||||
{
|
{
|
||||||
visitor_a.node_id_handshake (*this);
|
visitor_a.node_id_handshake (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t nano::node_id_handshake::size () const
|
||||||
|
{
|
||||||
|
return size (header);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nano::node_id_handshake::size (nano::message_header const & header_a)
|
||||||
|
{
|
||||||
|
size_t result (0);
|
||||||
|
if (header_a.node_id_handshake_is_query ())
|
||||||
|
{
|
||||||
|
result = sizeof (nano::uint256_union);
|
||||||
|
}
|
||||||
|
if (header_a.node_id_handshake_is_response ())
|
||||||
|
{
|
||||||
|
result += sizeof (nano::account) + sizeof (nano::signature);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nano::message_visitor::~message_visitor ()
|
nano::message_visitor::~message_visitor ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,19 +186,27 @@ public:
|
||||||
bool deserialize (nano::stream &);
|
bool deserialize (nano::stream &);
|
||||||
nano::block_type block_type () const;
|
nano::block_type block_type () const;
|
||||||
void block_type_set (nano::block_type);
|
void block_type_set (nano::block_type);
|
||||||
|
uint8_t count_get () const;
|
||||||
|
void count_set (uint8_t);
|
||||||
uint8_t version_max;
|
uint8_t version_max;
|
||||||
uint8_t version_using;
|
uint8_t version_using;
|
||||||
uint8_t version_min;
|
uint8_t version_min;
|
||||||
nano::message_type type;
|
nano::message_type type;
|
||||||
std::bitset<16> extensions;
|
std::bitset<16> extensions;
|
||||||
|
|
||||||
static size_t constexpr bulk_pull_count_present_flag = 0;
|
void flag_set (uint8_t);
|
||||||
|
static uint8_t constexpr bulk_pull_count_present_flag = 0;
|
||||||
bool bulk_pull_is_count_present () const;
|
bool bulk_pull_is_count_present () const;
|
||||||
|
static uint8_t constexpr node_id_handshake_query_flag = 0;
|
||||||
|
static uint8_t constexpr node_id_handshake_response_flag = 1;
|
||||||
|
bool node_id_handshake_is_query () const;
|
||||||
|
bool node_id_handshake_is_response () const;
|
||||||
|
|
||||||
/** Size of the payload in bytes. For some messages, the payload size is based on header flags. */
|
/** Size of the payload in bytes. For some messages, the payload size is based on header flags. */
|
||||||
size_t payload_length_bytes () const;
|
size_t payload_length_bytes () const;
|
||||||
|
|
||||||
static std::bitset<16> constexpr block_type_mask = std::bitset<16> (0x0f00);
|
static std::bitset<16> constexpr block_type_mask = std::bitset<16> (0x0f00);
|
||||||
|
static std::bitset<16> constexpr count_mask = std::bitset<16> (0xf000);
|
||||||
};
|
};
|
||||||
class message
|
class message
|
||||||
{
|
{
|
||||||
|
|
@ -289,6 +297,7 @@ public:
|
||||||
std::shared_ptr<nano::block> block;
|
std::shared_ptr<nano::block> block;
|
||||||
std::vector<std::pair<nano::block_hash, nano::block_hash>> roots_hashes;
|
std::vector<std::pair<nano::block_hash, nano::block_hash>> roots_hashes;
|
||||||
std::string roots_string () const;
|
std::string roots_string () const;
|
||||||
|
static size_t size (nano::block_type, size_t = 0);
|
||||||
};
|
};
|
||||||
class confirm_ack final : public message
|
class confirm_ack final : public message
|
||||||
{
|
{
|
||||||
|
|
@ -299,6 +308,7 @@ public:
|
||||||
void visit (nano::message_visitor &) const override;
|
void visit (nano::message_visitor &) const override;
|
||||||
bool operator== (nano::confirm_ack const &) const;
|
bool operator== (nano::confirm_ack const &) const;
|
||||||
std::shared_ptr<nano::vote> vote;
|
std::shared_ptr<nano::vote> vote;
|
||||||
|
static size_t size (nano::block_type, size_t = 0);
|
||||||
};
|
};
|
||||||
class frontier_req final : public message
|
class frontier_req final : public message
|
||||||
{
|
{
|
||||||
|
|
@ -363,14 +373,10 @@ public:
|
||||||
bool deserialize (nano::stream &);
|
bool deserialize (nano::stream &);
|
||||||
void visit (nano::message_visitor &) const override;
|
void visit (nano::message_visitor &) const override;
|
||||||
bool operator== (nano::node_id_handshake const &) const;
|
bool operator== (nano::node_id_handshake const &) const;
|
||||||
bool is_query_flag () const;
|
|
||||||
void set_query_flag (bool);
|
|
||||||
bool is_response_flag () const;
|
|
||||||
void set_response_flag (bool);
|
|
||||||
boost::optional<nano::uint256_union> query;
|
boost::optional<nano::uint256_union> query;
|
||||||
boost::optional<std::pair<nano::account, nano::signature>> response;
|
boost::optional<std::pair<nano::account, nano::signature>> response;
|
||||||
static size_t constexpr query_flag = 0;
|
size_t size () const;
|
||||||
static size_t constexpr response_flag = 1;
|
static size_t size (nano::message_header const &);
|
||||||
};
|
};
|
||||||
class message_visitor
|
class message_visitor
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue