diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -94,6 +94,11 @@ result_type operator()(const Peer &p) const { return p.proof->getId(); } }; +struct score_index { + using result_type = uint32_t; + result_type operator()(const Peer &p) const { return p.getScore(); } +}; + struct next_request_time {}; struct PendingNode { @@ -106,6 +111,7 @@ struct by_proofid; struct by_nodeid; +struct by_score; enum class ProofRegistrationResult { NONE = 0, @@ -137,7 +143,10 @@ bmi::hashed_unique>, // index by proof bmi::hashed_unique, proof_index, - SaltedProofIdHasher>>>; + SaltedProofIdHasher>, + // ordered by score, decreasing order + bmi::ordered_non_unique, score_index, + std::greater>>>; PeerId nextPeerId = 0; PeerSet peers; diff --git a/src/avalanche/test/peermanager_tests.cpp b/src/avalanche/test/peermanager_tests.cpp --- a/src/avalanche/test/peermanager_tests.cpp +++ b/src/avalanche/test/peermanager_tests.cpp @@ -41,6 +41,17 @@ auto it = pview.find(proof->getId()); return it == pview.end() ? NO_PEER : it->peerid; } + + static std::vector getOrderedScores(const PeerManager &pm) { + std::vector scores; + + auto &peerView = pm.peers.get(); + for (const Peer &peer : peerView) { + scores.push_back(peer.getScore()); + } + + return scores; + } }; } // namespace } // namespace avalanche @@ -1510,4 +1521,29 @@ BOOST_CHECK(!pm.shouldRequestMoreNodes()); } +BOOST_AUTO_TEST_CASE(score_ordering) { + avalanche::PeerManager pm; + + std::vector expectedScores(10); + // Expect the peers to be ordered by descending score + std::generate(expectedScores.rbegin(), expectedScores.rend(), + [n = 1]() mutable { return n++ * MIN_VALID_PROOF_SCORE; }); + + std::vector proofs; + proofs.reserve(expectedScores.size()); + for (uint32_t score : expectedScores) { + proofs.push_back(buildRandomProof(score)); + } + + // Shuffle the proofs so they are registered in a random score order + Shuffle(proofs.begin(), proofs.end(), FastRandomContext()); + for (auto &proof : proofs) { + BOOST_CHECK(pm.registerProof(proof)); + } + + auto peersScores = TestPeerManager::getOrderedScores(pm); + BOOST_CHECK_EQUAL_COLLECTIONS(peersScores.begin(), peersScores.end(), + expectedScores.begin(), expectedScores.end()); +} + BOOST_AUTO_TEST_SUITE_END()