From 6e5c0ca16b249886ba16ee9218686bce4062e890 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Wed, 12 Feb 2020 19:58:26 +0100 Subject: [PATCH] Return created election when adding to active_transactions (#2551) * 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. --- nano/core_test/active_transactions.cpp | 2 +- nano/core_test/conflicts.cpp | 37 +++---- nano/core_test/ledger.cpp | 148 +++++++++++-------------- nano/core_test/network.cpp | 4 +- nano/core_test/node.cpp | 14 +-- nano/node/active_transactions.cpp | 53 +++++---- nano/node/active_transactions.hpp | 4 +- nano/node/blockprocessor.cpp | 2 +- nano/node/node.cpp | 41 +++---- nano/rpc_test/rpc.cpp | 4 +- 10 files changed, 143 insertions(+), 166 deletions(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 8e9a011397..491ec6086b 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -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 active_guard (node.active.mutex); auto it (node.active.roots.begin ()); diff --git a/nano/core_test/conflicts.cpp b/nano/core_test/conflicts.cpp index 41ca3f10a1..ee6357f367 100644 --- a/nano/core_test/conflicts.cpp +++ b/nano/core_test/conflicts.cpp @@ -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 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 ()); } } @@ -39,20 +36,19 @@ TEST (conflicts, add_existing) auto send1 (std::make_shared (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 (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 (key2.pub, key2.prv, 0, send2)); node1.active.vote (vote1); ASSERT_EQ (1, node1.active.size ()); { nano::lock_guard 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)); } } @@ -65,12 +61,12 @@ TEST (conflicts, add_two) auto send1 (std::make_shared (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 (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 ()); } @@ -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 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 ())); } } diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 3c94809e39..ed438fa646 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -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 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::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1)); vote1->signature.bytes[0] ^= 1; @@ -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 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::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::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); } @@ -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 lock (node1.active.mutex); - auto votes1 (node1.active.roots.find (send1->qualified_root ())->election); lock.unlock (); nano::keypair key2; auto send2 (std::make_shared (genesis.hash (), key2.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); @@ -802,12 +799,12 @@ TEST (votes, add_two) auto vote1 (std::make_shared (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); } @@ -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::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 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 (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::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); } } @@ -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::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send1)); - std::shared_ptr votes1; - { - nano::lock_guard lock (node1.active.mutex); - votes1 = node1.active.roots.find (send1->qualified_root ())->election; - } auto channel (std::make_shared (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 (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::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 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 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); } @@ -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 votes1; - std::shared_ptr votes2; - { - nano::unique_lock 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::test_genesis_key.pub, nano::test_genesis_key.prv, 2, send1)); auto channel (std::make_shared (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::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 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); } @@ -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 votes1; - { - nano::unique_lock 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::test_genesis_key.pub, nano::test_genesis_key.prv, 1, send1)); auto channel (std::make_shared (node1.network.udp_channels, node1.network.endpoint (), node1.network_params.protocol.protocol_version)); node1.vote_processor.vote_blocking (vote1, channel); @@ -966,10 +950,11 @@ TEST (votes, add_cooldown) node1.work_generate_blocking (*send2); auto vote2 (std::make_shared (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 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); } @@ -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 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); diff --git a/nano/core_test/network.cpp b/nano/core_test/network.cpp index f6cc17ac9c..b820de7850 100644 --- a/nano/core_test/network.cpp +++ b/nano/core_test/network.cpp @@ -375,7 +375,7 @@ TEST (receivable_processor, confirm_insufficient_pos) auto block1 (std::make_shared (genesis.hash (), 0, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); node1.work_generate_blocking (*block1); ASSERT_EQ (nano::process_result::progress, node1.process (*block1).code); - node1.active.start (block1); + node1.active.insert (block1); nano::keypair key1; auto vote (std::make_shared (key1.pub, key1.prv, 0, block1)); nano::confirm_ack con1 (vote); @@ -390,7 +390,7 @@ TEST (receivable_processor, confirm_sufficient_pos) auto block1 (std::make_shared (genesis.hash (), 0, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0)); node1.work_generate_blocking (*block1); ASSERT_EQ (nano::process_result::progress, node1.process (*block1).code); - node1.active.start (block1); + node1.active.insert (block1); auto vote (std::make_shared (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 0, block1)); nano::confirm_ack con1 (vote); node1.network.process_message (con1, node1.network.udp_channels.create (node1.network.endpoint ())); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index 818abf2cf1..cb0e081e1b 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -1827,22 +1827,16 @@ TEST (node, rep_self_vote) node0->work_generate_blocking (*block0); ASSERT_EQ (nano::process_result::progress, node0->process (*block0).code); auto & active (node0->active); - active.start (block0); - std::shared_ptr election; - { - nano::unique_lock lock (active.mutex); - auto existing (active.roots.find (block0->qualified_root ())); - ASSERT_NE (active.roots.end (), existing); - election = existing->election; - } + auto election1 = active.insert (block0); node0->block_processor.generator.add (block0->hash ()); system.deadline_set (1s); // Wait until representatives are activated & make vote - while (election->last_votes_size () != 3) + while (election1.first->last_votes_size () != 3) { ASSERT_NO_ERROR (system.poll ()); } - auto & rep_votes (election->last_votes); + nano::unique_lock lock (active.mutex); + auto & rep_votes (election1.first->last_votes); ASSERT_NE (rep_votes.end (), rep_votes.find (nano::test_genesis_key.pub)); ASSERT_NE (rep_votes.end (), rep_votes.find (rep_big.pub)); } diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 2697a72010..d4d55186eb 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -105,7 +105,7 @@ void nano::active_transactions::search_frontiers (nano::transaction const & tran if (info.block_count > confirmation_height_info.height && !this->confirmation_height_processor.is_processing_block (info.head)) { auto block (this->node.store.block_get (transaction_a, info.head)); - if (!this->start (block, true)) + if (this->insert (block, true).first) { ++elections_count; // Calculate votes for local representatives @@ -232,7 +232,7 @@ void nano::active_transactions::election_escalate (std::shared_ptr block_a, bool const skip_delay_a, std::function)> const & confirmation_action_a) +std::pair, bool> nano::active_transactions::insert_impl (std::shared_ptr block_a, bool const skip_delay_a, std::function)> const & confirmation_action_a) { - nano::lock_guard lock (mutex); - return add (block_a, skip_delay_a, confirmation_action_a); -} - -bool nano::active_transactions::add (std::shared_ptr block_a, bool const skip_delay_a, std::function)> const & confirmation_action_a) -{ - auto error (true); + std::pair, bool> result = { nullptr, false }; if (!stopped) { auto root (block_a->qualified_root ()); auto existing (roots.get ().find (root)); - if (existing == roots.get ().end () && confirmed_set.get ().find (root) == confirmed_set.get ().end ()) + if (existing == roots.get ().end ()) { - auto hash (block_a->hash ()); - auto election (nano::make_shared (node, block_a, skip_delay_a, confirmation_action_a)); - uint64_t difficulty (0); - error = nano::work_validate (*block_a, &difficulty); - release_assert (!error); - roots.get ().emplace (nano::conflict_info{ root, difficulty, difficulty, election }); - blocks.emplace (hash, election); - adjust_difficulty (hash); - election->insert_inactive_votes_cache (hash); + if (confirmed_set.get ().find (root) == confirmed_set.get ().end ()) + { + result.second = true; + auto hash (block_a->hash ()); + result.first = nano::make_shared (node, block_a, skip_delay_a, confirmation_action_a); + uint64_t difficulty (0); + release_assert (!nano::work_validate (*block_a, &difficulty)); + roots.get ().emplace (nano::conflict_info{ root, difficulty, difficulty, result.first }); + blocks.emplace (hash, result.first); + adjust_difficulty (hash); + result.first->insert_inactive_votes_cache (hash); + } + } + else + { + result.first = existing->election; } } - return error; + return result; +} + +std::pair, bool> nano::active_transactions::insert (std::shared_ptr block_a, bool const skip_delay_a, std::function)> const & confirmation_action_a) +{ + nano::lock_guard lock (mutex); + return insert_impl (block_a, skip_delay_a, confirmation_action_a); } // Validate a vote and apply it to the current election if one exists @@ -718,7 +725,7 @@ void nano::active_transactions::update_difficulty (std::shared_ptr // Restart election for the upgraded block, previously dropped from elections lock.lock (); - add (existing_block); + insert_impl (existing_block); } } } diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index af2ebee723..11d5958880 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -78,7 +78,7 @@ class active_transactions final // Start an election for a block // Call action with confirmed block, may be different than what we started with // clang-format off - bool start (std::shared_ptr, bool const = false, std::function)> const & = [](std::shared_ptr) {}); + std::pair, bool> insert (std::shared_ptr, bool const = false, std::function)> const & = [](std::shared_ptr) {}); // clang-format on // Distinguishes replay votes, cannot be determined if the block is not in any election nano::vote_code vote (std::shared_ptr); @@ -135,7 +135,7 @@ class active_transactions final private: // Call action with confirmed block, may be different than what we started with // clang-format off - bool add (std::shared_ptr, bool const = false, std::function)> const & = [](std::shared_ptr) {}); + std::pair, bool> insert_impl (std::shared_ptr, bool const = false, std::function)> const & = [](std::shared_ptr) {}); // clang-format on void request_loop (); void search_frontiers (nano::transaction const &); diff --git a/nano/node/blockprocessor.cpp b/nano/node/blockprocessor.cpp index fc323df515..42b7194c28 100644 --- a/nano/node/blockprocessor.cpp +++ b/nano/node/blockprocessor.cpp @@ -379,7 +379,7 @@ void nano::block_processor::process_live (nano::block_hash const & hash_a, std:: } // Start collecting quorum on block - node.active.start (block_a, false); + node.active.insert (block_a, false); // Announce block contents to the network node.network.flood_block (block_a, false); diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 1bcd82cf77..2c674dc7b1 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -547,25 +547,26 @@ void nano::node::process_fork (nano::transaction const & transaction_a, std::sha if (ledger_block && !block_confirmed_or_being_confirmed (transaction_a, ledger_block->hash ())) { std::weak_ptr this_w (shared_from_this ()); - if (!active.start (ledger_block, false, [this_w, root](std::shared_ptr) { - if (auto this_l = this_w.lock ()) - { - auto attempt (this_l->bootstrap_initiator.current_attempt ()); - if (attempt && attempt->mode == nano::bootstrap_mode::legacy) - { - auto transaction (this_l->store.tx_begin_read ()); - auto account (this_l->ledger.store.frontier_get (transaction, root)); - if (!account.is_zero ()) - { - attempt->requeue_pull (nano::pull_info (account, root, root)); - } - else if (this_l->ledger.store.account_exists (transaction, root)) - { - attempt->requeue_pull (nano::pull_info (root, nano::block_hash (0), nano::block_hash (0))); - } - } - } - })) + if (active.insert (ledger_block, false, [this_w, root](std::shared_ptr) { + if (auto this_l = this_w.lock ()) + { + auto attempt (this_l->bootstrap_initiator.current_attempt ()); + if (attempt && attempt->mode == nano::bootstrap_mode::legacy) + { + auto transaction (this_l->store.tx_begin_read ()); + auto account (this_l->ledger.store.frontier_get (transaction, root)); + if (!account.is_zero ()) + { + attempt->requeue_pull (nano::pull_info (account, root, root)); + } + else if (this_l->ledger.store.account_exists (transaction, root)) + { + attempt->requeue_pull (nano::pull_info (root, nano::block_hash (0), nano::block_hash (0))); + } + } + } + }) + .first) { logger.always_log (boost::str (boost::format ("Resolving fork between our block: %1% and block %2% both with root %3%") % ledger_block->hash ().to_string () % block_a->hash ().to_string () % block_a->root ().to_string ())); network.broadcast_confirm_req (ledger_block); @@ -1076,7 +1077,7 @@ void nano::node::add_initial_peers () void nano::node::block_confirm (std::shared_ptr block_a) { - active.start (block_a, false); + active.insert (block_a, false); network.broadcast_confirm_req (block_a); // Calculate votes for local representatives if (config.enable_voting && wallets.rep_counts ().voting > 0 && active.active (*block_a)) diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 75127b5906..4b1580294e 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -2013,7 +2013,7 @@ TEST (rpc, process_subtype_open) ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, send).code); } scoped_io_thread_name_change scoped_thread_name_io; - node1.active.start (std::make_shared (send)); + node1.active.insert (std::make_shared (send)); nano::state_block open (key.pub, 0, key.pub, nano::Gxrb_ratio, send.hash (), key.prv, key.pub, *node1.work_generate_blocking (key.pub)); nano::node_rpc_config node_rpc_config; nano::ipc::ipc_server ipc_server (node1, node_rpc_config); @@ -2072,7 +2072,7 @@ TEST (rpc, process_subtype_receive) ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, send).code); } scoped_io_thread_name_change scoped_thread_name_io; - node1.active.start (std::make_shared (send)); + node1.active.insert (std::make_shared (send)); nano::state_block receive (nano::test_genesis_key.pub, send.hash (), nano::test_genesis_key.pub, nano::genesis_amount, send.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *node1.work_generate_blocking (send.hash ())); nano::node_rpc_config node_rpc_config; nano::ipc::ipc_server ipc_server (node1, node_rpc_config);