Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/peermanager_tests.cpp
Show All 30 Lines | struct TestPeerManager { | ||||
} | } | ||||
}; | }; | ||||
} // namespace | } // namespace | ||||
class TestConflictingProofHandler | class TestConflictingProofHandler | ||||
: public PeerManager::ConflictingProofHandler { | : public PeerManager::ConflictingProofHandler { | ||||
public: | public: | ||||
std::shared_ptr<Proof> lastProof; | std::shared_ptr<Proof> lastProof; | ||||
bool lastVote; | |||||
void onConflictingProof(const std::shared_ptr<Proof> &proof, | void onConflictingProof(const std::shared_ptr<Proof> &proof, | ||||
bool accepted) override { | bool accepted) override { | ||||
lastProof = proof; | lastProof = proof; | ||||
lastVote = accepted; | |||||
} | } | ||||
}; | }; | ||||
} // namespace avalanche | } // namespace avalanche | ||||
BOOST_FIXTURE_TEST_SUITE(peermanager_tests, TestingSetup) | BOOST_FIXTURE_TEST_SUITE(peermanager_tests, TestingSetup) | ||||
BOOST_AUTO_TEST_CASE(select_peer_linear) { | BOOST_AUTO_TEST_CASE(select_peer_linear) { | ||||
▲ Show 20 Lines • Show All 793 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(conflicting_proof_handler) { | ||||
for (size_t i = 1; i < 100; i++) { | for (size_t i = 1; i < 100; i++) { | ||||
auto proof_conflicting = buildProofWithSequence(i); | auto proof_conflicting = buildProofWithSequence(i); | ||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_conflicting), NO_PEER); | BOOST_CHECK_EQUAL(pm.getPeerId(proof_conflicting), NO_PEER); | ||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | ||||
proof_conflicting->getId()); | proof_conflicting->getId()); | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(conflicting_proof_same_pubkey) { | |||||
avalanche::PeerManager pm; | |||||
auto conflictingProofHandler = | |||||
std::make_shared<TestConflictingProofHandler>(); | |||||
auto handler = pm.handleConflictingProof(conflictingProofHandler); | |||||
const CKey key = CKey::MakeCompressedKey(); | |||||
const COutPoint outpoint(TxId(GetRandHash()), 0); | |||||
const Amount amount(10 * COIN); | |||||
const uint32_t height = 100; | |||||
const bool is_coinbase = false; | |||||
CScript script = GetScriptForDestination(PKHash(key.GetPubKey())); | |||||
{ | |||||
LOCK(cs_main); | |||||
CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | |||||
coins.AddCoin(outpoint, | |||||
Coin(CTxOut(amount, script), height, is_coinbase), false); | |||||
} | |||||
auto buildProofWithSequence = [&](uint64_t sequence) { | |||||
ProofBuilder pb(sequence, GetRandInt(std::numeric_limits<int>::max()), | |||||
key); | |||||
BOOST_CHECK(pb.addUTXO(outpoint, amount, height, is_coinbase, key)); | |||||
return std::make_shared<Proof>(pb.build()); | |||||
}; | |||||
auto proof_base = buildProofWithSequence(10); | |||||
BOOST_CHECK_NE(pm.getPeerId(proof_base), NO_PEER); | |||||
BOOST_CHECK(!conflictingProofHandler->lastProof); | |||||
auto proof_lowSequence = buildProofWithSequence(9); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_lowSequence), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_lowSequence->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, false); | |||||
auto proof_sameSequence = buildProofWithSequence(10); | |||||
// Collision might occur here, but it's so unlikely that it's not a concern | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_sameSequence), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_sameSequence->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, false); | |||||
auto proof_highSequence = buildProofWithSequence(11); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_highSequence), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_highSequence->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, true); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(conflicting_proof_different_pubkey) { | |||||
avalanche::PeerManager pm; | |||||
auto conflictingProofHandler = | |||||
std::make_shared<TestConflictingProofHandler>(); | |||||
auto handler = pm.handleConflictingProof(conflictingProofHandler); | |||||
const CKey key = CKey::MakeCompressedKey(); | |||||
const uint32_t height = 100; | |||||
const bool is_coinbase = false; | |||||
CScript script = GetScriptForDestination(PKHash(key.GetPubKey())); | |||||
auto addCoin = [&](const Amount &amount) { | |||||
LOCK(cs_main); | |||||
COutPoint outpoint(TxId(GetRandHash()), 0); | |||||
CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | |||||
coins.AddCoin(outpoint, | |||||
Coin(CTxOut(amount, script), height, is_coinbase), false); | |||||
return outpoint; | |||||
}; | |||||
const Amount conflictingOutpointAmount = 10 * COIN; | |||||
// This is the outpoint that will conflict through the test | |||||
COutPoint conflictingOutpoint = addCoin(conflictingOutpointAmount); | |||||
auto buildProofFromAmounts = [&](std::vector<Amount> amounts) { | |||||
CKey master = CKey::MakeCompressedKey(); | |||||
ProofBuilder pb(0, 0, std::move(master)); | |||||
BOOST_CHECK(pb.addUTXO(conflictingOutpoint, conflictingOutpointAmount, | |||||
height, is_coinbase, key)); | |||||
for (Amount &amount : amounts) { | |||||
auto outpoint = addCoin(amount); | |||||
BOOST_CHECK(pb.addUTXO(std::move(outpoint), amount, height, | |||||
is_coinbase, key)); | |||||
} | |||||
return std::make_shared<Proof>(pb.build()); | |||||
}; | |||||
auto proof_base = buildProofFromAmounts({10 * COIN, 10 * COIN}); | |||||
BOOST_CHECK_NE(pm.getPeerId(proof_base), NO_PEER); | |||||
BOOST_CHECK(!conflictingProofHandler->lastProof); | |||||
auto proof_lowAmount = buildProofFromAmounts({10 * COIN, 9 * COIN}); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_lowAmount), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_lowAmount->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, false); | |||||
auto proof_highAmount = buildProofFromAmounts({10 * COIN, 11 * COIN}); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_highAmount), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_highAmount->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, true); | |||||
auto proof_lowStakeCount = buildProofFromAmounts({20 * COIN}); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_lowStakeCount), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_lowStakeCount->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, true); | |||||
auto proof_highStakeCount = | |||||
buildProofFromAmounts({10 * COIN, 5 * COIN, 5 * COIN}); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_highStakeCount), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_highStakeCount->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, false); | |||||
auto proof_similar = buildProofFromAmounts({10 * COIN, 10 * COIN}); | |||||
BOOST_CHECK_EQUAL(pm.getPeerId(proof_similar), NO_PEER); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastProof->getId(), | |||||
proof_similar->getId()); | |||||
BOOST_CHECK_EQUAL(conflictingProofHandler->lastVote, | |||||
proof_similar->getId() < proof_base->getId()); | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |