Add tests for vote_processor (#2574)
This commit is contained in:
parent
1de3ea0260
commit
ae3c3e396a
4 changed files with 158 additions and 0 deletions
|
@ -37,6 +37,7 @@ add_executable (core_test
|
|||
uint256_union.cpp
|
||||
utility.cpp
|
||||
versioning.cpp
|
||||
vote_processor.cpp
|
||||
wallet.cpp
|
||||
wallets.cpp
|
||||
websocket.cpp
|
||||
|
|
142
nano/core_test/vote_processor.cpp
Normal file
142
nano/core_test/vote_processor.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
#include <nano/core_test/testutil.hpp>
|
||||
#include <nano/lib/jsonconfig.hpp>
|
||||
#include <nano/node/testing.hpp>
|
||||
#include <nano/node/vote_processor.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
TEST (vote_processor, codes)
|
||||
{
|
||||
nano::system system (1);
|
||||
auto & node (*system.nodes[0]);
|
||||
nano::genesis genesis;
|
||||
nano::keypair key;
|
||||
auto vote (std::make_shared<nano::vote> (key.pub, key.prv, 1, std::vector<nano::block_hash>{ genesis.open->hash () }));
|
||||
auto vote_invalid = std::make_shared<nano::vote> (*vote);
|
||||
vote_invalid->signature.bytes[0] ^= 1;
|
||||
auto channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version));
|
||||
|
||||
// Invalid signature
|
||||
ASSERT_EQ (nano::vote_code::invalid, node.vote_processor.vote_blocking (vote_invalid, channel, false));
|
||||
|
||||
// Hint of pre-validation
|
||||
ASSERT_NE (nano::vote_code::invalid, node.vote_processor.vote_blocking (vote_invalid, channel, true));
|
||||
|
||||
// No ongoing election
|
||||
ASSERT_EQ (nano::vote_code::indeterminate, node.vote_processor.vote_blocking (vote, channel));
|
||||
|
||||
// First vote from an account for an ongoing election
|
||||
ASSERT_TRUE (node.active.insert (genesis.open).second);
|
||||
ASSERT_EQ (nano::vote_code::vote, node.vote_processor.vote_blocking (vote, channel));
|
||||
|
||||
// Processing the same vote is a replay
|
||||
ASSERT_EQ (nano::vote_code::replay, node.vote_processor.vote_blocking (vote, channel));
|
||||
|
||||
// Invalid takes precedence
|
||||
ASSERT_EQ (nano::vote_code::invalid, node.vote_processor.vote_blocking (vote_invalid, channel));
|
||||
|
||||
// A higher sequence is not a replay
|
||||
++vote->sequence;
|
||||
ASSERT_EQ (nano::vote_code::invalid, node.vote_processor.vote_blocking (vote, channel));
|
||||
vote->signature = nano::sign_message (key.prv, key.pub, vote->hash ());
|
||||
ASSERT_EQ (nano::vote_code::vote, node.vote_processor.vote_blocking (vote, channel));
|
||||
|
||||
// Once the election is removed (confirmed / dropped) the vote is again indeterminate
|
||||
node.active.erase (*genesis.open);
|
||||
ASSERT_EQ (nano::vote_code::indeterminate, node.vote_processor.vote_blocking (vote, channel));
|
||||
}
|
||||
|
||||
TEST (vote_processor, flush)
|
||||
{
|
||||
nano::system system (1);
|
||||
auto & node (*system.nodes[0]);
|
||||
nano::genesis genesis;
|
||||
auto vote (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, std::vector<nano::block_hash>{ genesis.open->hash () }));
|
||||
auto channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version));
|
||||
for (unsigned i = 0; i < 2000; ++i)
|
||||
{
|
||||
node.vote_processor.vote (vote, channel);
|
||||
++vote->sequence; // invalidates votes without signing again
|
||||
}
|
||||
node.vote_processor.flush ();
|
||||
ASSERT_TRUE (node.vote_processor.empty ());
|
||||
}
|
||||
|
||||
TEST (vote_processor, invalid_signature)
|
||||
{
|
||||
nano::system system (1);
|
||||
auto & node (*system.nodes[0]);
|
||||
nano::genesis genesis;
|
||||
nano::keypair key;
|
||||
auto vote (std::make_shared<nano::vote> (key.pub, key.prv, 1, std::vector<nano::block_hash>{ genesis.open->hash () }));
|
||||
auto vote_invalid = std::make_shared<nano::vote> (*vote);
|
||||
vote_invalid->signature.bytes[0] ^= 1;
|
||||
auto channel (std::make_shared<nano::transport::channel_udp> (node.network.udp_channels, node.network.endpoint (), node.network_params.protocol.protocol_version));
|
||||
|
||||
auto election (node.active.insert (genesis.open));
|
||||
ASSERT_TRUE (election.first && election.second);
|
||||
ASSERT_EQ (1, election.first->last_votes.size ());
|
||||
node.vote_processor.vote (vote_invalid, channel);
|
||||
node.vote_processor.flush ();
|
||||
ASSERT_EQ (1, election.first->last_votes.size ());
|
||||
node.vote_processor.vote (vote, channel);
|
||||
node.vote_processor.flush ();
|
||||
ASSERT_EQ (2, election.first->last_votes.size ());
|
||||
}
|
||||
|
||||
namespace nano
|
||||
{
|
||||
TEST (vote_processor, weights)
|
||||
{
|
||||
nano::system system (4);
|
||||
auto & node (*system.nodes[0]);
|
||||
|
||||
// Create representatives of different weight levels
|
||||
// The online stake will be the minimum configurable due to online_reps sampling in tests
|
||||
auto const online = node.config.online_weight_minimum.number ();
|
||||
auto const level0 = online / 5000; // 0.02%
|
||||
auto const level1 = online / 500; // 0.2%
|
||||
auto const level2 = online / 50; // 2%
|
||||
|
||||
nano::keypair key0;
|
||||
nano::keypair key1;
|
||||
nano::keypair key2;
|
||||
|
||||
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
|
||||
system.wallet (1)->insert_adhoc (key0.prv);
|
||||
system.wallet (2)->insert_adhoc (key1.prv);
|
||||
system.wallet (3)->insert_adhoc (key2.prv);
|
||||
system.wallet (1)->store.representative_set (system.nodes[1]->wallets.tx_begin_write (), key0.pub);
|
||||
system.wallet (2)->store.representative_set (system.nodes[2]->wallets.tx_begin_write (), key1.pub);
|
||||
system.wallet (3)->store.representative_set (system.nodes[3]->wallets.tx_begin_write (), key2.pub);
|
||||
system.wallet (0)->send_sync (nano::test_genesis_key.pub, key0.pub, level0);
|
||||
system.wallet (0)->send_sync (nano::test_genesis_key.pub, key1.pub, level1);
|
||||
system.wallet (0)->send_sync (nano::test_genesis_key.pub, key2.pub, level2);
|
||||
|
||||
// Wait for representatives
|
||||
system.deadline_set (10s);
|
||||
while (node.ledger.cache.rep_weights.get_rep_amounts ().size () != 4)
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
node.vote_processor.calculate_weights ();
|
||||
|
||||
ASSERT_EQ (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (key0.pub));
|
||||
ASSERT_EQ (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (key0.pub));
|
||||
ASSERT_EQ (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (key0.pub));
|
||||
|
||||
ASSERT_NE (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (key1.pub));
|
||||
ASSERT_EQ (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (key1.pub));
|
||||
ASSERT_EQ (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (key1.pub));
|
||||
|
||||
ASSERT_NE (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (key2.pub));
|
||||
ASSERT_NE (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (key2.pub));
|
||||
ASSERT_EQ (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (key2.pub));
|
||||
|
||||
ASSERT_NE (node.vote_processor.representatives_1.end (), node.vote_processor.representatives_1.find (nano::test_genesis_key.pub));
|
||||
ASSERT_NE (node.vote_processor.representatives_2.end (), node.vote_processor.representatives_2.find (nano::test_genesis_key.pub));
|
||||
ASSERT_NE (node.vote_processor.representatives_3.end (), node.vote_processor.representatives_3.find (nano::test_genesis_key.pub));
|
||||
}
|
||||
}
|
|
@ -233,6 +233,18 @@ void nano::vote_processor::flush ()
|
|||
}
|
||||
}
|
||||
|
||||
size_t nano::vote_processor::size ()
|
||||
{
|
||||
nano::lock_guard<std::mutex> guard (mutex);
|
||||
return votes.size ();
|
||||
}
|
||||
|
||||
bool nano::vote_processor::empty ()
|
||||
{
|
||||
nano::lock_guard<std::mutex> guard (mutex);
|
||||
return votes.empty ();
|
||||
}
|
||||
|
||||
void nano::vote_processor::calculate_weights ()
|
||||
{
|
||||
nano::unique_lock<std::mutex> lock (mutex);
|
||||
|
|
|
@ -38,6 +38,8 @@ public:
|
|||
nano::vote_code vote_blocking (std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>, bool = false);
|
||||
void verify_votes (std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> const &);
|
||||
void flush ();
|
||||
size_t size ();
|
||||
bool empty ();
|
||||
void calculate_weights ();
|
||||
void stop ();
|
||||
|
||||
|
@ -67,6 +69,7 @@ private:
|
|||
std::thread thread;
|
||||
|
||||
friend std::unique_ptr<container_info_component> collect_container_info (vote_processor & vote_processor, const std::string & name);
|
||||
friend class vote_processor_weights_Test;
|
||||
};
|
||||
|
||||
std::unique_ptr<container_info_component> collect_container_info (vote_processor & vote_processor, const std::string & name);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue