Skip to content

Commit

Permalink
Merge pull request #4350 from pwojcikdev/larger-votes
Browse files Browse the repository at this point in the history
Larger votes preparation
  • Loading branch information
pwojcikdev authored Dec 12, 2023
2 parents 0912b9b + a770ea1 commit 220ac3d
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 39 deletions.
152 changes: 151 additions & 1 deletion nano/core_test/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,59 @@ TEST (message, publish_serialization)
ASSERT_EQ (nano::message_type::publish, header.type);
}

TEST (message, confirm_header_flags)
{
nano::message_header header_v2{ nano::dev::network_params.network, nano::message_type::confirm_req };
header_v2.confirm_set_v2 (true);

const uint8_t value = 0b0110'1001;

header_v2.count_v2_set (value); // Max count value

ASSERT_TRUE (header_v2.confirm_is_v2 ());
ASSERT_EQ (header_v2.count_v2_get (), value);

std::vector<uint8_t> bytes;
{
nano::vectorstream stream (bytes);
header_v2.serialize (stream);
}
nano::bufferstream stream (bytes.data (), bytes.size ());

bool error = false;
nano::message_header header (error, stream);
ASSERT_FALSE (error);
ASSERT_EQ (nano::message_type::confirm_req, header.type);

ASSERT_TRUE (header.confirm_is_v2 ());
ASSERT_EQ (header.count_v2_get (), value);
}

TEST (message, confirm_header_flags_max)
{
nano::message_header header_v2{ nano::dev::network_params.network, nano::message_type::confirm_req };
header_v2.confirm_set_v2 (true);
header_v2.count_v2_set (255); // Max count value

ASSERT_TRUE (header_v2.confirm_is_v2 ());
ASSERT_EQ (header_v2.count_v2_get (), 255);

std::vector<uint8_t> bytes;
{
nano::vectorstream stream (bytes);
header_v2.serialize (stream);
}
nano::bufferstream stream (bytes.data (), bytes.size ());

bool error = false;
nano::message_header header (error, stream);
ASSERT_FALSE (error);
ASSERT_EQ (nano::message_type::confirm_req, header.type);

ASSERT_TRUE (header.confirm_is_v2 ());
ASSERT_EQ (header.count_v2_get (), 255);
}

TEST (message, confirm_ack_hash_serialization)
{
std::vector<nano::block_hash> hashes;
Expand Down Expand Up @@ -126,10 +179,51 @@ TEST (message, confirm_ack_hash_serialization)
ASSERT_FALSE (error);
ASSERT_EQ (con1, con2);
ASSERT_EQ (hashes, con2.vote->hashes);
// Check overflow with max hashes
ASSERT_FALSE (header.confirm_is_v2 ());
ASSERT_EQ (header.count_get (), hashes.size ());
}

TEST (message, confirm_ack_hash_serialization_v2)
{
std::vector<nano::block_hash> hashes;
for (auto i (hashes.size ()); i < 255; i++)
{
nano::keypair key1;
nano::block_hash previous;
nano::random_pool::generate_block (previous.bytes.data (), previous.bytes.size ());
nano::block_builder builder;
auto block = builder
.state ()
.account (key1.pub)
.previous (previous)
.representative (key1.pub)
.balance (2)
.link (4)
.sign (key1.prv, key1.pub)
.work (5)
.build ();
hashes.push_back (block->hash ());
}

nano::keypair representative1;
auto vote (std::make_shared<nano::vote> (representative1.pub, representative1.prv, 0, 0, hashes));
nano::confirm_ack con1{ nano::dev::network_params.network, 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);
ASSERT_EQ (hashes, con2.vote->hashes);
ASSERT_TRUE (header.confirm_is_v2 ());
ASSERT_EQ (header.count_v2_get (), hashes.size ());
}

TEST (message, confirm_req_hash_serialization)
{
nano::keypair key1;
Expand Down Expand Up @@ -210,6 +304,62 @@ TEST (message, confirm_req_hash_batch_serialization)
ASSERT_EQ (req.roots_hashes, roots_hashes);
ASSERT_EQ (req2.roots_hashes, roots_hashes);
ASSERT_EQ (header.count_get (), req.roots_hashes.size ());
ASSERT_FALSE (header.confirm_is_v2 ());
}

TEST (message, confirm_req_hash_batch_serialization_v2)
{
nano::keypair key;
nano::keypair representative;
nano::block_builder builder;
auto open = builder
.state ()
.account (key.pub)
.previous (0)
.representative (representative.pub)
.balance (2)
.link (4)
.sign (key.prv, key.pub)
.work (5)
.build ();

std::vector<std::pair<nano::block_hash, nano::root>> roots_hashes;
roots_hashes.push_back (std::make_pair (open->hash (), open->root ()));
for (auto i (roots_hashes.size ()); i < 255; i++)
{
nano::keypair key1;
nano::block_hash previous;
nano::random_pool::generate_block (previous.bytes.data (), previous.bytes.size ());
auto block = builder
.state ()
.account (key1.pub)
.previous (previous)
.representative (representative.pub)
.balance (2)
.link (4)
.sign (key1.prv, key1.pub)
.work (5)
.build ();
roots_hashes.push_back (std::make_pair (block->hash (), block->root ()));
}

nano::confirm_req req{ nano::dev::network_params.network, 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.count_v2_get (), req.roots_hashes.size ());
ASSERT_TRUE (header.confirm_is_v2 ());
}

// this unit test checks that conversion of message_header to string works as expected
Expand Down
27 changes: 26 additions & 1 deletion nano/core_test/vote_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ TEST (vote_processor, codes)
// Hint of pre-validation
ASSERT_NE (nano::vote_code::invalid, node.vote_processor.vote_blocking (vote_invalid, channel, true));

// No ongoing election
// No ongoing election (vote goes to vote cache)
ASSERT_EQ (nano::vote_code::indeterminate, node.vote_processor.vote_blocking (vote, channel));

// Clear vote cache before starting election
node.vote_cache.clear ();

// First vote from an account for an ongoing election
node.start_election (blocks[0]);
std::shared_ptr<nano::election> election;
Expand Down Expand Up @@ -326,6 +329,28 @@ TEST (vote_processor, no_broadcast_local_with_a_principal_representative)
ASSERT_EQ (1, node.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::out));
}

/**
* Ensure that node behaves well with votes larger than 12 hashes, which was maximum before V26
*/
TEST (vote_processor, large_votes)
{
nano::test::system system (1);
auto & node = *system.nodes[0];

const int count = 32;
auto blocks = nano::test::setup_chain (system, node, count, nano::dev::genesis_key, /* do not confirm */ false);

ASSERT_TRUE (nano::test::start_elections (system, node, blocks));
ASSERT_TIMELY (5s, nano::test::active (node, blocks));

auto vote = nano::test::make_final_vote (nano::dev::genesis_key, blocks);
ASSERT_TRUE (vote->hashes.size () == count);

node.vote_processor.vote (vote, nano::test::fake_channel (node));

ASSERT_TIMELY (5s, nano::test::confirmed (node, blocks));
}

/**
* basic test to check that the timestamp mask is applied correctly on vote timestamp and duration fields
*/
Expand Down
Loading

0 comments on commit 220ac3d

Please sign in to comment.