Block uniquer (#1358)
* Changing references to shared_ptr instead of unique_ptr in preparation for global uniquing. * More returning of shared_ptr instead of unique_ptr. * Removing unused declaration. * Converting more unique_ptr<rai::block> to shared_ptr<rai::block> * Removing unique_ptr cruft from when we handled blocks by unique_ptr instead of shared_ptr. * Adding block-uniquing class to reduce memory usage for blocks. * Using block_uniquer when deserializing messages. * Adding rai::block function full_hash which produces a hash covering every member of a block, including parts that are not represented in the block hash, such as the signature or block work. * Creating vote_uniquer class to save memory storing votes. * Hooking up vote uniquer. * Performing block-uniquing on local copy instead of a potentially shared copy at the end of the function.
This commit is contained in:
parent
1941a00940
commit
376a80d3b4
23 changed files with 492 additions and 173 deletions
|
@ -294,8 +294,8 @@ TEST (block, publish_req_serialization)
|
|||
{
|
||||
rai::keypair key1;
|
||||
rai::keypair key2;
|
||||
auto block (std::unique_ptr<rai::send_block> (new rai::send_block (0, key2.pub, 200, rai::keypair ().prv, 2, 3)));
|
||||
rai::publish req (std::move (block));
|
||||
auto block (std::make_shared<rai::send_block> (0, key2.pub, 200, rai::keypair ().prv, 2, 3));
|
||||
rai::publish req (block);
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
rai::vectorstream stream (bytes);
|
||||
|
@ -315,8 +315,8 @@ TEST (block, confirm_req_serialization)
|
|||
{
|
||||
rai::keypair key1;
|
||||
rai::keypair key2;
|
||||
auto block (std::unique_ptr<rai::send_block> (new rai::send_block (0, key2.pub, 200, rai::keypair ().prv, 2, 3)));
|
||||
rai::confirm_req req (std::move (block));
|
||||
auto block (std::make_shared<rai::send_block> (0, key2.pub, 200, rai::keypair ().prv, 2, 3));
|
||||
rai::confirm_req req (block);
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
rai::vectorstream stream (bytes);
|
||||
|
@ -409,3 +409,44 @@ TEST (state_block, hashing)
|
|||
block.hashables.link.bytes[0] ^= 0x1;
|
||||
ASSERT_EQ (hash, block.hash ());
|
||||
}
|
||||
|
||||
TEST (block_uniquer, null)
|
||||
{
|
||||
rai::block_uniquer uniquer;
|
||||
ASSERT_EQ (nullptr, uniquer.unique (nullptr));
|
||||
}
|
||||
|
||||
TEST (block_uniquer, single)
|
||||
{
|
||||
rai::keypair key;
|
||||
auto block1 (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
auto block2 (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
std::weak_ptr<rai::state_block> block3 (block2);
|
||||
ASSERT_NE (nullptr, block3.lock ());
|
||||
rai::block_uniquer uniquer;
|
||||
auto block4 (uniquer.unique (block1));
|
||||
ASSERT_EQ (block1, block4);
|
||||
auto block5 (uniquer.unique (block2));
|
||||
ASSERT_EQ (block1, block5);
|
||||
block2.reset ();
|
||||
ASSERT_EQ (nullptr, block3.lock ());
|
||||
}
|
||||
|
||||
TEST (block_uniquer, cleanup)
|
||||
{
|
||||
rai::keypair key;
|
||||
auto block1 (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
auto block2 (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 1));
|
||||
rai::block_uniquer uniquer;
|
||||
auto block3 (uniquer.unique (block1));
|
||||
auto block4 (uniquer.unique (block2));
|
||||
block2.reset ();
|
||||
block4.reset ();
|
||||
ASSERT_EQ (2, uniquer.size ());
|
||||
auto iterations (0);
|
||||
while (uniquer.size () == 2)
|
||||
{
|
||||
auto block5 (uniquer.unique (block1));
|
||||
ASSERT_LT (iterations++, 200);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,3 +60,88 @@ TEST (conflicts, add_two)
|
|||
node1.active.start (send2);
|
||||
ASSERT_EQ (2, node1.active.roots.size ());
|
||||
}
|
||||
|
||||
TEST (vote_uniquer, null)
|
||||
{
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer uniquer (block_uniquer);
|
||||
ASSERT_EQ (nullptr, uniquer.unique (nullptr));
|
||||
}
|
||||
|
||||
// Show that an identical vote can be uniqued
|
||||
TEST (vote_uniquer, same_vote)
|
||||
{
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer uniquer (block_uniquer);
|
||||
rai::keypair key;
|
||||
auto vote1 (std::make_shared<rai::vote> (key.pub, key.prv, 0, std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0)));
|
||||
auto vote2 (std::make_shared<rai::vote> (key.pub, key.prv, 0, std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0)));
|
||||
ASSERT_EQ (vote1, uniquer.unique (vote1));
|
||||
ASSERT_EQ (vote1, uniquer.unique (vote2));
|
||||
}
|
||||
|
||||
// Show that a different vote for the same block will have the block uniqued
|
||||
TEST (vote_uniquer, same_block)
|
||||
{
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer uniquer (block_uniquer);
|
||||
rai::keypair key1;
|
||||
rai::keypair key2;
|
||||
auto vote1 (std::make_shared<rai::vote> (key1.pub, key1.prv, 0, std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key1.prv, key1.pub, 0)));
|
||||
auto vote2 (std::make_shared<rai::vote> (key2.pub, key2.prv, 0, std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key1.prv, key1.pub, 0)));
|
||||
ASSERT_EQ (vote1, uniquer.unique (vote1));
|
||||
ASSERT_EQ (vote2, uniquer.unique (vote2));
|
||||
ASSERT_NE (vote1, vote2);
|
||||
ASSERT_EQ (boost::get<std::shared_ptr<rai::block>> (vote1->blocks[0]), boost::get<std::shared_ptr<rai::block>> (vote2->blocks[0]));
|
||||
}
|
||||
|
||||
TEST (vote_uniquer, vbh_one)
|
||||
{
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer uniquer (block_uniquer);
|
||||
rai::keypair key;
|
||||
auto block (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
std::vector<rai::block_hash> hashes;
|
||||
hashes.push_back (block->hash ());
|
||||
auto vote1 (std::make_shared<rai::vote> (key.pub, key.prv, 0, hashes));
|
||||
auto vote2 (std::make_shared<rai::vote> (key.pub, key.prv, 0, hashes));
|
||||
ASSERT_EQ (vote1, uniquer.unique (vote1));
|
||||
ASSERT_EQ (vote1, uniquer.unique (vote2));
|
||||
}
|
||||
|
||||
TEST (vote_uniquer, vbh_two)
|
||||
{
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer uniquer (block_uniquer);
|
||||
rai::keypair key;
|
||||
auto block1 (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
std::vector<rai::block_hash> hashes1;
|
||||
hashes1.push_back (block1->hash ());
|
||||
auto block2 (std::make_shared<rai::state_block> (1, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
std::vector<rai::block_hash> hashes2;
|
||||
hashes2.push_back (block2->hash ());
|
||||
auto vote1 (std::make_shared<rai::vote> (key.pub, key.prv, 0, hashes1));
|
||||
auto vote2 (std::make_shared<rai::vote> (key.pub, key.prv, 0, hashes2));
|
||||
ASSERT_EQ (vote1, uniquer.unique (vote1));
|
||||
ASSERT_EQ (vote2, uniquer.unique (vote2));
|
||||
}
|
||||
|
||||
TEST (vote_uniquer, cleanup)
|
||||
{
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer uniquer (block_uniquer);
|
||||
rai::keypair key;
|
||||
auto vote1 (std::make_shared<rai::vote> (key.pub, key.prv, 0, std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0)));
|
||||
auto vote2 (std::make_shared<rai::vote> (key.pub, key.prv, 1, std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0)));
|
||||
auto vote3 (uniquer.unique (vote1));
|
||||
auto vote4 (uniquer.unique (vote2));
|
||||
vote2.reset ();
|
||||
vote4.reset ();
|
||||
ASSERT_EQ (2, uniquer.size ());
|
||||
auto iterations (0);
|
||||
while (uniquer.size () == 2)
|
||||
{
|
||||
auto vote5 (uniquer.unique (vote1));
|
||||
ASSERT_LT (iterations++, 200);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ TEST (message, keepalive_deserialize)
|
|||
|
||||
TEST (message, publish_serialization)
|
||||
{
|
||||
rai::publish publish (std::unique_ptr<rai::block> (new rai::send_block (0, 1, 2, rai::keypair ().prv, 4, 5)));
|
||||
rai::publish publish (std::make_shared<rai::send_block> (0, 1, 2, rai::keypair ().prv, 4, 5));
|
||||
ASSERT_EQ (rai::block_type::send, publish.header.block_type ());
|
||||
ASSERT_FALSE (publish.header.ipv4_only ());
|
||||
publish.header.ipv4_only_set (true);
|
||||
|
@ -72,7 +72,7 @@ TEST (message, publish_serialization)
|
|||
TEST (message, confirm_ack_serialization)
|
||||
{
|
||||
rai::keypair key1;
|
||||
auto vote (std::make_shared<rai::vote> (key1.pub, key1.prv, 0, std::unique_ptr<rai::block> (new rai::send_block (0, 1, 2, key1.prv, 4, 5))));
|
||||
auto vote (std::make_shared<rai::vote> (key1.pub, key1.prv, 0, std::make_shared<rai::send_block> (0, 1, 2, key1.prv, 4, 5)));
|
||||
rai::confirm_ack con1 (vote);
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
|
|
|
@ -75,8 +75,10 @@ TEST (message_parser, exact_confirm_ack_size)
|
|||
{
|
||||
rai::system system (24000, 1);
|
||||
test_visitor visitor;
|
||||
rai::message_parser parser (visitor, system.work);
|
||||
auto block (std::unique_ptr<rai::send_block> (new rai::send_block (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1))));
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer vote_uniquer (block_uniquer);
|
||||
rai::message_parser parser (block_uniquer, vote_uniquer, visitor, system.work);
|
||||
auto block (std::make_shared<rai::send_block> (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1)));
|
||||
auto vote (std::make_shared<rai::vote> (0, rai::keypair ().prv, 0, std::move (block)));
|
||||
rai::confirm_ack message (vote);
|
||||
std::vector<uint8_t> bytes;
|
||||
|
@ -106,8 +108,10 @@ TEST (message_parser, exact_confirm_req_size)
|
|||
{
|
||||
rai::system system (24000, 1);
|
||||
test_visitor visitor;
|
||||
rai::message_parser parser (visitor, system.work);
|
||||
auto block (std::unique_ptr<rai::send_block> (new rai::send_block (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1))));
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer vote_uniquer (block_uniquer);
|
||||
rai::message_parser parser (block_uniquer, vote_uniquer, visitor, system.work);
|
||||
auto block (std::make_shared<rai::send_block> (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1)));
|
||||
rai::confirm_req message (std::move (block));
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
|
@ -136,8 +140,10 @@ TEST (message_parser, exact_publish_size)
|
|||
{
|
||||
rai::system system (24000, 1);
|
||||
test_visitor visitor;
|
||||
rai::message_parser parser (visitor, system.work);
|
||||
auto block (std::unique_ptr<rai::send_block> (new rai::send_block (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1))));
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer vote_uniquer (block_uniquer);
|
||||
rai::message_parser parser (block_uniquer, vote_uniquer, visitor, system.work);
|
||||
auto block (std::make_shared<rai::send_block> (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1)));
|
||||
rai::publish message (std::move (block));
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
|
@ -166,7 +172,9 @@ TEST (message_parser, exact_keepalive_size)
|
|||
{
|
||||
rai::system system (24000, 1);
|
||||
test_visitor visitor;
|
||||
rai::message_parser parser (visitor, system.work);
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer vote_uniquer (block_uniquer);
|
||||
rai::message_parser parser (block_uniquer, vote_uniquer, visitor, system.work);
|
||||
rai::keepalive message;
|
||||
std::vector<uint8_t> bytes;
|
||||
{
|
||||
|
|
|
@ -201,7 +201,7 @@ TEST (network, send_valid_confirm_ack)
|
|||
rai::block_hash latest1 (system.nodes[0]->latest (rai::test_genesis_key.pub));
|
||||
rai::send_block block2 (latest1, key2.pub, 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (latest1));
|
||||
rai::block_hash latest2 (system.nodes[1]->latest (rai::test_genesis_key.pub));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (block2)));
|
||||
system.nodes[0]->process_active (std::make_shared<rai::send_block> (block2));
|
||||
system.deadline_set (10s);
|
||||
// Keep polling until latest block changes
|
||||
while (system.nodes[1]->latest (rai::test_genesis_key.pub) == latest2)
|
||||
|
@ -224,7 +224,7 @@ TEST (network, send_valid_publish)
|
|||
rai::send_block block2 (latest1, key2.pub, 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (latest1));
|
||||
auto hash2 (block2.hash ());
|
||||
rai::block_hash latest2 (system.nodes[1]->latest (rai::test_genesis_key.pub));
|
||||
system.nodes[1]->process_active (std::unique_ptr<rai::block> (new rai::send_block (block2)));
|
||||
system.nodes[1]->process_active (std::make_shared<rai::send_block> (block2));
|
||||
system.deadline_set (10s);
|
||||
while (system.nodes[0]->stats.count (rai::stat::type::message, rai::stat::detail::publish, rai::stat::dir::in) == 0)
|
||||
{
|
||||
|
@ -242,7 +242,7 @@ TEST (network, send_valid_publish)
|
|||
TEST (network, send_insufficient_work)
|
||||
{
|
||||
rai::system system (24000, 2);
|
||||
std::unique_ptr<rai::send_block> block (new rai::send_block (0, 1, 20, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||
auto block (std::make_shared<rai::send_block> (0, 1, 20, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||
rai::publish publish (std::move (block));
|
||||
std::shared_ptr<std::vector<uint8_t>> bytes (new std::vector<uint8_t>);
|
||||
{
|
||||
|
@ -584,8 +584,8 @@ TEST (bootstrap_processor, process_state)
|
|||
rai::genesis genesis;
|
||||
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
|
||||
auto node0 (system.nodes[0]);
|
||||
std::unique_ptr<rai::block> block1 (new rai::state_block (rai::test_genesis_key.pub, node0->latest (rai::test_genesis_key.pub), rai::test_genesis_key.pub, rai::genesis_amount - 100, rai::test_genesis_key.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||
std::unique_ptr<rai::block> block2 (new rai::state_block (rai::test_genesis_key.pub, block1->hash (), rai::test_genesis_key.pub, rai::genesis_amount, block1->hash (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||
auto block1 (std::make_shared<rai::state_block> (rai::test_genesis_key.pub, node0->latest (rai::test_genesis_key.pub), rai::test_genesis_key.pub, rai::genesis_amount - 100, rai::test_genesis_key.pub, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||
auto block2 (std::make_shared<rai::state_block> (rai::test_genesis_key.pub, block1->hash (), rai::test_genesis_key.pub, rai::genesis_amount, block1->hash (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||
node0->work_generate_blocking (*block1);
|
||||
node0->work_generate_blocking (*block2);
|
||||
node0->process (*block1);
|
||||
|
@ -636,13 +636,13 @@ TEST (bootstrap_processor, pull_diamond)
|
|||
{
|
||||
rai::system system (24000, 1);
|
||||
rai::keypair key;
|
||||
std::unique_ptr<rai::send_block> send1 (new rai::send_block (system.nodes[0]->latest (rai::test_genesis_key.pub), key.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (system.nodes[0]->latest (rai::test_genesis_key.pub))));
|
||||
auto send1 (std::make_shared<rai::send_block> (system.nodes[0]->latest (rai::test_genesis_key.pub), key.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (system.nodes[0]->latest (rai::test_genesis_key.pub))));
|
||||
ASSERT_EQ (rai::process_result::progress, system.nodes[0]->process (*send1).code);
|
||||
std::unique_ptr<rai::open_block> open (new rai::open_block (send1->hash (), 1, key.pub, key.prv, key.pub, system.work.generate (key.pub)));
|
||||
auto open (std::make_shared<rai::open_block> (send1->hash (), 1, key.pub, key.prv, key.pub, system.work.generate (key.pub)));
|
||||
ASSERT_EQ (rai::process_result::progress, system.nodes[0]->process (*open).code);
|
||||
std::unique_ptr<rai::send_block> send2 (new rai::send_block (open->hash (), rai::test_genesis_key.pub, std::numeric_limits<rai::uint128_t>::max () - 100, key.prv, key.pub, system.work.generate (open->hash ())));
|
||||
auto send2 (std::make_shared<rai::send_block> (open->hash (), rai::test_genesis_key.pub, std::numeric_limits<rai::uint128_t>::max () - 100, key.prv, key.pub, system.work.generate (open->hash ())));
|
||||
ASSERT_EQ (rai::process_result::progress, system.nodes[0]->process (*send2).code);
|
||||
std::unique_ptr<rai::receive_block> receive (new rai::receive_block (send1->hash (), send2->hash (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (send1->hash ())));
|
||||
auto receive (std::make_shared<rai::receive_block> (send1->hash (), send2->hash (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (send1->hash ())));
|
||||
ASSERT_EQ (rai::process_result::progress, system.nodes[0]->process (*receive).code);
|
||||
rai::node_init init1;
|
||||
auto node1 (std::make_shared<rai::node> (init1, system.service, 24002, rai::unique_path (), system.alarm, system.logging, system.work));
|
||||
|
@ -667,13 +667,13 @@ TEST (bootstrap_processor, push_diamond)
|
|||
auto wallet1 (node1->wallets.create (100));
|
||||
wallet1->insert_adhoc (rai::test_genesis_key.prv);
|
||||
wallet1->insert_adhoc (key.prv);
|
||||
std::unique_ptr<rai::send_block> send1 (new rai::send_block (system.nodes[0]->latest (rai::test_genesis_key.pub), key.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (system.nodes[0]->latest (rai::test_genesis_key.pub))));
|
||||
auto send1 (std::make_shared<rai::send_block> (system.nodes[0]->latest (rai::test_genesis_key.pub), key.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (system.nodes[0]->latest (rai::test_genesis_key.pub))));
|
||||
ASSERT_EQ (rai::process_result::progress, node1->process (*send1).code);
|
||||
std::unique_ptr<rai::open_block> open (new rai::open_block (send1->hash (), 1, key.pub, key.prv, key.pub, system.work.generate (key.pub)));
|
||||
auto open (std::make_shared<rai::open_block> (send1->hash (), 1, key.pub, key.prv, key.pub, system.work.generate (key.pub)));
|
||||
ASSERT_EQ (rai::process_result::progress, node1->process (*open).code);
|
||||
std::unique_ptr<rai::send_block> send2 (new rai::send_block (open->hash (), rai::test_genesis_key.pub, std::numeric_limits<rai::uint128_t>::max () - 100, key.prv, key.pub, system.work.generate (open->hash ())));
|
||||
auto send2 (std::make_shared<rai::send_block> (open->hash (), rai::test_genesis_key.pub, std::numeric_limits<rai::uint128_t>::max () - 100, key.prv, key.pub, system.work.generate (open->hash ())));
|
||||
ASSERT_EQ (rai::process_result::progress, node1->process (*send2).code);
|
||||
std::unique_ptr<rai::receive_block> receive (new rai::receive_block (send1->hash (), send2->hash (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (send1->hash ())));
|
||||
auto receive (std::make_shared<rai::receive_block> (send1->hash (), send2->hash (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (send1->hash ())));
|
||||
ASSERT_EQ (rai::process_result::progress, node1->process (*receive).code);
|
||||
node1->bootstrap_initiator.bootstrap (system.nodes[0]->network.endpoint ());
|
||||
system.deadline_set (10s);
|
||||
|
|
|
@ -148,9 +148,9 @@ TEST (node, send_out_of_order)
|
|||
rai::send_block send1 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2 (send1.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (send1.hash ()));
|
||||
rai::send_block send3 (send2.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 3, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (send2.hash ()));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send3)));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send2)));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send1)));
|
||||
system.nodes[0]->process_active (std::make_shared<rai::send_block> (send3));
|
||||
system.nodes[0]->process_active (std::make_shared<rai::send_block> (send2));
|
||||
system.nodes[0]->process_active (std::make_shared<rai::send_block> (send1));
|
||||
system.deadline_set (10s);
|
||||
while (std::any_of (system.nodes.begin (), system.nodes.end (), [&](std::shared_ptr<rai::node> const & node_a) { return node_a->balance (rai::test_genesis_key.pub) != rai::genesis_amount - system.nodes[0]->config.receive_minimum.number () * 3; }))
|
||||
{
|
||||
|
@ -1658,29 +1658,29 @@ TEST (node, vote_republish)
|
|||
rai::keypair key2;
|
||||
system.wallet (1)->insert_adhoc (key2.prv);
|
||||
rai::genesis genesis;
|
||||
rai::send_block send1 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send1)));
|
||||
auto send1 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto send2 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
system.nodes[0]->process_active (send1);
|
||||
system.deadline_set (5s);
|
||||
while (!system.nodes[1]->block (send1.hash ()))
|
||||
while (!system.nodes[1]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
system.nodes[0]->active.publish (std::unique_ptr<rai::block> (new rai::send_block (send2)));
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, std::unique_ptr<rai::block> (new rai::send_block (send2))));
|
||||
ASSERT_TRUE (system.nodes[0]->active.active (send1));
|
||||
ASSERT_TRUE (system.nodes[1]->active.active (send1));
|
||||
system.nodes[0]->active.publish (send2);
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, send2));
|
||||
ASSERT_TRUE (system.nodes[0]->active.active (*send1));
|
||||
ASSERT_TRUE (system.nodes[1]->active.active (*send1));
|
||||
system.nodes[0]->vote_processor.vote (vote, system.nodes[0]->network.endpoint ());
|
||||
while (!system.nodes[0]->block (send2.hash ()))
|
||||
while (!system.nodes[0]->block (send2->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
while (!system.nodes[1]->block (send2.hash ()))
|
||||
while (!system.nodes[1]->block (send2->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_FALSE (system.nodes[0]->block (send1.hash ()));
|
||||
ASSERT_FALSE (system.nodes[1]->block (send1.hash ()));
|
||||
ASSERT_FALSE (system.nodes[0]->block (send1->hash ()));
|
||||
ASSERT_FALSE (system.nodes[1]->block (send1->hash ()));
|
||||
system.deadline_set (5s);
|
||||
while (system.nodes[1]->balance (key2.pub) != system.nodes[0]->config.receive_minimum.number () * 2)
|
||||
{
|
||||
|
@ -1698,31 +1698,31 @@ TEST (node, vote_by_hash_republish)
|
|||
rai::keypair key2;
|
||||
system.wallet (1)->insert_adhoc (key2.prv);
|
||||
rai::genesis genesis;
|
||||
rai::send_block send1 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send1)));
|
||||
auto send1 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto send2 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
system.nodes[0]->process_active (send1);
|
||||
system.deadline_set (5s);
|
||||
while (!system.nodes[1]->block (send1.hash ()))
|
||||
while (!system.nodes[1]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
system.nodes[0]->active.publish (std::unique_ptr<rai::block> (new rai::send_block (send2)));
|
||||
system.nodes[0]->active.publish (send2);
|
||||
std::vector<rai::block_hash> vote_blocks;
|
||||
vote_blocks.push_back (send2.hash ());
|
||||
vote_blocks.push_back (send2->hash ());
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, vote_blocks));
|
||||
ASSERT_TRUE (system.nodes[0]->active.active (send1));
|
||||
ASSERT_TRUE (system.nodes[1]->active.active (send1));
|
||||
ASSERT_TRUE (system.nodes[0]->active.active (*send1));
|
||||
ASSERT_TRUE (system.nodes[1]->active.active (*send1));
|
||||
system.nodes[0]->vote_processor.vote (vote, system.nodes[0]->network.endpoint ());
|
||||
while (!system.nodes[0]->block (send2.hash ()))
|
||||
while (!system.nodes[0]->block (send2->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
while (!system.nodes[1]->block (send2.hash ()))
|
||||
while (!system.nodes[1]->block (send2->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_FALSE (system.nodes[0]->block (send1.hash ()));
|
||||
ASSERT_FALSE (system.nodes[1]->block (send1.hash ()));
|
||||
ASSERT_FALSE (system.nodes[0]->block (send1->hash ()));
|
||||
ASSERT_FALSE (system.nodes[1]->block (send1->hash ()));
|
||||
system.deadline_set (5s);
|
||||
while (system.nodes[1]->balance (key2.pub) != system.nodes[0]->config.receive_minimum.number () * 2)
|
||||
{
|
||||
|
@ -1743,31 +1743,31 @@ TEST (node, vote_by_hash_epoch_block_republish)
|
|||
system.nodes[0]->ledger.epoch_signer = epoch_signer.pub;
|
||||
system.nodes[1]->ledger.epoch_signer = epoch_signer.pub;
|
||||
rai::genesis genesis;
|
||||
rai::send_block send1 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::state_block epoch1 (rai::genesis_account, genesis.hash (), rai::genesis_account, rai::genesis_amount, system.nodes[0]->ledger.epoch_link, epoch_signer.prv, epoch_signer.pub, system.work.generate (genesis.hash ()));
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send1)));
|
||||
auto send1 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto epoch1 (std::make_shared<rai::state_block> (rai::genesis_account, genesis.hash (), rai::genesis_account, rai::genesis_amount, system.nodes[0]->ledger.epoch_link, epoch_signer.prv, epoch_signer.pub, system.work.generate (genesis.hash ())));
|
||||
system.nodes[0]->process_active (send1);
|
||||
system.deadline_set (5s);
|
||||
while (!system.nodes[1]->block (send1.hash ()))
|
||||
while (!system.nodes[1]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
system.nodes[0]->active.publish (std::unique_ptr<rai::block> (new rai::state_block (epoch1)));
|
||||
system.nodes[0]->active.publish (epoch1);
|
||||
std::vector<rai::block_hash> vote_blocks;
|
||||
vote_blocks.push_back (epoch1.hash ());
|
||||
vote_blocks.push_back (epoch1->hash ());
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, vote_blocks));
|
||||
ASSERT_TRUE (system.nodes[0]->active.active (send1));
|
||||
ASSERT_TRUE (system.nodes[1]->active.active (send1));
|
||||
ASSERT_TRUE (system.nodes[0]->active.active (*send1));
|
||||
ASSERT_TRUE (system.nodes[1]->active.active (*send1));
|
||||
system.nodes[0]->vote_processor.vote (vote, system.nodes[0]->network.endpoint ());
|
||||
while (!system.nodes[0]->block (epoch1.hash ()))
|
||||
while (!system.nodes[0]->block (epoch1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
while (!system.nodes[1]->block (epoch1.hash ()))
|
||||
while (!system.nodes[1]->block (epoch1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_FALSE (system.nodes[0]->block (send1.hash ()));
|
||||
ASSERT_FALSE (system.nodes[1]->block (send1.hash ()));
|
||||
ASSERT_FALSE (system.nodes[0]->block (send1->hash ()));
|
||||
ASSERT_FALSE (system.nodes[1]->block (send1->hash ()));
|
||||
}
|
||||
|
||||
TEST (node, fork_invalid_block_signature)
|
||||
|
@ -1775,30 +1775,30 @@ TEST (node, fork_invalid_block_signature)
|
|||
rai::system system (24000, 2);
|
||||
rai::keypair key2;
|
||||
rai::genesis genesis;
|
||||
rai::send_block send1 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2_corrupt (send2);
|
||||
send2_corrupt.signature = rai::signature (123);
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send1)));
|
||||
auto send1 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto send2 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto send2_corrupt (std::make_shared<rai::send_block> (*send2));
|
||||
send2_corrupt->signature = rai::signature (123);
|
||||
system.nodes[0]->process_active (send1);
|
||||
system.deadline_set (5s);
|
||||
while (!system.nodes[0]->block (send1.hash ()))
|
||||
while (!system.nodes[0]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, std::make_unique<rai::send_block> (send2)));
|
||||
auto vote_corrupt (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, std::make_unique<rai::send_block> (send2_corrupt)));
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, send2));
|
||||
auto vote_corrupt (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, send2_corrupt));
|
||||
system.nodes[1]->network.republish_vote (vote_corrupt);
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
system.nodes[1]->network.republish_vote (vote);
|
||||
while (system.nodes[0]->block (send1.hash ()))
|
||||
while (system.nodes[0]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
while (!system.nodes[0]->block (send2.hash ()))
|
||||
while (!system.nodes[0]->block (send2->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_EQ (system.nodes[0]->block (send2.hash ())->block_signature (), send2.block_signature ());
|
||||
ASSERT_EQ (system.nodes[0]->block (send2->hash ())->block_signature (), send2->block_signature ());
|
||||
}
|
||||
|
||||
TEST (node, fork_invalid_block_signature_vote_by_hash)
|
||||
|
@ -1806,35 +1806,35 @@ TEST (node, fork_invalid_block_signature_vote_by_hash)
|
|||
rai::system system (24000, 1);
|
||||
rai::keypair key2;
|
||||
rai::genesis genesis;
|
||||
rai::send_block send1 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2 (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ()));
|
||||
rai::send_block send2_corrupt (send2);
|
||||
send2_corrupt.signature = rai::signature (123);
|
||||
system.nodes[0]->process_active (std::unique_ptr<rai::block> (new rai::send_block (send1)));
|
||||
auto send1 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto send2 (std::make_shared<rai::send_block> (genesis.hash (), key2.pub, std::numeric_limits<rai::uint128_t>::max () - system.nodes[0]->config.receive_minimum.number () * 2, rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (genesis.hash ())));
|
||||
auto send2_corrupt (std::make_shared<rai::send_block> (*send2));
|
||||
send2_corrupt->signature = rai::signature (123);
|
||||
system.nodes[0]->process_active (send1);
|
||||
system.deadline_set (5s);
|
||||
while (!system.nodes[0]->block (send1.hash ()))
|
||||
while (!system.nodes[0]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
system.nodes[0]->active.publish (std::make_unique<rai::send_block> (send2_corrupt));
|
||||
system.nodes[0]->active.publish (send2_corrupt);
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
system.nodes[0]->active.publish (std::make_unique<rai::send_block> (send2));
|
||||
system.nodes[0]->active.publish (send2);
|
||||
std::vector<rai::block_hash> vote_blocks;
|
||||
vote_blocks.push_back (send2.hash ());
|
||||
vote_blocks.push_back (send2->hash ());
|
||||
auto vote (std::make_shared<rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, vote_blocks));
|
||||
{
|
||||
auto transaction (system.nodes[0]->store.tx_begin_read ());
|
||||
system.nodes[0]->vote_processor.vote_blocking (transaction, vote, system.nodes[0]->network.endpoint ());
|
||||
}
|
||||
while (system.nodes[0]->block (send1.hash ()))
|
||||
while (system.nodes[0]->block (send1->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
while (!system.nodes[0]->block (send2.hash ()))
|
||||
while (!system.nodes[0]->block (send2->hash ()))
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_EQ (system.nodes[0]->block (send2.hash ())->block_signature (), send2.block_signature ());
|
||||
ASSERT_EQ (system.nodes[0]->block (send2->hash ())->block_signature (), send2->block_signature ());
|
||||
}
|
||||
|
||||
TEST (node, block_processor_signatures)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <boost/endian/conversion.hpp>
|
||||
|
||||
#include <xxhash/xxhash.h>
|
||||
|
||||
/** Compare blocks, first by type, then content. This is an optimization over dynamic_cast, which is very slow on some platforms. */
|
||||
namespace
|
||||
{
|
||||
|
@ -69,6 +71,20 @@ rai::block_hash rai::block::hash () const
|
|||
return result;
|
||||
}
|
||||
|
||||
rai::block_hash rai::block::full_hash () const
|
||||
{
|
||||
rai::block_hash result;
|
||||
blake2b_state state;
|
||||
blake2b_init (&state, sizeof (result.bytes));
|
||||
blake2b_update (&state, hash ().bytes.data (), sizeof (hash ()));
|
||||
auto signature (block_signature ());
|
||||
blake2b_update (&state, signature.bytes.data (), sizeof (signature));
|
||||
auto work (block_work ());
|
||||
blake2b_update (&state, &work, sizeof (work));
|
||||
blake2b_final (&state, result.bytes.data (), sizeof (result.bytes));
|
||||
return result;
|
||||
}
|
||||
|
||||
void rai::send_block::visit (rai::block_visitor & visitor_a) const
|
||||
{
|
||||
visitor_a.send_block (*this);
|
||||
|
@ -1145,9 +1161,9 @@ void rai::state_block::signature_set (rai::uint512_union const & signature_a)
|
|||
signature = signature_a;
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::deserialize_block_json (boost::property_tree::ptree const & tree_a)
|
||||
std::shared_ptr<rai::block> rai::deserialize_block_json (boost::property_tree::ptree const & tree_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
try
|
||||
{
|
||||
auto type (tree_a.get<std::string> ("type"));
|
||||
|
@ -1200,14 +1216,18 @@ std::unique_ptr<rai::block> rai::deserialize_block_json (boost::property_tree::p
|
|||
catch (std::runtime_error const &)
|
||||
{
|
||||
}
|
||||
if (uniquer_a != nullptr)
|
||||
{
|
||||
result = uniquer_a->unique (result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::deserialize_block (rai::stream & stream_a)
|
||||
std::shared_ptr<rai::block> rai::deserialize_block (rai::stream & stream_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
rai::block_type type;
|
||||
auto error (read (stream_a, type));
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
if (!error)
|
||||
{
|
||||
result = rai::deserialize_block (stream_a, type);
|
||||
|
@ -1215,9 +1235,9 @@ std::unique_ptr<rai::block> rai::deserialize_block (rai::stream & stream_a)
|
|||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::deserialize_block (rai::stream & stream_a, rai::block_type type_a)
|
||||
std::shared_ptr<rai::block> rai::deserialize_block (rai::stream & stream_a, rai::block_type type_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
switch (type_a)
|
||||
{
|
||||
case rai::block_type::receive:
|
||||
|
@ -1274,6 +1294,10 @@ std::unique_ptr<rai::block> rai::deserialize_block (rai::stream & stream_a, rai:
|
|||
assert (false);
|
||||
break;
|
||||
}
|
||||
if (uniquer_a != nullptr)
|
||||
{
|
||||
result = uniquer_a->unique (result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1523,3 +1547,50 @@ void rai::receive_hashables::hash (blake2b_state & hash_a) const
|
|||
blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes));
|
||||
blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes));
|
||||
}
|
||||
|
||||
std::shared_ptr<rai::block> rai::block_uniquer::unique (std::shared_ptr<rai::block> block_a)
|
||||
{
|
||||
auto result (block_a);
|
||||
if (result != nullptr)
|
||||
{
|
||||
rai::uint256_union key (block_a->full_hash ());
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
auto & existing (blocks[key]);
|
||||
if (auto block_l = existing.lock ())
|
||||
{
|
||||
result = block_l;
|
||||
}
|
||||
else
|
||||
{
|
||||
existing = block_a;
|
||||
}
|
||||
for (auto i (0); i < cleanup_count; ++i)
|
||||
{
|
||||
rai::uint256_union random;
|
||||
rai::random_pool.GenerateBlock (random.bytes.data (), random.bytes.size ());
|
||||
auto existing (blocks.find (random));
|
||||
if (existing == blocks.end ())
|
||||
{
|
||||
existing = blocks.begin ();
|
||||
}
|
||||
if (existing != blocks.end ())
|
||||
{
|
||||
if (auto block_l = existing->second.lock ())
|
||||
{
|
||||
// Still live
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks.erase (existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t rai::block_uniquer::size ()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
return blocks.size ();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <blake2/blake2.h>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <streambuf>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace rai
|
||||
{
|
||||
|
@ -44,6 +45,8 @@ class block
|
|||
public:
|
||||
// Return a digest of the hashables in this block.
|
||||
rai::block_hash hash () const;
|
||||
// Return a digest of hashables and non-hashables in this block.
|
||||
rai::block_hash full_hash () const;
|
||||
std::string to_json ();
|
||||
virtual void hash (blake2b_state &) const = 0;
|
||||
virtual uint64_t block_work () const = 0;
|
||||
|
@ -302,8 +305,22 @@ public:
|
|||
virtual void state_block (rai::state_block const &) = 0;
|
||||
virtual ~block_visitor () = default;
|
||||
};
|
||||
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 &);
|
||||
/**
|
||||
* This class serves to find and return unique variants of a block in order to minimize memory usage
|
||||
*/
|
||||
class block_uniquer
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<rai::block> unique (std::shared_ptr<rai::block>);
|
||||
size_t size ();
|
||||
|
||||
private:
|
||||
std::mutex mutex;
|
||||
std::unordered_map<rai::uint256_union, std::weak_ptr<rai::block>> blocks;
|
||||
static unsigned constexpr cleanup_count = 2;
|
||||
};
|
||||
std::shared_ptr<rai::block> deserialize_block (rai::stream &, rai::block_uniquer * = nullptr);
|
||||
std::shared_ptr<rai::block> deserialize_block (rai::stream &, rai::block_type, rai::block_uniquer * = nullptr);
|
||||
std::shared_ptr<rai::block> deserialize_block_json (boost::property_tree::ptree const &, rai::block_uniquer * = nullptr);
|
||||
void serialize_block (rai::stream &, rai::block const &);
|
||||
}
|
||||
|
|
|
@ -604,7 +604,7 @@ void rai::bulk_push_client::start ()
|
|||
|
||||
void rai::bulk_push_client::push (rai::transaction const & transaction_a)
|
||||
{
|
||||
std::unique_ptr<rai::block> block;
|
||||
std::shared_ptr<rai::block> block;
|
||||
bool finished (false);
|
||||
while (block == nullptr && !finished)
|
||||
{
|
||||
|
@ -1652,7 +1652,7 @@ void rai::bulk_pull_server::set_current_end ()
|
|||
|
||||
void rai::bulk_pull_server::send_next ()
|
||||
{
|
||||
std::unique_ptr<rai::block> block (get_next ());
|
||||
auto block (get_next ());
|
||||
if (block != nullptr)
|
||||
{
|
||||
{
|
||||
|
@ -1675,9 +1675,9 @@ void rai::bulk_pull_server::send_next ()
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::bulk_pull_server::get_next ()
|
||||
std::shared_ptr<rai::block> rai::bulk_pull_server::get_next ()
|
||||
{
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
bool send_current = false, set_current_to_end = false;
|
||||
|
||||
/*
|
||||
|
|
|
@ -238,7 +238,7 @@ class bulk_pull_server : public std::enable_shared_from_this<rai::bulk_pull_serv
|
|||
public:
|
||||
bulk_pull_server (std::shared_ptr<rai::bootstrap_server> const &, std::unique_ptr<rai::bulk_pull>);
|
||||
void set_current_end ();
|
||||
std::unique_ptr<rai::block> get_next ();
|
||||
std::shared_ptr<rai::block> get_next ();
|
||||
void send_next ();
|
||||
void sent_action (boost::system::error_code const &, size_t);
|
||||
void send_finished ();
|
||||
|
@ -276,7 +276,7 @@ class bulk_pull_blocks_server : public std::enable_shared_from_this<rai::bulk_pu
|
|||
public:
|
||||
bulk_pull_blocks_server (std::shared_ptr<rai::bootstrap_server> const &, std::unique_ptr<rai::bulk_pull_blocks>);
|
||||
void set_params ();
|
||||
std::unique_ptr<rai::block> get_next ();
|
||||
std::shared_ptr<rai::block> get_next ();
|
||||
void send_next ();
|
||||
void send_finished ();
|
||||
void no_block_sent (boost::system::error_code const &, size_t);
|
||||
|
|
|
@ -146,7 +146,9 @@ std::string rai::message_parser::status_string ()
|
|||
return "[unknown parse_status]";
|
||||
}
|
||||
|
||||
rai::message_parser::message_parser (rai::message_visitor & visitor_a, rai::work_pool & pool_a) :
|
||||
rai::message_parser::message_parser (rai::block_uniquer & block_uniquer_a, rai::vote_uniquer & vote_uniquer_a, rai::message_visitor & visitor_a, rai::work_pool & pool_a) :
|
||||
block_uniquer (block_uniquer_a),
|
||||
vote_uniquer (vote_uniquer_a),
|
||||
visitor (visitor_a),
|
||||
pool (pool_a),
|
||||
status (parse_status::success)
|
||||
|
@ -237,7 +239,7 @@ void rai::message_parser::deserialize_keepalive (rai::stream & stream_a, rai::me
|
|||
void rai::message_parser::deserialize_publish (rai::stream & stream_a, rai::message_header const & header_a)
|
||||
{
|
||||
auto error (false);
|
||||
rai::publish incoming (error, stream_a, header_a);
|
||||
rai::publish incoming (error, stream_a, header_a, &block_uniquer);
|
||||
if (!error && at_end (stream_a))
|
||||
{
|
||||
if (!rai::work_validate (*incoming.block))
|
||||
|
@ -258,7 +260,7 @@ void rai::message_parser::deserialize_publish (rai::stream & stream_a, rai::mess
|
|||
void rai::message_parser::deserialize_confirm_req (rai::stream & stream_a, rai::message_header const & header_a)
|
||||
{
|
||||
auto error (false);
|
||||
rai::confirm_req incoming (error, stream_a, header_a);
|
||||
rai::confirm_req incoming (error, stream_a, header_a, &block_uniquer);
|
||||
if (!error && at_end (stream_a))
|
||||
{
|
||||
if (!rai::work_validate (*incoming.block))
|
||||
|
@ -279,7 +281,7 @@ void rai::message_parser::deserialize_confirm_req (rai::stream & stream_a, rai::
|
|||
void rai::message_parser::deserialize_confirm_ack (rai::stream & stream_a, rai::message_header const & header_a)
|
||||
{
|
||||
auto error (false);
|
||||
rai::confirm_ack incoming (error, stream_a, header_a);
|
||||
rai::confirm_ack incoming (error, stream_a, header_a, &vote_uniquer);
|
||||
if (!error && at_end (stream_a))
|
||||
{
|
||||
for (auto & vote_block : incoming.vote->blocks)
|
||||
|
@ -387,12 +389,12 @@ bool rai::keepalive::operator== (rai::keepalive const & other_a) const
|
|||
return peers == other_a.peers;
|
||||
}
|
||||
|
||||
rai::publish::publish (bool & error_a, rai::stream & stream_a, rai::message_header const & header_a) :
|
||||
rai::publish::publish (bool & error_a, rai::stream & stream_a, rai::message_header const & header_a, rai::block_uniquer * uniquer_a) :
|
||||
message (header_a)
|
||||
{
|
||||
if (!error_a)
|
||||
{
|
||||
error_a = deserialize (stream_a);
|
||||
error_a = deserialize (stream_a, uniquer_a);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,10 +405,10 @@ block (block_a)
|
|||
header.block_type_set (block->type ());
|
||||
}
|
||||
|
||||
bool rai::publish::deserialize (rai::stream & stream_a)
|
||||
bool rai::publish::deserialize (rai::stream & stream_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
assert (header.type == rai::message_type::publish);
|
||||
block = rai::deserialize_block (stream_a, header.block_type ());
|
||||
block = rai::deserialize_block (stream_a, header.block_type (), uniquer_a);
|
||||
auto result (block == nullptr);
|
||||
return result;
|
||||
}
|
||||
|
@ -428,12 +430,12 @@ bool rai::publish::operator== (rai::publish const & other_a) const
|
|||
return *block == *other_a.block;
|
||||
}
|
||||
|
||||
rai::confirm_req::confirm_req (bool & error_a, rai::stream & stream_a, rai::message_header const & header_a) :
|
||||
rai::confirm_req::confirm_req (bool & error_a, rai::stream & stream_a, rai::message_header const & header_a, rai::block_uniquer * uniquer_a) :
|
||||
message (header_a)
|
||||
{
|
||||
if (!error_a)
|
||||
{
|
||||
error_a = deserialize (stream_a);
|
||||
error_a = deserialize (stream_a, uniquer_a);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,10 +446,10 @@ block (block_a)
|
|||
header.block_type_set (block->type ());
|
||||
}
|
||||
|
||||
bool rai::confirm_req::deserialize (rai::stream & stream_a)
|
||||
bool rai::confirm_req::deserialize (rai::stream & stream_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
assert (header.type == rai::message_type::confirm_req);
|
||||
block = rai::deserialize_block (stream_a, header.block_type ());
|
||||
block = rai::deserialize_block (stream_a, header.block_type (), uniquer_a);
|
||||
auto result (block == nullptr);
|
||||
return result;
|
||||
}
|
||||
|
@ -469,10 +471,14 @@ bool rai::confirm_req::operator== (rai::confirm_req const & other_a) const
|
|||
return *block == *other_a.block;
|
||||
}
|
||||
|
||||
rai::confirm_ack::confirm_ack (bool & error_a, rai::stream & stream_a, rai::message_header const & header_a) :
|
||||
rai::confirm_ack::confirm_ack (bool & error_a, rai::stream & stream_a, rai::message_header const & header_a, rai::vote_uniquer * uniquer_a) :
|
||||
message (header_a),
|
||||
vote (std::make_shared<rai::vote> (error_a, stream_a, header.block_type ()))
|
||||
{
|
||||
if (uniquer_a)
|
||||
{
|
||||
vote = uniquer_a->unique (vote);
|
||||
}
|
||||
}
|
||||
|
||||
rai::confirm_ack::confirm_ack (std::shared_ptr<rai::vote> vote_a) :
|
||||
|
@ -490,10 +496,14 @@ vote (vote_a)
|
|||
}
|
||||
}
|
||||
|
||||
bool rai::confirm_ack::deserialize (rai::stream & stream_a)
|
||||
bool rai::confirm_ack::deserialize (rai::stream & stream_a, rai::vote_uniquer * uniquer_a)
|
||||
{
|
||||
assert (header.type == rai::message_type::confirm_ack);
|
||||
auto result (vote->deserialize (stream_a));
|
||||
if (uniquer_a)
|
||||
{
|
||||
vote = uniquer_a->unique (vote);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,7 +191,6 @@ public:
|
|||
message (rai::message_header const &);
|
||||
virtual ~message () = default;
|
||||
virtual void serialize (rai::stream &) = 0;
|
||||
virtual bool deserialize (rai::stream &) = 0;
|
||||
virtual void visit (rai::message_visitor &) const = 0;
|
||||
rai::message_header header;
|
||||
};
|
||||
|
@ -214,7 +213,7 @@ public:
|
|||
invalid_magic,
|
||||
invalid_network
|
||||
};
|
||||
message_parser (rai::message_visitor &, rai::work_pool &);
|
||||
message_parser (rai::block_uniquer &, rai::vote_uniquer &, rai::message_visitor &, rai::work_pool &);
|
||||
void deserialize_buffer (uint8_t const *, size_t);
|
||||
void deserialize_keepalive (rai::stream &, rai::message_header const &);
|
||||
void deserialize_publish (rai::stream &, rai::message_header const &);
|
||||
|
@ -222,6 +221,8 @@ public:
|
|||
void deserialize_confirm_ack (rai::stream &, rai::message_header const &);
|
||||
void deserialize_node_id_handshake (rai::stream &, rai::message_header const &);
|
||||
bool at_end (rai::stream &);
|
||||
rai::block_uniquer & block_uniquer;
|
||||
rai::vote_uniquer & vote_uniquer;
|
||||
rai::message_visitor & visitor;
|
||||
rai::work_pool & pool;
|
||||
parse_status status;
|
||||
|
@ -234,7 +235,7 @@ public:
|
|||
keepalive (bool &, rai::stream &, rai::message_header const &);
|
||||
keepalive ();
|
||||
void visit (rai::message_visitor &) const override;
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
bool operator== (rai::keepalive const &) const;
|
||||
std::array<rai::endpoint, 8> peers;
|
||||
|
@ -242,10 +243,10 @@ public:
|
|||
class publish : public message
|
||||
{
|
||||
public:
|
||||
publish (bool &, rai::stream &, rai::message_header const &);
|
||||
publish (bool &, rai::stream &, rai::message_header const &, rai::block_uniquer * = nullptr);
|
||||
publish (std::shared_ptr<rai::block>);
|
||||
void visit (rai::message_visitor &) const override;
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &, rai::block_uniquer * = nullptr);
|
||||
void serialize (rai::stream &) override;
|
||||
bool operator== (rai::publish const &) const;
|
||||
std::shared_ptr<rai::block> block;
|
||||
|
@ -253,9 +254,9 @@ public:
|
|||
class confirm_req : public message
|
||||
{
|
||||
public:
|
||||
confirm_req (bool &, rai::stream &, rai::message_header const &);
|
||||
confirm_req (bool &, rai::stream &, rai::message_header const &, rai::block_uniquer * = nullptr);
|
||||
confirm_req (std::shared_ptr<rai::block>);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &, rai::block_uniquer * = nullptr);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
bool operator== (rai::confirm_req const &) const;
|
||||
|
@ -264,9 +265,9 @@ public:
|
|||
class confirm_ack : public message
|
||||
{
|
||||
public:
|
||||
confirm_ack (bool &, rai::stream &, rai::message_header const &);
|
||||
confirm_ack (bool &, rai::stream &, rai::message_header const &, rai::vote_uniquer * = nullptr);
|
||||
confirm_ack (std::shared_ptr<rai::vote>);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &, rai::vote_uniquer * = nullptr);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
bool operator== (rai::confirm_ack const &) const;
|
||||
|
@ -277,7 +278,7 @@ class frontier_req : public message
|
|||
public:
|
||||
frontier_req ();
|
||||
frontier_req (bool &, rai::stream &, rai::message_header const &);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
bool operator== (rai::frontier_req const &) const;
|
||||
|
@ -290,7 +291,7 @@ class bulk_pull : public message
|
|||
public:
|
||||
bulk_pull ();
|
||||
bulk_pull (bool &, rai::stream &, rai::message_header const &);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
rai::uint256_union start;
|
||||
|
@ -301,7 +302,7 @@ class bulk_pull_account : public message
|
|||
public:
|
||||
bulk_pull_account ();
|
||||
bulk_pull_account (bool &, rai::stream &, rai::message_header const &);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
rai::uint256_union account;
|
||||
|
@ -313,7 +314,7 @@ class bulk_pull_blocks : public message
|
|||
public:
|
||||
bulk_pull_blocks ();
|
||||
bulk_pull_blocks (bool &, rai::stream &, rai::message_header const &);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
rai::block_hash min_hash;
|
||||
|
@ -326,7 +327,7 @@ class bulk_push : public message
|
|||
public:
|
||||
bulk_push ();
|
||||
bulk_push (rai::message_header const &);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
};
|
||||
|
@ -335,7 +336,7 @@ class node_id_handshake : public message
|
|||
public:
|
||||
node_id_handshake (bool &, rai::stream &, rai::message_header const &);
|
||||
node_id_handshake (boost::optional<rai::block_hash>, boost::optional<std::pair<rai::account, rai::signature>>);
|
||||
bool deserialize (rai::stream &) override;
|
||||
bool deserialize (rai::stream &);
|
||||
void serialize (rai::stream &) override;
|
||||
void visit (rai::message_visitor &) const override;
|
||||
bool operator== (rai::node_id_handshake const &) const;
|
||||
|
|
|
@ -1226,7 +1226,7 @@ MDB_val rai::mdb_store::block_raw_get (rai::transaction const & transaction_a, r
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
std::unique_ptr<rai::block> rai::mdb_store::block_random (rai::transaction const & transaction_a, MDB_dbi database)
|
||||
std::shared_ptr<rai::block> rai::mdb_store::block_random (rai::transaction const & transaction_a, MDB_dbi database)
|
||||
{
|
||||
rai::block_hash hash;
|
||||
rai::random_pool.GenerateBlock (hash.bytes.data (), hash.bytes.size ());
|
||||
|
@ -1240,11 +1240,11 @@ std::unique_ptr<rai::block> rai::mdb_store::block_random (rai::transaction const
|
|||
return block_get (transaction_a, rai::block_hash (existing->first));
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::mdb_store::block_random (rai::transaction const & transaction_a)
|
||||
std::shared_ptr<rai::block> rai::mdb_store::block_random (rai::transaction const & transaction_a)
|
||||
{
|
||||
auto count (block_count (transaction_a));
|
||||
auto region (rai::random_pool.GenerateWord32 (0, count.sum () - 1));
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
if (region < count.send)
|
||||
{
|
||||
result = block_random<rai::send_block> (transaction_a, send_blocks);
|
||||
|
@ -1315,11 +1315,11 @@ void rai::mdb_store::block_successor_clear (rai::transaction const & transaction
|
|||
block_put (transaction_a, hash_a, *block, 0, version);
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::mdb_store::block_get (rai::transaction const & transaction_a, rai::block_hash const & hash_a)
|
||||
std::shared_ptr<rai::block> rai::mdb_store::block_get (rai::transaction const & transaction_a, rai::block_hash const & hash_a)
|
||||
{
|
||||
rai::block_type type;
|
||||
auto value (block_raw_get (transaction_a, hash_a, type));
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
if (value.mv_size != 0)
|
||||
{
|
||||
rai::bufferstream stream (reinterpret_cast<uint8_t const *> (value.mv_data), value.mv_size);
|
||||
|
|
|
@ -155,8 +155,8 @@ public:
|
|||
void block_put (rai::transaction const &, rai::block_hash const &, rai::block const &, rai::block_hash const & = rai::block_hash (0), rai::epoch version = rai::epoch::epoch_0) override;
|
||||
rai::block_hash block_successor (rai::transaction const &, rai::block_hash const &) override;
|
||||
void block_successor_clear (rai::transaction const &, rai::block_hash const &) override;
|
||||
std::unique_ptr<rai::block> block_get (rai::transaction const &, rai::block_hash const &) override;
|
||||
std::unique_ptr<rai::block> block_random (rai::transaction const &) override;
|
||||
std::shared_ptr<rai::block> block_get (rai::transaction const &, rai::block_hash const &) override;
|
||||
std::shared_ptr<rai::block> block_random (rai::transaction const &) override;
|
||||
void block_del (rai::transaction const &, rai::block_hash const &) override;
|
||||
bool block_exists (rai::transaction const &, rai::block_hash const &) override;
|
||||
rai::block_counts block_count (rai::transaction const &) override;
|
||||
|
@ -367,7 +367,7 @@ public:
|
|||
private:
|
||||
MDB_dbi block_database (rai::block_type, rai::epoch);
|
||||
template <typename T>
|
||||
std::unique_ptr<rai::block> block_random (rai::transaction const &, MDB_dbi);
|
||||
std::shared_ptr<rai::block> block_random (rai::transaction const &, MDB_dbi);
|
||||
MDB_val block_raw_get (rai::transaction const &, rai::block_hash const &, rai::block_type &);
|
||||
void block_raw_put (rai::transaction const &, MDB_dbi, rai::block_hash const &, MDB_val);
|
||||
void clear (MDB_dbi);
|
||||
|
|
|
@ -608,7 +608,7 @@ void rai::network::receive_action (rai::udp_data * data_a)
|
|||
if (!rai::reserved_address (data_a->endpoint, false) && data_a->endpoint != endpoint ())
|
||||
{
|
||||
network_message_visitor visitor (node, data_a->endpoint);
|
||||
rai::message_parser parser (visitor, node.work);
|
||||
rai::message_parser parser (node.block_uniquer, node.vote_uniquer, visitor, node.work);
|
||||
parser.deserialize_buffer (data_a->buffer, data_a->size);
|
||||
if (parser.status != rai::message_parser::parse_status::success)
|
||||
{
|
||||
|
@ -1287,7 +1287,8 @@ block_processor_thread ([this]() {
|
|||
this->block_processor.process_blocks ();
|
||||
}),
|
||||
online_reps (*this),
|
||||
stats (config.stat_config)
|
||||
stats (config.stat_config),
|
||||
vote_uniquer (block_uniquer)
|
||||
{
|
||||
wallets.observer = [this](bool active) {
|
||||
observers.wallet.notify (active);
|
||||
|
@ -1725,7 +1726,7 @@ rai::uint128_t rai::node::balance (rai::account const & account_a)
|
|||
return ledger.account_balance (transaction, account_a);
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::node::block (rai::block_hash const & hash_a)
|
||||
std::shared_ptr<rai::block> rai::node::block (rai::block_hash const & hash_a)
|
||||
{
|
||||
auto transaction (store.tx_begin_read ());
|
||||
return store.block_get (transaction, hash_a);
|
||||
|
@ -2869,7 +2870,7 @@ void rai::active_transactions::announce_votes (std::unique_lock<std::mutex> & lo
|
|||
if there are less than 100 active elections */
|
||||
if (i->announcements % announcement_long == 1 && roots_size < 100)
|
||||
{
|
||||
std::unique_ptr<rai::block> previous (nullptr);
|
||||
std::shared_ptr<rai::block> previous;
|
||||
auto previous_hash (election_l->status.winner->previous ());
|
||||
if (!previous_hash.is_zero ())
|
||||
{
|
||||
|
|
|
@ -297,7 +297,6 @@ public:
|
|||
static unsigned const broadcast_interval_ms = (rai::rai_network == rai::rai_networks::rai_test_network) ? 10 : 50;
|
||||
void republish_block_batch (std::deque<std::shared_ptr<rai::block>>, unsigned = broadcast_interval_ms);
|
||||
void republish (rai::block_hash const &, std::shared_ptr<std::vector<uint8_t>>, rai::endpoint);
|
||||
void publish_broadcast (std::vector<rai::peer_information> &, std::unique_ptr<rai::block>);
|
||||
void confirm_send (rai::confirm_ack const &, std::shared_ptr<std::vector<uint8_t>>, rai::endpoint const &);
|
||||
void merge_peers (std::array<rai::endpoint, 8> const &);
|
||||
void send_keepalive (rai::endpoint const &);
|
||||
|
@ -425,7 +424,7 @@ public:
|
|||
void keepalive_preconfigured (std::vector<std::string> const &);
|
||||
rai::block_hash latest (rai::account const &);
|
||||
rai::uint128_t balance (rai::account const &);
|
||||
std::unique_ptr<rai::block> block (rai::block_hash const &);
|
||||
std::shared_ptr<rai::block> block (rai::block_hash const &);
|
||||
std::pair<rai::uint128_t, rai::uint128_t> balance_pending (rai::account const &);
|
||||
rai::uint128_t weight (rai::account const &);
|
||||
rai::account representative (rai::account const &);
|
||||
|
@ -472,6 +471,8 @@ public:
|
|||
rai::online_reps online_reps;
|
||||
rai::stat stats;
|
||||
rai::keypair node_id;
|
||||
rai::block_uniquer block_uniquer;
|
||||
rai::vote_uniquer vote_uniquer;
|
||||
static double constexpr price_max = 16.0;
|
||||
static double constexpr free_cutoff = 1024.0;
|
||||
static std::chrono::seconds constexpr period = std::chrono::seconds (60);
|
||||
|
|
|
@ -935,7 +935,7 @@ void rai::rpc_handler::blocks_info ()
|
|||
if (source)
|
||||
{
|
||||
rai::block_hash source_hash (node.ledger.block_source (transaction, *block));
|
||||
std::unique_ptr<rai::block> block_a (node.store.block_get (transaction, source_hash));
|
||||
auto block_a (node.store.block_get (transaction, source_hash));
|
||||
if (block_a != nullptr)
|
||||
{
|
||||
auto source_account (node.ledger.account (transaction, source_hash));
|
||||
|
@ -2649,7 +2649,7 @@ void rai::rpc_handler::republish ()
|
|||
if (sources != 0) // Republish source chain
|
||||
{
|
||||
rai::block_hash source (node.ledger.block_source (transaction, *block));
|
||||
std::unique_ptr<rai::block> block_a (node.store.block_get (transaction, source));
|
||||
auto block_a (node.store.block_get (transaction, source));
|
||||
std::vector<rai::block_hash> hashes;
|
||||
while (block_a != nullptr && hashes.size () < sources)
|
||||
{
|
||||
|
@ -2680,7 +2680,7 @@ void rai::rpc_handler::republish ()
|
|||
if (!node.store.pending_exists (transaction, rai::pending_key (destination, hash)))
|
||||
{
|
||||
rai::block_hash previous (node.ledger.latest (transaction, destination));
|
||||
std::unique_ptr<rai::block> block_d (node.store.block_get (transaction, previous));
|
||||
auto block_d (node.store.block_get (transaction, previous));
|
||||
rai::block_hash source;
|
||||
std::vector<rai::block_hash> hashes;
|
||||
while (block_d != nullptr && hash != source)
|
||||
|
@ -3426,7 +3426,7 @@ void rai::rpc_handler::wallet_republish ()
|
|||
{
|
||||
rai::account account (i->first);
|
||||
auto latest (node.ledger.latest (transaction, account));
|
||||
std::unique_ptr<rai::block> block;
|
||||
std::shared_ptr<rai::block> block;
|
||||
std::vector<rai::block_hash> hashes;
|
||||
while (!latest.is_zero () && hashes.size () < count)
|
||||
{
|
||||
|
|
|
@ -139,7 +139,7 @@ int main (int argc, char * const * argv)
|
|||
{
|
||||
rai::account_info info (i->second);
|
||||
rai::block_hash rep_block (node.node->ledger.representative_calculated (transaction, info.head));
|
||||
std::unique_ptr<rai::block> block (node.node->store.block_get (transaction, rep_block));
|
||||
auto block (node.node->store.block_get (transaction, rep_block));
|
||||
calculated[block->representative ()] += info.balance.number ();
|
||||
}
|
||||
total = 0;
|
||||
|
|
|
@ -166,8 +166,8 @@ public:
|
|||
virtual void block_put (rai::transaction const &, rai::block_hash const &, rai::block const &, rai::block_hash const & = rai::block_hash (0), rai::epoch version = rai::epoch::epoch_0) = 0;
|
||||
virtual rai::block_hash block_successor (rai::transaction const &, rai::block_hash const &) = 0;
|
||||
virtual void block_successor_clear (rai::transaction const &, rai::block_hash const &) = 0;
|
||||
virtual std::unique_ptr<rai::block> block_get (rai::transaction const &, rai::block_hash const &) = 0;
|
||||
virtual std::unique_ptr<rai::block> block_random (rai::transaction const &) = 0;
|
||||
virtual std::shared_ptr<rai::block> block_get (rai::transaction const &, rai::block_hash const &) = 0;
|
||||
virtual std::shared_ptr<rai::block> block_random (rai::transaction const &) = 0;
|
||||
virtual void block_del (rai::transaction const &, rai::block_hash const &) = 0;
|
||||
virtual bool block_exists (rai::transaction const &, rai::block_hash const &) = 0;
|
||||
virtual rai::block_counts block_count (rai::transaction const &) = 0;
|
||||
|
|
|
@ -404,12 +404,12 @@ signature (other_a.signature)
|
|||
{
|
||||
}
|
||||
|
||||
rai::vote::vote (bool & error_a, rai::stream & stream_a)
|
||||
rai::vote::vote (bool & error_a, rai::stream & stream_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
error_a = deserialize (stream_a);
|
||||
error_a = deserialize (stream_a, uniquer_a);
|
||||
}
|
||||
|
||||
rai::vote::vote (bool & error_a, rai::stream & stream_a, rai::block_type type_a)
|
||||
rai::vote::vote (bool & error_a, rai::stream & stream_a, rai::block_type type_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
if (!error_a)
|
||||
{
|
||||
|
@ -435,7 +435,7 @@ rai::vote::vote (bool & error_a, rai::stream & stream_a, rai::block_type type_a)
|
|||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<rai::block> block (rai::deserialize_block (stream_a, type_a));
|
||||
std::shared_ptr<rai::block> block (rai::deserialize_block (stream_a, type_a, uniquer_a));
|
||||
error_a = block == nullptr;
|
||||
if (!error_a)
|
||||
{
|
||||
|
@ -511,6 +511,18 @@ rai::uint256_union rai::vote::hash () const
|
|||
return result;
|
||||
}
|
||||
|
||||
rai::uint256_union rai::vote::full_hash () const
|
||||
{
|
||||
rai::uint256_union result;
|
||||
blake2b_state state;
|
||||
blake2b_init (&state, sizeof (result.bytes));
|
||||
blake2b_update (&state, hash ().bytes.data (), sizeof (hash ().bytes));
|
||||
blake2b_update (&state, account.bytes.data (), sizeof (account.bytes.data ()));
|
||||
blake2b_update (&state, signature.bytes.data (), sizeof (signature.bytes.data ()));
|
||||
blake2b_final (&state, result.bytes.data (), sizeof (result.bytes));
|
||||
return result;
|
||||
}
|
||||
|
||||
void rai::vote::serialize (rai::stream & stream_a, rai::block_type type)
|
||||
{
|
||||
write (stream_a, account);
|
||||
|
@ -556,7 +568,7 @@ void rai::vote::serialize (rai::stream & stream_a)
|
|||
}
|
||||
}
|
||||
|
||||
bool rai::vote::deserialize (rai::stream & stream_a)
|
||||
bool rai::vote::deserialize (rai::stream & stream_a, rai::block_uniquer * uniquer_a)
|
||||
{
|
||||
auto result (read (stream_a, account));
|
||||
if (!result)
|
||||
|
@ -591,7 +603,7 @@ bool rai::vote::deserialize (rai::stream & stream_a)
|
|||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<rai::block> block (rai::deserialize_block (stream_a, type));
|
||||
std::shared_ptr<rai::block> block (rai::deserialize_block (stream_a, type, uniquer_a));
|
||||
result = block == nullptr;
|
||||
if (!result)
|
||||
{
|
||||
|
@ -636,14 +648,69 @@ boost::transform_iterator<rai::iterate_vote_blocks_as_hash, rai::vote_blocks_vec
|
|||
return boost::transform_iterator<rai::iterate_vote_blocks_as_hash, rai::vote_blocks_vec_iter> (blocks.end (), rai::iterate_vote_blocks_as_hash ());
|
||||
}
|
||||
|
||||
rai::vote_uniquer::vote_uniquer (rai::block_uniquer & uniquer_a) :
|
||||
uniquer (uniquer_a)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<rai::vote> rai::vote_uniquer::unique (std::shared_ptr<rai::vote> vote_a)
|
||||
{
|
||||
auto result (vote_a);
|
||||
if (result != nullptr)
|
||||
{
|
||||
if (!result->blocks[0].which ())
|
||||
{
|
||||
result->blocks[0] = uniquer.unique (boost::get<std::shared_ptr<rai::block>> (result->blocks[0]));
|
||||
}
|
||||
rai::uint256_union key (vote_a->full_hash ());
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
auto & existing (votes[key]);
|
||||
if (auto block_l = existing.lock ())
|
||||
{
|
||||
result = block_l;
|
||||
}
|
||||
else
|
||||
{
|
||||
existing = vote_a;
|
||||
}
|
||||
for (auto i (0); i < cleanup_count; ++i)
|
||||
{
|
||||
rai::uint256_union random;
|
||||
rai::random_pool.GenerateBlock (random.bytes.data (), random.bytes.size ());
|
||||
auto existing (votes.find (random));
|
||||
if (existing == votes.end ())
|
||||
{
|
||||
existing = votes.begin ();
|
||||
}
|
||||
if (existing != votes.end ())
|
||||
{
|
||||
if (auto block_l = existing->second.lock ())
|
||||
{
|
||||
// Still live
|
||||
}
|
||||
else
|
||||
{
|
||||
votes.erase (existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t rai::vote_uniquer::size ()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock (mutex);
|
||||
return votes.size ();
|
||||
}
|
||||
|
||||
rai::genesis::genesis ()
|
||||
{
|
||||
boost::property_tree::ptree tree;
|
||||
std::stringstream istream (rai::genesis_block);
|
||||
boost::property_tree::read_json (istream, tree);
|
||||
auto block (rai::deserialize_block_json (tree));
|
||||
assert (dynamic_cast<rai::open_block *> (block.get ()) != nullptr);
|
||||
open.reset (static_cast<rai::open_block *> (block.release ()));
|
||||
open = rai::deserialize_block_json (tree);
|
||||
assert (open != nullptr);
|
||||
}
|
||||
|
||||
rai::block_hash rai::genesis::hash () const
|
||||
|
|
|
@ -146,17 +146,18 @@ class vote
|
|||
public:
|
||||
vote () = default;
|
||||
vote (rai::vote const &);
|
||||
vote (bool &, rai::stream &);
|
||||
vote (bool &, rai::stream &, rai::block_type);
|
||||
vote (bool &, rai::stream &, rai::block_uniquer * = nullptr);
|
||||
vote (bool &, rai::stream &, rai::block_type, rai::block_uniquer * = nullptr);
|
||||
vote (rai::account const &, rai::raw_key const &, uint64_t, std::shared_ptr<rai::block>);
|
||||
vote (rai::account const &, rai::raw_key const &, uint64_t, std::vector<rai::block_hash>);
|
||||
std::string hashes_string () const;
|
||||
rai::uint256_union hash () const;
|
||||
rai::uint256_union full_hash () const;
|
||||
bool operator== (rai::vote const &) const;
|
||||
bool operator!= (rai::vote const &) const;
|
||||
void serialize (rai::stream &, rai::block_type);
|
||||
void serialize (rai::stream &);
|
||||
bool deserialize (rai::stream &);
|
||||
bool deserialize (rai::stream &, rai::block_uniquer * = nullptr);
|
||||
bool validate ();
|
||||
boost::transform_iterator<rai::iterate_vote_blocks_as_hash, rai::vote_blocks_vec_iter> begin () const;
|
||||
boost::transform_iterator<rai::iterate_vote_blocks_as_hash, rai::vote_blocks_vec_iter> end () const;
|
||||
|
@ -171,6 +172,22 @@ public:
|
|||
rai::signature signature;
|
||||
static const std::string hash_prefix;
|
||||
};
|
||||
/**
|
||||
* This class serves to find and return unique variants of a vote in order to minimize memory usage
|
||||
*/
|
||||
class vote_uniquer
|
||||
{
|
||||
public:
|
||||
vote_uniquer (rai::block_uniquer &);
|
||||
std::shared_ptr<rai::vote> unique (std::shared_ptr<rai::vote>);
|
||||
size_t size ();
|
||||
|
||||
private:
|
||||
rai::block_uniquer & uniquer;
|
||||
std::mutex mutex;
|
||||
std::unordered_map<rai::uint256_union, std::weak_ptr<rai::vote>> votes;
|
||||
static unsigned constexpr cleanup_count = 2;
|
||||
};
|
||||
enum class vote_code
|
||||
{
|
||||
invalid, // Vote is not signed correctly
|
||||
|
@ -229,6 +246,6 @@ class genesis
|
|||
public:
|
||||
explicit genesis ();
|
||||
rai::block_hash hash () const;
|
||||
std::unique_ptr<rai::open_block> open;
|
||||
std::shared_ptr<rai::block> open;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -798,7 +798,7 @@ rai::account rai::ledger::account (rai::transaction const & transaction_a, rai::
|
|||
auto hash (hash_a);
|
||||
rai::block_hash successor (1);
|
||||
rai::block_info block_info;
|
||||
std::unique_ptr<rai::block> block (store.block_get (transaction_a, hash));
|
||||
auto block (store.block_get (transaction_a, hash));
|
||||
while (!successor.is_zero () && block->type () != rai::block_type::state && store.block_info_get (transaction_a, successor, block_info))
|
||||
{
|
||||
successor = store.block_successor (transaction_a, hash);
|
||||
|
@ -981,7 +981,7 @@ void rai::ledger::change_latest (rai::transaction const & transaction_a, rai::ac
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::ledger::successor (rai::transaction const & transaction_a, rai::uint256_union const & root_a)
|
||||
std::shared_ptr<rai::block> rai::ledger::successor (rai::transaction const & transaction_a, rai::uint256_union const & root_a)
|
||||
{
|
||||
rai::block_hash successor (0);
|
||||
if (store.account_exists (transaction_a, root_a))
|
||||
|
@ -995,7 +995,7 @@ std::unique_ptr<rai::block> rai::ledger::successor (rai::transaction const & tra
|
|||
{
|
||||
successor = store.block_successor (transaction_a, root_a);
|
||||
}
|
||||
std::unique_ptr<rai::block> result;
|
||||
std::shared_ptr<rai::block> result;
|
||||
if (!successor.is_zero ())
|
||||
{
|
||||
result = store.block_get (transaction_a, successor);
|
||||
|
@ -1004,12 +1004,12 @@ std::unique_ptr<rai::block> rai::ledger::successor (rai::transaction const & tra
|
|||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<rai::block> rai::ledger::forked_block (rai::transaction const & transaction_a, rai::block const & block_a)
|
||||
std::shared_ptr<rai::block> rai::ledger::forked_block (rai::transaction const & transaction_a, rai::block const & block_a)
|
||||
{
|
||||
assert (!store.block_exists (transaction_a, block_a.hash ()));
|
||||
auto root (block_a.root ());
|
||||
assert (store.block_exists (transaction_a, root) || store.account_exists (transaction_a, root));
|
||||
std::unique_ptr<rai::block> result (store.block_get (transaction_a, store.block_successor (transaction_a, root)));
|
||||
auto result (store.block_get (transaction_a, store.block_successor (transaction_a, root)));
|
||||
if (result == nullptr)
|
||||
{
|
||||
rai::account_info info;
|
||||
|
|
|
@ -25,8 +25,8 @@ public:
|
|||
rai::uint128_t account_balance (rai::transaction const &, rai::account const &);
|
||||
rai::uint128_t account_pending (rai::transaction const &, rai::account const &);
|
||||
rai::uint128_t weight (rai::transaction const &, rai::account const &);
|
||||
std::unique_ptr<rai::block> successor (rai::transaction const &, rai::block_hash const &);
|
||||
std::unique_ptr<rai::block> forked_block (rai::transaction const &, rai::block const &);
|
||||
std::shared_ptr<rai::block> successor (rai::transaction const &, rai::block_hash const &);
|
||||
std::shared_ptr<rai::block> forked_block (rai::transaction const &, rai::block const &);
|
||||
rai::block_hash latest (rai::transaction const &, rai::account const &);
|
||||
rai::block_hash latest_root (rai::transaction const &, rai::account const &);
|
||||
rai::block_hash representative (rai::transaction const &, rai::block_hash const &);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue