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
|
uint256_union.cpp
|
||||||
utility.cpp
|
utility.cpp
|
||||||
versioning.cpp
|
versioning.cpp
|
||||||
|
vote_processor.cpp
|
||||||
wallet.cpp
|
wallet.cpp
|
||||||
wallets.cpp
|
wallets.cpp
|
||||||
websocket.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 ()
|
void nano::vote_processor::calculate_weights ()
|
||||||
{
|
{
|
||||||
nano::unique_lock<std::mutex> lock (mutex);
|
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);
|
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 verify_votes (std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> const &);
|
||||||
void flush ();
|
void flush ();
|
||||||
|
size_t size ();
|
||||||
|
bool empty ();
|
||||||
void calculate_weights ();
|
void calculate_weights ();
|
||||||
void stop ();
|
void stop ();
|
||||||
|
|
||||||
|
|
@ -67,6 +69,7 @@ private:
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
|
|
||||||
friend std::unique_ptr<container_info_component> collect_container_info (vote_processor & vote_processor, const std::string & name);
|
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);
|
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