Skip to content

Commit

Permalink
Return created election when adding to active_transactions (#2551)
Browse files Browse the repository at this point in the history
* This changes the signature of active_transactions::start to match STL container ::insert signatures by returning a pointer to the newly created election and also a bool whether the election creation took place.
This allows the call site to retrieve the election that was inserted and determine if it was the initiator of the election creation.
Also updated tests that were taking extra steps to retrieve the newly created election.

* Renaming active_transactions::start/add to insert/insert_impl to more closely match the behavior that's expected.
  • Loading branch information
clemahieu committed Feb 12, 2020
1 parent 7ad1b49 commit 6e5c0ca
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 166 deletions.
2 changes: 1 addition & 1 deletion nano/core_test/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes)
}
ASSERT_EQ (1, node.active.inactive_votes_cache_size ());
// Start election
node.active.start (send1);
node.active.insert (send1);
{
nano::lock_guard<std::mutex> active_guard (node.active.mutex);
auto it (node.active.roots.begin ());
Expand Down
37 changes: 15 additions & 22 deletions nano/core_test/conflicts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@ TEST (conflicts, start_stop)
node1.work_generate_blocking (*send1);
ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code);
ASSERT_EQ (0, node1.active.size ());
node1.active.start (send1);
auto election1 = node1.active.insert (send1);
ASSERT_EQ (1, node1.active.size ());
{
nano::lock_guard<std::mutex> guard (node1.active.mutex);
auto existing1 (node1.active.roots.find (send1->qualified_root ()));
ASSERT_NE (node1.active.roots.end (), existing1);
auto votes1 (existing1->election);
ASSERT_NE (nullptr, votes1);
ASSERT_EQ (1, votes1->last_votes.size ());
ASSERT_NE (nullptr, election1.first);
ASSERT_EQ (1, election1.first->last_votes.size ());
}
}

Expand All @@ -39,20 +36,19 @@ TEST (conflicts, add_existing)
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send1);
ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code);
node1.active.start (send1);
node1.active.insert (send1);
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.active.start (send2);
auto election1 = node1.active.insert (send2);
ASSERT_EQ (1, node1.active.size ());
auto vote1 (std::make_shared<nano::vote> (key2.pub, key2.prv, 0, send2));
node1.active.vote (vote1);
ASSERT_EQ (1, node1.active.size ());
{
nano::lock_guard<std::mutex> guard (node1.active.mutex);
auto votes1 (node1.active.roots.find (send2->qualified_root ())->election);
ASSERT_NE (nullptr, votes1);
ASSERT_EQ (2, votes1->last_votes.size ());
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (key2.pub));
ASSERT_NE (nullptr, election1.first);
ASSERT_EQ (2, election1.first->last_votes.size ());
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (key2.pub));
}
}

Expand All @@ -65,12 +61,12 @@ TEST (conflicts, add_two)
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send1);
ASSERT_EQ (nano::process_result::progress, node1.process (*send1).code);
node1.active.start (send1);
node1.active.insert (send1);
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (send1->hash (), key2.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send2);
ASSERT_EQ (nano::process_result::progress, node1.process (*send2).code);
node1.active.start (send2);
node1.active.insert (send2);
ASSERT_EQ (2, node1.active.size ());
}

Expand Down Expand Up @@ -208,18 +204,15 @@ TEST (conflicts, dependency)
ASSERT_EQ (nano::process_result::progress, node1->process (*send1).code);
ASSERT_EQ (nano::process_result::progress, node1->process (*state_open1).code);
ASSERT_EQ (0, node1->active.size ());
node1->active.start (send1);
node1->active.start (state_open1);
auto election1 = node1->active.insert (send1);
node1->active.insert (state_open1);
ASSERT_EQ (2, node1->active.size ());
// Check dependency for send block
{
nano::lock_guard<std::mutex> guard (node1->active.mutex);
auto existing1 (node1->active.roots.find (send1->qualified_root ()));
ASSERT_NE (node1->active.roots.end (), existing1);
auto election1 (existing1->election);
ASSERT_NE (nullptr, election1);
ASSERT_EQ (1, election1->dependent_blocks.size ());
ASSERT_NE (election1->dependent_blocks.end (), election1->dependent_blocks.find (state_open1->hash ()));
ASSERT_NE (nullptr, election1.first);
ASSERT_EQ (1, election1.first->dependent_blocks.size ());
ASSERT_NE (election1.first->dependent_blocks.end (), election1.first->dependent_blocks.find (state_open1->hash ()));
}
}

Expand Down
148 changes: 65 additions & 83 deletions nano/core_test/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,11 +738,10 @@ TEST (votes, check_signature)
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
}
node1.active.start (send1);
auto election1 = node1.active.insert (send1);
{
nano::lock_guard<std::mutex> lock (node1.active.mutex);
auto votes1 (node1.active.roots.find (send1->qualified_root ())->election);
ASSERT_EQ (1, votes1->last_votes.size ());
ASSERT_EQ (1, election1.first->last_votes.size ());
}
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1));
vote1->signature.bytes[0] ^= 1;
Expand All @@ -762,21 +761,20 @@ TEST (votes, add_one)
node1.work_generate_blocking (*send1);
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
node1.active.start (send1);
auto election1 = node1.active.insert (send1);
nano::unique_lock<std::mutex> lock (node1.active.mutex);
auto votes1 (node1.active.roots.find (send1->qualified_root ())->election);
ASSERT_EQ (1, votes1->last_votes.size ());
ASSERT_EQ (1, election1.first->last_votes.size ());
lock.unlock ();
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1));
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
auto vote2 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send1));
ASSERT_EQ (nano::vote_code::indeterminate, node1.active.vote (vote2));
lock.lock ();
ASSERT_EQ (2, votes1->last_votes.size ());
auto existing1 (votes1->last_votes.find (nano::test_genesis_key.pub));
ASSERT_NE (votes1->last_votes.end (), existing1);
ASSERT_EQ (2, election1.first->last_votes.size ());
auto existing1 (election1.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_NE (election1.first->last_votes.end (), existing1);
ASSERT_EQ (send1->hash (), existing1->second.hash);
auto winner (*votes1->tally ().begin ());
auto winner (*election1.first->tally ().begin ());
ASSERT_EQ (*send1, *winner.second);
ASSERT_EQ (nano::genesis_amount - 100, winner.first);
}
Expand All @@ -791,9 +789,8 @@ TEST (votes, add_two)
node1.work_generate_blocking (*send1);
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
node1.active.start (send1);
auto election1 = node1.active.insert (send1);
nano::unique_lock<std::mutex> lock (node1.active.mutex);
auto votes1 (node1.active.roots.find (send1->qualified_root ())->election);
lock.unlock ();
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
Expand All @@ -802,12 +799,12 @@ TEST (votes, add_two)
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1));
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
lock.lock ();
ASSERT_EQ (3, votes1->last_votes.size ());
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), votes1->last_votes[nano::test_genesis_key.pub].hash);
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (key2.pub));
ASSERT_EQ (send2->hash (), votes1->last_votes[key2.pub].hash);
auto winner (*votes1->tally ().begin ());
ASSERT_EQ (3, election1.first->last_votes.size ());
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), election1.first->last_votes[nano::test_genesis_key.pub].hash);
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (key2.pub));
ASSERT_EQ (send2->hash (), election1.first->last_votes[key2.pub].hash);
auto winner (*election1.first->tally ().begin ());
ASSERT_EQ (*send1, *winner.second);
}

Expand All @@ -827,37 +824,36 @@ TEST (votes, add_existing)
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
}
node1.active.start (send1);
auto election1 = node1.active.insert (send1);
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1));
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote1));
// Block is already processed from vote
ASSERT_TRUE (node1.active.publish (send1));
nano::unique_lock<std::mutex> lock (node1.active.mutex);
auto votes1 (node1.active.roots.find (send1->qualified_root ())->election);
ASSERT_EQ (1, votes1->last_votes[nano::test_genesis_key.pub].sequence);
ASSERT_EQ (1, election1.first->last_votes[nano::test_genesis_key.pub].sequence);
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, nano::genesis_amount - nano::Gxrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send2);
auto vote2 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send2));
// Pretend we've waited the timeout
votes1->last_votes[nano::test_genesis_key.pub].time = std::chrono::steady_clock::now () - std::chrono::seconds (20);
election1.first->last_votes[nano::test_genesis_key.pub].time = std::chrono::steady_clock::now () - std::chrono::seconds (20);
lock.unlock ();
ASSERT_EQ (nano::vote_code::vote, node1.active.vote (vote2));
ASSERT_FALSE (node1.active.publish (send2));
lock.lock ();
ASSERT_EQ (2, votes1->last_votes[nano::test_genesis_key.pub].sequence);
ASSERT_EQ (2, election1.first->last_votes[nano::test_genesis_key.pub].sequence);
// Also resend the old vote, and see if we respect the sequence number
votes1->last_votes[nano::test_genesis_key.pub].time = std::chrono::steady_clock::now () - std::chrono::seconds (20);
election1.first->last_votes[nano::test_genesis_key.pub].time = std::chrono::steady_clock::now () - std::chrono::seconds (20);
lock.unlock ();
ASSERT_EQ (nano::vote_code::replay, node1.active.vote (vote1));
lock.lock ();
ASSERT_EQ (2, votes1->last_votes[nano::test_genesis_key.pub].sequence);
ASSERT_EQ (2, votes1->last_votes.size ());
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send2->hash (), votes1->last_votes[nano::test_genesis_key.pub].hash);
ASSERT_EQ (2, election1.first->last_votes[nano::test_genesis_key.pub].sequence);
ASSERT_EQ (2, election1.first->last_votes.size ());
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send2->hash (), election1.first->last_votes[nano::test_genesis_key.pub].hash);
{
auto transaction (node1.store.tx_begin_read ());
auto winner (*votes1->tally ().begin ());
auto winner (*election1.first->tally ().begin ());
ASSERT_EQ (*send2, *winner.second);
}
}
Expand All @@ -873,25 +869,24 @@ TEST (votes, add_old)
node1.work_generate_blocking (*send1);
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
node1.active.start (send1);
auto election1 = node1.active.insert (send1);
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send1));
std::shared_ptr<nano::election> votes1;
{
nano::lock_guard<std::mutex> lock (node1.active.mutex);
votes1 = node1.active.roots.find (send1->qualified_root ())->election;
}
auto channel (std::make_shared<nano::transport::channel_udp> (node1.network.udp_channels, node1.network.endpoint (), node1.network_params.protocol.protocol_version));
node1.vote_processor.vote_blocking (vote1, channel);
nano::keypair key2;
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send2);
auto vote2 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send2));
votes1->last_votes[nano::test_genesis_key.pub].time = std::chrono::steady_clock::now () - std::chrono::seconds (20);
{
nano::lock_guard<std::mutex> lock (node1.active.mutex);
election1.first->last_votes[nano::test_genesis_key.pub].time = std::chrono::steady_clock::now () - std::chrono::seconds (20);
}
node1.vote_processor.vote_blocking (vote2, channel);
ASSERT_EQ (2, votes1->last_votes_size ());
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), votes1->last_votes[nano::test_genesis_key.pub].hash);
auto winner (*votes1->tally ().begin ());
ASSERT_EQ (2, election1.first->last_votes_size ());
nano::lock_guard<std::mutex> lock (node1.active.mutex);
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), election1.first->last_votes[nano::test_genesis_key.pub].hash);
auto winner (*election1.first->tally ().begin ());
ASSERT_EQ (*send1, *winner.second);
}

Expand All @@ -909,35 +904,29 @@ TEST (votes, add_old_different_account)
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send2).code);
node1.active.start (send1);
node1.active.start (send2);
std::shared_ptr<nano::election> votes1;
std::shared_ptr<nano::election> votes2;
{
nano::unique_lock<std::mutex> lock (node1.active.mutex);
votes1 = node1.active.roots.find (send1->qualified_root ())->election;
votes2 = node1.active.roots.find (send2->qualified_root ())->election;
}
ASSERT_EQ (1, votes1->last_votes_size ());
ASSERT_EQ (1, votes2->last_votes_size ());
auto election1 = node1.active.insert (send1);
auto election2 = node1.active.insert (send2);
ASSERT_EQ (1, election1.first->last_votes_size ());
ASSERT_EQ (1, election2.first->last_votes_size ());
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send1));
auto channel (std::make_shared<nano::transport::channel_udp> (node1.network.udp_channels, node1.network.endpoint (), node1.network_params.protocol.protocol_version));
auto vote_result1 (node1.vote_processor.vote_blocking (vote1, channel));
ASSERT_EQ (nano::vote_code::vote, vote_result1);
ASSERT_EQ (2, votes1->last_votes.size ());
ASSERT_EQ (1, votes2->last_votes.size ());
ASSERT_EQ (2, election1.first->last_votes_size ());
ASSERT_EQ (1, election2.first->last_votes_size ());
auto vote2 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send2));
auto vote_result2 (node1.vote_processor.vote_blocking (vote2, channel));
ASSERT_EQ (nano::vote_code::vote, vote_result2);
ASSERT_EQ (2, votes1->last_votes.size ());
ASSERT_EQ (2, votes2->last_votes.size ());
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (nano::test_genesis_key.pub));
ASSERT_NE (votes2->last_votes.end (), votes2->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), votes1->last_votes[nano::test_genesis_key.pub].hash);
ASSERT_EQ (send2->hash (), votes2->last_votes[nano::test_genesis_key.pub].hash);
auto winner1 (*votes1->tally ().begin ());
ASSERT_EQ (2, election1.first->last_votes_size ());
ASSERT_EQ (2, election2.first->last_votes_size ());
nano::unique_lock<std::mutex> lock (node1.active.mutex);
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_NE (election2.first->last_votes.end (), election2.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), election1.first->last_votes[nano::test_genesis_key.pub].hash);
ASSERT_EQ (send2->hash (), election2.first->last_votes[nano::test_genesis_key.pub].hash);
auto winner1 (*election1.first->tally ().begin ());
ASSERT_EQ (*send1, *winner1.second);
auto winner2 (*votes2->tally ().begin ());
auto winner2 (*election2.first->tally ().begin ());
ASSERT_EQ (*send2, *winner2.second);
}

Expand All @@ -952,12 +941,7 @@ TEST (votes, add_cooldown)
node1.work_generate_blocking (*send1);
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send1).code);
node1.active.start (send1);
std::shared_ptr<nano::election> votes1;
{
nano::unique_lock<std::mutex> lock (node1.active.mutex);
votes1 = node1.active.roots.find (send1->qualified_root ())->election;
}
auto election1 = node1.active.insert (send1);
auto vote1 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1));
auto channel (std::make_shared<nano::transport::channel_udp> (node1.network.udp_channels, node1.network.endpoint (), node1.network_params.protocol.protocol_version));
node1.vote_processor.vote_blocking (vote1, channel);
Expand All @@ -966,10 +950,11 @@ TEST (votes, add_cooldown)
node1.work_generate_blocking (*send2);
auto vote2 (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send2));
node1.vote_processor.vote_blocking (vote2, channel);
ASSERT_EQ (2, votes1->last_votes.size ());
ASSERT_NE (votes1->last_votes.end (), votes1->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), votes1->last_votes[nano::test_genesis_key.pub].hash);
auto winner (*votes1->tally ().begin ());
nano::unique_lock<std::mutex> lock (node1.active.mutex);
ASSERT_EQ (2, election1.first->last_votes.size ());
ASSERT_NE (election1.first->last_votes.end (), election1.first->last_votes.find (nano::test_genesis_key.pub));
ASSERT_EQ (send1->hash (), election1.first->last_votes[nano::test_genesis_key.pub].hash);
auto winner (*election1.first->tally ().begin ());
ASSERT_EQ (*send1, *winner.second);
}

Expand Down Expand Up @@ -2659,18 +2644,15 @@ TEST (ledger, block_hash_account_conflict)
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *receive1).code);
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *send2).code);
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *open_epoch1).code);
node1.active.start (send1);
node1.active.start (receive1);
node1.active.start (send2);
node1.active.start (open_epoch1);
auto votes1 (node1.active.roots.find (send1->qualified_root ())->election);
auto votes2 (node1.active.roots.find (receive1->qualified_root ())->election);
auto votes3 (node1.active.roots.find (send2->qualified_root ())->election);
auto votes4 (node1.active.roots.find (open_epoch1->qualified_root ())->election);
auto winner1 (*votes1->tally ().begin ());
auto winner2 (*votes2->tally ().begin ());
auto winner3 (*votes3->tally ().begin ());
auto winner4 (*votes4->tally ().begin ());
auto election1 = node1.active.insert (send1);
auto election2 = node1.active.insert (receive1);
auto election3 = node1.active.insert (send2);
auto election4 = node1.active.insert (open_epoch1);
nano::lock_guard<std::mutex> lock (node1.active.mutex);
auto winner1 (*election1.first->tally ().begin ());
auto winner2 (*election2.first->tally ().begin ());
auto winner3 (*election3.first->tally ().begin ());
auto winner4 (*election4.first->tally ().begin ());
ASSERT_EQ (*send1, *winner1.second);
ASSERT_EQ (*receive1, *winner2.second);
ASSERT_EQ (*send2, *winner3.second);
Expand Down
Loading

0 comments on commit 6e5c0ca

Please sign in to comment.