Bitcoin Core  24.99.0
P2P Digital Currency
orphanage_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 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 #include <arith_uint256.h>
6 #include <pubkey.h>
7 #include <script/sign.h>
9 #include <script/standard.h>
10 #include <test/util/setup_common.h>
11 #include <txorphanage.h>
12 
13 #include <array>
14 #include <cstdint>
15 
16 #include <boost/test/unit_test.hpp>
17 
18 BOOST_FIXTURE_TEST_SUITE(orphanage_tests, TestingSetup)
19 
21 {
22 public:
24  {
25  return m_orphans.size();
26  }
27 
29  {
30  std::map<uint256, OrphanTx>::iterator it;
31  it = m_orphans.lower_bound(InsecureRand256());
32  if (it == m_orphans.end())
33  it = m_orphans.begin();
34  return it->second.tx;
35  }
36 };
37 
39 {
40  std::vector<unsigned char> keydata;
41  keydata = g_insecure_rand_ctx.randbytes(32);
42  key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn=*/true);
43  assert(key.IsValid());
44 }
45 
46 BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
47 {
48  // This test had non-deterministic coverage due to
49  // randomly selected seeds.
50  // This seed is chosen so that all branches of the function
51  // ecdsa_signature_parse_der_lax are executed during this test.
52  // Specifically branches that run only when an ECDSA
53  // signature's R and S values have leading zeros.
55 
56  TxOrphanageTest orphanage;
57  CKey key;
59  FillableSigningProvider keystore;
60  BOOST_CHECK(keystore.AddKey(key));
61 
63 
64  // 50 orphan transactions:
65  for (int i = 0; i < 50; i++)
66  {
68  tx.vin.resize(1);
69  tx.vin[0].prevout.n = 0;
70  tx.vin[0].prevout.hash = InsecureRand256();
71  tx.vin[0].scriptSig << OP_1;
72  tx.vout.resize(1);
73  tx.vout[0].nValue = 1*CENT;
74  tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
75 
76  orphanage.AddTx(MakeTransactionRef(tx), i);
77  }
78 
79  // ... and 50 that depend on other orphans:
80  for (int i = 0; i < 50; i++)
81  {
82  CTransactionRef txPrev = orphanage.RandomOrphan();
83 
85  tx.vin.resize(1);
86  tx.vin[0].prevout.n = 0;
87  tx.vin[0].prevout.hash = txPrev->GetHash();
88  tx.vout.resize(1);
89  tx.vout[0].nValue = 1*CENT;
90  tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
91  BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
92 
93  orphanage.AddTx(MakeTransactionRef(tx), i);
94  }
95 
96  // This really-big orphan should be ignored:
97  for (int i = 0; i < 10; i++)
98  {
99  CTransactionRef txPrev = orphanage.RandomOrphan();
100 
102  tx.vout.resize(1);
103  tx.vout[0].nValue = 1*CENT;
104  tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
105  tx.vin.resize(2777);
106  for (unsigned int j = 0; j < tx.vin.size(); j++)
107  {
108  tx.vin[j].prevout.n = j;
109  tx.vin[j].prevout.hash = txPrev->GetHash();
110  }
111  BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
112  // Re-use same signature for other inputs
113  // (they don't have to be valid for this test)
114  for (unsigned int j = 1; j < tx.vin.size(); j++)
115  tx.vin[j].scriptSig = tx.vin[0].scriptSig;
116 
117  BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
118  }
119 
120  // Test EraseOrphansFor:
121  for (NodeId i = 0; i < 3; i++)
122  {
123  size_t sizeBefore = orphanage.CountOrphans();
124  orphanage.EraseForPeer(i);
125  BOOST_CHECK(orphanage.CountOrphans() < sizeBefore);
126  }
127 
128  // Test LimitOrphanTxSize() function:
129  orphanage.LimitOrphans(40);
130  BOOST_CHECK(orphanage.CountOrphans() <= 40);
131  orphanage.LimitOrphans(10);
132  BOOST_CHECK(orphanage.CountOrphans() <= 10);
133  orphanage.LimitOrphans(0);
134  BOOST_CHECK(orphanage.CountOrphans() == 0);
135 }
136 
An encapsulated private key.
Definition: key.h:27
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:73
Fast randomness source.
Definition: random.h:143
std::vector< unsigned char > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:617
Fillable signing provider that keeps keys in an address->secret map.
virtual bool AddKey(const CKey &key)
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
Definition: txorphanage.h:21
void EraseForBlock(const CBlock &block) LOCKS_EXCLUDED(void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Erase all orphans included in or invalidated by a new block.
Definition: txorphanage.h:44
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Erase all orphans announced by a peer (eg, after that peer disconnects)
Definition: txorphanage.cpp:88
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
Add a new orphan transaction.
Definition: txorphanage.cpp:20
CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
256-bit opaque blob.
Definition: uint256.h:119
BOOST_AUTO_TEST_SUITE_END()
@ SIGHASH_ALL
Definition: interpreter.h:28
int64_t NodeId
Definition: net.h:92
#define BOOST_CHECK(expr)
Definition: object.cpp:16
static void MakeNewKeyWithFastRandomContext(CKey &key)
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:415
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:414
@ OP_1
Definition: script.h:79
FastRandomContext g_insecure_rand_ctx
This global and the helpers that use it are not thread-safe.
static constexpr CAmount CENT
Definition: setup_common.h:78
static uint256 InsecureRand256()
Definition: setup_common.h:73
bool SignSignature(const SigningProvider &provider, const CScript &fromPubKey, CMutableTransaction &txTo, unsigned int nIn, const CAmount &amount, int nHashType)
Produce a script signature for a transaction.
Definition: sign.cpp:568
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:334
A mutable version of CTransaction.
Definition: transaction.h:373
std::vector< CTxOut > vout
Definition: transaction.h:375
std::vector< CTxIn > vin
Definition: transaction.h:374
Testing setup that configures a complete environment.
Definition: setup_common.h:109
#define LOCK(cs)
Definition: sync.h:261
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
RecursiveMutex g_cs_orphans
Guards orphan transactions and extra txs for compact blocks.
Definition: txorphanage.cpp:18
assert(!tx.IsCoinBase())