diff --git a/src/xrpld/overlay/Slot.h b/src/xrpld/overlay/Slot.h index eb117600e7..cce4fa99f4 100644 --- a/src/xrpld/overlay/Slot.h +++ b/src/xrpld/overlay/Slot.h @@ -829,6 +829,15 @@ private: inline static validators peersWithValidators_{ beast::get_abstract_clock()}; + struct ValidatorInfo + { + size_t count; // the number of messages sent from this validator + time_point lastMessage; // timestamp of the last message + std::unordered_set peers; // a list of peer IDs that sent a + // message for this validator + }; + + hash_map considered_validators_; }; template @@ -864,6 +873,69 @@ Slots::addPeerMessage(uint256 const& key, id_t id) return true; } +template +std::optional +Slots::updateConsideredValidator( + PublicKey const& validator, + Peer::id_t peer) +{ + auto const now = clock_type::now(); + + auto it = considered_validators_.find(validator); + if (it == considered_validators_.end()) + { + considered_validators_.emplace(std::make_pair( + validator, + ValidatorInfo{ + .count = 1, + .lastMessage = now, + .peers = {peer}, + })); + + return {}; + } + + // the validator idled. Don't update it, it will be cleaned later + if (now - it->second.lastMessage > IDLED) + return {}; + + it->second.peers.insert(peer); + + it->second.lastMessage = now; + ++it->second.count; + + if (it->second.count < MAX_MESSAGE_THRESHOLD || + it->second.peers.size() < reduce_relay::MAX_SELECTED_PEERS) + return {}; + + auto const key = it->first; + considered_validators_.erase(it); + + return key; +} + +template +std::vector +Slots::cleanConsideredValidators() +{ + auto const now = clock_type::now(); + + std::vector keys; + for (auto it = considered_validators_.begin(); + it != considered_validators_.end();) + { + if (now - it->second.lastMessage > IDLED) + { + keys.push_back(it->first); + it = considered_validators_.erase(it); + } + else + ++it; + } + + return keys; +} + template void Slots::updateSlotAndSquelch(