Keeping entire vote instead of just the sequence number so it can be replayed out to the network.
This commit is contained in:
parent
2a50b2e10f
commit
fe17d2ad4d
13 changed files with 255 additions and 178 deletions
|
@ -589,25 +589,28 @@ TEST (block_store, sequence_increment)
|
||||||
bool init (false);
|
bool init (false);
|
||||||
rai::block_store store (init, rai::unique_path ());
|
rai::block_store store (init, rai::unique_path ());
|
||||||
ASSERT_TRUE (!init);
|
ASSERT_TRUE (!init);
|
||||||
rai::account account1 (1);
|
rai::keypair key1;
|
||||||
rai::account account2 (2);
|
rai::keypair key2;
|
||||||
|
auto block1 (std::make_shared <rai::open_block> (0, 1, 0, rai::keypair ().prv, 0, 0));
|
||||||
rai::transaction transaction (store.environment, nullptr, true);
|
rai::transaction transaction (store.environment, nullptr, true);
|
||||||
auto seq1 (store.sequence_atomic_inc (transaction, account1));
|
auto vote1 (store.vote_generate (transaction, key1.pub, key1.prv, block1));
|
||||||
ASSERT_EQ (1, seq1);
|
ASSERT_EQ (1, vote1->sequence);
|
||||||
auto seq2 (store.sequence_atomic_inc (transaction, account1));
|
auto vote2 (store.vote_generate (transaction, key1.pub, key1.prv, block1));
|
||||||
ASSERT_EQ (2, seq2);
|
ASSERT_EQ (2, vote2->sequence);
|
||||||
auto seq3 (store.sequence_atomic_inc (transaction, account2));
|
auto vote3 (store.vote_generate (transaction, key2.pub, key2.prv, block1));
|
||||||
ASSERT_EQ (1, seq3);
|
ASSERT_EQ (1, vote3->sequence);
|
||||||
auto seq4 (store.sequence_atomic_inc (transaction, account2));
|
auto vote4 (store.vote_generate (transaction, key2.pub, key2.prv, block1));
|
||||||
ASSERT_EQ (2, seq4);
|
ASSERT_EQ (2, vote4->sequence);
|
||||||
auto seq5 (store.sequence_atomic_observe (transaction, account1, 20));
|
vote1->sequence = 20;
|
||||||
ASSERT_EQ (20, seq5);
|
auto seq5 (store.vote_max (transaction, vote1));
|
||||||
auto seq6 (store.sequence_atomic_observe (transaction, account2, 30));
|
ASSERT_EQ (20, seq5->sequence);
|
||||||
ASSERT_EQ (30, seq6);
|
vote3->sequence = 30;
|
||||||
auto seq7 (store.sequence_atomic_inc (transaction, account1));
|
auto seq6 (store.vote_max (transaction, vote3));
|
||||||
ASSERT_EQ (21, seq7);
|
ASSERT_EQ (30, seq6->sequence);
|
||||||
auto seq8 (store.sequence_atomic_inc (transaction, account2));
|
auto vote5 (store.vote_generate (transaction, key1.pub, key1.prv, block1));
|
||||||
ASSERT_EQ (31, seq8);
|
ASSERT_EQ (21, vote5->sequence);
|
||||||
|
auto vote6 (store.vote_generate (transaction, key2.pub, key2.prv, block1));
|
||||||
|
ASSERT_EQ (31, vote6->sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST (block_store, upgrade_v2_v3)
|
TEST (block_store, upgrade_v2_v3)
|
||||||
|
@ -743,13 +746,13 @@ TEST (vote, validate)
|
||||||
ASSERT_TRUE (!init);
|
ASSERT_TRUE (!init);
|
||||||
rai::keypair key1;
|
rai::keypair key1;
|
||||||
auto send1 (std::make_shared <rai::send_block> (0, key1.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
auto send1 (std::make_shared <rai::send_block> (0, key1.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||||
rai::vote vote1 (key1.pub, key1.prv, 2, send1);
|
auto vote1 (std::make_shared <rai::vote> (key1.pub, key1.prv, 2, send1));
|
||||||
rai::transaction transaction (store.environment, nullptr, true);
|
rai::transaction transaction (store.environment, nullptr, true);
|
||||||
ASSERT_EQ (rai::vote_result::vote, vote1.validate (transaction, store));
|
ASSERT_EQ (rai::vote_result::vote, store.vote_validate (transaction, vote1));
|
||||||
vote1.signature.bytes [8] ^= 1;
|
vote1->signature.bytes [8] ^= 1;
|
||||||
ASSERT_EQ (rai::vote_result::invalid, vote1.validate (transaction, store));
|
ASSERT_EQ (rai::vote_result::invalid, store.vote_validate (transaction, vote1));
|
||||||
rai::vote vote2 (key1.pub, key1.prv, 1, send1);
|
auto vote2 (std::make_shared <rai::vote> (key1.pub, key1.prv, 1, send1));
|
||||||
ASSERT_EQ (rai::vote_result::replay, vote2.validate (transaction, store));
|
ASSERT_EQ (rai::vote_result::replay, store.vote_validate (transaction, vote2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST (block_store, upgrade_v5_v6)
|
TEST (block_store, upgrade_v5_v6)
|
||||||
|
@ -882,11 +885,12 @@ TEST (block_store, sequence_flush)
|
||||||
rai::block_store store (init, path);
|
rai::block_store store (init, path);
|
||||||
ASSERT_FALSE (init);
|
ASSERT_FALSE (init);
|
||||||
rai::transaction transaction (store.environment, nullptr, true);
|
rai::transaction transaction (store.environment, nullptr, true);
|
||||||
rai::account account (0);
|
rai::keypair key1;
|
||||||
auto seq1 (store.sequence_atomic_inc (transaction, account));
|
auto send1 (std::make_shared <rai::send_block> (0, 0, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||||
auto seq2 (store.sequence_get (transaction, account));
|
auto vote1 (store.vote_generate (transaction, key1.pub, key1.prv, send1));
|
||||||
ASSERT_NE (seq2, seq1);
|
auto seq2 (store.vote_get (transaction, vote1->account));
|
||||||
store.sequence_flush(transaction);
|
ASSERT_EQ (nullptr, seq2);
|
||||||
auto seq3 (store.sequence_get (transaction, account));
|
store.vote_flush (transaction);
|
||||||
ASSERT_EQ (seq3, seq1);
|
auto seq3 (store.vote_get (transaction, vote1->account));
|
||||||
|
ASSERT_EQ (*seq3, *vote1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ TEST (conflicts, add_existing)
|
||||||
node1.active.start (transaction, send2);
|
node1.active.start (transaction, send2);
|
||||||
}
|
}
|
||||||
ASSERT_EQ (1, node1.active.roots.size ());
|
ASSERT_EQ (1, node1.active.roots.size ());
|
||||||
rai::vote vote1 (key2.pub, key2.prv, 0, send2);
|
auto vote1 (std::make_shared <rai::vote> (key2.pub, key2.prv, 0, send2));
|
||||||
node1.active.vote (vote1);
|
node1.active.vote (vote1);
|
||||||
ASSERT_EQ (1, node1.active.roots.size ());
|
ASSERT_EQ (1, node1.active.roots.size ());
|
||||||
auto votes1 (node1.active.roots.find (send2->root ())->election);
|
auto votes1 (node1.active.roots.find (send2->root ())->election);
|
||||||
|
|
|
@ -733,9 +733,9 @@ TEST (votes, add_one)
|
||||||
}
|
}
|
||||||
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
||||||
ASSERT_EQ (1, votes1->votes.rep_votes.size ());
|
ASSERT_EQ (1, votes1->votes.rep_votes.size ());
|
||||||
rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1);
|
auto vote1 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1));
|
||||||
votes1->vote (vote1);
|
votes1->vote (vote1);
|
||||||
rai::vote vote2 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send1);
|
auto vote2 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send1));
|
||||||
votes1->vote (vote1);
|
votes1->vote (vote1);
|
||||||
ASSERT_EQ (2, votes1->votes.rep_votes.size ());
|
ASSERT_EQ (2, votes1->votes.rep_votes.size ());
|
||||||
auto existing1 (votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
auto existing1 (votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
||||||
|
@ -764,11 +764,11 @@ TEST (votes, add_two)
|
||||||
node1.active.start (transaction, send1);
|
node1.active.start (transaction, send1);
|
||||||
}
|
}
|
||||||
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
||||||
rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1);
|
auto vote1 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1));
|
||||||
votes1->vote (vote1);
|
votes1->vote (vote1);
|
||||||
rai::keypair key2;
|
rai::keypair key2;
|
||||||
auto send2 (std::make_shared <rai::send_block> (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
auto send2 (std::make_shared <rai::send_block> (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||||
rai::vote vote2 (key2.pub, key2.prv, 1, send2);
|
auto vote2 (std::make_shared <rai::vote> (key2.pub, key2.prv, 1, send2));
|
||||||
votes1->vote (vote2);
|
votes1->vote (vote2);
|
||||||
ASSERT_EQ (3, votes1->votes.rep_votes.size ());
|
ASSERT_EQ (3, votes1->votes.rep_votes.size ());
|
||||||
ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
||||||
|
@ -798,11 +798,11 @@ TEST (votes, add_existing)
|
||||||
node1.active.start (transaction, send1);
|
node1.active.start (transaction, send1);
|
||||||
}
|
}
|
||||||
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
||||||
rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1);
|
auto vote1 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send1));
|
||||||
votes1->vote (vote1);
|
votes1->vote (vote1);
|
||||||
rai::keypair key2;
|
rai::keypair key2;
|
||||||
auto send2 (std::make_shared <rai::send_block> (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
auto send2 (std::make_shared <rai::send_block> (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||||
rai::vote vote2 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send2);
|
auto vote2 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send2));
|
||||||
votes1->vote (vote2);
|
votes1->vote (vote2);
|
||||||
ASSERT_EQ (2, votes1->votes.rep_votes.size ());
|
ASSERT_EQ (2, votes1->votes.rep_votes.size ());
|
||||||
ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
||||||
|
@ -830,11 +830,11 @@ TEST (votes, add_old)
|
||||||
node1.active.start (transaction, send1);
|
node1.active.start (transaction, send1);
|
||||||
}
|
}
|
||||||
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
auto votes1 (node1.active.roots.find (send1->root ())->election);
|
||||||
rai::vote vote1 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send1);
|
auto vote1 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 2, send1));
|
||||||
node1.vote_processor.vote (vote1, rai::endpoint ());
|
node1.vote_processor.vote (vote1, rai::endpoint ());
|
||||||
rai::keypair key2;
|
rai::keypair key2;
|
||||||
auto send2 (std::make_shared <rai::send_block> (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
auto send2 (std::make_shared <rai::send_block> (genesis.hash (), key2.pub, 0, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0));
|
||||||
rai::vote vote2 (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send2);
|
auto vote2 (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 1, send2));
|
||||||
node1.vote_processor.vote (vote2, rai::endpoint ());
|
node1.vote_processor.vote (vote2, rai::endpoint ());
|
||||||
ASSERT_EQ (2, votes1->votes.rep_votes.size ());
|
ASSERT_EQ (2, votes1->votes.rep_votes.size ());
|
||||||
ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (rai::test_genesis_key.pub));
|
||||||
|
|
|
@ -76,7 +76,7 @@ TEST (message, publish_serialization)
|
||||||
TEST (message, confirm_ack_serialization)
|
TEST (message, confirm_ack_serialization)
|
||||||
{
|
{
|
||||||
rai::keypair key1;
|
rai::keypair key1;
|
||||||
rai::vote 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::unique_ptr <rai::block> (new rai::send_block (0, 1, 2, key1.prv, 4, 5))));
|
||||||
rai::confirm_ack con1 (vote);
|
rai::confirm_ack con1 (vote);
|
||||||
std::vector <uint8_t> bytes;
|
std::vector <uint8_t> bytes;
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,7 +59,7 @@ TEST (message_parser, exact_confirm_ack_size)
|
||||||
test_visitor visitor;
|
test_visitor visitor;
|
||||||
rai::message_parser parser (visitor, system.work);
|
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))));
|
auto block (std::unique_ptr <rai::send_block> (new rai::send_block (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1))));
|
||||||
rai::vote vote (0, rai::keypair ().prv, 0, std::move (block));
|
auto vote (std::make_shared <rai::vote> (0, rai::keypair ().prv, 0, std::move (block)));
|
||||||
rai::confirm_ack message (vote);
|
rai::confirm_ack message (vote);
|
||||||
std::vector <uint8_t> bytes;
|
std::vector <uint8_t> bytes;
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,19 +148,22 @@ TEST (network, multi_keepalive)
|
||||||
TEST (network, send_discarded_publish)
|
TEST (network, send_discarded_publish)
|
||||||
{
|
{
|
||||||
rai::system system (24000, 2);
|
rai::system system (24000, 2);
|
||||||
auto block (std::make_shared <rai::send_block> (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1)));
|
auto block (std::make_shared <rai::send_block> (1, 1, 2, rai::keypair ().prv, 4, system.work.generate (1)));
|
||||||
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
|
rai::genesis genesis;
|
||||||
system.nodes [0]->network.republish_block (transaction, block);
|
{
|
||||||
rai::genesis genesis;
|
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
|
||||||
ASSERT_EQ (genesis.hash (), system.nodes [0]->ledger.latest (transaction, rai::test_genesis_key.pub));
|
system.nodes [0]->network.republish_block (transaction, block);
|
||||||
ASSERT_EQ (genesis.hash (), system.nodes [1]->latest (rai::test_genesis_key.pub));
|
ASSERT_EQ (genesis.hash (), system.nodes [0]->ledger.latest (transaction, rai::test_genesis_key.pub));
|
||||||
|
ASSERT_EQ (genesis.hash (), system.nodes [1]->latest (rai::test_genesis_key.pub));
|
||||||
|
}
|
||||||
auto iterations (0);
|
auto iterations (0);
|
||||||
while (system.nodes [1]->network.incoming.publish == 0)
|
while (system.nodes [1]->network.incoming.publish == 0)
|
||||||
{
|
{
|
||||||
system.poll ();
|
system.poll ();
|
||||||
++iterations;
|
++iterations;
|
||||||
ASSERT_LT (iterations, 200);
|
ASSERT_LT (iterations, 200);
|
||||||
}
|
}
|
||||||
|
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
|
||||||
ASSERT_EQ (genesis.hash (), system.nodes [0]->ledger.latest (transaction, rai::test_genesis_key.pub));
|
ASSERT_EQ (genesis.hash (), system.nodes [0]->ledger.latest (transaction, rai::test_genesis_key.pub));
|
||||||
ASSERT_EQ (genesis.hash (), system.nodes [1]->latest (rai::test_genesis_key.pub));
|
ASSERT_EQ (genesis.hash (), system.nodes [1]->latest (rai::test_genesis_key.pub));
|
||||||
}
|
}
|
||||||
|
@ -267,7 +270,7 @@ TEST (receivable_processor, confirm_insufficient_pos)
|
||||||
node1.active.start (transaction, block1);
|
node1.active.start (transaction, block1);
|
||||||
}
|
}
|
||||||
rai::keypair key1;
|
rai::keypair key1;
|
||||||
rai::vote vote (key1.pub, key1.prv, 0, block1);
|
auto vote (std::make_shared <rai::vote> (key1.pub, key1.prv, 0, block1));
|
||||||
rai::confirm_ack con1 (vote);
|
rai::confirm_ack con1 (vote);
|
||||||
node1.process_message (con1, node1.network.endpoint ());
|
node1.process_message (con1, node1.network.endpoint ());
|
||||||
}
|
}
|
||||||
|
@ -284,7 +287,7 @@ TEST (receivable_processor, confirm_sufficient_pos)
|
||||||
rai::transaction transaction (node1.store.environment, nullptr, true);
|
rai::transaction transaction (node1.store.environment, nullptr, true);
|
||||||
node1.active.start (transaction, block1);
|
node1.active.start (transaction, block1);
|
||||||
}
|
}
|
||||||
rai::vote vote (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, block1);
|
auto vote (std::make_shared <rai::vote> (rai::test_genesis_key.pub, rai::test_genesis_key.prv, 0, block1));
|
||||||
rai::confirm_ack con1 (vote);
|
rai::confirm_ack con1 (vote);
|
||||||
node1.process_message (con1, node1.network.endpoint ());
|
node1.process_message (con1, node1.network.endpoint ());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1045,7 +1045,7 @@ TEST (node, fork_no_vote_quorum)
|
||||||
auto send2 (std::make_shared <rai::send_block> (block->hash (), key2, (rai::genesis_amount / 4) - (node1.config.receive_minimum.number () * 2), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (block->hash ())));
|
auto send2 (std::make_shared <rai::send_block> (block->hash (), key2, (rai::genesis_amount / 4) - (node1.config.receive_minimum.number () * 2), rai::test_genesis_key.prv, rai::test_genesis_key.pub, system.work.generate (block->hash ())));
|
||||||
rai::raw_key key3;
|
rai::raw_key key3;
|
||||||
ASSERT_FALSE (system.wallet (1)->store.fetch (rai::transaction (system.wallet (1)->store.environment, nullptr, false), key1, key3));
|
ASSERT_FALSE (system.wallet (1)->store.fetch (rai::transaction (system.wallet (1)->store.environment, nullptr, false), key1, key3));
|
||||||
rai::vote vote (key1, key3, 0, send2);
|
auto vote (std::make_shared <rai::vote> (key1, key3, 0, send2));
|
||||||
rai::confirm_ack confirm (vote);
|
rai::confirm_ack confirm (vote);
|
||||||
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
||||||
{
|
{
|
||||||
|
|
|
@ -207,7 +207,7 @@ void rai::message_parser::deserialize_confirm_ack (uint8_t const * buffer_a, siz
|
||||||
rai::confirm_ack incoming (error_l, stream);
|
rai::confirm_ack incoming (error_l, stream);
|
||||||
if (!error_l && at_end (stream))
|
if (!error_l && at_end (stream))
|
||||||
{
|
{
|
||||||
if (!pool.work_validate (*incoming.vote.block))
|
if (!pool.work_validate (*incoming.vote->block))
|
||||||
{
|
{
|
||||||
visitor.confirm_ack (incoming);
|
visitor.confirm_ack (incoming);
|
||||||
}
|
}
|
||||||
|
@ -363,15 +363,15 @@ bool rai::confirm_req::operator == (rai::confirm_req const & other_a) const
|
||||||
|
|
||||||
rai::confirm_ack::confirm_ack (bool & error_a, rai::stream & stream_a) :
|
rai::confirm_ack::confirm_ack (bool & error_a, rai::stream & stream_a) :
|
||||||
message (error_a, stream_a),
|
message (error_a, stream_a),
|
||||||
vote (error_a, stream_a, block_type ())
|
vote (std::make_shared <rai::vote> (error_a, stream_a))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
rai::confirm_ack::confirm_ack (rai::vote const & vote_a) :
|
rai::confirm_ack::confirm_ack (std::shared_ptr <rai::vote> vote_a) :
|
||||||
message (rai::message_type::confirm_ack),
|
message (rai::message_type::confirm_ack),
|
||||||
vote (vote_a)
|
vote (vote_a)
|
||||||
{
|
{
|
||||||
block_type_set (vote.block->type ());
|
block_type_set (vote->block->type ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rai::confirm_ack::deserialize (rai::stream & stream_a)
|
bool rai::confirm_ack::deserialize (rai::stream & stream_a)
|
||||||
|
@ -381,17 +381,17 @@ bool rai::confirm_ack::deserialize (rai::stream & stream_a)
|
||||||
assert (type == rai::message_type::confirm_ack);
|
assert (type == rai::message_type::confirm_ack);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
result = read (stream_a, vote.account);
|
result = read (stream_a, vote->account);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
result = read (stream_a, vote.signature);
|
result = read (stream_a, vote->signature);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
result = read (stream_a, vote.sequence);
|
result = read (stream_a, vote->sequence);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
vote.block = rai::deserialize_block (stream_a, block_type ());
|
vote->block = rai::deserialize_block (stream_a, block_type ());
|
||||||
result = vote.block == nullptr;
|
result = vote->block == nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,17 +401,14 @@ bool rai::confirm_ack::deserialize (rai::stream & stream_a)
|
||||||
|
|
||||||
void rai::confirm_ack::serialize (rai::stream & stream_a)
|
void rai::confirm_ack::serialize (rai::stream & stream_a)
|
||||||
{
|
{
|
||||||
assert (block_type () == rai::block_type::send || block_type () == rai::block_type::receive || block_type () == rai::block_type::open || block_type () == rai::block_type::change);
|
assert (block_type () == rai::block_type::send || block_type () == rai::block_type::receive || block_type () == rai::block_type::open || block_type () == rai::block_type::change);
|
||||||
write_header (stream_a);
|
write_header (stream_a);
|
||||||
write (stream_a, vote.account);
|
vote->serialize (stream_a);
|
||||||
write (stream_a, vote.signature);
|
|
||||||
write (stream_a, vote.sequence);
|
|
||||||
vote.block->serialize (stream_a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rai::confirm_ack::operator == (rai::confirm_ack const & other_a) const
|
bool rai::confirm_ack::operator == (rai::confirm_ack const & other_a) const
|
||||||
{
|
{
|
||||||
auto result (vote.account == other_a.vote.account && *vote.block == *other_a.vote.block && vote.signature == other_a.vote.signature && vote.sequence == other_a.vote.sequence);
|
auto result (*vote == *other_a.vote);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,12 +171,12 @@ class confirm_ack : public message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
confirm_ack (bool &, rai::stream &);
|
confirm_ack (bool &, rai::stream &);
|
||||||
confirm_ack (rai::vote const &);
|
confirm_ack (std::shared_ptr <rai::vote>);
|
||||||
bool deserialize (rai::stream &) override;
|
bool deserialize (rai::stream &) override;
|
||||||
void serialize (rai::stream &) override;
|
void serialize (rai::stream &) override;
|
||||||
void visit (rai::message_visitor &) const override;
|
void visit (rai::message_visitor &) const override;
|
||||||
bool operator == (rai::confirm_ack const &) const;
|
bool operator == (rai::confirm_ack const &) const;
|
||||||
rai::vote vote;
|
std::shared_ptr <rai::vote> vote;
|
||||||
};
|
};
|
||||||
class frontier_req : public message
|
class frontier_req : public message
|
||||||
{
|
{
|
||||||
|
|
|
@ -173,8 +173,7 @@ bool confirm_block (MDB_txn * transaction_a, rai::node & node_a, T & list_a, std
|
||||||
node_a.wallets.foreach_representative (transaction_a, [&result, &block_a, &list_a, &node_a, &transaction_a] (rai::public_key const & pub_a, rai::raw_key const & prv_a)
|
node_a.wallets.foreach_representative (transaction_a, [&result, &block_a, &list_a, &node_a, &transaction_a] (rai::public_key const & pub_a, rai::raw_key const & prv_a)
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
auto sequence (node_a.store.sequence_atomic_inc (transaction_a, pub_a));
|
auto vote (node_a.store.vote_generate (transaction_a, pub_a, prv_a, block_a));
|
||||||
rai::vote vote (pub_a, prv_a, sequence, block_a);
|
|
||||||
rai::confirm_ack confirm (vote);
|
rai::confirm_ack confirm (vote);
|
||||||
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
||||||
{
|
{
|
||||||
|
@ -236,11 +235,11 @@ void rai::network::republish_block (MDB_txn * transaction, std::shared_ptr <rai:
|
||||||
// 1) Only if they are a non-replay vote of a block that's actively settling. Settling blocks are limited by block PoW
|
// 1) Only if they are a non-replay vote of a block that's actively settling. Settling blocks are limited by block PoW
|
||||||
// 2) Only if a vote for this block hasn't been received in the previous X second. This prevents rapid publishing of votes with increasing sequence numbers.
|
// 2) Only if a vote for this block hasn't been received in the previous X second. This prevents rapid publishing of votes with increasing sequence numbers.
|
||||||
// 3) The rep has a weight > Y to prevent creating a lot of small-weight accounts to send out votes
|
// 3) The rep has a weight > Y to prevent creating a lot of small-weight accounts to send out votes
|
||||||
void rai::network::republish_vote (std::chrono::system_clock::time_point const & last_vote, rai::vote const & vote_a)
|
void rai::network::republish_vote (std::chrono::system_clock::time_point const & last_vote, std::shared_ptr <rai::vote> vote_a)
|
||||||
{
|
{
|
||||||
if (last_vote < std::chrono::system_clock::now () - std::chrono::seconds (1))
|
if (last_vote < std::chrono::system_clock::now () - std::chrono::seconds (1))
|
||||||
{
|
{
|
||||||
if (node.weight (vote_a.account) > rai::Mxrb_ratio * 256)
|
if (node.weight (vote_a->account) > rai::Mxrb_ratio * 256)
|
||||||
{
|
{
|
||||||
rai::confirm_ack confirm (vote_a);
|
rai::confirm_ack confirm (vote_a);
|
||||||
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
std::shared_ptr <std::vector <uint8_t>> bytes (new std::vector <uint8_t>);
|
||||||
|
@ -380,12 +379,12 @@ public:
|
||||||
{
|
{
|
||||||
if (node.config.logging.network_message_logging ())
|
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%") % sender % message_a.vote->block->hash ().to_string ());
|
||||||
}
|
}
|
||||||
++node.network.incoming.confirm_ack;
|
++node.network.incoming.confirm_ack;
|
||||||
node.peers.contacted (sender, message_a.version_using);
|
node.peers.contacted (sender, message_a.version_using);
|
||||||
node.peers.insert (sender, message_a.version_using);
|
node.peers.insert (sender, message_a.version_using);
|
||||||
node.process_active (message_a.vote.block);
|
node.process_active (message_a.vote->block);
|
||||||
node.vote_processor.vote (message_a.vote, sender);
|
node.vote_processor.vote (message_a.vote, sender);
|
||||||
}
|
}
|
||||||
void bulk_pull (rai::bulk_pull const &) override
|
void bulk_pull (rai::bulk_pull const &) override
|
||||||
|
@ -991,12 +990,12 @@ node (node_a)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
rai::vote_result rai::vote_processor::vote (rai::vote const & vote_a, rai::endpoint endpoint_a)
|
rai::vote_result rai::vote_processor::vote (std::shared_ptr <rai::vote> vote_a, rai::endpoint endpoint_a)
|
||||||
{
|
{
|
||||||
rai::vote_result result;
|
rai::vote_result result;
|
||||||
{
|
{
|
||||||
rai::transaction transaction (node.store.environment, nullptr, false);
|
rai::transaction transaction (node.store.environment, nullptr, false);
|
||||||
result = vote_a.validate (transaction, node.store);
|
result = node.store.vote_validate (transaction, vote_a);
|
||||||
}
|
}
|
||||||
if (node.config.logging.vote_logging ())
|
if (node.config.logging.vote_logging ())
|
||||||
{
|
{
|
||||||
|
@ -1013,7 +1012,7 @@ rai::vote_result rai::vote_processor::vote (rai::vote const & vote_a, rai::endpo
|
||||||
status = "Vote";
|
status = "Vote";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BOOST_LOG (node.log) << boost::str (boost::format ("Vote from: %1% sequence: %2% block: %3% status: %4%") % vote_a.account.to_account () % std::to_string (vote_a.sequence) % vote_a.block->hash ().to_string () % status);
|
BOOST_LOG (node.log) << boost::str (boost::format ("Vote from: %1% sequence: %2% block: %3% status: %4%") % vote_a->account.to_account () % std::to_string (vote_a->sequence) % vote_a->block->hash ().to_string () % status);
|
||||||
}
|
}
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
|
@ -1431,19 +1430,19 @@ block_processor (*this)
|
||||||
this->network.send_keepalive (endpoint_a);
|
this->network.send_keepalive (endpoint_a);
|
||||||
rep_query (*this, endpoint_a);
|
rep_query (*this, endpoint_a);
|
||||||
});
|
});
|
||||||
observers.vote.add ([this] (rai::vote const & vote_a, rai::endpoint const &)
|
observers.vote.add ([this] (std::shared_ptr <rai::vote> vote_a, rai::endpoint const &)
|
||||||
{
|
{
|
||||||
active.vote (vote_a);
|
active.vote (vote_a);
|
||||||
});
|
});
|
||||||
observers.vote.add ([this] (rai::vote const & vote_a, rai::endpoint const &)
|
observers.vote.add ([this] (std::shared_ptr <rai::vote> vote_a, rai::endpoint const &)
|
||||||
{
|
{
|
||||||
this->gap_cache.vote (vote_a);
|
this->gap_cache.vote (vote_a);
|
||||||
});
|
});
|
||||||
observers.vote.add ([this] (rai::vote const & vote_a, rai::endpoint const & endpoint_a)
|
observers.vote.add ([this] (std::shared_ptr <rai::vote> vote_a, rai::endpoint const & endpoint_a)
|
||||||
{
|
{
|
||||||
if (this->rep_crawler.exists (vote_a.block->hash ()))
|
if (this->rep_crawler.exists (vote_a->block->hash ()))
|
||||||
{
|
{
|
||||||
auto weight_l (weight (vote_a.account));
|
auto weight_l (weight (vote_a->account));
|
||||||
// We see a valid non-replay vote for a block we requested, this node is probably a representative
|
// We see a valid non-replay vote for a block we requested, this node is probably a representative
|
||||||
if (peers.rep_response (endpoint_a, weight_l))
|
if (peers.rep_response (endpoint_a, weight_l))
|
||||||
{
|
{
|
||||||
|
@ -1515,11 +1514,11 @@ void rai::gap_cache::add (MDB_txn * transaction_a, std::shared_ptr <rai::block>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rai::gap_cache::vote (rai::vote const & vote_a)
|
void rai::gap_cache::vote (std::shared_ptr <rai::vote> vote_a)
|
||||||
{
|
{
|
||||||
rai::transaction transaction (node.store.environment, nullptr, false);
|
rai::transaction transaction (node.store.environment, nullptr, false);
|
||||||
std::lock_guard <std::mutex> lock (mutex);
|
std::lock_guard <std::mutex> lock (mutex);
|
||||||
auto hash (vote_a.block->hash ());
|
auto hash (vote_a->block->hash ());
|
||||||
auto existing (blocks.get <1> ().find (hash));
|
auto existing (blocks.get <1> ().find (hash));
|
||||||
if (existing != blocks.get <1> ().end ())
|
if (existing != blocks.get <1> ().end ())
|
||||||
{
|
{
|
||||||
|
@ -1574,7 +1573,7 @@ void rai::network::confirm_send (rai::confirm_ack const & confirm_a, std::shared
|
||||||
{
|
{
|
||||||
if (node.config.logging.network_publish_logging ())
|
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%") % confirm_a.vote->block->hash ().to_string () % endpoint_a);
|
||||||
}
|
}
|
||||||
std::weak_ptr <rai::node> node_w (node.shared ());
|
std::weak_ptr <rai::node> node_w (node.shared ());
|
||||||
++outgoing.confirm_ack;
|
++outgoing.confirm_ack;
|
||||||
|
@ -1880,7 +1879,7 @@ void rai::node::ongoing_vote_flush ()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
rai::transaction transaction (store.environment, nullptr, true);
|
rai::transaction transaction (store.environment, nullptr, true);
|
||||||
store.sequence_flush (transaction);
|
store.vote_flush (transaction);
|
||||||
}
|
}
|
||||||
std::weak_ptr <rai::node> node_w (shared_from_this ());
|
std::weak_ptr <rai::node> node_w (shared_from_this ());
|
||||||
alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [node_w] ()
|
alarm.add (std::chrono::system_clock::now () + std::chrono::seconds (5), [node_w] ()
|
||||||
|
@ -2621,7 +2620,7 @@ void rai::election::compute_rep_votes (MDB_txn * transaction_a)
|
||||||
{
|
{
|
||||||
node.wallets.foreach_representative (transaction_a, [this, transaction_a] (rai::public_key const & pub_a, rai::raw_key const & prv_a)
|
node.wallets.foreach_representative (transaction_a, [this, transaction_a] (rai::public_key const & pub_a, rai::raw_key const & prv_a)
|
||||||
{
|
{
|
||||||
rai::vote vote (pub_a, prv_a, this->node.store.sequence_atomic_inc (transaction_a, pub_a), last_winner);
|
auto vote (this->node.store.vote_generate (transaction_a, pub_a, prv_a, last_winner));
|
||||||
this->votes.vote (vote);
|
this->votes.vote (vote);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2712,12 +2711,12 @@ void rai::election::confirm_cutoff (MDB_txn * transaction_a)
|
||||||
confirm_once (transaction_a);
|
confirm_once (transaction_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rai::election::vote (rai::vote const & vote_a)
|
void rai::election::vote (std::shared_ptr <rai::vote> vote_a)
|
||||||
{
|
{
|
||||||
node.network.republish_vote (last_vote, vote_a);
|
node.network.republish_vote (last_vote, vote_a);
|
||||||
last_vote = std::chrono::system_clock::now ();
|
last_vote = std::chrono::system_clock::now ();
|
||||||
rai::transaction transaction (node.store.environment, nullptr, true);
|
rai::transaction transaction (node.store.environment, nullptr, true);
|
||||||
assert (vote_a.validate (transaction, node.store) != rai::vote_result::invalid);
|
assert (node.store.vote_validate (transaction, vote_a) != rai::vote_result::invalid);
|
||||||
votes.vote (vote_a);
|
votes.vote (vote_a);
|
||||||
confirm_if_quarum (transaction);
|
confirm_if_quarum (transaction);
|
||||||
}
|
}
|
||||||
|
@ -2798,12 +2797,12 @@ void rai::active_transactions::start (MDB_txn * transaction_a, std::shared_ptr <
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate a vote and apply it to the current election if one exists
|
// Validate a vote and apply it to the current election if one exists
|
||||||
void rai::active_transactions::vote (rai::vote const & vote_a)
|
void rai::active_transactions::vote (std::shared_ptr <rai::vote> vote_a)
|
||||||
{
|
{
|
||||||
std::shared_ptr <rai::election> election;
|
std::shared_ptr <rai::election> election;
|
||||||
{
|
{
|
||||||
std::lock_guard <std::mutex> lock (mutex);
|
std::lock_guard <std::mutex> lock (mutex);
|
||||||
auto root (vote_a.block->root ());
|
auto root (vote_a->block->root ());
|
||||||
auto existing (roots.find (root));
|
auto existing (roots.find (root));
|
||||||
if (existing != roots.end ())
|
if (existing != roots.end ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,7 +42,7 @@ class election : public std::enable_shared_from_this <rai::election>
|
||||||
void confirm_once (MDB_txn *);
|
void confirm_once (MDB_txn *);
|
||||||
public:
|
public:
|
||||||
election (MDB_txn *, rai::node &, std::shared_ptr <rai::block>, std::function <void (std::shared_ptr <rai::block>)> const &);
|
election (MDB_txn *, rai::node &, std::shared_ptr <rai::block>, std::function <void (std::shared_ptr <rai::block>)> const &);
|
||||||
void vote (rai::vote const &);
|
void vote (std::shared_ptr <rai::vote>);
|
||||||
// Check if we have vote quorum
|
// Check if we have vote quorum
|
||||||
bool have_quorum (MDB_txn *);
|
bool have_quorum (MDB_txn *);
|
||||||
// Tell the network our view of the winner
|
// Tell the network our view of the winner
|
||||||
|
@ -78,7 +78,7 @@ public:
|
||||||
// Start an election for a block
|
// Start an election for a block
|
||||||
// Call action with confirmed block, may be different than what we started with
|
// Call action with confirmed block, may be different than what we started with
|
||||||
void start (MDB_txn *, std::shared_ptr <rai::block>, std::function <void (std::shared_ptr <rai::block>)> const & = [] (std::shared_ptr <rai::block>) {});
|
void start (MDB_txn *, std::shared_ptr <rai::block>, std::function <void (std::shared_ptr <rai::block>)> const & = [] (std::shared_ptr <rai::block>) {});
|
||||||
void vote (rai::vote const &);
|
void vote (std::shared_ptr <rai::vote>);
|
||||||
// Is the root of this block in the roots container
|
// Is the root of this block in the roots container
|
||||||
bool active (rai::block const &);
|
bool active (rai::block const &);
|
||||||
void announce_votes ();
|
void announce_votes ();
|
||||||
|
@ -131,7 +131,7 @@ class gap_cache
|
||||||
public:
|
public:
|
||||||
gap_cache (rai::node &);
|
gap_cache (rai::node &);
|
||||||
void add (MDB_txn *, std::shared_ptr <rai::block>);
|
void add (MDB_txn *, std::shared_ptr <rai::block>);
|
||||||
void vote (rai::vote const &);
|
void vote (std::shared_ptr <rai::vote>);
|
||||||
rai::uint128_t bootstrap_threshold (MDB_txn *);
|
rai::uint128_t bootstrap_threshold (MDB_txn *);
|
||||||
void purge_old ();
|
void purge_old ();
|
||||||
boost::multi_index_container
|
boost::multi_index_container
|
||||||
|
@ -300,7 +300,7 @@ public:
|
||||||
void receive_action (boost::system::error_code const &, size_t);
|
void receive_action (boost::system::error_code const &, size_t);
|
||||||
void rpc_action (boost::system::error_code const &, size_t);
|
void rpc_action (boost::system::error_code const &, size_t);
|
||||||
void rebroadcast_reps (std::shared_ptr <rai::block>);
|
void rebroadcast_reps (std::shared_ptr <rai::block>);
|
||||||
void republish_vote (std::chrono::system_clock::time_point const &, rai::vote const &);
|
void republish_vote (std::chrono::system_clock::time_point const &, std::shared_ptr <rai::vote>);
|
||||||
void republish_block (MDB_txn *, std::shared_ptr <rai::block>);
|
void republish_block (MDB_txn *, std::shared_ptr <rai::block>);
|
||||||
void republish (rai::block_hash const &, std::shared_ptr <std::vector <uint8_t>>, rai::endpoint);
|
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 publish_broadcast (std::vector <rai::peer_information> &, std::unique_ptr <rai::block>);
|
||||||
|
@ -408,7 +408,7 @@ class node_observers
|
||||||
public:
|
public:
|
||||||
rai::observer_set <std::shared_ptr <rai::block>, rai::account const &, rai::amount const &> blocks;
|
rai::observer_set <std::shared_ptr <rai::block>, rai::account const &, rai::amount const &> blocks;
|
||||||
rai::observer_set <rai::account const &, bool> wallet;
|
rai::observer_set <rai::account const &, bool> wallet;
|
||||||
rai::observer_set <rai::vote const &, rai::endpoint const &> vote;
|
rai::observer_set <std::shared_ptr <rai::vote>, rai::endpoint const &> vote;
|
||||||
rai::observer_set <rai::endpoint const &> endpoint;
|
rai::observer_set <rai::endpoint const &> endpoint;
|
||||||
rai::observer_set <> disconnect;
|
rai::observer_set <> disconnect;
|
||||||
rai::observer_set <> started;
|
rai::observer_set <> started;
|
||||||
|
@ -417,7 +417,7 @@ class vote_processor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
vote_processor (rai::node &);
|
vote_processor (rai::node &);
|
||||||
rai::vote_result vote (rai::vote const &, rai::endpoint);
|
rai::vote_result vote (std::shared_ptr <rai::vote>, rai::endpoint);
|
||||||
rai::node & node;
|
rai::node & node;
|
||||||
};
|
};
|
||||||
// The network is crawled for representatives by ocassionally sending a unicast confirm_req for a specific block and watching to see if it's acknowledged with a vote.
|
// The network is crawled for representatives by ocassionally sending a unicast confirm_req for a specific block and watching to see if it's acknowledged with a vote.
|
||||||
|
|
159
rai/secure.cpp
159
rai/secure.cpp
|
@ -172,23 +172,23 @@ id (block_a->root ())
|
||||||
rep_votes.insert (std::make_pair (rai::not_an_account, block_a));
|
rep_votes.insert (std::make_pair (rai::not_an_account, block_a));
|
||||||
}
|
}
|
||||||
|
|
||||||
rai::tally_result rai::votes::vote (rai::vote const & vote_a)
|
rai::tally_result rai::votes::vote (std::shared_ptr <rai::vote> vote_a)
|
||||||
{
|
{
|
||||||
rai::tally_result result;
|
rai::tally_result result;
|
||||||
auto existing (rep_votes.find (vote_a.account));
|
auto existing (rep_votes.find (vote_a->account));
|
||||||
if (existing == rep_votes.end ())
|
if (existing == rep_votes.end ())
|
||||||
{
|
{
|
||||||
// Vote on this block hasn't been seen from rep before
|
// Vote on this block hasn't been seen from rep before
|
||||||
result = rai::tally_result::vote;
|
result = rai::tally_result::vote;
|
||||||
rep_votes.insert (std::make_pair (vote_a.account, vote_a.block));
|
rep_votes.insert (std::make_pair (vote_a->account, vote_a->block));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(*existing->second == *vote_a.block))
|
if (!(*existing->second == *vote_a->block))
|
||||||
{
|
{
|
||||||
// Rep changed their vote
|
// Rep changed their vote
|
||||||
result = rai::tally_result::changed;
|
result = rai::tally_result::changed;
|
||||||
existing->second = vote_a.block;
|
existing->second = vote_a->block;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1534,7 +1534,7 @@ checksum (0)
|
||||||
error_a |= mdb_dbi_open (transaction, "unchecked", MDB_CREATE | MDB_DUPSORT, &unchecked) != 0;
|
error_a |= mdb_dbi_open (transaction, "unchecked", MDB_CREATE | MDB_DUPSORT, &unchecked) != 0;
|
||||||
error_a |= mdb_dbi_open (transaction, "unsynced", MDB_CREATE, &unsynced) != 0;
|
error_a |= mdb_dbi_open (transaction, "unsynced", MDB_CREATE, &unsynced) != 0;
|
||||||
error_a |= mdb_dbi_open (transaction, "checksum", MDB_CREATE, &checksum) != 0;
|
error_a |= mdb_dbi_open (transaction, "checksum", MDB_CREATE, &checksum) != 0;
|
||||||
error_a |= mdb_dbi_open (transaction, "sequence", MDB_CREATE, &sequence) != 0;
|
error_a |= mdb_dbi_open (transaction, "sequence", MDB_CREATE, &vote) != 0;
|
||||||
error_a |= mdb_dbi_open (transaction, "meta", MDB_CREATE, &meta) != 0;
|
error_a |= mdb_dbi_open (transaction, "meta", MDB_CREATE, &meta) != 0;
|
||||||
if (!error_a)
|
if (!error_a)
|
||||||
{
|
{
|
||||||
|
@ -2480,72 +2480,111 @@ void rai::block_store::checksum_del (MDB_txn * transaction_a, uint64_t prefix, u
|
||||||
assert (status == 0);
|
assert (status == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rai::block_store::sequence_flush (MDB_txn * transaction_a)
|
void rai::block_store::vote_flush (MDB_txn * transaction_a)
|
||||||
{
|
{
|
||||||
std::unordered_map <rai::account, uint64_t> sequence_cache_l;
|
std::unordered_map <rai::account, std::shared_ptr <rai::vote>> sequence_cache_l;
|
||||||
{
|
{
|
||||||
std::lock_guard <std::mutex> lock (sequence_mutex);
|
std::lock_guard <std::mutex> lock (vote_mutex);
|
||||||
sequence_cache_l.swap (sequence_cache);
|
sequence_cache_l.swap (vote_cache);
|
||||||
}
|
}
|
||||||
for (auto i (sequence_cache_l.begin ()), n (sequence_cache_l.end ()); i != n; ++i)
|
for (auto i (sequence_cache_l.begin ()), n (sequence_cache_l.end ()); i != n; ++i)
|
||||||
{
|
{
|
||||||
auto status1 (mdb_put (transaction_a, sequence, i->first.val (), rai::mdb_val (sizeof (i->second), &i->second), 0));
|
std::vector <uint8_t> vector;
|
||||||
|
{
|
||||||
|
rai::vectorstream stream (vector);
|
||||||
|
i->second->serialize (stream);
|
||||||
|
}
|
||||||
|
auto status1 (mdb_put (transaction_a, vote, i->first.val (), rai::mdb_val (vector.size (), vector.data ()), 0));
|
||||||
assert (status1 == 0);
|
assert (status1 == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rai::block_store::sequence_get (MDB_txn * transaction_a, rai::account const & account_a)
|
std::shared_ptr <rai::vote> rai::block_store::vote_get (MDB_txn * transaction_a, rai::account const & account_a)
|
||||||
{
|
{
|
||||||
uint64_t result (0);
|
std::shared_ptr <rai::vote> result;
|
||||||
MDB_val value;
|
MDB_val value;
|
||||||
auto status (mdb_get (transaction_a, sequence, account_a.val (), &value));
|
auto status (mdb_get (transaction_a, vote, account_a.val (), &value));
|
||||||
assert (status == 0 || status == MDB_NOTFOUND);
|
assert (status == 0 || status == MDB_NOTFOUND);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
rai::bufferstream stream (reinterpret_cast <uint8_t const *> (value.mv_data), value.mv_size);
|
result = std::make_shared <rai::vote> (value);
|
||||||
auto error (rai::read (stream, result));
|
assert (result != nullptr);
|
||||||
assert (!error);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rai::block_store::sequence_current (MDB_txn * transaction_a, rai::account const & account_a)
|
std::shared_ptr <rai::vote> rai::block_store::vote_current (MDB_txn * transaction_a, rai::account const & account_a)
|
||||||
{
|
{
|
||||||
assert (!sequence_mutex.try_lock ());
|
assert (!vote_mutex.try_lock ());
|
||||||
uint64_t result (0);
|
std::shared_ptr <rai::vote> result;
|
||||||
auto existing (sequence_cache.find (account_a));
|
auto existing (vote_cache.find (account_a));
|
||||||
if (existing != sequence_cache.end ())
|
if (existing != vote_cache.end ())
|
||||||
{
|
{
|
||||||
result = existing->second;
|
result = existing->second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = sequence_get (transaction_a, account_a);
|
result = vote_get (transaction_a, account_a);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rai::block_store::sequence_atomic_inc (MDB_txn * transaction_a, rai::account const & account_a)
|
std::shared_ptr <rai::vote> rai::block_store::vote_generate (MDB_txn * transaction_a, rai::account const & account_a, rai::raw_key const & key_a, std::shared_ptr <rai::block> block_a)
|
||||||
{
|
{
|
||||||
std::lock_guard <std::mutex> lock (sequence_mutex);
|
std::shared_ptr <rai::vote> result;
|
||||||
auto result (sequence_current (transaction_a, account_a));
|
uint64_t sequence = 0;
|
||||||
result += 1;
|
{
|
||||||
sequence_cache [account_a] = result;
|
std::lock_guard <std::mutex> lock (vote_mutex);
|
||||||
|
result = vote_current (transaction_a, account_a);
|
||||||
|
sequence = (result ? result->sequence : 0) + 1;
|
||||||
|
}
|
||||||
|
result = std::make_shared <rai::vote> (account_a, key_a, sequence, block_a);
|
||||||
|
vote_cache [account_a] = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rai::block_store::sequence_atomic_observe (MDB_txn * transaction_a, rai::account const & account_a, uint64_t sequence_a)
|
std::shared_ptr <rai::vote> rai::block_store::vote_max (MDB_txn * transaction_a, std::shared_ptr <rai::vote> vote_a)
|
||||||
{
|
{
|
||||||
std::lock_guard <std::mutex> lock (sequence_mutex);
|
std::lock_guard <std::mutex> lock (vote_mutex);
|
||||||
auto current (sequence_current (transaction_a, account_a));
|
auto current (vote_current (transaction_a, vote_a->account));
|
||||||
auto result (std::max (current, sequence_a));
|
auto result (vote_a);
|
||||||
if (sequence_a > current)
|
if (current != nullptr)
|
||||||
{
|
{
|
||||||
sequence_cache [account_a] = sequence_a;
|
if (current->sequence > result->sequence)
|
||||||
|
{
|
||||||
|
result = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vote_cache [vote_a->account] = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
rai::vote_result rai::block_store::vote_validate (MDB_txn * transaction_a, std::shared_ptr <rai::vote> vote_a)
|
||||||
|
{
|
||||||
|
auto result (rai::vote_result::invalid);
|
||||||
|
// Reject unsigned votes
|
||||||
|
if (!rai::validate_message (vote_a->account, vote_a->hash (), vote_a->signature))
|
||||||
|
{
|
||||||
|
result = rai::vote_result::replay;
|
||||||
|
// Make sure this sequence number is > any we've seen from this account before
|
||||||
|
if (vote_max (transaction_a, vote_a) == vote_a)
|
||||||
|
{
|
||||||
|
result = rai::vote_result::vote;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rai::vote::operator == (rai::vote const & other_a) const
|
||||||
|
{
|
||||||
|
return sequence == other_a.sequence && *block == *other_a.block && account == other_a.account && signature == other_a.signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rai::vote::operator != (rai::vote const & other_a) const
|
||||||
|
{
|
||||||
|
return ! (*this == other_a);
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
class root_visitor : public rai::block_visitor
|
class root_visitor : public rai::block_visitor
|
||||||
|
@ -3301,6 +3340,27 @@ signature (other_a.signature)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rai::vote::vote (bool & error_a, rai::stream & stream_a)
|
||||||
|
{
|
||||||
|
if (!error_a)
|
||||||
|
{
|
||||||
|
error_a = rai::read (stream_a, account.bytes);
|
||||||
|
if (!error_a)
|
||||||
|
{
|
||||||
|
error_a = rai::read (stream_a, signature.bytes);
|
||||||
|
if (!error_a)
|
||||||
|
{
|
||||||
|
error_a = rai::read (stream_a, sequence);
|
||||||
|
if (!error_a)
|
||||||
|
{
|
||||||
|
block = rai::deserialize_block (stream_a);
|
||||||
|
error_a = block == nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (!error_a)
|
if (!error_a)
|
||||||
|
@ -3330,6 +3390,19 @@ signature (rai::sign_message (prv_a, account_a, hash ()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rai::vote::vote (MDB_val const & value_a)
|
||||||
|
{
|
||||||
|
rai::bufferstream stream (reinterpret_cast <uint8_t const *> (value_a.mv_data), value_a.mv_size);
|
||||||
|
auto error (rai::read (stream, account.bytes));
|
||||||
|
assert (!error);
|
||||||
|
error = rai::read (stream, signature.bytes);
|
||||||
|
assert (!error);
|
||||||
|
error = rai::read (stream, sequence);
|
||||||
|
assert (!error);
|
||||||
|
block = rai::deserialize_block (stream);
|
||||||
|
assert (block != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
rai::uint256_union rai::vote::hash () const
|
rai::uint256_union rai::vote::hash () const
|
||||||
{
|
{
|
||||||
rai::uint256_union result;
|
rai::uint256_union result;
|
||||||
|
@ -3346,20 +3419,12 @@ rai::uint256_union rai::vote::hash () const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rai::vote_result rai::vote::validate (MDB_txn * transaction_a, rai::block_store & store_a) const
|
void rai::vote::serialize (rai::stream & stream_a)
|
||||||
{
|
{
|
||||||
auto result (rai::vote_result::invalid);
|
write (stream_a, account);
|
||||||
// Reject unsigned votes
|
write (stream_a, signature);
|
||||||
if (!rai::validate_message (account, hash (), signature))
|
write (stream_a, sequence);
|
||||||
{
|
rai::serialize_block (stream_a, *block);
|
||||||
result = rai::vote_result::replay;
|
|
||||||
// Make sure this sequence number is > any we've seen from this account before
|
|
||||||
if (store_a.sequence_atomic_observe (transaction_a, account, sequence) == sequence)
|
|
||||||
{
|
|
||||||
result = rai::vote_result::vote;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rai::genesis::genesis ()
|
rai::genesis::genesis ()
|
||||||
|
|
|
@ -313,6 +313,33 @@ public:
|
||||||
size_t open;
|
size_t open;
|
||||||
size_t change;
|
size_t change;
|
||||||
};
|
};
|
||||||
|
enum class vote_result
|
||||||
|
{
|
||||||
|
invalid, // Vote is not signed correctly
|
||||||
|
replay, // Vote does not have the highest sequence number, it's a replay
|
||||||
|
vote // Vote has the highest sequence number
|
||||||
|
};
|
||||||
|
class vote
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
vote () = default;
|
||||||
|
vote (rai::vote const &);
|
||||||
|
vote (bool &, rai::stream &);
|
||||||
|
vote (bool &, rai::stream &, rai::block_type);
|
||||||
|
vote (rai::account const &, rai::raw_key const &, uint64_t, std::shared_ptr <rai::block>);
|
||||||
|
vote (MDB_val const &);
|
||||||
|
rai::uint256_union hash () const;
|
||||||
|
bool operator == (rai::vote const &) const;
|
||||||
|
bool operator != (rai::vote const &) const;
|
||||||
|
void serialize (rai::stream &);
|
||||||
|
// Vote round sequence number
|
||||||
|
uint64_t sequence;
|
||||||
|
std::shared_ptr <rai::block> block;
|
||||||
|
// Account that's voting
|
||||||
|
rai::account account;
|
||||||
|
// Signature of sequence + block hash
|
||||||
|
rai::signature signature;
|
||||||
|
};
|
||||||
class block_store
|
class block_store
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -388,13 +415,18 @@ public:
|
||||||
bool checksum_get (MDB_txn *, uint64_t, uint8_t, rai::checksum &);
|
bool checksum_get (MDB_txn *, uint64_t, uint8_t, rai::checksum &);
|
||||||
void checksum_del (MDB_txn *, uint64_t, uint8_t);
|
void checksum_del (MDB_txn *, uint64_t, uint8_t);
|
||||||
|
|
||||||
uint64_t sequence_get (MDB_txn *, rai::account const &);
|
rai::vote_result vote_validate (MDB_txn *, std::shared_ptr <rai::vote>);
|
||||||
uint64_t sequence_atomic_inc (MDB_txn *, rai::account const &);
|
// Return latest vote for an account from store
|
||||||
uint64_t sequence_atomic_observe (MDB_txn *, rai::account const &, uint64_t);
|
std::shared_ptr <rai::vote> vote_get (MDB_txn *, rai::account const &);
|
||||||
uint64_t sequence_current (MDB_txn *, rai::account const &);
|
// Populate vote with the next sequence number
|
||||||
void sequence_flush (MDB_txn *);
|
std::shared_ptr <rai::vote> vote_generate (MDB_txn *, rai::account const &, rai::raw_key const &, std::shared_ptr <rai::block>);
|
||||||
std::mutex sequence_mutex;
|
// Return either vote or the stored vote with a higher sequence number
|
||||||
std::unordered_map <rai::account, uint64_t> sequence_cache;
|
std::shared_ptr <rai::vote> vote_max (MDB_txn *, std::shared_ptr <rai::vote>);
|
||||||
|
// Return latest vote for an account considering the vote cache
|
||||||
|
std::shared_ptr <rai::vote> vote_current (MDB_txn *, rai::account const &);
|
||||||
|
void vote_flush (MDB_txn *);
|
||||||
|
std::mutex vote_mutex;
|
||||||
|
std::unordered_map <rai::account, std::shared_ptr <rai::vote>> vote_cache;
|
||||||
|
|
||||||
void version_put (MDB_txn *, int);
|
void version_put (MDB_txn *, int);
|
||||||
int version_get (MDB_txn *);
|
int version_get (MDB_txn *);
|
||||||
|
@ -432,8 +464,8 @@ public:
|
||||||
MDB_dbi unsynced;
|
MDB_dbi unsynced;
|
||||||
// (uint56_t, uint8_t) -> block_hash // Mapping of region to checksum
|
// (uint56_t, uint8_t) -> block_hash // Mapping of region to checksum
|
||||||
MDB_dbi checksum;
|
MDB_dbi checksum;
|
||||||
// account -> uint64_t // Highest vote sequence observed for account
|
// account -> uint64_t // Highest vote observed for account
|
||||||
MDB_dbi sequence;
|
MDB_dbi vote;
|
||||||
// uint256_union -> ? // Meta information about block store
|
// uint256_union -> ? // Meta information about block store
|
||||||
MDB_dbi meta;
|
MDB_dbi meta;
|
||||||
};
|
};
|
||||||
|
@ -457,29 +489,6 @@ public:
|
||||||
rai::account account;
|
rai::account account;
|
||||||
rai::amount amount;
|
rai::amount amount;
|
||||||
};
|
};
|
||||||
enum class vote_result
|
|
||||||
{
|
|
||||||
invalid, // Vote is not signed correctly
|
|
||||||
replay, // Vote does not have the highest sequence number, it's a replay
|
|
||||||
vote // Vote has the highest sequence number
|
|
||||||
};
|
|
||||||
class vote
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
vote () = default;
|
|
||||||
vote (rai::vote const &);
|
|
||||||
vote (bool &, rai::stream &, rai::block_type);
|
|
||||||
vote (rai::account const &, rai::raw_key const &, uint64_t, std::shared_ptr <rai::block>);
|
|
||||||
rai::uint256_union hash () const;
|
|
||||||
rai::vote_result validate (MDB_txn *, rai::block_store &) const;
|
|
||||||
// Vote round sequence number
|
|
||||||
uint64_t sequence;
|
|
||||||
std::shared_ptr <rai::block> block;
|
|
||||||
// Account that's voting
|
|
||||||
rai::account account;
|
|
||||||
// Signature of sequence + block hash
|
|
||||||
rai::signature signature;
|
|
||||||
};
|
|
||||||
enum class tally_result
|
enum class tally_result
|
||||||
{
|
{
|
||||||
vote,
|
vote,
|
||||||
|
@ -490,7 +499,7 @@ class votes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
votes (std::shared_ptr <rai::block>);
|
votes (std::shared_ptr <rai::block>);
|
||||||
rai::tally_result vote (rai::vote const &);
|
rai::tally_result vote (std::shared_ptr <rai::vote>);
|
||||||
// Root block of fork
|
// Root block of fork
|
||||||
rai::block_hash id;
|
rai::block_hash id;
|
||||||
// All votes received by account
|
// All votes received by account
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue