2015-12-13 14:51:43 +01:00
|
|
|
// Copyright (c) 2011-2015 The Bitcoin Core developers
|
2014-12-13 05:09:33 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2014-03-18 10:11:00 +01:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2011-09-06 22:09:04 +02:00
|
|
|
// Unit tests for denial-of-service detection/prevention code
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
#include <banman.h>
|
2020-03-19 23:46:56 +01:00
|
|
|
#include <chainparams.h>
|
|
|
|
#include <keystore.h>
|
|
|
|
#include <net.h>
|
|
|
|
#include <net_processing.h>
|
|
|
|
#include <pow.h>
|
|
|
|
#include <script/sign.h>
|
|
|
|
#include <serialize.h>
|
2021-06-27 08:33:13 +02:00
|
|
|
#include <util/system.h>
|
2020-03-19 23:46:56 +01:00
|
|
|
#include <validation.h>
|
|
|
|
|
|
|
|
#include <test/test_dash.h>
|
2015-03-03 16:49:12 +01:00
|
|
|
|
2012-01-03 23:33:31 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-02-16 14:01:00 +01:00
|
|
|
// Tests these internal-to-net_processing.cpp methods:
|
2017-01-04 12:22:49 +01:00
|
|
|
extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
|
2014-08-28 19:23:24 +02:00
|
|
|
extern void EraseOrphansFor(NodeId peer);
|
2012-04-23 20:14:03 +02:00
|
|
|
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
|
2020-04-16 00:17:05 +02:00
|
|
|
// We don't need this, since we kept declaration in net_processing.h when backporting (#13417)
|
|
|
|
// extern void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="");
|
2018-07-14 05:07:19 +02:00
|
|
|
|
2014-09-20 09:53:50 +02:00
|
|
|
struct COrphanTx {
|
2017-01-04 12:22:49 +01:00
|
|
|
CTransactionRef tx;
|
2014-09-20 09:53:50 +02:00
|
|
|
NodeId fromPeer;
|
2016-12-05 11:09:19 +01:00
|
|
|
int64_t nTimeExpire;
|
2014-09-20 09:53:50 +02:00
|
|
|
};
|
2018-08-31 14:32:29 +02:00
|
|
|
extern CCriticalSection g_cs_orphans;
|
|
|
|
extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
|
2012-02-29 16:14:18 +01:00
|
|
|
|
2018-05-04 22:42:39 +02:00
|
|
|
static CService ip(uint32_t i)
|
2012-01-03 23:33:31 +01:00
|
|
|
{
|
|
|
|
struct in_addr s;
|
|
|
|
s.s_addr = i;
|
2013-05-07 15:16:25 +02:00
|
|
|
return CService(CNetAddr(s), Params().GetDefaultPort());
|
2012-01-03 23:33:31 +01:00
|
|
|
}
|
2011-09-06 22:09:04 +02:00
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
static NodeId id = 0;
|
|
|
|
|
2017-11-02 20:13:17 +01:00
|
|
|
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds);
|
|
|
|
|
2018-06-12 14:02:14 +02:00
|
|
|
BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
|
2011-09-06 22:09:04 +02:00
|
|
|
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
// 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)
|
|
|
|
{
|
2019-01-21 18:45:59 +01:00
|
|
|
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
|
|
|
|
auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
|
|
|
|
// Mock an outbound peer
|
|
|
|
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
2019-09-25 12:25:39 +02:00
|
|
|
CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", /*fInboundIn=*/ false);
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
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.
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
BOOST_CHECK(chainActive.Tip() != nullptr);
|
|
|
|
BOOST_CHECK(chainActive.Tip()->nChainWork > 0);
|
|
|
|
}
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
|
|
|
|
// Test starts here
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode1.cs_vSend);
|
2018-06-27 12:30:00 +02:00
|
|
|
BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
|
|
|
|
dummyNode1.vSendMsg.clear();
|
|
|
|
dummyNode1.nSendMsgSize = 0;
|
|
|
|
}
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
|
|
|
|
int64_t nStartTime = GetTime();
|
|
|
|
// Wait 21 minutes
|
|
|
|
SetMockTime(nStartTime+21*60);
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode1.cs_vSend);
|
2018-06-27 12:30:00 +02:00
|
|
|
BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
|
|
|
|
}
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
// Wait 3 more minutes
|
|
|
|
SetMockTime(nStartTime+24*60);
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
BOOST_CHECK(dummyNode1.fDisconnect == true);
|
|
|
|
SetMockTime(0);
|
|
|
|
|
|
|
|
bool dummy;
|
|
|
|
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
|
|
|
|
}
|
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman)
|
2017-11-02 20:13:17 +01:00
|
|
|
{
|
2018-12-13 22:44:26 +01:00
|
|
|
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
|
2019-09-25 12:25:39 +02:00
|
|
|
vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false));
|
2017-11-02 20:13:17 +01:00
|
|
|
CNode &node = *vNodes.back();
|
|
|
|
node.SetSendVersion(PROTOCOL_VERSION);
|
|
|
|
|
|
|
|
peerLogic.InitializeNode(&node);
|
|
|
|
node.nVersion = 1;
|
|
|
|
node.fSuccessfullyConnected = true;
|
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
connman->AddNode(node);
|
2017-11-02 20:13:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
|
|
|
|
{
|
2019-01-21 18:45:59 +01:00
|
|
|
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
|
|
|
|
auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
|
|
|
|
|
2017-11-02 20:13:17 +01:00
|
|
|
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) {
|
2019-01-21 18:45:59 +01:00
|
|
|
AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
|
2017-11-02 20:13:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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).
|
2019-01-21 18:45:59 +01:00
|
|
|
AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
|
2017-11-02 20:13:17 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
connman->ClearNodes();
|
2017-11-02 20:13:17 +01:00
|
|
|
}
|
|
|
|
|
2011-09-06 22:09:04 +02:00
|
|
|
BOOST_AUTO_TEST_CASE(DoS_banning)
|
|
|
|
{
|
2019-01-21 18:45:59 +01:00
|
|
|
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
|
|
|
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
|
|
|
|
auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
|
2017-08-09 18:06:31 +02:00
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
banman->ClearBanned();
|
2017-07-05 05:45:23 +02:00
|
|
|
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
2017-06-05 15:39:11 +02:00
|
|
|
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
|
2017-07-27 16:28:05 +02:00
|
|
|
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
|
2017-09-08 01:00:49 +02:00
|
|
|
peerLogic->InitializeNode(&dummyNode1);
|
2013-11-18 01:25:17 +01:00
|
|
|
dummyNode1.nVersion = 1;
|
2017-08-17 20:37:22 +02:00
|
|
|
dummyNode1.fSuccessfullyConnected = true;
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode1.GetId(), 100); // Should get banned
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(banman->IsBanned(addr1));
|
|
|
|
BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
|
2011-09-06 22:09:04 +02:00
|
|
|
|
2017-07-05 05:45:23 +02:00
|
|
|
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
|
2017-06-05 15:39:11 +02:00
|
|
|
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
|
2017-07-27 16:28:05 +02:00
|
|
|
dummyNode2.SetSendVersion(PROTOCOL_VERSION);
|
2017-09-08 01:00:49 +02:00
|
|
|
peerLogic->InitializeNode(&dummyNode2);
|
2013-11-18 01:25:17 +01:00
|
|
|
dummyNode2.nVersion = 1;
|
2017-08-17 20:37:22 +02:00
|
|
|
dummyNode2.fSuccessfullyConnected = true;
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode2.GetId(), 50);
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode2.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(!banman->IsBanned(addr2)); // 2 not banned yet...
|
|
|
|
BOOST_CHECK(banman->IsBanned(addr1)); // ... but 1 still should be
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode2.GetId(), 50);
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode2.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(banman->IsBanned(addr2));
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
|
|
|
|
bool dummy;
|
|
|
|
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
|
|
|
|
peerLogic->FinalizeNode(dummyNode2.GetId(), dummy);
|
2012-10-05 19:22:21 +02:00
|
|
|
}
|
2011-09-06 22:09:04 +02:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(DoS_banscore)
|
|
|
|
{
|
2019-01-21 18:45:59 +01:00
|
|
|
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
|
|
|
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
|
|
|
|
auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
|
2017-08-09 18:06:31 +02:00
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
banman->ClearBanned();
|
2019-06-24 18:44:27 +02:00
|
|
|
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
|
2017-07-05 05:45:23 +02:00
|
|
|
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
2017-06-05 15:39:11 +02:00
|
|
|
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
|
2017-07-27 16:28:05 +02:00
|
|
|
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
|
2017-09-08 01:00:49 +02:00
|
|
|
peerLogic->InitializeNode(&dummyNode1);
|
2013-11-18 01:25:17 +01:00
|
|
|
dummyNode1.nVersion = 1;
|
2017-08-17 20:37:22 +02:00
|
|
|
dummyNode1.fSuccessfullyConnected = true;
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode1.GetId(), 100);
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
|
|
|
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(!banman->IsBanned(addr1));
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode1.GetId(), 10);
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
|
|
|
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(!banman->IsBanned(addr1));
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode1.GetId(), 1);
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
|
|
|
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(banman->IsBanned(addr1));
|
2019-06-24 18:44:27 +02:00
|
|
|
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
|
|
|
|
bool dummy;
|
|
|
|
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
|
2011-09-06 22:09:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(DoS_bantime)
|
|
|
|
{
|
2019-01-21 18:45:59 +01:00
|
|
|
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
|
|
|
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
|
|
|
|
auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
|
2017-08-09 18:06:31 +02:00
|
|
|
|
2019-01-21 18:45:59 +01:00
|
|
|
banman->ClearBanned();
|
2013-04-13 07:13:08 +02:00
|
|
|
int64_t nStartTime = GetTime();
|
2011-09-06 22:09:04 +02:00
|
|
|
SetMockTime(nStartTime); // Overrides future calls to GetTime()
|
|
|
|
|
2017-07-05 05:45:23 +02:00
|
|
|
CAddress addr(ip(0xa0b0c001), NODE_NONE);
|
2017-06-05 15:39:11 +02:00
|
|
|
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true);
|
2017-07-27 16:28:05 +02:00
|
|
|
dummyNode.SetSendVersion(PROTOCOL_VERSION);
|
2017-09-08 01:00:49 +02:00
|
|
|
peerLogic->InitializeNode(&dummyNode);
|
2013-11-18 01:25:17 +01:00
|
|
|
dummyNode.nVersion = 1;
|
2017-08-17 20:37:22 +02:00
|
|
|
dummyNode.fSuccessfullyConnected = true;
|
2011-09-06 22:09:04 +02:00
|
|
|
|
2017-11-10 17:52:27 +01:00
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
Misbehaving(dummyNode.GetId(), 100);
|
|
|
|
}
|
2018-06-27 12:30:00 +02:00
|
|
|
{
|
2020-07-16 13:03:34 +02:00
|
|
|
LOCK(dummyNode.cs_sendProcessing);
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
|
2018-06-27 12:30:00 +02:00
|
|
|
}
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(banman->IsBanned(addr));
|
2011-09-06 22:09:04 +02:00
|
|
|
|
|
|
|
SetMockTime(nStartTime+60*60);
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(banman->IsBanned(addr));
|
2011-09-06 22:09:04 +02:00
|
|
|
|
|
|
|
SetMockTime(nStartTime+60*60*24+1);
|
2019-01-21 18:45:59 +01:00
|
|
|
BOOST_CHECK(!banman->IsBanned(addr));
|
Merge #11490: Disconnect from outbound peers with bad headers chains
e065249 Add unit test for outbound peer eviction (Suhas Daftuar)
5a6d00c Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar)
c60fd71 Disconnecting from bad outbound peers in IBD (Suhas Daftuar)
Pull request description:
The first commit will disconnect an outbound peer that serves us a headers chain with insufficient work while we're in IBD.
The second commit introduces a way to disconnect outbound peers whose chains fall out of sync with ours:
For a given outbound peer, we check whether their best known block (which is known from the blocks they announce to us) has at least as much work as our tip. If it doesn't, we set a 20 minute timeout, and if we still haven't heard about a block with as much work as our tip had when we set the timeout, then we send a single getheaders message, and wait 2 more minutes. If after two minutes their best known block has insufficient work, we disconnect that peer.
We protect 4 of our outbound peers (who provide some "good" headers chains, ie a chain with at least as much work as our tip at some point) from being subject to this logic, to prevent excessive network topology changes as a result of this algorithm, while still ensuring that we have a reasonable number of nodes not known to be on bogus chains.
We also don't require our peers to be on the same chain as us, to prevent accidental partitioning of the network in the event of a chain split. Note that if our peers are ever on a more work chain than our tip, then we will download and validate it, and then either reorg to it, or learn of a consensus incompatibility with that peer and disconnect. This PR is designed to protect against peers that are on a less work chain which we may never try to download and validate.
Tree-SHA512: 2e0169a1dd8a7fb95980573ac4a201924bffdd724c19afcab5efcef076fdbe1f2cec7dc5f5d7e0a6327216f56d3828884f73642e00c8534b56ec2bb4c854a656
2017-10-26 21:53:19 +02:00
|
|
|
|
|
|
|
bool dummy;
|
|
|
|
peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
|
2012-01-03 23:33:31 +01:00
|
|
|
}
|
2011-09-06 22:09:04 +02:00
|
|
|
|
2018-05-04 22:42:39 +02:00
|
|
|
static CTransactionRef RandomOrphan()
|
2012-02-29 16:14:18 +01:00
|
|
|
{
|
2014-09-20 09:53:50 +02:00
|
|
|
std::map<uint256, COrphanTx>::iterator it;
|
2018-08-31 14:32:29 +02:00
|
|
|
LOCK2(cs_main, g_cs_orphans);
|
2017-06-07 23:59:41 +02:00
|
|
|
it = mapOrphanTransactions.lower_bound(InsecureRand256());
|
2012-02-29 16:14:18 +01:00
|
|
|
if (it == mapOrphanTransactions.end())
|
|
|
|
it = mapOrphanTransactions.begin();
|
2014-09-20 09:53:50 +02:00
|
|
|
return it->second.tx;
|
2012-02-29 16:14:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
|
|
|
{
|
|
|
|
CKey key;
|
|
|
|
key.MakeNewKey(true);
|
|
|
|
CBasicKeyStore keystore;
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(keystore.AddKey(key));
|
2012-02-29 16:14:18 +01:00
|
|
|
|
|
|
|
// 50 orphan transactions:
|
|
|
|
for (int i = 0; i < 50; i++)
|
|
|
|
{
|
2014-06-07 13:53:27 +02:00
|
|
|
CMutableTransaction tx;
|
2012-02-29 16:14:18 +01:00
|
|
|
tx.vin.resize(1);
|
|
|
|
tx.vin[0].prevout.n = 0;
|
2017-06-07 23:59:41 +02:00
|
|
|
tx.vin[0].prevout.hash = InsecureRand256();
|
2012-02-29 16:14:18 +01:00
|
|
|
tx.vin[0].scriptSig << OP_1;
|
|
|
|
tx.vout.resize(1);
|
|
|
|
tx.vout[0].nValue = 1*CENT;
|
2014-09-11 19:15:29 +02:00
|
|
|
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
|
2012-02-29 16:14:18 +01:00
|
|
|
|
2017-01-04 12:22:49 +01:00
|
|
|
AddOrphanTx(MakeTransactionRef(tx), i);
|
2012-02-29 16:14:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ... and 50 that depend on other orphans:
|
|
|
|
for (int i = 0; i < 50; i++)
|
|
|
|
{
|
2017-01-04 12:22:49 +01:00
|
|
|
CTransactionRef txPrev = RandomOrphan();
|
2012-02-29 16:14:18 +01:00
|
|
|
|
2014-06-07 13:53:27 +02:00
|
|
|
CMutableTransaction tx;
|
2012-02-29 16:14:18 +01:00
|
|
|
tx.vin.resize(1);
|
|
|
|
tx.vin[0].prevout.n = 0;
|
2017-01-04 12:22:49 +01:00
|
|
|
tx.vin[0].prevout.hash = txPrev->GetHash();
|
2012-02-29 16:14:18 +01:00
|
|
|
tx.vout.resize(1);
|
|
|
|
tx.vout[0].nValue = 1*CENT;
|
2014-09-11 19:15:29 +02:00
|
|
|
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
|
2012-02-29 16:14:18 +01:00
|
|
|
|
2017-01-04 12:22:49 +01:00
|
|
|
AddOrphanTx(MakeTransactionRef(tx), i);
|
2012-02-29 16:14:18 +01:00
|
|
|
}
|
|
|
|
|
2012-05-15 21:53:30 +02:00
|
|
|
// This really-big orphan should be ignored:
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
{
|
2017-01-04 12:22:49 +01:00
|
|
|
CTransactionRef txPrev = RandomOrphan();
|
2012-05-15 21:53:30 +02:00
|
|
|
|
2014-06-07 13:53:27 +02:00
|
|
|
CMutableTransaction tx;
|
2012-05-15 21:53:30 +02:00
|
|
|
tx.vout.resize(1);
|
|
|
|
tx.vout[0].nValue = 1*CENT;
|
2014-09-11 19:15:29 +02:00
|
|
|
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
|
2016-06-20 14:45:34 +02:00
|
|
|
tx.vin.resize(2777);
|
2012-05-24 18:18:50 +02:00
|
|
|
for (unsigned int j = 0; j < tx.vin.size(); j++)
|
2012-05-15 21:53:30 +02:00
|
|
|
{
|
|
|
|
tx.vin[j].prevout.n = j;
|
2017-01-04 12:22:49 +01:00
|
|
|
tx.vin[j].prevout.hash = txPrev->GetHash();
|
2012-05-15 21:53:30 +02:00
|
|
|
}
|
2018-12-14 20:21:21 +01:00
|
|
|
BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
|
2012-05-15 21:53:30 +02:00
|
|
|
// Re-use same signature for other inputs
|
|
|
|
// (they don't have to be valid for this test)
|
2012-05-24 18:18:50 +02:00
|
|
|
for (unsigned int j = 1; j < tx.vin.size(); j++)
|
2012-05-15 21:53:30 +02:00
|
|
|
tx.vin[j].scriptSig = tx.vin[0].scriptSig;
|
|
|
|
|
2017-01-04 12:22:49 +01:00
|
|
|
BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i));
|
2014-08-28 19:23:24 +02:00
|
|
|
}
|
|
|
|
|
2018-08-31 14:32:29 +02:00
|
|
|
LOCK2(cs_main, g_cs_orphans);
|
2014-08-28 19:23:24 +02:00
|
|
|
// Test EraseOrphansFor:
|
|
|
|
for (NodeId i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
size_t sizeBefore = mapOrphanTransactions.size();
|
|
|
|
EraseOrphansFor(i);
|
|
|
|
BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore);
|
2012-05-15 21:53:30 +02:00
|
|
|
}
|
|
|
|
|
2012-02-29 16:14:18 +01:00
|
|
|
// Test LimitOrphanTxSize() function:
|
|
|
|
LimitOrphanTxSize(40);
|
|
|
|
BOOST_CHECK(mapOrphanTransactions.size() <= 40);
|
|
|
|
LimitOrphanTxSize(10);
|
|
|
|
BOOST_CHECK(mapOrphanTransactions.size() <= 10);
|
|
|
|
LimitOrphanTxSize(0);
|
|
|
|
BOOST_CHECK(mapOrphanTransactions.empty());
|
|
|
|
}
|
|
|
|
|
2011-09-06 22:09:04 +02:00
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|