diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -66,8 +66,8 @@ std::shared_ptr proof; - Peer(PeerId peerid_, Proof proof_) - : peerid(peerid_), proof(std::make_shared(std::move(proof_))) {} + Peer(PeerId peerid_, std::shared_ptr proof_) + : peerid(peerid_), proof(std::move(proof_)) {} const ProofId &getProofId() const { return proof->getId(); } uint32_t getScore() const { return proof->getScore(); } @@ -128,7 +128,7 @@ /** * Node API. */ - bool addNode(NodeId nodeid, const Proof &proof, + bool addNode(NodeId nodeid, std::shared_ptr proof, const Delegation &delegation); bool removeNode(NodeId nodeid); @@ -152,7 +152,7 @@ * Provide the PeerId associated with the given proof. If the peer does not * exist, then it is created. */ - PeerId getPeerId(const Proof &proof); + PeerId getPeerId(std::shared_ptr proof); /** * Remove an existing peer. @@ -183,7 +183,7 @@ std::vector getNodeIdsForPeer(PeerId peerId) const; private: - PeerSet::iterator fetchOrCreatePeer(const Proof &proof); + PeerSet::iterator fetchOrCreatePeer(std::shared_ptr proof); 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 @@ -13,21 +13,21 @@ namespace avalanche { -bool PeerManager::addNode(NodeId nodeid, const Proof &proof, +bool PeerManager::addNode(NodeId nodeid, std::shared_ptr proof, const Delegation &delegation) { - auto it = fetchOrCreatePeer(proof); - if (it == peers.end()) { + DelegationState state; + CPubKey pubkey; + if (!delegation.verify(state, *proof, pubkey)) { return false; } - const PeerId peerid = it->peerid; - - DelegationState state; - CPubKey pubkey; - if (!delegation.verify(state, proof, pubkey)) { + auto it = fetchOrCreatePeer(std::move(proof)); + if (it == peers.end()) { return false; } + const PeerId peerid = it->peerid; + auto nit = nodes.find(nodeid); if (nit == nodes.end()) { if (!nodes.emplace(nodeid, peerid, std::move(pubkey)).second) { @@ -180,17 +180,17 @@ } } -PeerId PeerManager::getPeerId(const Proof &proof) { - auto it = fetchOrCreatePeer(proof); +PeerId PeerManager::getPeerId(std::shared_ptr proof) { + auto it = fetchOrCreatePeer(std::move(proof)); return it == peers.end() ? NO_PEER : it->peerid; } PeerManager::PeerSet::iterator -PeerManager::fetchOrCreatePeer(const Proof &proof) { +PeerManager::fetchOrCreatePeer(std::shared_ptr proof) { { // Check if we already know of that peer. auto &pview = peers.get(); - auto it = pview.find(proof.getId()); + auto it = pview.find(proof->getId()); if (it != pview.end()) { return peers.project<0>(it); } @@ -202,7 +202,7 @@ const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); ProofValidationState state; - if (!proof.verify(state, coins)) { + if (!proof->verify(state, coins)) { return peers.end(); } } @@ -212,7 +212,7 @@ // Attach UTXOs to this proof. std::unordered_set conflicting_peerids; - for (const auto &s : proof.getStakes()) { + for (const auto &s : proof->getStakes()) { auto p = utxos.emplace(s.getStake().getUTXO(), peerid); if (!p.second) { // We have a collision with an existing proof. @@ -222,7 +222,7 @@ // For now, if there is a conflict, just ceanup the mess. if (conflicting_peerids.size() > 0) { - for (const auto &s : proof.getStakes()) { + for (const auto &s : proof->getStakes()) { auto it = utxos.find(s.getStake().getUTXO()); assert(it != utxos.end()); diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp --- a/src/avalanche/processor.cpp +++ b/src/avalanche/processor.cpp @@ -154,7 +154,8 @@ if (m_processor->mustRegisterProof && !::ChainstateActive().IsInitialBlockDownload()) { - m_processor->peerManager->getPeerId(m_processor->peerData->proof); + m_processor->peerManager->getPeerId( + std::make_shared(m_processor->peerData->proof)); m_processor->mustRegisterProof = false; } @@ -444,7 +445,8 @@ bool Processor::addNode(NodeId nodeid, const Proof &proof, const Delegation &delegation) { LOCK(cs_peerManager); - return peerManager->addNode(nodeid, proof, delegation); + return peerManager->addNode(nodeid, std::make_shared(proof), + delegation); } bool Processor::forNode(NodeId nodeid, 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 @@ -154,6 +154,10 @@ } } +static std::shared_ptr getRandomProofPtr(uint32_t score) { + return std::make_shared(buildRandomProof(score)); +} + BOOST_AUTO_TEST_CASE(peer_probabilities) { // No peers. avalanche::PeerManager pm; @@ -162,14 +166,15 @@ const NodeId node0 = 42, node1 = 69, node2 = 37; // One peer, we always return it. - Proof proof0 = buildRandomProof(MIN_VALID_PROOF_SCORE); - Delegation dg0 = DelegationBuilder(proof0).build(); + std::shared_ptr proof0 = getRandomProofPtr(MIN_VALID_PROOF_SCORE); + Delegation dg0 = DelegationBuilder(*proof0).build(); pm.addNode(node0, proof0, dg0); BOOST_CHECK_EQUAL(pm.selectNode(), node0); // Two peers, verify ratio. - Proof proof1 = buildRandomProof(2 * MIN_VALID_PROOF_SCORE); - Delegation dg1 = DelegationBuilder(proof1).build(); + std::shared_ptr proof1 = + getRandomProofPtr(2 * MIN_VALID_PROOF_SCORE); + Delegation dg1 = DelegationBuilder(*proof1).build(); pm.addNode(node1, proof1, dg1); std::unordered_map results = {}; @@ -182,8 +187,8 @@ BOOST_CHECK(abs(2 * results[0] - results[1]) < 500); // Three peers, verify ratio. - Proof proof2 = buildRandomProof(MIN_VALID_PROOF_SCORE); - Delegation dg2 = DelegationBuilder(proof2).build(); + std::shared_ptr proof2 = getRandomProofPtr(MIN_VALID_PROOF_SCORE); + Delegation dg2 = DelegationBuilder(*proof2).build(); pm.addNode(node2, proof2, dg2); results.clear(); @@ -204,10 +209,10 @@ // Add 4 peers. std::array peerids; for (int i = 0; i < 4; i++) { - Proof p = buildRandomProof(100); + std::shared_ptr p = getRandomProofPtr(100); peerids[i] = pm.getPeerId(p); BOOST_CHECK( - pm.addNode(InsecureRand32(), p, DelegationBuilder(p).build())); + pm.addNode(InsecureRand32(), p, DelegationBuilder(*p).build())); } BOOST_CHECK_EQUAL(pm.getSlotCount(), 400); @@ -237,10 +242,10 @@ // Add 4 more peers. for (int i = 0; i < 4; i++) { - Proof p = buildRandomProof(100); + std::shared_ptr p = getRandomProofPtr(100); peerids[i + 4] = pm.getPeerId(p); BOOST_CHECK( - pm.addNode(InsecureRand32(), p, DelegationBuilder(p).build())); + pm.addNode(InsecureRand32(), p, DelegationBuilder(*p).build())); } BOOST_CHECK_EQUAL(pm.getSlotCount(), 700); @@ -280,10 +285,10 @@ // Add 4 peers. std::array peerids; for (int i = 0; i < 4; i++) { - Proof p = buildRandomProof(100); + std::shared_ptr p = getRandomProofPtr(100); peerids[i] = pm.getPeerId(p); BOOST_CHECK( - pm.addNode(InsecureRand32(), p, DelegationBuilder(p).build())); + pm.addNode(InsecureRand32(), p, DelegationBuilder(*p).build())); } // Remove all peers. @@ -308,8 +313,9 @@ avalanche::PeerManager pm; // Create one peer. - Proof proof = buildRandomProof(10000000 * MIN_VALID_PROOF_SCORE); - Delegation dg = DelegationBuilder(proof).build(); + std::shared_ptr proof = + getRandomProofPtr(10000000 * MIN_VALID_PROOF_SCORE); + Delegation dg = DelegationBuilder(*proof).build(); BOOST_CHECK_EQUAL(pm.selectNode(), NO_NODE); // Add 4 nodes. @@ -347,8 +353,8 @@ // Move a node from a peer to another. This peer has a very low score such // as chances of being picked are 1 in 10 million. - Proof altproof = buildRandomProof(MIN_VALID_PROOF_SCORE); - Delegation altdg = DelegationBuilder(altproof).build(); + std::shared_ptr altproof = getRandomProofPtr(MIN_VALID_PROOF_SCORE); + Delegation altdg = DelegationBuilder(*altproof).build(); BOOST_CHECK(pm.addNode(3, altproof, altdg)); int node3selected = 0; @@ -396,7 +402,7 @@ pb.addUTXO(o, v, height, false, key); } - return pm.getPeerId(pb.build()); + return pm.getPeerId(std::make_shared(pb.build())); }; // Add one peer. 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 @@ -139,9 +139,11 @@ Delegation dg = DelegationBuilder(proof).build(); std::array nodes; + std::shared_ptr shared_proof = + std::make_shared(std::move(proof)); for (CNode *&n : nodes) { n = ConnectNode(NODE_AVALANCHE); - BOOST_CHECK(pm.addNode(n->GetId(), proof, dg)); + BOOST_CHECK(pm.addNode(n->GetId(), shared_proof, dg)); } return nodes; @@ -748,9 +750,11 @@ Delegation dg = DelegationBuilder(proof).build(); std::array nodes; + std::shared_ptr shared_proof = + std::make_shared(std::move(proof)); for (auto &n : nodes) { n = ConnectNode(NODE_AVALANCHE); - BOOST_CHECK(pm.addNode(n->GetId(), proof, dg)); + BOOST_CHECK(pm.addNode(n->GetId(), shared_proof, dg)); } // Add a block to poll