Skip to content

Commit

Permalink
Epoch open blocks should have corresponding pending entries (#2673)
Browse files Browse the repository at this point in the history
* Epoch open blocks should have corresponding pending entries
* Simplify pending check condition
* Add block store function pending_any ()
  • Loading branch information
SergiySW committed Apr 2, 2020
1 parent 775359b commit caf5f35
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 6 deletions.
4 changes: 3 additions & 1 deletion nano/core_test/conflicts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,14 @@ TEST (conflicts, adjusted_difficulty)
ASSERT_GT (adjusted_difficulties.find (open2->hash ())->second, adjusted_difficulties.find (change1->hash ())->second);
// Independent elections can have higher difficulty than adjusted tree
nano::keypair key4;
auto send5 (std::make_shared<nano::state_block> (key3.pub, change1->hash (), nano::test_genesis_key.pub, 0, key4.pub, key3.prv, key3.pub, *system.work.generate (change1->hash ()))); // Pending for open epoch block
node1.process_active (send5);
auto open_epoch2 (std::make_shared<nano::state_block> (key4.pub, 0, 0, 0, node1.ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (key4.pub, adjusted_difficulties.find (send1->hash ())->second)));
ASSERT_GT (open_epoch2->difficulty (), adjusted_difficulties.find (send1->hash ())->second);
node1.process_active (open_epoch2);
node1.block_processor.flush ();
system.deadline_set (3s);
while (node1.active.size () != 11)
while (node1.active.size () != 12)
{
ASSERT_NO_ERROR (system.poll ());
}
Expand Down
13 changes: 13 additions & 0 deletions nano/core_test/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2568,16 +2568,29 @@ TEST (ledger, successor_epoch)
nano::state_block open (key1.pub, 0, key1.pub, 1, send1.hash (), key1.prv, key1.pub, *pool.generate (key1.pub));
nano::state_block change (key1.pub, open.hash (), key1.pub, 1, 0, key1.prv, key1.pub, *pool.generate (open.hash ()));
auto open_hash = open.hash ();
nano::send_block send2 (send1.hash (), reinterpret_cast<nano::account const &> (open_hash), nano::genesis_amount - 2, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (send1.hash ()));
nano::state_block epoch_open (reinterpret_cast<nano::account const &> (open_hash), 0, 0, 0, node1.ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (open.hash ()));
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, open).code);
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, change).code);
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, send2).code);
ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, epoch_open).code);
ASSERT_EQ (change, *node1.ledger.successor (transaction, change.qualified_root ()));
ASSERT_EQ (epoch_open, *node1.ledger.successor (transaction, epoch_open.qualified_root ()));
}

TEST (ledger, epoch_open_pending)
{
nano::system system (1);
auto & node1 (*system.nodes[0]);
nano::work_pool pool (std::numeric_limits<unsigned>::max ());
nano::keypair key1;
nano::state_block epoch_open (key1.pub, 0, 0, 0, node1.ledger.epoch_link (nano::epoch::epoch_1), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (key1.pub));
auto transaction (node1.store.tx_begin_write ());
ASSERT_EQ (nano::process_result::block_position, node1.ledger.process (transaction, epoch_open).code);
}

TEST (ledger, block_hash_account_conflict)
{
nano::block_builder builder;
Expand Down
13 changes: 8 additions & 5 deletions nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3041,22 +3041,25 @@ TEST (node, epoch_conflict_confirm)
auto send (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - 1, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
auto open (std::make_shared<nano::state_block> (key.pub, 0, key.pub, 1, send->hash (), key.prv, key.pub, *system.work.generate (key.pub)));
auto change (std::make_shared<nano::state_block> (key.pub, open->hash (), key.pub, 1, 0, key.prv, key.pub, *system.work.generate (open->hash ())));
auto epoch (std::make_shared<nano::state_block> (change->root (), 0, 0, 0, node0->ledger.epoch_link (nano::epoch::epoch_1), epoch_signer.prv, epoch_signer.pub, *system.work.generate (open->hash ())));
auto send2 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 2, open->hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send->hash ())));
auto epoch_open (std::make_shared<nano::state_block> (change->root (), 0, 0, 0, node0->ledger.epoch_link (nano::epoch::epoch_1), epoch_signer.prv, epoch_signer.pub, *system.work.generate (open->hash ())));
{
auto transaction (node0->store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node0->block_processor.process_one (transaction, send).code);
ASSERT_EQ (nano::process_result::progress, node0->block_processor.process_one (transaction, send2).code);
ASSERT_EQ (nano::process_result::progress, node0->block_processor.process_one (transaction, open).code);
}
{
auto transaction (node1->store.tx_begin_write ());
ASSERT_EQ (nano::process_result::progress, node1->block_processor.process_one (transaction, send).code);
ASSERT_EQ (nano::process_result::progress, node1->block_processor.process_one (transaction, send2).code);
ASSERT_EQ (nano::process_result::progress, node1->block_processor.process_one (transaction, open).code);
}
node0->process_active (change);
node0->process_active (epoch);
node0->process_active (epoch_open);
node0->block_processor.flush ();
system.deadline_set (5s);
while (!node0->block (change->hash ()) || !node0->block (epoch->hash ()) || !node1->block (change->hash ()) || !node1->block (epoch->hash ()))
while (!node0->block (change->hash ()) || !node0->block (epoch_open->hash ()) || !node1->block (change->hash ()) || !node1->block (epoch_open->hash ()))
{
ASSERT_NO_ERROR (system.poll ());
}
Expand All @@ -3068,7 +3071,7 @@ TEST (node, epoch_conflict_confirm)
{
nano::lock_guard<std::mutex> lock (node0->active.mutex);
ASSERT_TRUE (node0->active.blocks.find (change->hash ()) != node0->active.blocks.end ());
ASSERT_TRUE (node0->active.blocks.find (epoch->hash ()) != node0->active.blocks.end ());
ASSERT_TRUE (node0->active.blocks.find (epoch_open->hash ()) != node0->active.blocks.end ());
}
system.wallet (1)->insert_adhoc (nano::test_genesis_key.prv);
system.deadline_set (5s);
Expand All @@ -3079,7 +3082,7 @@ TEST (node, epoch_conflict_confirm)
{
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->hash ()));
ASSERT_TRUE (node0->ledger.store.block_exists (transaction, epoch_open->hash ()));
}
}

Expand Down
1 change: 1 addition & 0 deletions nano/secure/blockstore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ class block_store
virtual void pending_del (nano::write_transaction const &, nano::pending_key const &) = 0;
virtual bool pending_get (nano::transaction const &, nano::pending_key const &, nano::pending_info &) = 0;
virtual bool pending_exists (nano::transaction const &, nano::pending_key const &) = 0;
virtual bool pending_any (nano::transaction const &, nano::account const &) = 0;
virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_begin (nano::transaction const &, nano::pending_key const &) = 0;
virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_begin (nano::transaction const &) = 0;
virtual nano::store_iterator<nano::pending_key, nano::pending_info> pending_end () = 0;
Expand Down
6 changes: 6 additions & 0 deletions nano/secure/blockstore_partial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ class block_store_partial : public block_store
return iterator != pending_end () && nano::pending_key (iterator->first) == key_a;
}

bool pending_any (nano::transaction const & transaction_a, nano::account const & account_a) override
{
auto iterator (pending_begin (transaction_a, nano::pending_key (account_a, 0)));
return iterator != pending_end () && nano::pending_key (iterator->first).account == account_a;
}

bool unchecked_exists (nano::transaction const & transaction_a, nano::unchecked_key const & unchecked_key_a) override
{
nano::db_val<Val> value;
Expand Down
6 changes: 6 additions & 0 deletions nano/secure/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,12 @@ void ledger_processor::epoch_block_impl (nano::state_block & block_a)
else
{
result.code = block_a.hashables.representative.is_zero () ? nano::process_result::progress : nano::process_result::representative_mismatch;
// Non-exisitng account should have pending entries
if (result.code == nano::process_result::progress)
{
bool pending_exists = ledger.store.pending_any (transaction, block_a.hashables.account);
result.code = pending_exists ? nano::process_result::progress : nano::process_result::block_position;
}
}
if (result.code == nano::process_result::progress)
{
Expand Down

0 comments on commit caf5f35

Please sign in to comment.