Page MenuHomePhabricator

D11667.id34128.diff
No OneTemporary

D11667.id34128.diff

diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h
--- a/src/avalanche/peermanager.h
+++ b/src/avalanche/peermanager.h
@@ -11,6 +11,7 @@
#include <avalanche/proofradixtreeadapter.h>
#include <coins.h>
#include <consensus/validation.h>
+#include <eventloop.h>
#include <pubkey.h>
#include <radix.h>
#include <salteduint256hasher.h>
@@ -30,6 +31,8 @@
#include <unordered_set>
#include <vector>
+class CScheduler;
+
namespace avalanche {
/**
@@ -223,7 +226,11 @@
uint32_t totalPeersScore = 0;
uint32_t connectedPeersScore = 0;
+ EventLoop cleanupTask;
+
public:
+ PeerManager(CScheduler &scheduler);
+
/**
* Node API.
*/
diff --git a/src/avalanche/peermanager.cpp b/src/avalanche/peermanager.cpp
--- a/src/avalanche/peermanager.cpp
+++ b/src/avalanche/peermanager.cpp
@@ -8,12 +8,21 @@
#include <avalanche/delegation.h>
#include <avalanche/validation.h>
#include <random.h>
+#include <scheduler.h>
#include <validation.h> // For ChainstateActive()
#include <algorithm>
#include <cassert>
namespace avalanche {
+PeerManager::PeerManager(CScheduler &scheduler) {
+ scheduler.scheduleEvery(
+ [this]() -> bool {
+ this->cleanupDanglingProofs();
+ return true;
+ },
+ 5min);
+}
bool PeerManager::addNode(NodeId nodeid, const ProofId &proofid) {
auto &pview = peers.get<by_proofid>();
diff --git a/src/avalanche/processor.h b/src/avalanche/processor.h
--- a/src/avalanche/processor.h
+++ b/src/avalanche/processor.h
@@ -174,8 +174,9 @@
std::unique_ptr<interfaces::Handler> chainNotificationsHandler;
Processor(const ArgsManager &argsman, interfaces::Chain &chain,
- CConnman *connmanIn, std::unique_ptr<PeerData> peerDataIn,
- CKey sessionKeyIn, uint32_t minQuorumTotalScoreIn,
+ CConnman *connmanIn, CScheduler &scheduler,
+ std::unique_ptr<PeerData> peerDataIn, CKey sessionKeyIn,
+ uint32_t minQuorumTotalScoreIn,
double minQuorumConnectedScoreRatioIn,
int64_t minAvaproofsNodeCountIn, uint32_t staleVoteThresholdIn,
uint32_t staleVoteFactorIn);
@@ -186,6 +187,7 @@
static std::unique_ptr<Processor> MakeProcessor(const ArgsManager &argsman,
interfaces::Chain &chain,
CConnman *connman,
+ CScheduler &scheduler,
bilingual_str &error);
void setQueryTimeoutDuration(std::chrono::milliseconds d) {
diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp
--- a/src/avalanche/processor.cpp
+++ b/src/avalanche/processor.cpp
@@ -138,15 +138,16 @@
};
Processor::Processor(const ArgsManager &argsman, interfaces::Chain &chain,
- CConnman *connmanIn, std::unique_ptr<PeerData> peerDataIn,
- CKey sessionKeyIn, uint32_t minQuorumTotalScoreIn,
+ CConnman *connmanIn, CScheduler &scheduler,
+ std::unique_ptr<PeerData> peerDataIn, CKey sessionKeyIn,
+ uint32_t minQuorumTotalScoreIn,
double minQuorumConnectedScoreRatioIn,
int64_t minAvaproofsNodeCountIn,
uint32_t staleVoteThresholdIn, uint32_t staleVoteFactorIn)
: connman(connmanIn),
queryTimeoutDuration(argsman.GetArg(
"-avatimeout", AVALANCHE_DEFAULT_QUERY_TIMEOUT.count())),
- round(0), peerManager(std::make_unique<PeerManager>()),
+ round(0), peerManager(std::make_unique<PeerManager>(scheduler)),
peerData(std::move(peerDataIn)), sessionKey(std::move(sessionKeyIn)),
minQuorumScore(minQuorumTotalScoreIn),
minQuorumConnectedScoreRatio(minQuorumConnectedScoreRatioIn),
@@ -166,6 +167,7 @@
std::unique_ptr<Processor> Processor::MakeProcessor(const ArgsManager &argsman,
interfaces::Chain &chain,
CConnman *connman,
+ CScheduler &scheduler,
bilingual_str &error) {
std::unique_ptr<PeerData> peerData;
CKey masterKey;
@@ -325,9 +327,10 @@
// We can't use std::make_unique with a private constructor
return std::unique_ptr<Processor>(new Processor(
- argsman, chain, connman, std::move(peerData), std::move(sessionKey),
- Proof::amountToScore(minQuorumStake), minQuorumConnectedStakeRatio,
- minAvaproofsNodeCount, staleVoteThreshold, staleVoteFactor));
+ argsman, chain, connman, scheduler, std::move(peerData),
+ std::move(sessionKey), Proof::amountToScore(minQuorumStake),
+ minQuorumConnectedStakeRatio, minAvaproofsNodeCount, staleVoteThreshold,
+ staleVoteFactor));
}
bool Processor::addBlockToReconcile(const CBlockIndex *pindex) {
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
@@ -279,7 +279,8 @@
BOOST_AUTO_TEST_CASE(peer_probabilities) {
// No peers.
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
BOOST_CHECK_EQUAL(pm.selectNode(), NO_NODE);
const NodeId node0 = 42, node1 = 69, node2 = 37;
@@ -315,7 +316,8 @@
BOOST_AUTO_TEST_CASE(remove_peer) {
// No peers.
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
BOOST_CHECK_EQUAL(pm.selectPeer(), NO_PEER);
// Add 4 peers.
@@ -390,7 +392,8 @@
}
BOOST_AUTO_TEST_CASE(compact_slots) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
// Add 4 peers.
std::array<PeerId, 4> peerids;
@@ -419,7 +422,8 @@
}
BOOST_AUTO_TEST_CASE(node_crud) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
// Create one peer.
auto proof = buildRandomProof(10000000 * MIN_VALID_PROOF_SCORE);
@@ -479,7 +483,8 @@
}
BOOST_AUTO_TEST_CASE(node_binding) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto proof = buildRandomProof(MIN_VALID_PROOF_SCORE);
const ProofId &proofid = proof->getId();
@@ -578,7 +583,8 @@
}
BOOST_AUTO_TEST_CASE(node_binding_reorg) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto key = CKey::MakeCompressedKey();
@@ -645,7 +651,8 @@
addCoin({txid2, i}, key);
}
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
CKey masterKey = CKey::MakeCompressedKey();
const auto getPeerId = [&](const std::vector<COutPoint> &outpoints) {
return TestPeerManager::registerAndGetPeerId(
@@ -698,7 +705,8 @@
}
BOOST_AUTO_TEST_CASE(orphan_proofs) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto key = CKey::MakeCompressedKey();
@@ -872,7 +880,8 @@
}
BOOST_AUTO_TEST_CASE(dangling_node) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto proof = buildRandomProof(MIN_VALID_PROOF_SCORE);
PeerId peerid = TestPeerManager::registerAndGetPeerId(pm, proof);
@@ -917,7 +926,8 @@
}
BOOST_AUTO_TEST_CASE(proof_accessors) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
constexpr int numProofs = 10;
@@ -961,7 +971,8 @@
}
BOOST_FIXTURE_TEST_CASE(conflicting_proof_rescan, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1016,7 +1027,8 @@
BOOST_CHECK_EQUAL(comparator(candidate, reference), expectAccepted);
BOOST_CHECK_EQUAL(comparator(reference, candidate), !expectAccepted);
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
BOOST_CHECK(pm.registerProof(reference));
BOOST_CHECK(pm.isBoundToPeer(reference->getId()));
@@ -1086,7 +1098,8 @@
}
BOOST_AUTO_TEST_CASE(conflicting_orphans) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1133,7 +1146,8 @@
}
BOOST_FIXTURE_TEST_CASE(preferred_conflicting_proof, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
const COutPoint conflictingOutpoint = createUtxo(key);
@@ -1164,7 +1178,8 @@
}
BOOST_FIXTURE_TEST_CASE(update_next_conflict_time, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto now = GetTime<std::chrono::seconds>();
SetMockTime(now.count());
@@ -1197,7 +1212,8 @@
}
BOOST_FIXTURE_TEST_CASE(register_force_accept, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1261,7 +1277,8 @@
}
BOOST_FIXTURE_TEST_CASE(evicted_proof, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1291,7 +1308,8 @@
}
BOOST_AUTO_TEST_CASE(conflicting_proof_cooldown) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1359,7 +1377,8 @@
}
BOOST_FIXTURE_TEST_CASE(reject_proof, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1434,7 +1453,8 @@
}
BOOST_AUTO_TEST_CASE(should_request_more_nodes) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto proof = buildRandomProof(MIN_VALID_PROOF_SCORE);
BOOST_CHECK(pm.registerProof(proof));
@@ -1482,7 +1502,8 @@
}
BOOST_AUTO_TEST_CASE(score_ordering) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
std::vector<uint32_t> expectedScores(10);
// Expect the peers to be ordered by descending score
@@ -1507,7 +1528,8 @@
}
BOOST_FIXTURE_TEST_CASE(known_score_tracking, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const CKey key = CKey::MakeCompressedKey();
@@ -1616,7 +1638,8 @@
}
BOOST_AUTO_TEST_CASE(connected_score_tracking) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const auto checkScores = [&pm](uint32_t known, uint32_t connected) {
BOOST_CHECK_EQUAL(pm.getTotalPeersScore(), known);
@@ -1704,7 +1727,8 @@
}
BOOST_FIXTURE_TEST_CASE(proof_radix_tree, NoCoolDownFixture) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
gArgs.ForceSetArg("-enableavalancheproofreplacement", "1");
@@ -1820,7 +1844,8 @@
}
BOOST_AUTO_TEST_CASE(received_avaproofs) {
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
auto addNode = [&](NodeId nodeid) {
auto proof = buildRandomProof(MIN_VALID_PROOF_SCORE);
@@ -1843,7 +1868,8 @@
BOOST_FIXTURE_TEST_CASE(cleanup_dangling_proof, NoCoolDownFixture) {
gArgs.ForceSetArg("-enableavalancheproofreplacement", "1");
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
+ ;
const auto now = GetTime<std::chrono::seconds>();
auto mocktime = now;
diff --git a/src/avalanche/test/processor_tests.cpp b/src/avalanche/test/processor_tests.cpp
--- a/src/avalanche/test/processor_tests.cpp
+++ b/src/avalanche/test/processor_tests.cpp
@@ -111,7 +111,8 @@
// Get the processor ready.
bilingual_str error;
m_processor = Processor::MakeProcessor(*m_node.args, *m_node.chain,
- m_node.connman.get(), error);
+ m_node.connman.get(),
+ *m_node.scheduler, error);
BOOST_CHECK(m_processor);
}
@@ -1143,7 +1144,8 @@
bilingual_str error;
std::unique_ptr<Processor> processor = Processor::MakeProcessor(
- *m_node.args, *m_node.chain, m_node.connman.get(), error);
+ *m_node.args, *m_node.chain, m_node.connman.get(), *m_node.scheduler,
+ error);
BOOST_CHECK(processor != nullptr);
BOOST_CHECK(processor->getLocalProof() != nullptr);
@@ -1291,7 +1293,8 @@
bilingual_str error;
std::unique_ptr<Processor> processor = Processor::MakeProcessor(
- *m_node.args, *m_node.chain, m_node.connman.get(), error);
+ *m_node.args, *m_node.chain, m_node.connman.get(),
+ *m_node.scheduler, error);
if (std::get<3>(*it)) {
BOOST_CHECK(processor != nullptr);
@@ -1320,7 +1323,8 @@
bilingual_str error;
auto processor = Processor::MakeProcessor(argsman, *m_node.chain,
- m_node.connman.get(), error);
+ m_node.connman.get(),
+ *m_node.scheduler, error);
BOOST_CHECK_EQUAL(processor->isQuorumEstablished(),
minAvaproofsMessages <= 0);
@@ -1377,7 +1381,8 @@
bilingual_str error;
m_processor = Processor::MakeProcessor(*m_node.args, *m_node.chain,
- m_node.connman.get(), error);
+ m_node.connman.get(),
+ *m_node.scheduler, error);
BOOST_CHECK(m_processor != nullptr);
BOOST_CHECK(error.empty());
diff --git a/src/avalanche/test/proofpool_tests.cpp b/src/avalanche/test/proofpool_tests.cpp
--- a/src/avalanche/test/proofpool_tests.cpp
+++ b/src/avalanche/test/proofpool_tests.cpp
@@ -76,7 +76,7 @@
BOOST_AUTO_TEST_CASE(rescan) {
ProofPool testPool;
- avalanche::PeerManager pm;
+ avalanche::PeerManager pm(*m_node.scheduler);
testPool.rescan(pm);
BOOST_CHECK_EQUAL(testPool.size(), 0);
diff --git a/src/init.cpp b/src/init.cpp
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -2544,7 +2544,7 @@
// Step 6.5 (I guess ?): Initialize Avalanche.
bilingual_str avalancheError;
g_avalanche = avalanche::Processor::MakeProcessor(
- args, *node.chain, node.connman.get(), avalancheError);
+ args, *node.chain, node.connman.get(), *node.scheduler, avalancheError);
if (!g_avalanche) {
InitError(avalancheError);
return false;
diff --git a/test/functional/abc_feature_proof_cleanup.py b/test/functional/abc_feature_proof_cleanup.py
new file mode 100644
--- /dev/null
+++ b/test/functional/abc_feature_proof_cleanup.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Test the dangling proofs cleanup
+"""
+
+import time
+
+from test_framework.avatools import (
+ gen_proof,
+ get_ava_p2p_interface,
+ get_proof_ids,
+)
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+# Interval between 2 proof cleanups
+AVALANCHE_CLEANUP_INTERVAL = 5 * 60
+# Dangling proof timeout
+AVALANCHE_DANGLING_PROOF_TIMEOUT = 15 * 60
+
+
+class ProofsCleanupTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.extra_args = [[
+ '-enableavalanche=1',
+ ]] * self.num_nodes
+
+ def run_test(self):
+ node = self.nodes[0]
+
+ mocktime = int(time.time())
+ node.setmocktime(mocktime)
+
+ proofs = []
+ peers = []
+ # The first 5 peers have a node attached
+ for _ in range(5):
+ key, proof = gen_proof(node)
+
+ peer = get_ava_p2p_interface(node)
+ node.addavalanchenode(
+ peer.nodeid,
+ key.get_pubkey().get_bytes().hex(),
+ proof.serialize().hex())
+
+ proofs.append(proof)
+ peers.append(peer)
+
+ # The last 5 peers have no node attached
+ for _ in range(5):
+ _, proof = gen_proof(node)
+ node.sendavalancheproof(proof.serialize().hex())
+ proofs.append(proof)
+
+ peer_info = node.getavalanchepeerinfo()
+ assert_equal(len(peer_info), 10)
+ assert_equal(set(get_proof_ids(node)),
+ set([proof.proofid for proof in proofs]))
+
+ self.log.info("No proof is cleaned before the timeout expires")
+
+ mocktime += AVALANCHE_DANGLING_PROOF_TIMEOUT - 1
+ node.setmocktime(mocktime)
+ # Run the cleanup, the proofs are still there
+ node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL)
+ assert_equal(len(peer_info), 10)
+
+ self.log.info("Check the proofs with attached nodes are not cleaned")
+
+ # Expire the dangling proof timeout
+ mocktime += 1
+ node.setmocktime(mocktime)
+
+ # Run the cleanup, the proofs with no node are cleaned
+ node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL)
+ self.wait_until(lambda: set(get_proof_ids(node)) == set(
+ [proof.proofid for proof in proofs[:5]]), timeout=5)
+
+ self.log.info(
+ "Check the proofs are cleaned on next cleanup after the nodes disconnected")
+
+ for peer in peers:
+ peer.peer_disconnect()
+ peer.wait_for_disconnect()
+
+ node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL)
+ self.wait_until(lambda: get_proof_ids(node) == [])
+
+
+if __name__ == '__main__':
+ ProofsCleanupTest().main()

File Metadata

Mime Type
text/plain
Expires
Tue, May 20, 20:49 (9 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5865920
Default Alt Text
D11667.id34128.diff (17 KB)

Event Timeline