Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epoch open blocks should have corresponding pending entries #2673

Merged
merged 5 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -2992,22 +2992,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 @@ -3019,7 +3022,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 @@ -3030,7 +3033,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