Adding test to show votes can be replayed to help reps who have lost track of their highest sequence number. This automatic healing avoids the need to manually re-update sequence numbers if they were ever lost, for instance when reloading a seed on a new node.
This commit is contained in:
parent
314dbd7096
commit
ed72bd5b70
2 changed files with 56 additions and 3 deletions
|
@ -1364,3 +1364,39 @@ TEST (node, send_callback)
|
|||
}
|
||||
ASSERT_EQ (std::numeric_limits <rai::uint128_t>::max () - system.nodes [0]->config.receive_minimum.number (), system.nodes [0]->balance (rai::test_genesis_key.pub));
|
||||
}
|
||||
|
||||
// Check that votes get replayed back to nodes if they sent an old sequence number.
|
||||
// This helps representatives continue from their last sequence number if their node is reinitialized and the old sequence number is lost
|
||||
TEST (node, vote_replay)
|
||||
{
|
||||
rai::system system (24000, 2);
|
||||
rai::keypair key;
|
||||
auto open (std::make_shared <rai::open_block> (0, 1, key.pub, key.prv, key.pub, 0));
|
||||
system.nodes [0]->generate_work (*open);
|
||||
for (auto i (0); i < 11000; ++i)
|
||||
{
|
||||
rai::transaction transaction (system.nodes [1]->store.environment, nullptr, false);
|
||||
auto vote (system.nodes [1]->store.vote_generate (transaction, rai::test_genesis_key.pub, rai::test_genesis_key.prv, open));
|
||||
}
|
||||
{
|
||||
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
|
||||
std::lock_guard <std::mutex> lock (system.nodes [0]->store.vote_mutex);
|
||||
auto vote (system.nodes [0]->store.vote_current (transaction, rai::test_genesis_key.pub));
|
||||
ASSERT_EQ (nullptr, vote);
|
||||
}
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
auto block (system.wallet (0)->send_action (rai::test_genesis_key.pub, key.pub, rai::Gxrb_ratio));
|
||||
ASSERT_NE (nullptr, block);
|
||||
auto done (false);
|
||||
auto iterations (0);
|
||||
while (!done)
|
||||
{
|
||||
system.poll ();
|
||||
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
|
||||
std::lock_guard <std::mutex> lock (system.nodes [0]->store.vote_mutex);
|
||||
auto vote (system.nodes [0]->store.vote_current (transaction, rai::test_genesis_key.pub));
|
||||
done = vote && (vote->sequence >= 10000);
|
||||
++iterations;
|
||||
ASSERT_GT (400, iterations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,13 +379,30 @@ public:
|
|||
{
|
||||
if (node.config.logging.network_message_logging ())
|
||||
{
|
||||
BOOST_LOG (node.log) << boost::str (boost::format ("Received confirm_ack message from %1% for %2%") % sender % message_a.vote->block->hash ().to_string ());
|
||||
BOOST_LOG (node.log) << boost::str (boost::format ("Received confirm_ack message from %1% for %2% sequence %3%") % sender % message_a.vote->block->hash ().to_string () % std::to_string (message_a.vote->sequence));
|
||||
}
|
||||
++node.network.incoming.confirm_ack;
|
||||
node.peers.contacted (sender, message_a.version_using);
|
||||
node.peers.insert (sender, message_a.version_using);
|
||||
node.process_active (message_a.vote->block);
|
||||
node.vote_processor.vote (message_a.vote, sender);
|
||||
auto vote (node.vote_processor.vote (message_a.vote, sender));
|
||||
if (vote.code == rai::vote_code::replay)
|
||||
{
|
||||
assert (vote.vote->sequence > message_a.vote->sequence);
|
||||
// This tries to assist rep nodes that have lost track of their highest sequence number by replaying our highest known vote back to them
|
||||
// Only do this if the sequence number is significantly different to account for network reordering
|
||||
// Amplify attack considerations: We're sending out a confirm_ack in response to a confirm_ack for no net traffic increase
|
||||
if (vote.vote->sequence - message_a.vote->sequence > 10000)
|
||||
{
|
||||
rai::confirm_ack confirm (vote.vote);
|
||||
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
||||
{
|
||||
rai::vectorstream stream (*bytes);
|
||||
confirm.serialize (stream);
|
||||
}
|
||||
node.network.confirm_send (confirm, bytes, sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
void bulk_pull (rai::bulk_pull const &) override
|
||||
{
|
||||
|
@ -1573,7 +1590,7 @@ void rai::network::confirm_send (rai::confirm_ack const & confirm_a, std::shared
|
|||
{
|
||||
if (node.config.logging.network_publish_logging ())
|
||||
{
|
||||
BOOST_LOG (node.log) << boost::str (boost::format ("Sending confirm_ack for block %1% to %2%") % confirm_a.vote->block->hash ().to_string () % endpoint_a);
|
||||
BOOST_LOG (node.log) << boost::str (boost::format ("Sending confirm_ack for block %1% to %2% sequence %3%") % confirm_a.vote->block->hash ().to_string () % endpoint_a % std::to_string (confirm_a.vote->sequence));
|
||||
}
|
||||
std::weak_ptr <rai::node> node_w (node.shared ());
|
||||
++outgoing.confirm_ack;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue