aboutsummaryrefslogtreecommitdiff
path: root/src/test/DoS_tests.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2017-11-03 15:32:02 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2017-11-03 15:42:50 -0700
commitf518d9ae6aa525c4cd360a16f07a9272cbef558d (patch)
tree335ee53ff19753f10dfd40b42570e0419701e183 /src/test/DoS_tests.cpp
parentf224cbc3d8f4478d30e121126658c2ab22c6fb90 (diff)
parent8195cb0d7fc4f8699b35aff7a43ed2fb3013608c (diff)
downloadbitcoin-f518d9ae6aa525c4cd360a16f07a9272cbef558d.tar.xz
Merge #11592: 0.15: Backportsv0.15.1rc1
8195cb0d7 rpc: further constrain the libevent workaround (Cory Fields) 34153a7e4 rpc: work-around an upstream libevent bug (Cory Fields) fc308a6cd Add unit test for stale tip checking (Suhas Daftuar) 2ed0647ac Add CConnmanTest to mutate g_connman in tests (João Barbosa) a607a95d8 Connect to an extra outbound peer if our tip is stale (Suhas Daftuar) 459f2db42 Track tip update time and last new block announcement from each peer (Suhas Daftuar) 49bf09018 net: Allow connecting to extra outbound peers (Suhas Daftuar) bb83fe190 Add release notes describing blockmaxweight deprecation (Matt Corallo) 4c82cea99 Use a sensible default for blockmaxweight (Matt Corallo) 7871a7d3b Deprecate confusing blockmaxsize, fix getmininginfo output (Matt Corallo) 6baa317b5 Fix minchainwork test for 0.15 backport (Suhas Daftuar) 55b7abfa8 Make p2p-acceptablock not an extended test (Matt Corallo) 5bec7744d [qa] test that invalid blocks on an invalid chain get a disconnect (Matt Corallo) 92d6105c4 Reject headers building on invalid chains by tracking invalidity (Matt Corallo) 51001d684 Accept unrequested blocks with work equal to our tip (Matt Corallo) c6e4d0ce8 Stop always storing blocks from whitelisted peers (Matt Corallo) e976c36dd Rewrite p2p-acceptblock in preparation for slight behavior changes (Matt Corallo) ec8dedff4 net: Add missing lock in ProcessHeadersMessage(...) (practicalswift) 59b210d9a Disconnect outbound peers relaying invalid headers (Suhas Daftuar) fc966bbd2 moveonly: factor out headers processing into separate function (Suhas Daftuar) e3272242e Add unit test for outbound peer eviction (Suhas Daftuar) 9961abf9e Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar) bf191a718 Disconnecting from bad outbound peers in IBD (Suhas Daftuar) d570aa429 Fix uninitialized g_connman crash in Shutdown() (MeshCollider) 0a5477c7e net: stop both net/net_processing before destroying them (Cory Fields) b4136f21c net: drop unused connman param (Cory Fields) dc897e53d net: use an interface class rather than signals for message processing (Cory Fields) 8aee55af3 net: pass CConnman via pointer rather than reference (Cory Fields) 6f279652b Rename fAddnode to a more-descriptive "manual_connection" (Matt Corallo) ffb6ea4e5 Add comment explaining forced processing of compact blocks (Suhas Daftuar) 2df65eeb9 qa: add test for minchainwork use in acceptblock (Suhas Daftuar) 3acec3878 Don't process unrequested, low-work blocks (Suhas Daftuar) 0e9d04bf0 [qa] Test nMinimumChainWork (Suhas Daftuar) da4908c3a Allow setting nMinimumChainWork on command line (Suhas Daftuar) 41088795d qa: Remove never used return value of sync_with_ping (MarcoFalke) f3457d0e8 qa: Make tmpdir option an absolute path (MarcoFalke) 9c8006dc3 Avoid opening copied wallet databases simultaneously (Russell Yanofsky) de7053f11 [wallet] Fix leak in CDB constructor (João Barbosa) fd79ed6b2 Ensure backupwallet fails when attempting to backup to source file (Tomas van der Wansem) d94fc336c scripted-diff: rename assert_raises_jsonrpc to assert_raises_rpc error (John Newbery) 623de0acb [tests] do not allow assert_raises_message to be called with JSONRPCException (John Newbery) 5b728c8e9 [tests] remove direct testing on JSONRPCException from individual test cases (John Newbery) Pull request description: Tree-SHA512: 9fdb5c47844a899271023d8d445f7fc728e3ad71916490cd9783464684967594b07cda05dd644b722bfcea9fade74d06cfc501e1a68abf118d6d03fbbf7d7707
Diffstat (limited to 'src/test/DoS_tests.cpp')
-rw-r--r--src/test/DoS_tests.cpp162
1 files changed, 151 insertions, 11 deletions
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index ffbeeb7d91..d1f9e63ecf 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -40,8 +40,138 @@ CService ip(uint32_t i)
static NodeId id = 0;
+void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds);
+
BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup)
+// Test eviction of an outbound peer whose chain never advances
+// Mock a node connection, and use mocktime to simulate a peer
+// which never sends any headers messages. PeerLogic should
+// decide to evict that outbound peer, after the appropriate timeouts.
+// Note that we protect 4 outbound nodes from being subject to
+// this logic; this test takes advantage of that protection only
+// being applied to nodes which send headers with sufficient
+// work.
+BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
+{
+ std::atomic<bool> interruptDummy(false);
+
+ // Mock an outbound peer
+ CAddress addr1(ip(0xa0b0c001), NODE_NONE);
+ CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", /*fInboundIn=*/ false);
+ dummyNode1.SetSendVersion(PROTOCOL_VERSION);
+
+ peerLogic->InitializeNode(&dummyNode1);
+ dummyNode1.nVersion = 1;
+ dummyNode1.fSuccessfullyConnected = true;
+
+ // This test requires that we have a chain with non-zero work.
+ BOOST_CHECK(chainActive.Tip() != nullptr);
+ BOOST_CHECK(chainActive.Tip()->nChainWork > 0);
+
+ // Test starts here
+ peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders
+ BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
+ dummyNode1.vSendMsg.clear();
+
+ int64_t nStartTime = GetTime();
+ // Wait 21 minutes
+ SetMockTime(nStartTime+21*60);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders
+ BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
+ // Wait 3 more minutes
+ SetMockTime(nStartTime+24*60);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in disconnect
+ BOOST_CHECK(dummyNode1.fDisconnect == true);
+ SetMockTime(0);
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
+}
+
+void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
+{
+ CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE);
+ vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false));
+ CNode &node = *vNodes.back();
+ node.SetSendVersion(PROTOCOL_VERSION);
+
+ peerLogic.InitializeNode(&node);
+ node.nVersion = 1;
+ node.fSuccessfullyConnected = true;
+
+ CConnmanTest::AddNode(node);
+}
+
+BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
+{
+ const Consensus::Params& consensusParams = Params().GetConsensus();
+ constexpr int nMaxOutbound = 8;
+ CConnman::Options options;
+ options.nMaxConnections = 125;
+ options.nMaxOutbound = nMaxOutbound;
+ options.nMaxFeeler = 1;
+
+ connman->Init(options);
+ std::vector<CNode *> vNodes;
+
+ // Mock some outbound peers
+ for (int i=0; i<nMaxOutbound; ++i) {
+ AddRandomOutboundPeer(vNodes, *peerLogic);
+ }
+
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+
+ // No nodes should be marked for disconnection while we have no extra peers
+ for (const CNode *node : vNodes) {
+ BOOST_CHECK(node->fDisconnect == false);
+ }
+
+ SetMockTime(GetTime() + 3*consensusParams.nPowTargetSpacing + 1);
+
+ // Now tip should definitely be stale, and we should look for an extra
+ // outbound peer
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+ BOOST_CHECK(connman->GetTryNewOutboundPeer());
+
+ // Still no peers should be marked for disconnection
+ 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(vNodes, *peerLogic);
+
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+ for (int i=0; i<nMaxOutbound; ++i) {
+ BOOST_CHECK(vNodes[i]->fDisconnect == false);
+ }
+ // Last added node should get marked for eviction
+ BOOST_CHECK(vNodes.back()->fDisconnect == true);
+
+ vNodes.back()->fDisconnect = false;
+
+ // Update the last announced block time for the last
+ // peer, and check that the next newest node gets evicted.
+ UpdateLastBlockAnnounceTime(vNodes.back()->GetId(), GetTime());
+
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+ for (int i=0; i<nMaxOutbound-1; ++i) {
+ BOOST_CHECK(vNodes[i]->fDisconnect == false);
+ }
+ BOOST_CHECK(vNodes[nMaxOutbound-1]->fDisconnect == true);
+ BOOST_CHECK(vNodes.back()->fDisconnect == false);
+
+ bool dummy;
+ for (const CNode *node : vNodes) {
+ peerLogic->FinalizeNode(node->GetId(), dummy);
+ }
+
+ CConnmanTest::ClearNodes();
+}
+
BOOST_AUTO_TEST_CASE(DoS_banning)
{
std::atomic<bool> interruptDummy(false);
@@ -50,27 +180,31 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode1, *connman);
+ peerLogic->InitializeNode(&dummyNode1);
dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
Misbehaving(dummyNode1.GetId(), 100); // Should get banned
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr1));
BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
dummyNode2.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode2, *connman);
+ peerLogic->InitializeNode(&dummyNode2);
dummyNode2.nVersion = 1;
dummyNode2.fSuccessfullyConnected = true;
Misbehaving(dummyNode2.GetId(), 50);
- SendMessages(&dummyNode2, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode2, interruptDummy);
BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
Misbehaving(dummyNode2.GetId(), 50);
- SendMessages(&dummyNode2, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode2, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr2));
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
+ peerLogic->FinalizeNode(dummyNode2.GetId(), dummy);
}
BOOST_AUTO_TEST_CASE(DoS_banscore)
@@ -82,19 +216,22 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode1, *connman);
+ peerLogic->InitializeNode(&dummyNode1);
dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
Misbehaving(dummyNode1.GetId(), 100);
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(!connman->IsBanned(addr1));
Misbehaving(dummyNode1.GetId(), 10);
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(!connman->IsBanned(addr1));
Misbehaving(dummyNode1.GetId(), 1);
- SendMessages(&dummyNode1, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr1));
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
}
BOOST_AUTO_TEST_CASE(DoS_bantime)
@@ -108,12 +245,12 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CAddress addr(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true);
dummyNode.SetSendVersion(PROTOCOL_VERSION);
- GetNodeSignals().InitializeNode(&dummyNode, *connman);
+ peerLogic->InitializeNode(&dummyNode);
dummyNode.nVersion = 1;
dummyNode.fSuccessfullyConnected = true;
Misbehaving(dummyNode.GetId(), 100);
- SendMessages(&dummyNode, *connman, interruptDummy);
+ peerLogic->SendMessages(&dummyNode, interruptDummy);
BOOST_CHECK(connman->IsBanned(addr));
SetMockTime(nStartTime+60*60);
@@ -121,6 +258,9 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
SetMockTime(nStartTime+60*60*24+1);
BOOST_CHECK(!connman->IsBanned(addr));
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
}
CTransactionRef RandomOrphan()