diff --git a/src/test/avalanche_tests.cpp b/src/test/avalanche_tests.cpp --- a/src/test/avalanche_tests.cpp +++ b/src/test/avalanche_tests.cpp @@ -25,6 +25,21 @@ static uint64_t getRound(const AvalancheProcessor &p) { return p.round; } }; +struct CConnmanTest : public CConnman { + using CConnman::CConnman; + void AddNode(CNode &node) { + LOCK(cs_vNodes); + vNodes.push_back(&node); + } + void ClearNodes() { + LOCK(cs_vNodes); + for (CNode *node : vNodes) { + delete node; + } + vNodes.clear(); + } +}; + BOOST_FIXTURE_TEST_SUITE(avalanche_tests, TestChain100Setup) #define REGISTER_VOTE_AND_CHECK(vr, vote, state, finalized, confidence) \ @@ -157,32 +172,31 @@ return CService(CNetAddr(s), Params().GetDefaultPort()); } -std::unique_ptr ConnectNode(const Config &config, ServiceFlags nServices, - PeerLogicValidation &peerLogic) { +CNode *ConnectNode(const Config &config, ServiceFlags nServices, + PeerLogicValidation &peerLogic, CConnmanTest *connman) { static NodeId id = 0; CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE); - std::unique_ptr nodeptr(new CNode(id++, ServiceFlags(NODE_NETWORK), - 0, INVALID_SOCKET, addr, 0, 0, - CAddress(), "", - /*fInboundIn=*/false)); - CNode &node = *nodeptr; - node.SetSendVersion(PROTOCOL_VERSION); - node.nServices = nServices; - peerLogic.InitializeNode(config, &node); - node.nVersion = 1; - node.fSuccessfullyConnected = true; - - CConnmanTest::AddNode(node); - return nodeptr; + auto node = new CNode(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, + addr, 0, 0, CAddress(), "", + /*fInboundIn=*/false); + node->SetSendVersion(PROTOCOL_VERSION); + node->nServices = nServices; + peerLogic.InitializeNode(config, node); + node->nVersion = 1; + node->fSuccessfullyConnected = true; + + connman->AddNode(*node); + return node; } -std::array, 8> -ConnectNodes(const Config &config, AvalancheProcessor &p, - ServiceFlags nServices, PeerLogicValidation &peerLogic) { - std::array, 8> nodes; - for (auto &n : nodes) { - n = ConnectNode(config, nServices, peerLogic); +std::array ConnectNodes(const Config &config, AvalancheProcessor &p, + ServiceFlags nServices, + PeerLogicValidation &peerLogic, + CConnmanTest *connman) { + std::array nodes; + for (CNode *&n : nodes) { + n = ConnectNode(config, nServices, peerLogic, connman); BOOST_CHECK(p.addPeer(n->GetId(), 0)); } @@ -196,17 +210,22 @@ } BOOST_AUTO_TEST_CASE(block_register) { - AvalancheProcessor p(g_connman.get()); + const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); std::vector updates; CBlock block = CreateAndProcessBlock({}, CScript()); const uint256 blockHash = block.GetHash(); const CBlockIndex *pindex = mapBlockIndex[blockHash]; - const Config &config = GetConfig(); - // Create nodes that supports avalanche. - auto avanodes = ConnectNodes(config, p, NODE_AVALANCHE, *peerLogic); + auto avanodes = + ConnectNodes(config, p, NODE_AVALANCHE, *peerLogic, connman.get()); // Querying for random block returns false. BOOST_CHECK(!p.isAccepted(pindex)); @@ -351,19 +370,24 @@ BOOST_CHECK(!p.addBlockToReconcile(pindex)); BOOST_CHECK(p.isAccepted(pindex)); - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(multi_block_register) { - AvalancheProcessor p(g_connman.get()); + const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); CBlockIndex indexA, indexB; std::vector updates; - const Config &config = GetConfig(); - // Create several nodes that support avalanche. - auto avanodes = ConnectNodes(config, p, NODE_AVALANCHE, *peerLogic); + auto avanodes = + ConnectNodes(config, p, NODE_AVALANCHE, *peerLogic, connman.get()); // Make sure the block has a hash. CBlock blockA = CreateAndProcessBlock({}, CScript()); @@ -458,11 +482,17 @@ invs = AvalancheTest::getInvsForNextPoll(p); BOOST_CHECK_EQUAL(invs.size(), 0); - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(poll_and_response) { - AvalancheProcessor p(g_connman.get()); + const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); std::vector updates; @@ -470,14 +500,13 @@ const uint256 blockHash = block.GetHash(); const CBlockIndex *pindex = mapBlockIndex[blockHash]; - const Config &config = GetConfig(); - // There is no node to query. BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), NO_NODE); // Create a node that supports avalanche and one that doesn't. - auto oldnode = ConnectNode(config, NODE_NONE, *peerLogic); - auto avanode = ConnectNode(config, NODE_AVALANCHE, *peerLogic); + ConnectNode(config, NODE_NONE, *peerLogic, connman.get()); + auto avanode = + ConnectNode(config, NODE_AVALANCHE, *peerLogic, connman.get()); NodeId avanodeid = avanode->GetId(); BOOST_CHECK(p.addPeer(avanodeid, 0)); @@ -594,11 +623,17 @@ BOOST_CHECK_EQUAL(updates.size(), 0); BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(poll_inflight_timeout, *boost::unit_test::timeout(60)) { - AvalancheProcessor p(g_connman.get()); + const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); std::vector updates; @@ -610,8 +645,8 @@ BOOST_CHECK(p.addBlockToReconcile(pindex)); // Create a node that supports avalanche. - const Config &config = GetConfig(); - auto avanode = ConnectNode(config, NODE_AVALANCHE, *peerLogic); + auto avanode = + ConnectNode(config, NODE_AVALANCHE, *peerLogic, connman.get()); NodeId avanodeid = avanode->GetId(); BOOST_CHECK(p.addPeer(avanodeid, 0)); @@ -648,17 +683,22 @@ BOOST_CHECK(!p.registerVotes(avanodeid, next(resp), updates)); } - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(poll_inflight_count) { - AvalancheProcessor p(g_connman.get()); const Config &config = GetConfig(); + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); + // Create enough nodes so that we run into the inflight request limit. - std::array, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes; + std::array nodes; for (auto &n : nodes) { - n = ConnectNode(config, NODE_AVALANCHE, *peerLogic); + n = ConnectNode(config, NODE_AVALANCHE, *peerLogic, connman.get()); BOOST_CHECK(p.addPeer(n->GetId(), 0)); } @@ -702,21 +742,26 @@ BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); BOOST_CHECK(invs[0].hash == blockHash); - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(quorum_diversity) { - AvalancheProcessor p(g_connman.get()); + const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); std::vector updates; CBlock block = CreateAndProcessBlock({}, CScript()); const uint256 blockHash = block.GetHash(); const CBlockIndex *pindex = mapBlockIndex[blockHash]; - const Config &config = GetConfig(); - // Create nodes that supports avalanche. - auto avanodes = ConnectNodes(config, p, NODE_AVALANCHE, *peerLogic); + auto avanodes = + ConnectNodes(config, p, NODE_AVALANCHE, *peerLogic, connman.get()); // Querying for random block returns false. BOOST_CHECK(!p.isAccepted(pindex)); @@ -769,11 +814,17 @@ firstNodeId, {round, 0, {AvalancheVote(0, blockHash)}}, updates)); BOOST_CHECK_EQUAL(p.getConfidence(pindex), confidence + 1); - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(event_loop) { - AvalancheProcessor p(g_connman.get()); + const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + + AvalancheProcessor p(connman.get()); CScheduler s; CBlock block = CreateAndProcessBlock({}, CScript()); @@ -793,11 +844,9 @@ // Start the scheduler thread. std::thread schedulerThread(std::bind(&CScheduler::serviceQueue, &s)); - // Create a node and a block to query. - const Config &config = GetConfig(); - // Create a node that supports avalanche. - auto avanode = ConnectNode(config, NODE_AVALANCHE, *peerLogic); + auto avanode = + ConnectNode(config, NODE_AVALANCHE, *peerLogic, connman.get()); NodeId nodeid = avanode->GetId(); BOOST_CHECK(p.addPeer(nodeid, 0)); @@ -853,7 +902,7 @@ s.stop(true); schedulerThread.join(); - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(destructor) { diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -22,6 +22,21 @@ #include +struct CConnmanTest : public CConnman { + using CConnman::CConnman; + void AddNode(CNode &node) { + LOCK(cs_vNodes); + vNodes.push_back(&node); + } + void ClearNodes() { + LOCK(cs_vNodes); + for (CNode *node : vNodes) { + delete node; + } + vNodes.clear(); + } +}; + // Tests these internal-to-net_processing.cpp methods: extern bool AddOrphanTx(const CTransactionRef &tx, NodeId peer); extern void EraseOrphansFor(NodeId peer); @@ -57,6 +72,10 @@ const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr1, @@ -114,8 +133,9 @@ } static void AddRandomOutboundPeer(const Config &config, - std::vector> &vNodes, - PeerLogicValidation &peerLogic) { + std::vector &vNodes, + PeerLogicValidation &peerLogic, + CConnmanTest *connman) { CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE); vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", @@ -127,11 +147,16 @@ node.nVersion = 1; node.fSuccessfullyConnected = true; - CConnmanTest::AddNode(node); + connman->AddNode(node); } BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { const Config &config = GetConfig(); + + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + const Consensus::Params &consensusParams = config.GetChainParams().GetConsensus(); constexpr int nMaxOutbound = 8; @@ -141,17 +166,17 @@ options.nMaxFeeler = 1; connman->Init(options); - std::vector> vNodes; + std::vector vNodes; // Mock some outbound peers for (int i = 0; i < nMaxOutbound; ++i) { - AddRandomOutboundPeer(config, vNodes, *peerLogic); + AddRandomOutboundPeer(config, vNodes, *peerLogic, connman.get()); } peerLogic->CheckForStaleTipAndEvictPeers(consensusParams); // No nodes should be marked for disconnection while we have no extra peers - for (auto const &node : vNodes) { + for (const CNode *node : vNodes) { BOOST_CHECK(node->fDisconnect == false); } @@ -163,14 +188,14 @@ BOOST_CHECK(connman->GetTryNewOutboundPeer()); // Still no peers should be marked for disconnection - for (auto const &node : vNodes) { + for (const CNode *node : vNodes) { BOOST_CHECK(node->fDisconnect == false); } // If we add one more peer, something should get marked for eviction // on the next check (since we're mocking the time to be in the future, the // required time connected check should be satisfied). - AddRandomOutboundPeer(config, vNodes, *peerLogic); + AddRandomOutboundPeer(config, vNodes, *peerLogic, connman.get()); peerLogic->CheckForStaleTipAndEvictPeers(consensusParams); for (int i = 0; i < nMaxOutbound; ++i) { @@ -193,17 +218,21 @@ BOOST_CHECK(vNodes.back()->fDisconnect == false); bool dummy; - for (auto const &node : vNodes) { + for (const CNode *node : vNodes) { peerLogic->FinalizeNode(config, node->GetId(), dummy); } - CConnmanTest::ClearNodes(); + connman->ClearNodes(); } BOOST_AUTO_TEST_CASE(DoS_banning) { const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, @@ -263,6 +292,10 @@ const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + connman->ClearBanned(); // because 11 is my favorite number. gArgs.ForceSetArg("-banscore", "111"); @@ -310,6 +343,10 @@ const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto connman = std::make_unique(config, 0x1337, 0x1337); + auto peerLogic = + std::make_unique(connman.get(), scheduler, false); + connman->ClearBanned(); int64_t nStartTime = GetTime(); // Overrides future calls to GetTime() diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -74,17 +74,11 @@ */ class CConnman; class CNode; -struct CConnmanTest { - static void AddNode(CNode &node); - static void ClearNodes(); -}; class PeerLogicValidation; struct TestingSetup : public BasicTestingSetup { boost::thread_group threadGroup; - CConnman *connman; CScheduler scheduler; - std::unique_ptr peerLogic; explicit TestingSetup( const std::string &chainName = CBaseChainParams::MAIN); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -31,16 +31,6 @@ FastRandomContext g_insecure_rand_ctx; -void CConnmanTest::AddNode(CNode &node) { - LOCK(g_connman->cs_vNodes); - g_connman->vNodes.push_back(&node); -} - -void CConnmanTest::ClearNodes() { - LOCK(g_connman->cs_vNodes); - g_connman->vNodes.clear(); -} - std::ostream &operator<<(std::ostream &os, const uint256 &num) { os << num.ToString(); return os; @@ -125,12 +115,8 @@ for (int i = 0; i < nScriptCheckThreads - 1; i++) { threadGroup.create_thread(&ThreadScriptCheck); } - // Deterministic randomness for tests. - g_connman = std::unique_ptr(new CConnman(config, 0x1337, 0x1337)); - connman = g_connman.get(); - peerLogic.reset( - new PeerLogicValidation(connman, scheduler, /*enable_bip61=*/true)); + g_connman = std::make_unique(config, 0x1337, 0x1337); } TestingSetup::~TestingSetup() { @@ -139,7 +125,6 @@ GetMainSignals().FlushBackgroundCallbacks(); GetMainSignals().UnregisterBackgroundSignalScheduler(); g_connman.reset(); - peerLogic.reset(); UnloadBlockIndex(); pcoinsTip.reset(); pcoinsdbview.reset();