Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14864605
D11667.id34128.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Subscribers
None
D11667.id34128.diff
View Options
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
Details
Attached
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)
Attached To
D11667: [avalanche] Run the proofs cleanup on a schedule
Event Timeline
Log In to Comment