diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -268,7 +268,7 @@ bool isOrphan(const ProofId &proofid) const; private: - PeerSet::iterator fetchOrCreatePeer(const ProofRef &proof); + bool createPeer(const ProofRef &proof); bool addOrUpdateNode(const PeerSet::iterator &it, NodeId nodeid); bool addNodeToPeer(const PeerSet::iterator &it); bool removeNodeFromPeer(const PeerSet::iterator &it, uint32_t count = 1); diff --git a/src/avalanche/peermanager.cpp b/src/avalanche/peermanager.cpp --- a/src/avalanche/peermanager.cpp +++ b/src/avalanche/peermanager.cpp @@ -142,8 +142,35 @@ return nodes.modify(it, [&](Node &n) { n.nextRequestTime = timeout; }); } +static bool isOrphanState(const ProofValidationState &state) { + return state.GetResult() == ProofValidationResult::MISSING_UTXO || + state.GetResult() == ProofValidationResult::HEIGHT_MISMATCH; +} + bool PeerManager::registerProof(const ProofRef &proof) { - return !exists(proof->getId()) && fetchOrCreatePeer(proof) != peers.end(); + if (exists(proof->getId())) { + // The proof is already registered, or orphaned. + return false; + } + + // Check the proof's validity. + ProofValidationState state; + bool valid = [&](ProofValidationState &state) { + LOCK(cs_main); + const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); + return proof->verify(state, coins); + }(state); + + if (!valid) { + if (isOrphanState(state)) { + orphanProofs.addProof(proof); + } + + // Reject invalid proof. + return false; + } + + return createPeer(proof); } NodeId PeerManager::selectNode() { @@ -169,11 +196,6 @@ return NO_NODE; } -static bool isOrphanState(const ProofValidationState &state) { - return state.GetResult() == ProofValidationResult::MISSING_UTXO || - state.GetResult() == ProofValidationResult::HEIGHT_MISMATCH; -} - void PeerManager::updatedBlockTip() { std::vector invalidPeers; std::vector newOrphans; @@ -231,38 +253,15 @@ return orphanProofs.getProof(proofid) != nullptr; } -PeerManager::PeerSet::iterator -PeerManager::fetchOrCreatePeer(const ProofRef &proof) { +bool PeerManager::createPeer(const ProofRef &proof) { assert(proof); - const ProofId &proofid = proof->getId(); - { - // Check if we already know of that peer. - auto &pview = peers.get(); - auto it = pview.find(proofid); - if (it != pview.end()) { - return peers.project<0>(it); - } - } - - // Check the proof's validity. - ProofValidationState state; - bool valid = [&](ProofValidationState &state) { - LOCK(cs_main); - const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); - return proof->verify(state, coins); - }(state); - if (!valid) { - if (isOrphanState(state)) { - orphanProofs.addProof(proof); - } + const ProofId &proofid = proof->getId(); - // Reject invalid proof. - return peers.end(); + if (isValid(proofid)) { + return false; } - orphanProofs.removeProof(proofid); - // New peer means new peerid! const PeerId peerid = nextPeerId++; @@ -292,7 +291,7 @@ // invalidated. orphanProofs.addProof(proof); - return peers.end(); + return false; } // We have no peer for this proof, time to create it. @@ -315,7 +314,7 @@ addOrUpdateNode(inserted.first, nodeid); } - return inserted.first; + return true; } bool PeerManager::removePeer(const PeerId peerid) {