Branch data Line data Source code
# 1 : : // Copyright (c) 2011-2020 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : // Unit tests for denial-of-service detection/prevention code
# 6 : :
# 7 : : #include <arith_uint256.h>
# 8 : : #include <banman.h>
# 9 : : #include <chainparams.h>
# 10 : : #include <net.h>
# 11 : : #include <net_processing.h>
# 12 : : #include <pubkey.h>
# 13 : : #include <script/sign.h>
# 14 : : #include <script/signingprovider.h>
# 15 : : #include <script/standard.h>
# 16 : : #include <serialize.h>
# 17 : : #include <txorphanage.h>
# 18 : : #include <util/string.h>
# 19 : : #include <util/system.h>
# 20 : : #include <util/time.h>
# 21 : : #include <validation.h>
# 22 : :
# 23 : : #include <test/util/setup_common.h>
# 24 : :
# 25 : : #include <array>
# 26 : : #include <stdint.h>
# 27 : :
# 28 : : #include <boost/test/unit_test.hpp>
# 29 : :
# 30 : : struct CConnmanTest : public CConnman {
# 31 : : using CConnman::CConnman;
# 32 : : void AddNode(CNode& node)
# 33 : 24 : {
# 34 : 24 : LOCK(cs_vNodes);
# 35 : 24 : vNodes.push_back(&node);
# 36 : 24 : }
# 37 : : void ClearNodes()
# 38 : 4 : {
# 39 : 4 : LOCK(cs_vNodes);
# 40 [ + + ]: 24 : for (CNode* node : vNodes) {
# 41 : 24 : delete node;
# 42 : 24 : }
# 43 : 4 : vNodes.clear();
# 44 : 4 : }
# 45 : : };
# 46 : :
# 47 : : static CService ip(uint32_t i)
# 48 : 28 : {
# 49 : 28 : struct in_addr s;
# 50 : 28 : s.s_addr = i;
# 51 : 28 : return CService(CNetAddr(s), Params().GetDefaultPort());
# 52 : 28 : }
# 53 : :
# 54 : : static NodeId id = 0;
# 55 : :
# 56 : : void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds);
# 57 : :
# 58 : : BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
# 59 : :
# 60 : : // Test eviction of an outbound peer whose chain never advances
# 61 : : // Mock a node connection, and use mocktime to simulate a peer
# 62 : : // which never sends any headers messages. PeerLogic should
# 63 : : // decide to evict that outbound peer, after the appropriate timeouts.
# 64 : : // Note that we protect 4 outbound nodes from being subject to
# 65 : : // this logic; this test takes advantage of that protection only
# 66 : : // being applied to nodes which send headers with sufficient
# 67 : : // work.
# 68 : : BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
# 69 : 2 : {
# 70 : 2 : const CChainParams& chainparams = Params();
# 71 : 2 : auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
# 72 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
# 73 : 2 : *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
# 74 : :
# 75 : : // Mock an outbound peer
# 76 : 2 : CAddress addr1(ip(0xa0b0c001), NODE_NONE);
# 77 : 2 : CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr1, /* nKeyedNetGroupIn */ 0, /* nLocalHostNonceIn */ 0, CAddress(), /* pszDest */ "", ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false);
# 78 : 2 : dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
# 79 : :
# 80 : 2 : peerLogic->InitializeNode(&dummyNode1);
# 81 : 2 : dummyNode1.fSuccessfullyConnected = true;
# 82 : :
# 83 : : // This test requires that we have a chain with non-zero work.
# 84 : 2 : {
# 85 : 2 : LOCK(cs_main);
# 86 : 2 : BOOST_CHECK(::ChainActive().Tip() != nullptr);
# 87 : 2 : BOOST_CHECK(::ChainActive().Tip()->nChainWork > 0);
# 88 : 2 : }
# 89 : :
# 90 : : // Test starts here
# 91 : 2 : {
# 92 : 2 : LOCK(dummyNode1.cs_sendProcessing);
# 93 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
# 94 : 2 : }
# 95 : 2 : {
# 96 : 2 : LOCK(dummyNode1.cs_vSend);
# 97 : 2 : BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
# 98 : 2 : dummyNode1.vSendMsg.clear();
# 99 : 2 : }
# 100 : :
# 101 : 2 : int64_t nStartTime = GetTime();
# 102 : : // Wait 21 minutes
# 103 : 2 : SetMockTime(nStartTime+21*60);
# 104 : 2 : {
# 105 : 2 : LOCK(dummyNode1.cs_sendProcessing);
# 106 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
# 107 : 2 : }
# 108 : 2 : {
# 109 : 2 : LOCK(dummyNode1.cs_vSend);
# 110 : 2 : BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
# 111 : 2 : }
# 112 : : // Wait 3 more minutes
# 113 : 2 : SetMockTime(nStartTime+24*60);
# 114 : 2 : {
# 115 : 2 : LOCK(dummyNode1.cs_sendProcessing);
# 116 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect
# 117 : 2 : }
# 118 : 2 : BOOST_CHECK(dummyNode1.fDisconnect == true);
# 119 : :
# 120 : 2 : peerLogic->FinalizeNode(dummyNode1);
# 121 : 2 : }
# 122 : :
# 123 : : static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman)
# 124 : 18 : {
# 125 : 18 : CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
# 126 : 18 : vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr, /* nKeyedNetGroupIn */ 0, /* nLocalHostNonceIn */ 0, CAddress(), /* pszDest */ "", ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false));
# 127 : 18 : CNode &node = *vNodes.back();
# 128 : 18 : node.SetCommonVersion(PROTOCOL_VERSION);
# 129 : :
# 130 : 18 : peerLogic.InitializeNode(&node);
# 131 : 18 : node.fSuccessfullyConnected = true;
# 132 : :
# 133 : 18 : connman->AddNode(node);
# 134 : 18 : }
# 135 : :
# 136 : : BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
# 137 : 2 : {
# 138 : 2 : const CChainParams& chainparams = Params();
# 139 : 2 : auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman);
# 140 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
# 141 : 2 : *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
# 142 : :
# 143 : 2 : constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
# 144 : 2 : CConnman::Options options;
# 145 : 2 : options.nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
# 146 : 2 : options.m_max_outbound_full_relay = max_outbound_full_relay;
# 147 : 2 : options.nMaxFeeler = MAX_FEELER_CONNECTIONS;
# 148 : :
# 149 : 2 : connman->Init(options);
# 150 : 2 : std::vector<CNode *> vNodes;
# 151 : :
# 152 : : // Mock some outbound peers
# 153 [ + + ]: 18 : for (int i=0; i<max_outbound_full_relay; ++i) {
# 154 : 16 : AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
# 155 : 16 : }
# 156 : :
# 157 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 158 : :
# 159 : : // No nodes should be marked for disconnection while we have no extra peers
# 160 [ + + ]: 16 : for (const CNode *node : vNodes) {
# 161 : 16 : BOOST_CHECK(node->fDisconnect == false);
# 162 : 16 : }
# 163 : :
# 164 : 2 : SetMockTime(GetTime() + 3 * chainparams.GetConsensus().nPowTargetSpacing + 1);
# 165 : :
# 166 : : // Now tip should definitely be stale, and we should look for an extra
# 167 : : // outbound peer
# 168 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 169 : 2 : BOOST_CHECK(connman->GetTryNewOutboundPeer());
# 170 : :
# 171 : : // Still no peers should be marked for disconnection
# 172 [ + + ]: 16 : for (const CNode *node : vNodes) {
# 173 : 16 : BOOST_CHECK(node->fDisconnect == false);
# 174 : 16 : }
# 175 : :
# 176 : : // If we add one more peer, something should get marked for eviction
# 177 : : // on the next check (since we're mocking the time to be in the future, the
# 178 : : // required time connected check should be satisfied).
# 179 : 2 : AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
# 180 : :
# 181 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 182 [ + + ]: 18 : for (int i = 0; i < max_outbound_full_relay; ++i) {
# 183 : 16 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 184 : 16 : }
# 185 : : // Last added node should get marked for eviction
# 186 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == true);
# 187 : :
# 188 : 2 : vNodes.back()->fDisconnect = false;
# 189 : :
# 190 : : // Update the last announced block time for the last
# 191 : : // peer, and check that the next newest node gets evicted.
# 192 : 2 : UpdateLastBlockAnnounceTime(vNodes.back()->GetId(), GetTime());
# 193 : :
# 194 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 195 [ + + ]: 16 : for (int i = 0; i < max_outbound_full_relay - 1; ++i) {
# 196 : 14 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 197 : 14 : }
# 198 : 2 : BOOST_CHECK(vNodes[max_outbound_full_relay-1]->fDisconnect == true);
# 199 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == false);
# 200 : :
# 201 [ + + ]: 18 : for (const CNode *node : vNodes) {
# 202 : 18 : peerLogic->FinalizeNode(*node);
# 203 : 18 : }
# 204 : :
# 205 : 2 : connman->ClearNodes();
# 206 : 2 : }
# 207 : :
# 208 : : BOOST_AUTO_TEST_CASE(peer_discouragement)
# 209 : 2 : {
# 210 : 2 : const CChainParams& chainparams = Params();
# 211 : 2 : auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
# 212 : 2 : auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman);
# 213 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
# 214 : 2 : *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
# 215 : :
# 216 : 2 : CNetAddr tor_netaddr;
# 217 : 2 : BOOST_REQUIRE(
# 218 : 2 : tor_netaddr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
# 219 : 2 : const CService tor_service{tor_netaddr, Params().GetDefaultPort()};
# 220 : :
# 221 : 2 : const std::array<CAddress, 3> addr{CAddress{ip(0xa0b0c001), NODE_NONE},
# 222 : 2 : CAddress{ip(0xa0b0c002), NODE_NONE},
# 223 : 2 : CAddress{tor_service, NODE_NONE}};
# 224 : :
# 225 : 2 : const CNetAddr other_addr{ip(0xa0b0ff01)}; // Not any of addr[].
# 226 : :
# 227 : 2 : std::array<CNode*, 3> nodes;
# 228 : :
# 229 : 2 : banman->ClearBanned();
# 230 : 2 : nodes[0] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[0], /* nKeyedNetGroupIn */ 0,
# 231 : 2 : /* nLocalHostNonceIn */ 0, CAddress(), /* pszDest */ "",
# 232 : 2 : ConnectionType::INBOUND, /* inbound_onion */ false};
# 233 : 2 : nodes[0]->SetCommonVersion(PROTOCOL_VERSION);
# 234 : 2 : peerLogic->InitializeNode(nodes[0]);
# 235 : 2 : nodes[0]->fSuccessfullyConnected = true;
# 236 : 2 : connman->AddNode(*nodes[0]);
# 237 : 2 : peerLogic->Misbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ ""); // Should be discouraged
# 238 : 2 : {
# 239 : 2 : LOCK(nodes[0]->cs_sendProcessing);
# 240 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[0]));
# 241 : 2 : }
# 242 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 243 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 244 : 2 : BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged
# 245 : :
# 246 : 2 : nodes[1] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[1], /* nKeyedNetGroupIn */ 1,
# 247 : 2 : /* nLocalHostNonceIn */ 1, CAddress(), /* pszDest */ "",
# 248 : 2 : ConnectionType::INBOUND, /* inbound_onion */ false};
# 249 : 2 : nodes[1]->SetCommonVersion(PROTOCOL_VERSION);
# 250 : 2 : peerLogic->InitializeNode(nodes[1]);
# 251 : 2 : nodes[1]->fSuccessfullyConnected = true;
# 252 : 2 : connman->AddNode(*nodes[1]);
# 253 : 2 : peerLogic->Misbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1, /* message */ "");
# 254 : 2 : {
# 255 : 2 : LOCK(nodes[1]->cs_sendProcessing);
# 256 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
# 257 : 2 : }
# 258 : : // [0] is still discouraged/disconnected.
# 259 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 260 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 261 : : // [1] is not discouraged/disconnected yet.
# 262 : 2 : BOOST_CHECK(!banman->IsDiscouraged(addr[1]));
# 263 : 2 : BOOST_CHECK(!nodes[1]->fDisconnect);
# 264 : 2 : peerLogic->Misbehaving(nodes[1]->GetId(), 1, /* message */ ""); // [1] reaches discouragement threshold
# 265 : 2 : {
# 266 : 2 : LOCK(nodes[1]->cs_sendProcessing);
# 267 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
# 268 : 2 : }
# 269 : : // Expect both [0] and [1] to be discouraged/disconnected now.
# 270 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 271 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 272 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[1]));
# 273 : 2 : BOOST_CHECK(nodes[1]->fDisconnect);
# 274 : :
# 275 : : // Make sure non-IP peers are discouraged and disconnected properly.
# 276 : :
# 277 : 2 : nodes[2] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[2], /* nKeyedNetGroupIn */ 1,
# 278 : 2 : /* nLocalHostNonceIn */ 1, CAddress(), /* pszDest */ "",
# 279 : 2 : ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false};
# 280 : 2 : nodes[2]->SetCommonVersion(PROTOCOL_VERSION);
# 281 : 2 : peerLogic->InitializeNode(nodes[2]);
# 282 : 2 : nodes[2]->fSuccessfullyConnected = true;
# 283 : 2 : connman->AddNode(*nodes[2]);
# 284 : 2 : peerLogic->Misbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ "");
# 285 : 2 : {
# 286 : 2 : LOCK(nodes[2]->cs_sendProcessing);
# 287 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[2]));
# 288 : 2 : }
# 289 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 290 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[1]));
# 291 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[2]));
# 292 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 293 : 2 : BOOST_CHECK(nodes[1]->fDisconnect);
# 294 : 2 : BOOST_CHECK(nodes[2]->fDisconnect);
# 295 : :
# 296 [ + + ]: 6 : for (CNode* node : nodes) {
# 297 : 6 : peerLogic->FinalizeNode(*node);
# 298 : 6 : }
# 299 : 2 : connman->ClearNodes();
# 300 : 2 : }
# 301 : :
# 302 : : BOOST_AUTO_TEST_CASE(DoS_bantime)
# 303 : 2 : {
# 304 : 2 : const CChainParams& chainparams = Params();
# 305 : 2 : auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
# 306 : 2 : auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
# 307 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
# 308 : 2 : *m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
# 309 : :
# 310 : 2 : banman->ClearBanned();
# 311 : 2 : int64_t nStartTime = GetTime();
# 312 : 2 : SetMockTime(nStartTime); // Overrides future calls to GetTime()
# 313 : :
# 314 : 2 : CAddress addr(ip(0xa0b0c001), NODE_NONE);
# 315 : 2 : CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, /* nKeyedNetGroupIn */ 4, /* nLocalHostNonceIn */ 4, CAddress(), /* pszDest */ "", ConnectionType::INBOUND, /* inbound_onion */ false);
# 316 : 2 : dummyNode.SetCommonVersion(PROTOCOL_VERSION);
# 317 : 2 : peerLogic->InitializeNode(&dummyNode);
# 318 : 2 : dummyNode.fSuccessfullyConnected = true;
# 319 : :
# 320 : 2 : peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ "");
# 321 : 2 : {
# 322 : 2 : LOCK(dummyNode.cs_sendProcessing);
# 323 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
# 324 : 2 : }
# 325 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr));
# 326 : :
# 327 : 2 : peerLogic->FinalizeNode(dummyNode);
# 328 : 2 : }
# 329 : :
# 330 : : class TxOrphanageTest : public TxOrphanage
# 331 : : {
# 332 : : public:
# 333 : : inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
# 334 : 18 : {
# 335 : 18 : return m_orphans.size();
# 336 : 18 : }
# 337 : :
# 338 : : CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
# 339 : 120 : {
# 340 : 120 : std::map<uint256, OrphanTx>::iterator it;
# 341 : 120 : it = m_orphans.lower_bound(InsecureRand256());
# 342 [ - + ]: 120 : if (it == m_orphans.end())
# 343 : 0 : it = m_orphans.begin();
# 344 : 120 : return it->second.tx;
# 345 : 120 : }
# 346 : : };
# 347 : :
# 348 : : static void MakeNewKeyWithFastRandomContext(CKey& key)
# 349 : 2 : {
# 350 : 2 : std::vector<unsigned char> keydata;
# 351 : 2 : keydata = g_insecure_rand_ctx.randbytes(32);
# 352 : 2 : key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn*/ true);
# 353 : 2 : assert(key.IsValid());
# 354 : 2 : }
# 355 : :
# 356 : : BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
# 357 : 2 : {
# 358 : : // This test had non-deterministic coverage due to
# 359 : : // randomly selected seeds.
# 360 : : // This seed is chosen so that all branches of the function
# 361 : : // ecdsa_signature_parse_der_lax are executed during this test.
# 362 : : // Specifically branches that run only when an ECDSA
# 363 : : // signature's R and S values have leading zeros.
# 364 : 2 : g_insecure_rand_ctx = FastRandomContext(ArithToUint256(arith_uint256(33)));
# 365 : :
# 366 : 2 : TxOrphanageTest orphanage;
# 367 : 2 : CKey key;
# 368 : 2 : MakeNewKeyWithFastRandomContext(key);
# 369 : 2 : FillableSigningProvider keystore;
# 370 : 2 : BOOST_CHECK(keystore.AddKey(key));
# 371 : :
# 372 : 2 : LOCK(g_cs_orphans);
# 373 : :
# 374 : : // 50 orphan transactions:
# 375 [ + + ]: 102 : for (int i = 0; i < 50; i++)
# 376 : 100 : {
# 377 : 100 : CMutableTransaction tx;
# 378 : 100 : tx.vin.resize(1);
# 379 : 100 : tx.vin[0].prevout.n = 0;
# 380 : 100 : tx.vin[0].prevout.hash = InsecureRand256();
# 381 : 100 : tx.vin[0].scriptSig << OP_1;
# 382 : 100 : tx.vout.resize(1);
# 383 : 100 : tx.vout[0].nValue = 1*CENT;
# 384 : 100 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
# 385 : :
# 386 : 100 : orphanage.AddTx(MakeTransactionRef(tx), i);
# 387 : 100 : }
# 388 : :
# 389 : : // ... and 50 that depend on other orphans:
# 390 [ + + ]: 102 : for (int i = 0; i < 50; i++)
# 391 : 100 : {
# 392 : 100 : CTransactionRef txPrev = orphanage.RandomOrphan();
# 393 : :
# 394 : 100 : CMutableTransaction tx;
# 395 : 100 : tx.vin.resize(1);
# 396 : 100 : tx.vin[0].prevout.n = 0;
# 397 : 100 : tx.vin[0].prevout.hash = txPrev->GetHash();
# 398 : 100 : tx.vout.resize(1);
# 399 : 100 : tx.vout[0].nValue = 1*CENT;
# 400 : 100 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
# 401 : 100 : BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
# 402 : :
# 403 : 100 : orphanage.AddTx(MakeTransactionRef(tx), i);
# 404 : 100 : }
# 405 : :
# 406 : : // This really-big orphan should be ignored:
# 407 [ + + ]: 22 : for (int i = 0; i < 10; i++)
# 408 : 20 : {
# 409 : 20 : CTransactionRef txPrev = orphanage.RandomOrphan();
# 410 : :
# 411 : 20 : CMutableTransaction tx;
# 412 : 20 : tx.vout.resize(1);
# 413 : 20 : tx.vout[0].nValue = 1*CENT;
# 414 : 20 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
# 415 : 20 : tx.vin.resize(2777);
# 416 [ + + ]: 55560 : for (unsigned int j = 0; j < tx.vin.size(); j++)
# 417 : 55540 : {
# 418 : 55540 : tx.vin[j].prevout.n = j;
# 419 : 55540 : tx.vin[j].prevout.hash = txPrev->GetHash();
# 420 : 55540 : }
# 421 : 20 : BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
# 422 : : // Re-use same signature for other inputs
# 423 : : // (they don't have to be valid for this test)
# 424 [ + + ]: 55540 : for (unsigned int j = 1; j < tx.vin.size(); j++)
# 425 : 55520 : tx.vin[j].scriptSig = tx.vin[0].scriptSig;
# 426 : :
# 427 : 20 : BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
# 428 : 20 : }
# 429 : :
# 430 : : // Test EraseOrphansFor:
# 431 [ + + ]: 8 : for (NodeId i = 0; i < 3; i++)
# 432 : 6 : {
# 433 : 6 : size_t sizeBefore = orphanage.CountOrphans();
# 434 : 6 : orphanage.EraseForPeer(i);
# 435 : 6 : BOOST_CHECK(orphanage.CountOrphans() < sizeBefore);
# 436 : 6 : }
# 437 : :
# 438 : : // Test LimitOrphanTxSize() function:
# 439 : 2 : orphanage.LimitOrphans(40);
# 440 : 2 : BOOST_CHECK(orphanage.CountOrphans() <= 40);
# 441 : 2 : orphanage.LimitOrphans(10);
# 442 : 2 : BOOST_CHECK(orphanage.CountOrphans() <= 10);
# 443 : 2 : orphanage.LimitOrphans(0);
# 444 : 2 : BOOST_CHECK(orphanage.CountOrphans() == 0);
# 445 : 2 : }
# 446 : :
# 447 : : BOOST_AUTO_TEST_SUITE_END()
|