diff --git a/rai/node/node.cpp b/rai/node/node.cpp index 24634653..c8a826d9 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -811,13 +811,14 @@ void rai::vote_processor::process_loop () } active = true; lock.unlock (); + verify_votes (votes_l); { std::unique_lock active_single_lock (node.active.mutex); auto transaction (node.store.tx_begin_read ()); uint64_t count (1); for (auto & i : votes_l) { - vote_blocking (transaction, i.first, i.second); + vote_blocking (transaction, i.first, i.second, true); // Free active_transactions mutex each 100 processed votes if (count % 100 == 0) { @@ -867,13 +868,51 @@ void rai::vote_processor::vote (std::shared_ptr vote_a, rai::endpoint } } +void rai::vote_processor::verify_votes (std::deque, rai::endpoint>> & votes_a) +{ + auto size (votes_a.size ()); + std::vector messages; + messages.reserve (size); + std::vector hashes; + hashes.reserve (size); + std::vector lengths (size, sizeof (rai::uint256_union)); + std::vector pub_keys; + pub_keys.reserve (size); + std::vector signatures; + signatures.reserve (size); + std::vector verifications; + verifications.resize (size); + for (auto & vote : votes_a) + { + hashes.push_back (vote.first->hash ()); + messages.push_back (hashes.back ().bytes.data ()); + pub_keys.push_back (vote.first->account.bytes.data ()); + signatures.push_back (vote.first->signature.bytes.data ()); + } + /* Verifications is vector if signatures check results + validate_message_batch returing "true" if there are at least 1 invalid signature */ + rai::validate_message_batch (messages.data (), lengths.data (), pub_keys.data (), signatures.data (), size, verifications.data ()); + std::remove_reference_t result; + auto i (0); + for (auto & vote : votes_a) + { + assert (verifications[i] == 1 || verifications[i] == 0); + if (verifications[i] == 1) + { + result.push_back (vote); + } + ++i; + } + votes_a.swap (result); +} + // node.active.mutex lock required -rai::vote_code rai::vote_processor::vote_blocking (rai::transaction const & transaction_a, std::shared_ptr vote_a, rai::endpoint endpoint_a) +rai::vote_code rai::vote_processor::vote_blocking (rai::transaction const & transaction_a, std::shared_ptr vote_a, rai::endpoint endpoint_a, bool validated) { assert (endpoint_a.address ().is_v6 ()); assert (!node.active.mutex.try_lock ()); auto result (rai::vote_code::invalid); - if (!vote_a->validate ()) + if (validated || !vote_a->validate ()) { auto max_vote (node.store.vote_max (transaction_a, vote_a)); result = rai::vote_code::replay; diff --git a/rai/node/node.hpp b/rai/node/node.hpp index 1655e861..9f74a916 100644 --- a/rai/node/node.hpp +++ b/rai/node/node.hpp @@ -342,7 +342,8 @@ public: vote_processor (rai::node &); void vote (std::shared_ptr, rai::endpoint); // node.active.mutex lock required - rai::vote_code vote_blocking (rai::transaction const &, std::shared_ptr, rai::endpoint); + rai::vote_code vote_blocking (rai::transaction const &, std::shared_ptr, rai::endpoint, bool = false); + void verify_votes (std::deque, rai::endpoint>> &); void flush (); rai::node & node; void stop ();