diff --git a/src/avalanche/proofpool.h b/src/avalanche/proofpool.h
--- a/src/avalanche/proofpool.h
+++ b/src/avalanche/proofpool.h
@@ -64,6 +64,9 @@
                                    SaltedProofIdHasher>>>
         pool;
 
+    bool cacheClean = true;
+    size_t cacheProofCount = 0;
+
 public:
     enum AddProofStatus {
         REJECTED = 0,   //!< Rejected due to conflicts
@@ -104,6 +107,7 @@
     ProofRef getProof(const COutPoint &outpoint) const;
 
     size_t size() const { return pool.size(); }
+    size_t countProofs();
 };
 
 } // namespace avalanche
diff --git a/src/avalanche/proofpool.cpp b/src/avalanche/proofpool.cpp
--- a/src/avalanche/proofpool.cpp
+++ b/src/avalanche/proofpool.cpp
@@ -46,6 +46,7 @@
         return AddProofStatus::REJECTED;
     }
 
+    cacheClean = false;
     return AddProofStatus::SUCCEED;
 }
 
@@ -68,6 +69,7 @@
     status = addProofIfNoConflict(proof);
     assert(status == AddProofStatus::SUCCEED);
 
+    cacheClean = false;
     return AddProofStatus::SUCCEED;
 }
 
@@ -75,6 +77,7 @@
 // reference to a proof member. This proof will be deleted during the erasure
 // loop so we pass it by value.
 bool ProofPool::removeProof(ProofId proofid) {
+    cacheClean = false;
     auto &poolView = pool.get<by_proofid>();
     return poolView.erase(proofid);
 }
@@ -82,6 +85,7 @@
 void ProofPool::rescan(PeerManager &peerManager) {
     auto previousPool = std::move(pool);
     pool.clear();
+    cacheClean = false;
 
     for (auto &entry : previousPool) {
         peerManager.registerProof(entry.proof);
@@ -99,4 +103,25 @@
     return it == pool.end() ? ProofRef() : it->proof;
 }
 
+size_t ProofPool::countProofs() {
+    if (cacheClean) {
+        return cacheProofCount;
+    }
+
+    size_t count = 0;
+    ProofId lastProofId;
+    auto &poolView = pool.get<by_proofid>();
+    for (auto it = poolView.begin(); it != poolView.end(); it++) {
+        const ProofId &proofId = it->proof->getId();
+        if (lastProofId != proofId) {
+            lastProofId = proofId;
+            count++;
+        }
+    }
+
+    cacheProofCount = count;
+    cacheClean = true;
+    return cacheProofCount;
+}
+
 } // namespace avalanche
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
@@ -29,11 +29,13 @@
         auto proof = buildRandomProof(MIN_VALID_PROOF_SCORE);
         BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
                           ProofPool::AddProofStatus::SUCCEED);
+        BOOST_CHECK_EQUAL(testPool.countProofs(), i + 1);
 
         // Trying to add them again will return a duplicated status
         for (size_t j = 0; j < 10; j++) {
             BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
                               ProofPool::AddProofStatus::DUPLICATED);
+            BOOST_CHECK_EQUAL(testPool.countProofs(), i + 1);
         }
         proofs.push_back(std::move(proof));
     }
@@ -51,21 +53,25 @@
     auto proof_seq10 = buildProofWithSequence(10);
     BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof_seq10),
                       ProofPool::AddProofStatus::SUCCEED);
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 11);
     proofs.push_back(std::move(proof_seq10));
 
     auto proof_seq20 = buildProofWithSequence(20);
     BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof_seq20),
                       ProofPool::AddProofStatus::REJECTED);
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 11);
 
     // Removing proofs which are not in the pool will fail
     for (size_t i = 0; i < 10; i++) {
         BOOST_CHECK(!testPool.removeProof(ProofId(GetRandHash())));
     }
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 11);
 
     for (auto proof : proofs) {
         BOOST_CHECK(testPool.removeProof(proof->getId()));
     }
     BOOST_CHECK_EQUAL(testPool.size(), 0);
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
 }
 
 BOOST_AUTO_TEST_CASE(rescan) {
@@ -74,6 +80,7 @@
 
     testPool.rescan(pm);
     BOOST_CHECK_EQUAL(testPool.size(), 0);
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
 
     // No peer should be created
     bool hasPeer = false;
@@ -86,6 +93,7 @@
         BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
                           ProofPool::AddProofStatus::SUCCEED);
         poolProofs.insert(std::move(proof));
+        BOOST_CHECK_EQUAL(testPool.countProofs(), i + 1);
     }
 
     testPool.rescan(pm);
@@ -96,6 +104,7 @@
     BOOST_CHECK_EQUAL_COLLECTIONS(poolProofs.begin(), poolProofs.end(),
                                   pmProofs.begin(), pmProofs.end());
     BOOST_CHECK_EQUAL(testPool.size(), 0);
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
 }
 
 BOOST_AUTO_TEST_CASE(proof_override) {
@@ -125,14 +134,17 @@
     BOOST_CHECK_EQUAL(testPool.addProofIfPreferred(proof_seq10),
                       ProofPool::AddProofStatus::SUCCEED);
     BOOST_CHECK(testPool.getProof(proof_seq10->getId()));
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 1);
 
     BOOST_CHECK_EQUAL(testPool.addProofIfPreferred(proof_seq20),
                       ProofPool::AddProofStatus::SUCCEED);
     BOOST_CHECK(testPool.getProof(proof_seq20->getId()));
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 2);
 
     BOOST_CHECK_EQUAL(testPool.addProofIfPreferred(proof_seq30),
                       ProofPool::AddProofStatus::SUCCEED);
     BOOST_CHECK(testPool.getProof(proof_seq30->getId()));
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 3);
 
     // Build a proof that conflicts with the above 3, but has a higher sequence
     auto proof_seq123 = buildProofWithSequenceAndOutpoints(
@@ -149,6 +161,7 @@
     BOOST_CHECK_EQUAL_COLLECTIONS(
         conflictingProofs.begin(), conflictingProofs.end(),
         expectedConflictingProofs.begin(), expectedConflictingProofs.end());
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 3);
     BOOST_CHECK(!testPool.getProof(proof_seq123->getId()));
     BOOST_CHECK(testPool.getProof(proof_seq10->getId()));
     BOOST_CHECK(testPool.getProof(proof_seq20->getId()));
@@ -162,6 +175,7 @@
     BOOST_CHECK_EQUAL_COLLECTIONS(
         conflictingProofs.begin(), conflictingProofs.end(),
         expectedConflictingProofs.begin(), expectedConflictingProofs.end());
+    BOOST_CHECK_EQUAL(testPool.countProofs(), 1);
     BOOST_CHECK(testPool.getProof(proof_seq123->getId()));
     BOOST_CHECK(!testPool.getProof(proof_seq10->getId()));
     BOOST_CHECK(!testPool.getProof(proof_seq20->getId()));