diff --git a/rai/node/node.cpp b/rai/node/node.cpp index eabc6c30..69d06a75 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -3472,8 +3472,15 @@ void rai::election::compute_rep_votes (MDB_txn * transaction_a) void rai::election::broadcast_winner (MDB_txn * transaction_a) { - compute_rep_votes (transaction_a); - node.network.republish_block (transaction_a, status.winner); + if (node.ledger.could_fit (transaction_a, *status.winner)) + { + compute_rep_votes (transaction); + node.network.republish_block (transaction, status.winner); + } + else + { + abort (); + } } void rai::election::confirm_once (MDB_txn * transaction_a) @@ -3490,6 +3497,11 @@ void rai::election::confirm_once (MDB_txn * transaction_a) } } +void rai::election::abort () +{ + confirmed = true; +} + bool rai::election::have_quorum (rai::tally_t const & tally_a) { auto i (tally_a.begin ()); @@ -3605,7 +3617,7 @@ void rai::active_transactions::announce_votes () for (auto i (roots.begin ()), n (roots.end ()); i != n; ++i) { auto election_l (i->election); - if ((!node.store.root_exists (transaction, election_l->votes.id) || election_l->confirmed) && i->announcements >= announcement_min - 1) + if (election_l->confirmed && i->announcements >= announcement_min - 1) { if (election_l->confirmed) { diff --git a/rai/node/node.hpp b/rai/node/node.hpp index d06ba0a0..a623cdde 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -55,6 +55,7 @@ class election : public std::enable_shared_from_this { std::function)> confirmation_action; void confirm_once (MDB_txn *); + void abort (); public: election (rai::node &, std::shared_ptr, std::function)> const &); diff --git a/rai/secure/ledger.cpp b/rai/secure/ledger.cpp index 81ad22f9..8fff538f 100644 --- a/rai/secure/ledger.cpp +++ b/rai/secure/ledger.cpp @@ -891,6 +891,52 @@ void rai::ledger::dump_account_chain (rai::account const & account_a) } } +class block_fit_visitor : public rai::block_visitor +{ +public: + block_fit_visitor(rai::ledger & ledger_a, MDB_txn * transaction_a) : + ledger (ledger_a), + transaction (transaction_a), + result (false) + { + } + void send_block (rai::send_block const & block_a) override + { + result = ledger.store.block_exists(transaction, block_a.previous()); + } + void receive_block (rai::receive_block const & block_a) override + { + result = ledger.store.block_exists(transaction, block_a.previous()); + result &= ledger.store.block_exists(transaction, block_a.source()); + } + void open_block (rai::open_block const & block_a) override + { + result = ledger.store.block_exists(transaction, block_a.source ()); + } + void change_block (rai::change_block const & block_a) override + { + result = ledger.store.block_exists(transaction, block_a.previous()); + } + void state_block (rai::state_block const & block_a) override + { + result = block_a.previous().is_zero() || ledger.store.block_exists (transaction, block_a.previous()); + if (result && !ledger.is_send (transaction, block_a)) + { + result &= ledger.store.block_exists(transaction, block_a.hashables.link); + } + } + rai::ledger & ledger; + MDB_txn * transaction; + bool result; +}; + +bool rai::ledger::could_fit (MDB_txn * transaction_a, rai::block const & block_a) +{ + block_fit_visitor visitor (*this, transaction_a); + block_a.visit (visitor); + return visitor.result; +} + void rai::ledger::checksum_update (MDB_txn * transaction_a, rai::block_hash const & hash_a) { rai::checksum value; diff --git a/rai/secure/ledger.hpp b/rai/secure/ledger.hpp index a191df75..92467e0b 100644 --- a/rai/secure/ledger.hpp +++ b/rai/secure/ledger.hpp @@ -45,6 +45,7 @@ public: void checksum_update (MDB_txn *, rai::block_hash const &); rai::checksum checksum (MDB_txn *, rai::account const &, rai::account const &); void dump_account_chain (rai::account const &); + bool could_fit (MDB_txn *, rai::block const &); static rai::uint128_t const unit; rai::block_store & store; rai::stat & stats;