Allowing blocks to be replaced with higher-work versions.

This commit is contained in:
clemahieu 2015-09-11 18:11:42 -05:00
commit 33d32f7f94
5 changed files with 78 additions and 2 deletions

View file

@ -525,4 +525,19 @@ TEST (block_store, frontier)
ASSERT_EQ (account, store.frontier_get (transaction, hash));
store.frontier_del (transaction, hash);
ASSERT_TRUE (store.frontier_get (transaction, hash).is_zero ());
}
TEST (block_store, block_replace)
{
bool init (false);
rai::block_store store (init, rai::unique_path ());
ASSERT_TRUE (!init);
rai::send_block send1 (0, 0, 0, 0, 0, 1);
rai::send_block send2 (0, 0, 0, 0, 0, 2);
rai::transaction transaction (store.environment, nullptr, true);
store.block_put (transaction, 0, send1);
store.block_put (transaction, 0, send2);
auto block3 (store.block_get (transaction, 0));
ASSERT_NE (nullptr, block3);
ASSERT_EQ (2, block3->block_work ());
}

View file

@ -401,4 +401,40 @@ TEST (node_config, random_rep)
rai::node_config config1 (100, logging1);
auto rep (config1.random_representative ());
ASSERT_NE (config1.preconfigured_representatives.end (), std::find (config1.preconfigured_representatives.begin (), config1.preconfigured_representatives.end (), rep));
}
TEST (node, block_replace)
{
rai::system system (24000, 2);
system.wallet (0)->insert (rai::test_genesis_key.prv);
ASSERT_FALSE (system.wallet (0)->send_sync (rai::test_genesis_key.pub, 0, 1000));
std::unique_ptr <rai::block> block1;
{
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
block1 = system.nodes [0]->store.block_get (transaction, system.nodes [0]->ledger.latest (transaction, rai::test_genesis_key.pub));
}
ASSERT_NE (nullptr, block1);
auto initial_work (block1->block_work ());
while (rai::work_value (block1->root (), block1->block_work ()) <= rai::work_value (block1->root (), initial_work))
{
system.work.generate (*block1);
}
system.nodes [1]->network.republish_block (block1->clone (), 0);
auto iterations1 (0);
std::unique_ptr <rai::block> block2;
while (block2 == nullptr)
{
system.poll ();
++iterations1;
ASSERT_LT (iterations1, 200);
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
auto block (system.nodes [0]->store.block_get (transaction, system.nodes [0]->ledger.latest (transaction, rai::test_genesis_key.pub)));
if (block->block_work () != initial_work)
{
block2 = std::move (block);
}
}
ASSERT_NE (initial_work, block1->block_work ());
ASSERT_EQ (block1->block_work (), block2->block_work ());
ASSERT_GT (rai::work_value (block2->root (), block2->block_work ()), rai::work_value (block1->root (), initial_work));
}

View file

@ -2309,6 +2309,24 @@ rai::process_return rai::node::process_receive (rai::block const & block_a)
}
case rai::process_result::old:
{
{
auto root (block_a.root ());
auto hash (block_a.hash ());
rai::transaction transaction (store.environment, nullptr, true);
auto existing (store.block_get (transaction, hash));
if (existing != nullptr)
{
// Replace block with one that has higher work value
if (rai::work_value (root, block_a.block_work ()) > rai::work_value (root, existing->block_work ()))
{
store.block_put (transaction, hash, block_a);
}
}
else
{
// Could have been rolled back, maybe
}
}
if (config.logging.ledger_duplicate_logging ())
{
BOOST_LOG (log) << boost::str (boost::format ("Old for: %1%") % block_a.hash ().to_string ());

View file

@ -564,7 +564,7 @@ void rai::serialize_block (rai::stream & stream_a, rai::block const & block_a)
block_a.serialize (stream_a);
}
bool rai::work_validate (rai::block_hash const & root_a, uint64_t work_a)
uint64_t rai::work_value (rai::block_hash const & root_a, uint64_t work_a)
{
uint64_t result;
blake2b_state hash;
@ -572,7 +572,13 @@ bool rai::work_validate (rai::block_hash const & root_a, uint64_t work_a)
blake2b_update (&hash, reinterpret_cast <uint8_t *> (&work_a), sizeof (work_a));
blake2b_update (&hash, root_a.bytes.data (), root_a.bytes.size ());
blake2b_final (&hash, reinterpret_cast <uint8_t *> (&result), sizeof (result));
return result < rai::block::publish_threshold;
return result;
}
bool rai::work_validate (rai::block_hash const & root_a, uint64_t work_a)
{
auto result (rai::work_value (root_a, work_a) < rai::block::publish_threshold);
return result;
}
bool rai::work_validate (rai::block & block_a)

View file

@ -96,6 +96,7 @@ std::unique_ptr <rai::block> deserialize_block (rai::stream &);
std::unique_ptr <rai::block> deserialize_block (rai::stream &, rai::block_type);
std::unique_ptr <rai::block> deserialize_block_json (boost::property_tree::ptree const &);
void serialize_block (rai::stream &, rai::block const &);
uint64_t work_value (rai::block_hash const &, uint64_t);
bool work_validate (rai::block &);
bool work_validate (rai::block_hash const &, uint64_t);
class send_hashables