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

Check if existing block is already confirmed in active_transactions add #2055

Merged
merged 15 commits into from Jun 10, 2019
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion nano/core_test/active_transactions.cpp
Expand Up @@ -71,10 +71,11 @@ TEST (active_transactions, long_unconfirmed_size)

TEST (active_transactions, adjusted_difficulty_priority)
{
bool delay_frontier_confirmation_height_updating = true;
nano::system system;
nano::node_config node_config (24000, system.logging);
node_config.enable_voting = false;
auto & node1 = *system.add_node (node_config);
auto & node1 = *system.add_node (node_config, delay_frontier_confirmation_height_updating);
nano::genesis genesis;
nano::keypair key1, key2, key3;
auto transaction (node1.store.tx_begin_read ());
Expand Down
44 changes: 23 additions & 21 deletions nano/core_test/conflicts.cpp
Expand Up @@ -192,26 +192,30 @@ TEST (conflicts, reprioritize)

TEST (conflicts, dependency)
{
nano::system system (24000, 1);
auto & node1 (*system.nodes[0]);
bool delay_frontier_confirmation_height_updating (true);
nano::system system;
auto node1 = system.add_node (nano::node_config (24000, system.logging), delay_frontier_confirmation_height_updating);
nano::genesis genesis;
nano::keypair key1;
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);
ASSERT_EQ (0, node1.active.size ());
node1.active.start (genesis.open);
node1.active.start (send1);
ASSERT_EQ (2, node1.active.size ());
// Check dependecy for genesis block
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - nano::xrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1->work_generate_blocking (*send1);
auto state_open1 (std::make_shared<nano::state_block> (key1.pub, 0, nano::test_genesis_key.pub, nano::xrb_ratio, send1->hash (), key1.prv, key1.pub, 0));
node1->work_generate_blocking (*state_open1);
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);
ASSERT_EQ (2, node1->active.size ());
// Check dependecy for send block
wezrule marked this conversation as resolved.
Show resolved Hide resolved
{
std::lock_guard<std::mutex> guard (node1.active.mutex);
auto existing1 (node1.active.roots.find (genesis.open->qualified_root ()));
ASSERT_NE (node1.active.roots.end (), existing1);
std::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 (send1->hash ()));
ASSERT_NE (election1->dependent_blocks.end (), election1->dependent_blocks.find (state_open1->hash ()));
}
}

Expand All @@ -224,7 +228,6 @@ TEST (conflicts, adjusted_difficulty)
nano::keypair key2;
nano::keypair key3;
ASSERT_EQ (0, node1.active.size ());
node1.active.start (genesis.open);
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, nano::genesis_amount - 2 * nano::xrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (genesis.hash ())));
node1.process_active (send1);
auto send2 (std::make_shared<nano::send_block> (send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 3 * nano::xrb_ratio, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (send1->hash ())));
Expand All @@ -248,21 +251,20 @@ TEST (conflicts, adjusted_difficulty)
node1.process_active (change1);
node1.block_processor.flush ();
system.deadline_set (3s);
while (node1.active.size () != 11)
while (node1.active.size () != 10)
{
ASSERT_NO_ERROR (system.poll ());
}
std::unordered_map<nano::block_hash, uint64_t> adjusted_difficulties;
{
std::lock_guard<std::mutex> guard (node1.active.mutex);
ASSERT_EQ (node1.active.roots.get<1> ().begin ()->election->status.winner->hash (), genesis.hash ());
ASSERT_EQ (node1.active.roots.get<1> ().begin ()->election->status.winner->hash (), send1->hash ());
for (auto i (node1.active.roots.get<1> ().begin ()), n (node1.active.roots.get<1> ().end ()); i != n; ++i)
{
adjusted_difficulties.insert (std::make_pair (i->election->status.winner->hash (), i->adjusted_difficulty));
}
}
// genesis
ASSERT_GT (adjusted_difficulties.find (genesis.hash ())->second, adjusted_difficulties.find (send1->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (send1->hash ())->second, adjusted_difficulties.find (send2->hash ())->second);
ASSERT_GT (adjusted_difficulties.find (send2->hash ())->second, adjusted_difficulties.find (receive1->hash ())->second);
// key1
Expand All @@ -277,14 +279,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 open_epoch2 (std::make_shared<nano::state_block> (key4.pub, 0, 0, 0, node1.ledger.epoch_link, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (key4.pub, adjusted_difficulties.find (genesis.hash ())->second)));
auto open_epoch2 (std::make_shared<nano::state_block> (key4.pub, 0, 0, 0, node1.ledger.epoch_link, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (key4.pub, adjusted_difficulties.find (send1->hash ())->second)));
uint64_t difficulty;
ASSERT_FALSE (nano::work_validate (*open_epoch2, &difficulty));
ASSERT_GT (difficulty, adjusted_difficulties.find (genesis.hash ())->second);
ASSERT_GT (difficulty, adjusted_difficulties.find (send1->hash ())->second);
node1.process_active (open_epoch2);
node1.block_processor.flush ();
system.deadline_set (3s);
while (node1.active.size () != 12)
while (node1.active.size () != 11)
{
ASSERT_NO_ERROR (system.poll ());
}
Expand Down
10 changes: 7 additions & 3 deletions nano/core_test/websocket.cpp
Expand Up @@ -315,11 +315,12 @@ TEST (websocket, confirmation_options)
nano::keypair key;
auto balance = nano::genesis_amount;
auto send_amount = node1->config.online_weight_minimum.number () + 1;
nano::block_hash previous (node1->latest (nano::test_genesis_key.pub));
{
nano::block_hash previous (node1->latest (nano::test_genesis_key.pub));
balance -= send_amount;
auto send (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, previous, nano::test_genesis_key.pub, balance, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (previous)));
node1->process_active (send);
previous = send->hash ();
}

// Wait for client thread to finish, no confirmation message should be received with given filter
Expand All @@ -346,6 +347,7 @@ TEST (websocket, confirmation_options)
client_thread_2_finished = true;
});

node1->block_processor.flush ();
// Wait for the subscribe action to be acknowledged
system.deadline_set (5s);
while (!ack_ready)
Expand All @@ -358,12 +360,13 @@ TEST (websocket, confirmation_options)

// Quick-confirm another block
{
nano::block_hash previous (node1->latest (nano::test_genesis_key.pub));
balance -= send_amount;
auto send (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, previous, nano::test_genesis_key.pub, balance, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (previous)));
node1->process_active (send);
previous = send->hash ();
}

node1->block_processor.flush ();
// Wait for confirmation message
system.deadline_set (5s);
while (!client_thread_2_finished)
Expand All @@ -384,12 +387,13 @@ TEST (websocket, confirmation_options)
// Confirm a legacy block
// When filtering options are enabled, legacy blocks are always filtered
{
nano::block_hash previous (node1->latest (nano::test_genesis_key.pub));
balance -= send_amount;
auto send (std::make_shared<nano::send_block> (previous, key.pub, balance, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (previous)));
node1->process_active (send);
previous = send->hash ();
}

node1->block_processor.flush ();
// Wait for client thread to finish, no confirmation message should be received
system.deadline_set (5s);
while (!client_thread_3_finished)
Expand Down
7 changes: 5 additions & 2 deletions nano/node/active_transactions.cpp
Expand Up @@ -431,13 +431,16 @@ bool nano::active_transactions::add (std::shared_ptr<nano::block> block_a, std::
auto existing (roots.find (root));
if (existing == roots.end ())
{
// Check if existing block is already confirmed
assert (node.ledger.block_not_confirmed_or_not_exists (*block_a));
auto hash (block_a->hash ());
auto election (nano::make_shared<nano::election> (node, block_a, confirmation_action_a));
uint64_t difficulty (0);
auto error (nano::work_validate (*block_a, &difficulty));
release_assert (!error);
roots.insert (nano::conflict_info{ root, difficulty, difficulty, election });
blocks.insert (std::make_pair (block_a->hash (), election));
adjust_difficulty (block_a->hash ());
blocks.insert (std::make_pair (hash, election));
adjust_difficulty (hash);
}
error = existing != roots.end ();
if (error)
Expand Down
12 changes: 12 additions & 0 deletions nano/secure/ledger.cpp
Expand Up @@ -1062,6 +1062,18 @@ bool nano::ledger::block_confirmed (nano::transaction const & transaction_a, nan
return confirmed;
}

bool nano::ledger::block_not_confirmed_or_not_exists (nano::block const & block_a) const
{
bool result (true);
auto hash (block_a.hash ());
auto transaction (store.tx_begin_read ());
if (store.block_exists (transaction, block_a.type (), hash))
{
result = !block_confirmed (transaction, hash);
}
return result;
}

namespace nano
{
std::unique_ptr<seq_con_info_component> collect_seq_con_info (ledger & ledger, const std::string & name)
Expand Down
1 change: 1 addition & 0 deletions nano/secure/ledger.hpp
Expand Up @@ -28,6 +28,7 @@ class ledger final
std::shared_ptr<nano::block> successor (nano::transaction const &, nano::qualified_root const &);
std::shared_ptr<nano::block> forked_block (nano::transaction const &, nano::block const &);
bool block_confirmed (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const;
bool block_not_confirmed_or_not_exists (nano::block const & block_a) const;
nano::block_hash latest (nano::transaction const &, nano::account const &);
nano::block_hash latest_root (nano::transaction const &, nano::account const &);
nano::block_hash representative (nano::transaction const &, nano::block_hash const &);
Expand Down