Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/peermanager_tests.cpp
Show First 20 Lines • Show All 1,559 Lines • ▼ Show 20 Lines | for (auto &proof : proofs) { | ||||
BOOST_CHECK(pm.registerProof(proof)); | BOOST_CHECK(pm.registerProof(proof)); | ||||
} | } | ||||
auto peersScores = TestPeerManager::getOrderedScores(pm); | auto peersScores = TestPeerManager::getOrderedScores(pm); | ||||
BOOST_CHECK_EQUAL_COLLECTIONS(peersScores.begin(), peersScores.end(), | BOOST_CHECK_EQUAL_COLLECTIONS(peersScores.begin(), peersScores.end(), | ||||
expectedScores.begin(), expectedScores.end()); | expectedScores.begin(), expectedScores.end()); | ||||
} | } | ||||
BOOST_FIXTURE_TEST_CASE(registered_score_tracking, NoCoolDownFixture) { | |||||
avalanche::PeerManager pm; | |||||
const CKey key = CKey::MakeCompressedKey(); | |||||
const Amount amount10(10 * COIN); | |||||
const Amount amount20(20 * COIN); | |||||
const Amount amount30 = amount10 + amount20; | |||||
const uint32_t height = 100; | |||||
const bool is_coinbase = false; | |||||
CScript script = GetScriptForDestination(PKHash(key.GetPubKey())); | |||||
const COutPoint conflictingOutpoint(TxId(GetRandHash()), 0); | |||||
{ | |||||
LOCK(cs_main); | |||||
CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | |||||
coins.AddCoin(conflictingOutpoint, | |||||
Coin(CTxOut(amount10, script), height, is_coinbase), | |||||
false); | |||||
} | |||||
const COutPoint secondaryOutpoint(TxId(GetRandHash()), 1); | |||||
{ | |||||
LOCK(cs_main); | |||||
CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | |||||
coins.AddCoin(secondaryOutpoint, | |||||
Coin(CTxOut(amount20, script), height, is_coinbase), | |||||
false); | |||||
} | |||||
auto buildProofWithSequenceAndOutpoints = | |||||
[&](int64_t sequence, | |||||
const std::vector<std::tuple<COutPoint, Amount>> &outpoints) { | |||||
ProofBuilder pb(sequence, 0, key); | |||||
for (const auto &outpoint : outpoints) { | |||||
BOOST_CHECK(pb.addUTXO(std::get<0>(outpoint), | |||||
std::get<1>(outpoint), height, | |||||
is_coinbase, key)); | |||||
} | |||||
return pb.build(); | |||||
}; | |||||
auto proofSeq10 = buildProofWithSequenceAndOutpoints( | |||||
10, {{conflictingOutpoint, amount10}, {secondaryOutpoint, amount20}}); | |||||
auto proofSeq20 = buildProofWithSequenceAndOutpoints( | |||||
20, {{conflictingOutpoint, amount10}}); | |||||
auto orphan30 = buildProofWithSequenceAndOutpoints( | |||||
30, {{conflictingOutpoint, amount10}, | |||||
{COutPoint{TxId(GetRandHash()), 0}, amount10}}); | |||||
// Add proof and check that we have its score tracked | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), 0); | |||||
BOOST_CHECK(pm.registerProof(proofSeq20)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
// Ensure failing to add new proofs doesn't affect the score | |||||
BOOST_CHECK(!pm.registerProof(proofSeq10)); | |||||
BOOST_CHECK(!pm.registerProof(orphan30)); | |||||
BOOST_CHECK(pm.isBoundToPeer(proofSeq20->getId())); | |||||
BOOST_CHECK(pm.isInConflictingPool(proofSeq10->getId())); | |||||
BOOST_CHECK(pm.isOrphan(orphan30->getId())); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
auto checkRejectDefault = [&](const ProofId &proofid) { | |||||
BOOST_CHECK(pm.exists(proofid)); | |||||
const bool isOrphan = pm.isOrphan(proofid); | |||||
BOOST_CHECK(pm.rejectProof( | |||||
proofid, avalanche::PeerManager::RejectionMode::DEFAULT)); | |||||
BOOST_CHECK(!pm.isBoundToPeer(proofid)); | |||||
BOOST_CHECK_EQUAL(pm.exists(proofid), !isOrphan); | |||||
}; | |||||
auto checkRejectInvalidate = [&](const ProofId &proofid) { | |||||
BOOST_CHECK(pm.exists(proofid)); | |||||
BOOST_CHECK(pm.rejectProof( | |||||
proofid, avalanche::PeerManager::RejectionMode::INVALIDATE)); | |||||
}; | |||||
// Reject from the orphan pool doesn't affect tracked score | |||||
checkRejectDefault(orphan30->getId()); | |||||
BOOST_CHECK(!pm.registerProof(orphan30)); | |||||
BOOST_CHECK(pm.isOrphan(orphan30->getId())); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
checkRejectInvalidate(orphan30->getId()); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
// Reject from the conflicting pool | |||||
checkRejectDefault(proofSeq10->getId()); | |||||
checkRejectInvalidate(proofSeq10->getId()); | |||||
// Add again a proof to the conflicting pool | |||||
BOOST_CHECK(!pm.registerProof(proofSeq10)); | |||||
BOOST_CHECK(pm.isInConflictingPool(proofSeq10->getId())); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
// Reject from the valid pool, default mode | |||||
// Now the score should change as the new peer is promoted | |||||
checkRejectDefault(proofSeq20->getId()); | |||||
BOOST_CHECK(!pm.isInConflictingPool(proofSeq10->getId())); | |||||
BOOST_CHECK(pm.isBoundToPeer(proofSeq10->getId())); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount30)); | |||||
// Reject from the valid pool, invalidate mode | |||||
// Now the score should change as the old peer is re-promoted | |||||
checkRejectInvalidate(proofSeq10->getId()); | |||||
// The conflicting proof should also be promoted to a peer | |||||
BOOST_CHECK(!pm.isInConflictingPool(proofSeq20->getId())); | |||||
BOOST_CHECK(pm.isBoundToPeer(proofSeq20->getId())); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
// Trying to remove non-existent peer doesn't affect score | |||||
BOOST_CHECK(!pm.removePeer(1234)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), Proof::amountToScore(amount10)); | |||||
BOOST_CHECK(pm.removePeer(2)); | |||||
Fabien: Don't rely on peer id, retrieve it instead | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), 0); | |||||
} | |||||
FabienUnsubmitted Not Done Inline ActionsYou never checked that the scores sum up in the presence of several peers Fabien: You never checked that the scores sum up in the presence of several peers | |||||
BOOST_AUTO_TEST_CASE(allocated_score_tracking) { | |||||
avalanche::PeerManager pm; | |||||
// Create one peer. | |||||
auto proof = buildRandomProof(10000000 * MIN_VALID_PROOF_SCORE); | |||||
uint32_t score1 = 1000000000; | |||||
FabienUnsubmitted Not Done Inline Actionsuint32_t score1 = 10000000 * MIN_VALID_PROOF_SCORE; auto proof = buildRandomProof(score1); Fabien: ```
uint32_t score1 = 10000000 * MIN_VALID_PROOF_SCORE;
auto proof = buildRandomProof(score1)… | |||||
BOOST_CHECK(pm.registerProof(proof)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), 0); | |||||
// Add 4 nodes. We should now have an allocated score but it shouldn't | |||||
// matter how many nodes we add. | |||||
const ProofId &proofid = proof->getId(); | |||||
for (int i = 0; i < 4; i++) { | |||||
BOOST_CHECK(pm.addNode(i, proofid)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score1); | |||||
} | |||||
// Remove a node, check that it doesn't change the score | |||||
BOOST_CHECK(pm.removeNode(2)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score1); | |||||
// Create a new peer. Without a node it doesn't affect allocated score and | |||||
// after adding a node it does. | |||||
uint32_t score2 = 100; | |||||
proof = buildRandomProof(MIN_VALID_PROOF_SCORE); | |||||
FabienUnsubmitted Not Done Inline ActionsDito Fabien: Dito | |||||
BOOST_CHECK(pm.registerProof(proof)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1 + score2); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score1); | |||||
BOOST_CHECK(pm.addNode(3, proof->getId())); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1 + score2); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score1 + score2); | |||||
// The first peer has two nodes left. Remove one and nothing happens, remove | |||||
// the other and its score is no longer allocated. | |||||
BOOST_CHECK(pm.removeNode(0)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1 + score2); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score1 + score2); | |||||
BOOST_CHECK(pm.removeNode(1)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score1 + score2); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score2); | |||||
// Removing a peer with no allocated score has no affect. | |||||
BOOST_CHECK(pm.removePeer(0)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score2); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), score2); | |||||
// Remove the second peer's last node remove's its allocated score. | |||||
BOOST_CHECK(pm.removeNode(3)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), score2); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), 0); | |||||
// Removing the last peer takes us back to 0. | |||||
BOOST_CHECK(pm.removePeer(1)); | |||||
BOOST_CHECK_EQUAL(pm.getRegisteredScore(), 0); | |||||
BOOST_CHECK_EQUAL(pm.getAllocatedScore(), 0); | |||||
} | |||||
FabienUnsubmitted Not Done Inline ActionsYou can also test that removing a peer with nodes reduce the allocated score as expected Fabien: You can also test that removing a peer with nodes reduce the allocated score as expected | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |
Don't rely on peer id, retrieve it instead