diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -159,6 +159,7 @@ * exists, then it is created. */ PeerId getPeerId(const Proof &proof); + PeerId getPeerId(const Proof &proof, ProofValidationState &state); /** * Remove an existing peer. @@ -189,7 +190,8 @@ std::vector getNodeIdsForPeer(PeerId peerId) const; private: - PeerSet::iterator fetchOrCreatePeer(const Proof &proof); + PeerSet::iterator fetchOrCreatePeer(const Proof &proof, + ProofValidationState &state); 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 @@ -15,7 +15,8 @@ bool PeerManager::addNode(NodeId nodeid, const Proof &proof, const Delegation &delegation) { - auto it = fetchOrCreatePeer(proof); + ProofValidationState validationState; + auto it = fetchOrCreatePeer(proof, validationState); if (it == peers.end()) { return false; } @@ -181,12 +182,18 @@ } PeerId PeerManager::getPeerId(const Proof &proof) { - auto it = fetchOrCreatePeer(proof); + ProofValidationState state; + return getPeerId(proof, state); +} + +PeerId PeerManager::getPeerId(const Proof &proof, ProofValidationState &state) { + auto it = fetchOrCreatePeer(proof, state); return it == peers.end() ? NO_PEER : it->peerid; } PeerManager::PeerSet::iterator -PeerManager::fetchOrCreatePeer(const Proof &proof) { +PeerManager::fetchOrCreatePeer(const Proof &proof, + ProofValidationState &state) { { // Check if we already know of that peer. auto &pview = peers.get(); @@ -201,7 +208,6 @@ LOCK(cs_main); const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); - ProofValidationState state; if (!proof.verify(state, coins)) { return peers.end(); } diff --git a/src/avalanche/processor.h b/src/avalanche/processor.h --- a/src/avalanche/processor.h +++ b/src/avalanche/processor.h @@ -256,6 +256,12 @@ class NotificationsHandler; std::unique_ptr chainNotificationsHandler; + /** + * Flag indicating that the proof must be registered at first new block + * after IBD + */ + bool mustRegisterProof = false; + public: Processor(interfaces::Chain &chain, CConnman *connmanIn, NodePeerManager *nodePeerManagerIn); diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp --- a/src/avalanche/processor.cpp +++ b/src/avalanche/processor.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include // For DecodeSecret #include // For ::PeerManager @@ -149,6 +150,20 @@ void updatedBlockTip() override { LOCK(m_processor->cs_peerManager); + + if (m_processor->mustRegisterProof && + !::ChainstateActive().IsInitialBlockDownload()) { + ProofValidationState state; + m_processor->peerManager->getPeerId(m_processor->peerData->proof, + state); + // If proof validation failed due to missing UTXO, maybe the UTXO + // will be in a future block. + if (state.IsValid() || + state.GetResult() != ProofValidationResult::MISSING_UTXO) { + m_processor->mustRegisterProof = false; + } + } + m_processor->peerManager->updatedBlockTip(); } }; @@ -174,13 +189,8 @@ SER_NETWORK, 0); stream >> peerData->proof; - // Ensure the peer manager knows about it. - // FIXME: There is no way to register the proof at this time because - // we might not have the proper chainstate at the moment. We need to - // find a way to delay the registration of the proof until after IBD - // has finished and the chain state is settled. - // LOCK(cs_peerManager); - // peerManager->getPeerId(peerData->proof); + // Schedule proof registration at the first new block after IBD. + mustRegisterProof = true; } // Generate the delegation to the session key.