diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -127,10 +127,14 @@ NodeSet nodes; + std::unique_ptr rejectedProofs; + static constexpr int SELECT_PEER_MAX_RETRY = 3; static constexpr int SELECT_NODE_MAX_RETRY = 3; public: + PeerManager(); + /** * Node API. */ @@ -188,6 +192,9 @@ std::vector getPeers() const; std::vector getNodeIdsForPeer(PeerId peerId) const; + // For testing only + void rejectProof(ProofId proofId); + 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 @@ -13,6 +13,11 @@ namespace avalanche { +PeerManager::PeerManager() + : rejectedProofs( + // This filter uses the same parameters as the tx recentRejects. + std::make_unique(120000, 0.000001)) {} + bool PeerManager::addNode(NodeId nodeid, const Proof &proof, const Delegation &delegation) { auto it = fetchOrCreatePeer(proof); @@ -171,6 +176,9 @@ ProofValidationState state; if (!p.proof.verify(state, coins)) { invalidPeers.push_back(p.peerid); + if (state.GetResult() != ProofValidationResult::MISSING_UTXO) { + rejectedProofs->insert(p.proof.getId()); + } } } } @@ -196,6 +204,10 @@ } } + if (rejectedProofs->contains(proof.getId())) { + return peers.end(); + } + { // Reject invalid proof. LOCK(cs_main); @@ -203,6 +215,9 @@ ProofValidationState state; if (!proof.verify(state, coins)) { + if (state.GetResult() != ProofValidationResult::MISSING_UTXO) { + rejectedProofs->insert(proof.getId()); + } return peers.end(); } } @@ -456,4 +471,8 @@ return nodeids; } +void PeerManager::rejectProof(ProofId proofId) { + rejectedProofs->insert(proofId); +} + } // namespace avalanche 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 @@ -436,6 +436,14 @@ // Mutliple inputs, collision on both inputs. BOOST_CHECK_EQUAL(getPeerId({COutPoint(txid1, 0), COutPoint(txid2, 2)}), NO_PEER); + + // Make a new good proof but add it to rejectedProofs to pretend + // that we previously found it to be bad. + ProofBuilder pb(0, 0, CPubKey()); + pb.addUTXO(COutPoint(txid1, 5), v, height, false, key); + Proof p(pb.build()); + pm.rejectProof(p.getId()); + BOOST_CHECK_EQUAL(pm.getPeerId(p), NO_PEER); } BOOST_AUTO_TEST_SUITE_END()