Allowing blocks to be replaced with higher-work versions.
This commit is contained in:
parent
207bf38f9b
commit
33d32f7f94
5 changed files with 78 additions and 2 deletions
|
@ -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 ());
|
||||
}
|
|
@ -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));
|
||||
}
|
18
rai/node.cpp
18
rai/node.cpp
|
@ -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 ());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue