diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -20,6 +20,7 @@ #include #include +#include #include namespace avalanche { @@ -68,6 +69,7 @@ Peer(PeerId peerid_, Proof proof_) : peerid(peerid_), proof(std::move(proof_)) {} + const Proof &getProof() const { return proof; } const ProofId &getProofId() const { return proof.getId(); } uint32_t getScore() const { return proof.getScore(); } }; @@ -181,6 +183,8 @@ std::vector getPeers() const; std::vector getNodeIdsForPeer(PeerId peerId) const; + std::optional getProof(const ProofId &proofid) const; + private: PeerSet::iterator fetchOrCreatePeer(const Proof &proof); bool addNodeToPeer(const PeerSet::iterator &it); diff --git a/src/avalanche/peermanager.cpp b/src/avalanche/peermanager.cpp --- a/src/avalanche/peermanager.cpp +++ b/src/avalanche/peermanager.cpp @@ -185,6 +185,13 @@ return it == peers.end() ? NO_PEER : it->peerid; } +std::optional PeerManager::getProof(const ProofId &proofid) const { + auto &pview = peers.get(); + auto it = pview.find(proofid); + return it == pview.end() ? std::nullopt + : std::make_optional(it->getProof()); +} + PeerManager::PeerSet::iterator PeerManager::fetchOrCreatePeer(const Proof &proof) { { diff --git a/src/avalanche/processor.h b/src/avalanche/processor.h --- a/src/avalanche/processor.h +++ b/src/avalanche/processor.h @@ -25,6 +25,7 @@ #include #include #include +#include #include class ArgsManager; @@ -302,6 +303,9 @@ */ uint256 buildRemoteSighash(CNode *pfrom) const; + bool addProof(const Proof &proof); + std::optional getProof(const ProofId &proofid) const; + /* * Return whether the avalanche service flag should be set. */ diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp --- a/src/avalanche/processor.cpp +++ b/src/avalanche/processor.cpp @@ -501,6 +501,17 @@ return true; } +bool Processor::addProof(const Proof &proof) { + LOCK(cs_peerManager); + return !peerManager->getProof(proof.getId()) && + peerManager->getPeerId(proof) != NO_PEER; +} + +std::optional Processor::getProof(const ProofId &proofid) const { + LOCK(cs_peerManager); + return peerManager->getProof(proofid); +} + bool Processor::startEventLoop(CScheduler &scheduler) { return eventLoop.startEventLoop( scheduler, [this]() { this->runEventLoop(); }, AVALANCHE_TIME_STEP); 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 @@ -20,6 +20,8 @@ #include +#include + using namespace avalanche; namespace avalanche { @@ -971,4 +973,40 @@ schedulerThread.join(); } +BOOST_AUTO_TEST_CASE(proof_accessors) { + constexpr int numProofs = 10; + + std::vector proofs; + proofs.reserve(numProofs); + for (int i = 0; i < numProofs; i++) { + proofs.push_back(GetProof()); + } + + for (int i = 0; i < numProofs; i++) { + BOOST_CHECK(m_processor->addProof(proofs[i])); + // Fail to add an existing proof + BOOST_CHECK(!m_processor->addProof(proofs[i])); + + for (int added = 0; added <= i; added++) { + std::optional proof = + m_processor->getProof(proofs[added].getId()); + BOOST_CHECK(proof); + BOOST_CHECK_EQUAL(proof->getId(), proofs[added].getId()); + } + + for (int missing = i + 1; missing < numProofs; missing++) { + BOOST_CHECK(!m_processor->getProof(proofs[missing].getId())); + } + } + + // No stake, copied from proof_tests.cpp + const std::string badProofHex( + "96527eae083f1f24625f049d9e54bb9a2102a93d98bf42ab90cfc0bf9e7c634ed76a7" + "3e95b02cacfd357b64e4fb6c92e92dd00"); + bilingual_str error; + Proof badProof; + BOOST_CHECK(Proof::FromHex(badProof, badProofHex, error)); + BOOST_CHECK(!m_processor->addProof(badProof)); +} + BOOST_AUTO_TEST_SUITE_END()