diff --git a/rai/node/common.cpp b/rai/node/common.cpp index ec7fb0bd..17d8885c 100644 --- a/rai/node/common.cpp +++ b/rai/node/common.cpp @@ -367,9 +367,9 @@ vote (error_a, stream_a, block_type ()) { } -rai::confirm_ack::confirm_ack (rai::vote & vote_a) : +rai::confirm_ack::confirm_ack (rai::vote const & vote_a) : message (rai::message_type::confirm_ack), -vote (std::move (vote_a)) +vote (vote_a) { block_type_set (vote.block->type ()); } diff --git a/rai/node/common.hpp b/rai/node/common.hpp index 350bc01f..403d3c93 100644 --- a/rai/node/common.hpp +++ b/rai/node/common.hpp @@ -171,7 +171,7 @@ class confirm_ack : public message { public: confirm_ack (bool &, rai::stream &); - confirm_ack (rai::vote &); + confirm_ack (rai::vote const &); bool deserialize (rai::stream &) override; void serialize (rai::stream &) override; void visit (rai::message_visitor &) const override; diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 2a38ba9d..e8fa5849 100755 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -159,21 +159,6 @@ void rai::network::rebroadcast_reps (rai::block & block_a) } } -template -void confirm_broadcast (rai::node & node_a, T & list_a, rai::vote & vote_a) -{ - rai::confirm_ack confirm (vote_a); - std::shared_ptr > bytes (new std::vector ); - { - rai::vectorstream stream (*bytes); - confirm.serialize (stream); - } - for (auto j (list_a.begin ()), m (list_a.end ()); j != m; ++j) - { - node_a.network.confirm_send (confirm, bytes, *j); - } -} - template bool confirm_block (rai::node & node_a, T & list_a, std::unique_ptr block_a) { @@ -186,7 +171,16 @@ bool confirm_block (rai::node & node_a, T & list_a, std::unique_ptr result = true; auto sequence (node_a.store.sequence_atomic_inc (transaction, pub_a)); rai::vote vote (pub_a, prv_a, sequence, block_a->clone ()); - confirm_broadcast (node_a, list_a, vote); + rai::confirm_ack confirm (vote); + std::shared_ptr > bytes (new std::vector ); + { + rai::vectorstream stream (*bytes); + confirm.serialize (stream); + } + for (auto j (list_a.begin ()), m (list_a.end ()); j != m; ++j) + { + node_a.network.confirm_send (confirm, bytes, *j); + } }); } return result; @@ -235,6 +229,31 @@ void rai::network::republish_block (rai::block & block) } } +// In order to rate limit network traffic we republish: +// 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. +// 3) The rep has a weight > Y to prevent creating a lot of small-weight accounts to send out votes +void rai::network::republish (std::chrono::system_clock::time_point const & last_vote, rai::vote const & vote_a) +{ + if (last_vote < std::chrono::system_clock::now () - std::chrono::seconds (1)) + { + if (node.weight (vote_a.account) > rai::Mrai_ratio * 256) + { + rai::confirm_ack confirm (vote_a); + std::shared_ptr > bytes (new std::vector ); + { + rai::vectorstream stream (*bytes); + confirm.serialize (stream); + } + auto list (node.peers.list_sqrt ()); + for (auto j (list.begin ()), m (list.end ()); j != m; ++j) + { + node.network.confirm_send (confirm, bytes, *j); + } + } + } +} + void rai::network::broadcast_confirm_req (rai::block const & block_a) { auto list (node.peers.list ()); @@ -2513,6 +2532,8 @@ void rai::election::confirm_cutoff (MDB_txn * transaction_a) void rai::election::vote (rai::vote const & vote_a) { + node.network.republish (last_vote, vote_a); + last_vote = std::chrono::system_clock::now (); rai::transaction transaction (node.store.environment, nullptr, true); assert (vote_a.validate (transaction, node.store) != rai::vote_result::invalid); votes.vote (vote_a); diff --git a/rai/node/node.hpp b/rai/node/node.hpp index ba0646ef..81d93a75 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -268,6 +268,7 @@ public: void receive_action (boost::system::error_code const &, size_t); void rpc_action (boost::system::error_code const &, size_t); void rebroadcast_reps (rai::block &); + void republish (std::chrono::system_clock::time_point const &, rai::vote const &); void republish_block (rai::block &); void republish (rai::block_hash const &, std::shared_ptr >, rai::endpoint); void publish_broadcast (std::vector &, std::unique_ptr ); diff --git a/rai/secure.cpp b/rai/secure.cpp index 8a8613b5..db4db56b 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -3191,6 +3191,14 @@ transaction (transaction_a) { } +rai::vote::vote (rai::vote const & other_a) : +sequence (other_a.sequence), +block (other_a.block->clone ()), +account (other_a.account), +signature (other_a.signature) +{ +} + rai::vote::vote (bool & error_a, rai::stream & stream_a, rai::block_type type_a) { if (!error_a) diff --git a/rai/secure.hpp b/rai/secure.hpp index a04e2966..5ecf163b 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -453,6 +453,7 @@ 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::unique_ptr ); rai::uint256_union hash () const;