Fix active transactions difficulty update for state blocks (#2279)

* Fix active transactions difficulty update for state blocks
due to verify_state_blocks () old blocks filter
* Remove unused read transaction
* Formatting
This commit is contained in:
Sergey Kroshnin 2019-09-04 13:40:43 +03:00 committed by GitHub
commit a4c70b773d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 14 deletions

View file

@ -512,3 +512,54 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes)
}
ASSERT_EQ (2, system.nodes[0]->stats.count (nano::stat::type::election, nano::stat::detail::vote_cached));
}
TEST (active_transactions, update_difficulty)
{
nano::system system (24000, 2);
auto & node1 = *system.nodes[0];
auto & node2 = *system.nodes[1];
nano::genesis genesis;
nano::keypair key1;
// Generate blocks & start elections
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (genesis.hash ())));
uint64_t difficulty1 (0);
nano::work_validate (*send1, &difficulty1);
auto send2 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 200, key1.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (send1->hash ())));
uint64_t difficulty2 (0);
nano::work_validate (*send2, &difficulty2);
node1.process_active (send1);
node1.process_active (send2);
node1.block_processor.flush ();
system.deadline_set (10s);
while (node1.active.size () != 2 || node2.active.size () != 2)
{
ASSERT_NO_ERROR (system.poll ());
}
// Update work with higher difficulty
node1.work_generate_blocking (*send1, difficulty1 + 1);
node1.work_generate_blocking (*send2, difficulty2 + 1);
node1.process_active (send1);
node1.process_active (send2);
node1.block_processor.flush ();
system.deadline_set (10s);
bool done (false);
while (!done)
{
{
// node1
nano::lock_guard<std::mutex> guard1 (node1.active.mutex);
auto const existing1 (node1.active.roots.find (send1->qualified_root ()));
ASSERT_NE (existing1, node1.active.roots.end ());
auto const existing2 (node1.active.roots.find (send2->qualified_root ()));
ASSERT_NE (existing2, node1.active.roots.end ());
// node2
nano::lock_guard<std::mutex> guard2 (node2.active.mutex);
auto const existing3 (node2.active.roots.find (send1->qualified_root ()));
ASSERT_NE (existing3, node2.active.roots.end ());
auto const existing4 (node2.active.roots.find (send2->qualified_root ()));
ASSERT_NE (existing4, node2.active.roots.end ());
done = (existing1->difficulty > difficulty1) && (existing2->difficulty > difficulty2) && (existing3->difficulty > difficulty1) && (existing4->difficulty > difficulty2);
}
ASSERT_NO_ERROR (system.poll ());
}
}

View file

@ -147,20 +147,12 @@ bool nano::block_processor::have_blocks ()
return !blocks.empty () || !forced.empty () || !state_blocks.empty ();
}
void nano::block_processor::verify_state_blocks (nano::transaction const & transaction_a, nano::unique_lock<std::mutex> & lock_a, size_t max_count)
void nano::block_processor::verify_state_blocks (nano::unique_lock<std::mutex> & lock_a, size_t max_count)
{
assert (!mutex.try_lock ());
nano::timer<std::chrono::milliseconds> timer_l (nano::timer_state::started);
std::deque<nano::unchecked_info> items;
for (auto i (0); i < max_count && !state_blocks.empty (); i++)
{
auto & item (state_blocks.front ());
if (!node.ledger.store.block_exists (transaction_a, item.block->type (), item.block->hash ()))
{
items.push_back (std::move (item));
}
state_blocks.pop_front ();
}
items.swap (state_blocks);
lock_a.unlock ();
if (!items.empty ())
{
@ -253,10 +245,9 @@ void nano::block_processor::process_batch (nano::unique_lock<std::mutex> & lock_
if (!state_blocks.empty ())
{
size_t max_verification_batch (node.flags.block_processor_verification_size != 0 ? node.flags.block_processor_verification_size : 2048 * (node.config.signature_checker_threads + 1));
auto transaction (node.store.tx_begin_read ());
while (!state_blocks.empty () && timer_l.before_deadline (std::chrono::seconds (2)))
{
verify_state_blocks (transaction, lock_a, max_verification_batch);
verify_state_blocks (lock_a, max_verification_batch);
}
}
}
@ -354,7 +345,7 @@ void nano::block_processor::process_batch (nano::unique_lock<std::mutex> & lock_
Because verification is long process, avoid large deque verification inside of write transaction */
if (blocks.empty () && !state_blocks.empty ())
{
verify_state_blocks (transaction, lock_a, 256 * (node.config.signature_checker_threads + 1));
verify_state_blocks (lock_a, 256 * (node.config.signature_checker_threads + 1));
}
}
awaiting_write = false;

View file

@ -56,7 +56,7 @@ public:
private:
void queue_unchecked (nano::write_transaction const &, nano::block_hash const &);
void verify_state_blocks (nano::transaction const & transaction_a, nano::unique_lock<std::mutex> &, size_t = std::numeric_limits<size_t>::max ());
void verify_state_blocks (nano::unique_lock<std::mutex> &, size_t = std::numeric_limits<size_t>::max ());
void process_batch (nano::unique_lock<std::mutex> &);
void process_live (nano::block_hash const &, std::shared_ptr<nano::block>, const bool = false);
bool stopped;