Fixing issue where blocks received during bootstrap would be republished.
This commit is contained in:
parent
ffebcf389c
commit
4b7c66379a
3 changed files with 78 additions and 33 deletions
|
@ -687,13 +687,13 @@ TEST (node, fork_publish)
|
|||
rai::send_block send1 (genesis.hash (), key1.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
rai::keypair key2;
|
||||
rai::send_block send2 (genesis.hash (), key2.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
node1.process_receive_many (send1);
|
||||
node1.process_receive_republish (send1.clone (), 0);
|
||||
ASSERT_EQ (1, node1.active.roots.size ());
|
||||
auto existing (node1.active.roots.find (send1.root ()));
|
||||
ASSERT_NE (node1.active.roots.end (), existing);
|
||||
auto election (existing->election);
|
||||
ASSERT_EQ (2, election->votes.rep_votes.size ());
|
||||
node1.process_receive_many (send2);
|
||||
node1.process_receive_republish (send2.clone (), 0);
|
||||
auto existing1 (election->votes.rep_votes.find (rai::test_genesis_key.pub));
|
||||
ASSERT_NE (election->votes.rep_votes.end (), existing1);
|
||||
ASSERT_EQ (send1, *existing1->second);
|
||||
|
@ -862,33 +862,46 @@ TEST (node, fork_multi_flip)
|
|||
}
|
||||
|
||||
// Blocks that are no longer actively being voted on should be able to be evicted through bootstrapping.
|
||||
// This could happen if a fork wasn't resolved before the process previously shut down
|
||||
TEST (node, fork_bootstrap_flip)
|
||||
{
|
||||
rai::system system (24000, 2);
|
||||
auto & node1 (*system.nodes [0]);
|
||||
auto & node2 (*system.nodes [1]);
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
rai::block_hash latest (system.nodes [0]->latest (rai::test_genesis_key.pub));
|
||||
rai::system system0 (24000, 1);
|
||||
rai::system system1 (24001, 1);
|
||||
auto & node1 (*system0.nodes [0]);
|
||||
auto & node2 (*system1.nodes [0]);
|
||||
system0.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
rai::block_hash latest (system0.nodes [0]->latest (rai::test_genesis_key.pub));
|
||||
rai::keypair key1;
|
||||
std::unique_ptr <rai::send_block> send1 (new rai::send_block (latest, key1.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (latest)));
|
||||
rai::send_block send1 (latest, key1.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system0.work.generate (latest));
|
||||
rai::keypair key2;
|
||||
std::unique_ptr <rai::send_block> send2 (new rai::send_block (latest, key2.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (latest)));
|
||||
node1.process_receive_many (*send1);
|
||||
node2.process_receive_many (*send2);
|
||||
system.wallet (0)->send_action (rai::test_genesis_key.pub, key1.pub, 100);
|
||||
auto iterations2 (0);
|
||||
auto again (true);
|
||||
rai::send_block send2 (latest, key2.pub, rai::genesis_amount - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system0.work.generate (latest));
|
||||
// Insert but don't rebroadcast, simulating well-established blocks
|
||||
node1.process_receive_many (send1);
|
||||
node2.process_receive_many (send2);
|
||||
{
|
||||
rai::transaction transaction (node2.store.environment, nullptr, false);
|
||||
ASSERT_TRUE (node2.store.block_exists (transaction, send2->hash ()));
|
||||
ASSERT_TRUE (node2.store.block_exists (transaction, send2.hash ()));
|
||||
}
|
||||
node1.network.send_keepalive (node2.network.endpoint ());
|
||||
auto iterations1 (0);
|
||||
while (node2.peers.empty ())
|
||||
{
|
||||
system0.poll ();
|
||||
system1.poll ();
|
||||
++iterations1;
|
||||
ASSERT_LT (iterations1, 1000);
|
||||
}
|
||||
node2.bootstrap_initiator.bootstrap (node1.network.endpoint ());
|
||||
auto again (true);
|
||||
auto iterations2 (0);
|
||||
while (again)
|
||||
{
|
||||
system.poll ();
|
||||
system0.poll ();
|
||||
system1.poll ();
|
||||
++iterations2;
|
||||
ASSERT_LT (iterations2, 200);
|
||||
rai::transaction transaction (node2.store.environment, nullptr, false);
|
||||
again = !node2.store.block_exists (transaction, send1->hash ());
|
||||
again = !node2.store.block_exists (transaction, send1.hash ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1090,6 @@ TEST (node, broadcast_elected)
|
|||
//std::cerr << "Big: " << rep_big.pub.to_account () << std::endl;
|
||||
//std::cerr << "Small: " << rep_small.pub.to_account () << std::endl;
|
||||
//std::cerr << "Other: " << rep_other.pub.to_account () << std::endl;
|
||||
rai::block_hash fork_hash;
|
||||
{
|
||||
rai::transaction transaction0 (node0->store.environment, nullptr, true);
|
||||
rai::transaction transaction1 (node1->store.environment, nullptr, true);
|
||||
|
@ -1088,13 +1100,10 @@ TEST (node, broadcast_elected)
|
|||
rai::open_block open_small (fund_small.hash (), rep_small.pub, rep_small.pub, rep_small.prv, rep_small.pub, 0);
|
||||
rai::send_block fund_other (fund_small.hash (), rep_other.pub, 125, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
rai::open_block open_other (fund_other.hash (), rep_other.pub, rep_other.pub, rep_other.prv, rep_other.pub, 0);
|
||||
rai::send_block fork0 (fund_other.hash (), rep_small.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
fork_hash = fork0.hash ();
|
||||
node0->generate_work (fund_big);
|
||||
node0->generate_work (open_big);
|
||||
node0->generate_work (fund_small);
|
||||
node0->generate_work (open_small);
|
||||
node0->generate_work (fork0);
|
||||
ASSERT_EQ (rai::process_result::progress, node0->ledger.process (transaction0, fund_big).code);
|
||||
ASSERT_EQ (rai::process_result::progress, node1->ledger.process (transaction1, fund_big).code);
|
||||
ASSERT_EQ (rai::process_result::progress, node2->ledger.process (transaction2, fund_big).code);
|
||||
|
@ -1113,12 +1122,14 @@ TEST (node, broadcast_elected)
|
|||
ASSERT_EQ (rai::process_result::progress, node0->ledger.process (transaction0, open_other).code);
|
||||
ASSERT_EQ (rai::process_result::progress, node1->ledger.process (transaction1, open_other).code);
|
||||
ASSERT_EQ (rai::process_result::progress, node2->ledger.process (transaction2, open_other).code);
|
||||
node0->process_receive_many (transaction0, fork0);
|
||||
node1->process_receive_many (transaction1, fork0);
|
||||
}
|
||||
system.wallet (0)->insert_adhoc (rep_big.prv);
|
||||
system.wallet (1)->insert_adhoc (rep_small.prv);
|
||||
system.wallet (2)->insert_adhoc (rep_other.prv);
|
||||
rai::send_block fork0 (node2->latest (rai::test_genesis_key.pub), rep_small.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
node0->generate_work (fork0);
|
||||
node0->process_receive_republish (fork0.clone (), 0);
|
||||
node1->process_receive_republish (fork0.clone (), 0);
|
||||
rai::send_block fork1 (node2->latest (rai::test_genesis_key.pub), rep_big.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
node0->generate_work (fork1);
|
||||
system.wallet (2)->insert_adhoc (rep_small.prv);
|
||||
|
@ -1126,11 +1137,11 @@ TEST (node, broadcast_elected)
|
|||
//std::cerr << "fork0: " << fork_hash.to_string () << std::endl;
|
||||
//std::cerr << "fork1: " << fork1.hash ().to_string () << std::endl;
|
||||
auto iterations (0);
|
||||
while (!node2->ledger.block_exists (fork_hash))
|
||||
while (!node2->ledger.block_exists (fork0.hash ()))
|
||||
{
|
||||
system.poll ();
|
||||
ASSERT_TRUE (node0->ledger.block_exists(fork_hash));
|
||||
ASSERT_TRUE (node1->ledger.block_exists(fork_hash));
|
||||
ASSERT_TRUE (node0->ledger.block_exists (fork0.hash ()));
|
||||
ASSERT_TRUE (node1->ledger.block_exists (fork0.hash ()));
|
||||
++iterations;
|
||||
ASSERT_LT (iterations, 200);
|
||||
}
|
||||
|
@ -1167,3 +1178,29 @@ TEST (node, rep_self_vote)
|
|||
ASSERT_NE (rep_votes.end (), rep_votes.find (rai::test_genesis_key.pub));
|
||||
ASSERT_NE (rep_votes.end (), rep_votes.find (rep_big.pub));
|
||||
}
|
||||
|
||||
// Bootstrapping shouldn't republish the blocks to the network.
|
||||
TEST (node, bootstrap_no_publish)
|
||||
{
|
||||
rai::system system0 (24000, 1);
|
||||
rai::system system1 (24001, 1);
|
||||
auto node0 (system0.nodes [0]);
|
||||
auto node1 (system1.nodes [0]);
|
||||
rai::keypair key0;
|
||||
// node0 knows about send0 but node1 doesn't.
|
||||
rai::send_block send0 (system0.nodes [0]->latest (rai::test_genesis_key.pub), key0.pub, 500, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
|
||||
{
|
||||
rai::transaction transaction (node0->store.environment, nullptr, true);
|
||||
ASSERT_EQ (rai::process_result::progress, system0.nodes [0]->ledger.process (transaction, send0).code);
|
||||
}
|
||||
node1->bootstrap_initiator.bootstrap (node0->network.endpoint ());
|
||||
ASSERT_TRUE (node1->bootstrap_initiator.in_progress ());
|
||||
ASSERT_TRUE (node1->active.roots.empty ());
|
||||
while (node1->bootstrap_initiator.in_progress ())
|
||||
{
|
||||
system0.poll ();
|
||||
system1.poll ();
|
||||
// There should never be an active transaction because the only activity is bootstrapping 1 block which shouldn't be publishing.
|
||||
ASSERT_TRUE (node1->active.roots.empty ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -527,7 +527,7 @@ void rai::bulk_pull_client::process_end ()
|
|||
block_flush ();
|
||||
rai::pull_synchronization synchronization (connection->connection->node->log, [this] (rai::transaction & transaction_a, rai::block const & block_a)
|
||||
{
|
||||
connection->connection->node->process_receive_many (transaction_a, block_a, [this] (rai::process_return result_a, rai::block const & block_a)
|
||||
connection->connection->node->process_receive_many (transaction_a, block_a, [this, &transaction_a] (rai::process_return result_a, rai::block const & block_a)
|
||||
{
|
||||
switch (result_a.code)
|
||||
{
|
||||
|
@ -535,9 +535,17 @@ void rai::bulk_pull_client::process_end ()
|
|||
case rai::process_result::old:
|
||||
break;
|
||||
case rai::process_result::fork:
|
||||
{
|
||||
auto node_l (connection->connection->node);
|
||||
auto block (node_l->store.block_get (transaction_a, node_l->store.block_successor (transaction_a, block_a.root ())));
|
||||
node_l->active.start (transaction_a, *block, [node_l] (rai::block & block_a)
|
||||
{
|
||||
node_l->process_confirmed (block_a);
|
||||
});
|
||||
connection->connection->node->network.broadcast_confirm_req (block_a);
|
||||
BOOST_LOG (connection->connection->node->log) << boost::str (boost::format ("Fork received in bootstrap for block: %1%") % block_a.hash ().to_string ());
|
||||
break;
|
||||
}
|
||||
case rai::process_result::gap_previous:
|
||||
case rai::process_result::gap_source:
|
||||
if (connection->connection->node->config.logging.bulk_pull_logging ())
|
||||
|
|
|
@ -1174,12 +1174,17 @@ void rai::node::process_receive_republish (std::unique_ptr <rai::block> incoming
|
|||
{
|
||||
rai::transaction transaction (store.environment, nullptr, true);
|
||||
assert (incoming != nullptr);
|
||||
process_receive_many (transaction, *incoming, [this, rebroadcast_a, &completed] (rai::process_return result_a, rai::block const & block_a)
|
||||
process_receive_many (transaction, *incoming, [this, rebroadcast_a, &completed, &transaction] (rai::process_return result_a, rai::block const & block_a)
|
||||
{
|
||||
switch (result_a.code)
|
||||
{
|
||||
case rai::process_result::progress:
|
||||
{
|
||||
auto node_l (shared_from_this ());
|
||||
active.start (transaction, block_a, [node_l] (rai::block & block_a)
|
||||
{
|
||||
node_l->process_confirmed (block_a);
|
||||
});
|
||||
completed.push_back (std::make_tuple (result_a, block_a.clone ()));
|
||||
break;
|
||||
}
|
||||
|
@ -1233,11 +1238,6 @@ rai::process_return rai::node::process_receive_one (rai::transaction & transacti
|
|||
block_a.serialize_json (block);
|
||||
BOOST_LOG (log) << boost::str (boost::format ("Processing block %1% %2%") % block_a.hash ().to_string () % block);
|
||||
}
|
||||
auto node_l (shared_from_this ());
|
||||
active.start (transaction_a, block_a, [node_l] (rai::block & block_a)
|
||||
{
|
||||
node_l->process_confirmed (block_a);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case rai::process_result::gap_previous:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue