Fix epoch_conflict_confirm
test (#3906)
* Add test utility functions * Fix `epoch_conflict_confirm` test * Renaming
This commit is contained in:
parent
6bf38ffb04
commit
55625db016
5 changed files with 158 additions and 42 deletions
|
@ -2689,9 +2689,9 @@ TEST (node, epoch_conflict_confirm)
|
|||
nano::test::system system;
|
||||
nano::node_config node_config (nano::test::get_available_port (), system.logging);
|
||||
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
|
||||
auto node0 = system.add_node (node_config);
|
||||
auto & node0 = *system.add_node (node_config);
|
||||
node_config.peering_port = nano::test::get_available_port ();
|
||||
auto node1 = system.add_node (node_config);
|
||||
auto & node1 = *system.add_node (node_config);
|
||||
nano::keypair key;
|
||||
nano::keypair epoch_signer (nano::dev::genesis_key);
|
||||
nano::state_block_builder builder;
|
||||
|
@ -2736,44 +2736,44 @@ TEST (node, epoch_conflict_confirm)
|
|||
.previous (0)
|
||||
.representative (0)
|
||||
.balance (0)
|
||||
.link (node0->ledger.epoch_link (nano::epoch::epoch_1))
|
||||
.link (node0.ledger.epoch_link (nano::epoch::epoch_1))
|
||||
.sign (epoch_signer.prv, epoch_signer.pub)
|
||||
.work (*system.work.generate (open->hash ()))
|
||||
.build_shared ();
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*send).code);
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*send2).code);
|
||||
ASSERT_EQ (nano::process_result::progress, node1->process (*open).code);
|
||||
// Confirm block in node1 to allow generating votes
|
||||
node1->block_confirm (open);
|
||||
auto election (node1->active.election (open->qualified_root ()));
|
||||
ASSERT_NE (nullptr, election);
|
||||
election->force_confirm ();
|
||||
ASSERT_TIMELY (3s, node1->block_confirmed (open->hash ()));
|
||||
ASSERT_EQ (nano::process_result::progress, node0->process (*send).code);
|
||||
ASSERT_EQ (nano::process_result::progress, node0->process (*send2).code);
|
||||
ASSERT_EQ (nano::process_result::progress, node0->process (*open).code);
|
||||
node0->process_active (change);
|
||||
node0->process_active (epoch_open);
|
||||
ASSERT_TIMELY (10s, node0->block (change->hash ()) && node0->block (epoch_open->hash ()) && node1->block (change->hash ()) && node1->block (epoch_open->hash ()));
|
||||
// Confirm blocks in node1 to allow generating votes
|
||||
nano::test::blocks_confirm (*node1, { change, epoch_open }, true /* forced */);
|
||||
ASSERT_TIMELY (3s, node1->block_confirmed (change->hash ()) && node1->block_confirmed (epoch_open->hash ()));
|
||||
// Start elections for node0
|
||||
nano::test::blocks_confirm (*node0, { change, epoch_open });
|
||||
ASSERT_EQ (2, node0->active.size ());
|
||||
{
|
||||
nano::lock_guard<nano::mutex> lock (node0->active.mutex);
|
||||
ASSERT_TRUE (node0->active.blocks.find (change->hash ()) != node0->active.blocks.end ());
|
||||
ASSERT_TRUE (node0->active.blocks.find (epoch_open->hash ()) != node0->active.blocks.end ());
|
||||
}
|
||||
|
||||
// Process initial blocks on node1
|
||||
ASSERT_TRUE (nano::test::process (node1, { send, send2, open }));
|
||||
|
||||
// Confirm open block in node1 to allow generating votes
|
||||
ASSERT_TRUE (nano::test::confirm (node1, { open }));
|
||||
ASSERT_TIMELY (5s, nano::test::confirmed (node1, { open }));
|
||||
|
||||
// Process initial blocks on node0
|
||||
ASSERT_TRUE (nano::test::process (node0, { send, send2, open }));
|
||||
|
||||
// Process conflicting blocks on node 0 as blocks coming from live network
|
||||
ASSERT_TRUE (nano::test::process_live (node0, { change, epoch_open }));
|
||||
|
||||
// Ensure blocks were propagated to both nodes
|
||||
ASSERT_TIMELY (5s, nano::test::exists (node0, { change, epoch_open }));
|
||||
ASSERT_TIMELY (5s, nano::test::exists (node1, { change, epoch_open }));
|
||||
|
||||
// Confirm initial blocks in node1 to allow generating votes later
|
||||
ASSERT_TRUE (nano::test::confirm (node1, { change, epoch_open, send2 }));
|
||||
ASSERT_TIMELY (5s, nano::test::confirmed (node1, { change, epoch_open, send2 }));
|
||||
|
||||
// Start elections for node0 for conflicting change and epoch_open blocks (those two blocks have the same root)
|
||||
ASSERT_TRUE (nano::test::activate (node0, { change, epoch_open }));
|
||||
ASSERT_TIMELY (5s, nano::test::active (node0, { change, epoch_open }));
|
||||
|
||||
// Make node1 a representative
|
||||
system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv);
|
||||
ASSERT_TIMELY (5s, node0->active.election (change->qualified_root ()) == nullptr);
|
||||
ASSERT_TIMELY (5s, node0->active.empty ());
|
||||
{
|
||||
auto transaction (node0->store.tx_begin_read ());
|
||||
ASSERT_TRUE (node0->ledger.store.block.exists (transaction, change->hash ()));
|
||||
ASSERT_TRUE (node0->ledger.store.block.exists (transaction, epoch_open->hash ()));
|
||||
}
|
||||
|
||||
// Ensure the elections for conflicting blocks have completed
|
||||
ASSERT_TIMELY (5s, nano::test::active (node0, { change, epoch_open }));
|
||||
|
||||
// Ensure both conflicting blocks were successfully processed and confirmed
|
||||
ASSERT_TIMELY (5s, nano::test::confirmed (node0, { change, epoch_open }));
|
||||
}
|
||||
|
||||
// Test disabled because it's failing intermittently.
|
||||
|
|
|
@ -511,6 +511,12 @@ bool nano::active_transactions::active (nano::block const & block_a)
|
|||
return roots.get<tag_root> ().find (block_a.qualified_root ()) != roots.get<tag_root> ().end () && blocks.find (block_a.hash ()) != blocks.end ();
|
||||
}
|
||||
|
||||
bool nano::active_transactions::active (const nano::block_hash & hash)
|
||||
{
|
||||
nano::lock_guard<nano::mutex> guard{ mutex };
|
||||
return blocks.find (hash) != blocks.end ();
|
||||
}
|
||||
|
||||
std::shared_ptr<nano::election> nano::active_transactions::election (nano::qualified_root const & root_a) const
|
||||
{
|
||||
std::shared_ptr<nano::election> result;
|
||||
|
|
|
@ -151,6 +151,10 @@ public:
|
|||
// Is the root of this block in the roots container
|
||||
bool active (nano::block const &);
|
||||
bool active (nano::qualified_root const &);
|
||||
/*
|
||||
* Is the block hash present in any active election
|
||||
*/
|
||||
bool active (nano::block_hash const &);
|
||||
std::shared_ptr<nano::election> election (nano::qualified_root const &) const;
|
||||
std::shared_ptr<nano::block> winner (nano::block_hash const &) const;
|
||||
// Returns a list of elections sorted by difficulty
|
||||
|
|
|
@ -50,6 +50,15 @@ bool nano::test::process (nano::node & node, std::vector<std::shared_ptr<nano::b
|
|||
return true;
|
||||
}
|
||||
|
||||
bool nano::test::process_live (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
for (auto & block : blocks)
|
||||
{
|
||||
node.process_active (block);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nano::test::confirm (nano::node & node, std::vector<nano::block_hash> hashes)
|
||||
{
|
||||
// Finish processing all blocks
|
||||
|
@ -79,9 +88,7 @@ bool nano::test::confirm (nano::node & node, std::vector<nano::block_hash> hashe
|
|||
|
||||
bool nano::test::confirm (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
std::vector<nano::block_hash> hashes;
|
||||
std::transform (blocks.begin (), blocks.end (), std::back_inserter (hashes), [] (auto & block) { return block->hash (); });
|
||||
return confirm (node, hashes);
|
||||
return confirm (node, blocks_to_hashes (blocks));
|
||||
}
|
||||
|
||||
bool nano::test::confirmed (nano::node & node, std::vector<nano::block_hash> hashes)
|
||||
|
@ -98,9 +105,61 @@ bool nano::test::confirmed (nano::node & node, std::vector<nano::block_hash> has
|
|||
|
||||
bool nano::test::confirmed (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
std::vector<nano::block_hash> hashes;
|
||||
std::transform (blocks.begin (), blocks.end (), std::back_inserter (hashes), [] (auto & block) { return block->hash (); });
|
||||
return confirmed (node, hashes);
|
||||
return confirmed (node, blocks_to_hashes (blocks));
|
||||
}
|
||||
|
||||
bool nano::test::exists (nano::node & node, std::vector<nano::block_hash> hashes)
|
||||
{
|
||||
for (auto & hash : hashes)
|
||||
{
|
||||
if (!node.block (hash))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nano::test::exists (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
return exists (node, blocks_to_hashes (blocks));
|
||||
}
|
||||
|
||||
bool nano::test::activate (nano::node & node, std::vector<nano::block_hash> hashes)
|
||||
{
|
||||
for (auto & hash : hashes)
|
||||
{
|
||||
auto disk_block = node.block (hash);
|
||||
if (disk_block == nullptr)
|
||||
{
|
||||
// Block does not exist in the ledger yet
|
||||
return false;
|
||||
}
|
||||
node.scheduler.manual (disk_block);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nano::test::activate (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
return activate (node, blocks_to_hashes (blocks));
|
||||
}
|
||||
|
||||
bool nano::test::active (nano::node & node, std::vector<nano::block_hash> hashes)
|
||||
{
|
||||
for (auto & hash : hashes)
|
||||
{
|
||||
if (!node.active.active (hash))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nano::test::active (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
return active (node, blocks_to_hashes (blocks));
|
||||
}
|
||||
|
||||
std::shared_ptr<nano::vote> nano::test::make_vote (nano::keypair key, std::vector<nano::block_hash> hashes, uint64_t timestamp, uint8_t duration)
|
||||
|
@ -113,4 +172,11 @@ std::shared_ptr<nano::vote> nano::test::make_vote (nano::keypair key, std::vecto
|
|||
std::vector<nano::block_hash> hashes;
|
||||
std::transform (blocks.begin (), blocks.end (), std::back_inserter (hashes), [] (auto & block) { return block->hash (); });
|
||||
return make_vote (key, hashes, timestamp, duration);
|
||||
}
|
||||
|
||||
std::vector<nano::block_hash> nano::test::blocks_to_hashes (std::vector<std::shared_ptr<nano::block>> blocks)
|
||||
{
|
||||
std::vector<nano::block_hash> hashes;
|
||||
std::transform (blocks.begin (), blocks.end (), std::back_inserter (hashes), [] (auto & block) { return block->hash (); });
|
||||
return hashes;
|
||||
}
|
|
@ -224,6 +224,12 @@ namespace test
|
|||
@return true if all blocks were successfully processed and inserted into ledger
|
||||
*/
|
||||
bool process (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks);
|
||||
/*
|
||||
* Convenience function to process multiple blocks as if they were live blocks arriving from the network
|
||||
* It is not guaranted that those blocks will be inserted into ledger (there might be forks, missing links etc)
|
||||
* @return true if all blocks were successfully processed
|
||||
*/
|
||||
bool process_live (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks);
|
||||
/*
|
||||
* Convenience function to confirm a list of blocks
|
||||
* The actual confirmation will happen asynchronously, check for that with `nano::test::confirmed (..)` function
|
||||
|
@ -246,6 +252,36 @@ namespace test
|
|||
* @return true if all blocks are confirmed, false otherwise
|
||||
*/
|
||||
bool confirmed (nano::node & node, std::vector<nano::block_hash> hashes);
|
||||
/*
|
||||
* Convenience function to check whether a list of hashes exists in node ledger.
|
||||
* @return true if all blocks are fully processed and inserted in the ledger, false otherwise
|
||||
*/
|
||||
bool exists (nano::node & node, std::vector<nano::block_hash> hashes);
|
||||
/*
|
||||
* Convenience function to check whether a list of blocks exists in node ledger.
|
||||
* @return true if all blocks are fully processed and inserted in the ledger, false otherwise
|
||||
*/
|
||||
bool exists (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks);
|
||||
/*
|
||||
* Convenience function to start elections for a list of hashes. Blocks are loaded from ledger.
|
||||
* @return true if all blocks exist and were queued to election scheduler
|
||||
*/
|
||||
bool activate (nano::node & node, std::vector<nano::block_hash> hashes);
|
||||
/*
|
||||
* Convenience function to start elections for a list of hashes. Blocks are loaded from ledger.
|
||||
* @return true if all blocks exist and were queued to election scheduler
|
||||
*/
|
||||
bool activate (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks);
|
||||
/*
|
||||
* Convenience function that checks whether all hashes from list have currently active elections
|
||||
* @return true if all blocks have currently active elections, false othersie
|
||||
*/
|
||||
bool active (nano::node & node, std::vector<nano::block_hash> hashes);
|
||||
/*
|
||||
* Convenience function that checks whether all hashes from list have currently active elections
|
||||
* @return true if all blocks have currently active elections, false othersie
|
||||
*/
|
||||
bool active (nano::node & node, std::vector<std::shared_ptr<nano::block>> blocks);
|
||||
/*
|
||||
* Convenience function to create a new vote from list of blocks
|
||||
*/
|
||||
|
@ -254,5 +290,9 @@ namespace test
|
|||
* Convenience function to create a new vote from list of block hashes
|
||||
*/
|
||||
std::shared_ptr<nano::vote> make_vote (nano::keypair key, std::vector<nano::block_hash> hashes, uint64_t timestamp = 0, uint8_t duration = 0);
|
||||
/*
|
||||
* Converts list of blocks to list of hashes
|
||||
*/
|
||||
std::vector<nano::block_hash> blocks_to_hashes (std::vector<std::shared_ptr<nano::block>> blocks);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue