Bitcoin Core  25.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 <test/util/random.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:
23  inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
24  {
25  LOCK(m_mutex);
26  return m_orphans.size();
27  }
28 
30  {
31  LOCK(m_mutex);
32  std::map<uint256, OrphanTx>::iterator it;
33  it = m_orphans.lower_bound(InsecureRand256());
34  if (it == m_orphans.end())
35  it = m_orphans.begin();
36  return it->second.tx;
37  }
38 };
39 
41 {
42  std::vector<unsigned char> keydata;
43  keydata = g_insecure_rand_ctx.randbytes(32);
44  key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn=*/true);
45  assert(key.IsValid());
46 }
47 
48 BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
49 {
50  // This test had non-deterministic coverage due to
51  // randomly selected seeds.
52  // This seed is chosen so that all branches of the function
53  // ecdsa_signature_parse_der_lax are executed during this test.
54  // Specifically branches that run only when an ECDSA
55  // signature's R and S values have leading zeros.
57 
58  TxOrphanageTest orphanage;
59  CKey key;
61  FillableSigningProvider keystore;
62  BOOST_CHECK(keystore.AddKey(key));
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  SignatureData empty;
92  BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
93 
94  orphanage.AddTx(MakeTransactionRef(tx), i);
95  }
96 
97  // This really-big orphan should be ignored:
98  for (int i = 0; i < 10; i++)
99  {
100  CTransactionRef txPrev = orphanage.RandomOrphan();
101 
103  tx.vout.resize(1);
104  tx.vout[0].nValue = 1*CENT;
105  tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
106  tx.vin.resize(2777);
107  for (unsigned int j = 0; j < tx.vin.size(); j++)
108  {
109  tx.vin[j].prevout.n = j;
110  tx.vin[j].prevout.hash = txPrev->GetHash();
111  }
112  SignatureData empty;
113  BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
114  // Re-use same signature for other inputs
115  // (they don't have to be valid for this test)
116  for (unsigned int j = 1; j < tx.vin.size(); j++)
117  tx.vin[j].scriptSig = tx.vin[0].scriptSig;
118 
119  BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
120  }
121 
122  // Test EraseOrphansFor:
123  for (NodeId i = 0; i < 3; i++)
124  {
125  size_t sizeBefore = orphanage.CountOrphans();
126  orphanage.EraseForPeer(i);
127  BOOST_CHECK(orphanage.CountOrphans() < sizeBefore);
128  }
129 
130  // Test LimitOrphanTxSize() function:
131  orphanage.LimitOrphans(40);
132  BOOST_CHECK(orphanage.CountOrphans() <= 40);
133  orphanage.LimitOrphans(10);
134  BOOST_CHECK(orphanage.CountOrphans() <= 10);
135  orphanage.LimitOrphans(0);
136  BOOST_CHECK(orphanage.CountOrphans() == 0);
137 }
138 
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
An encapsulated private key.
Definition: key.h:33
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:99
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:188
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:79
Fast randomness source.
Definition: random.h:144
std::vector< B > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:596
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
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new orphan transaction.
Definition: txorphanage.cpp:19
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans announced by a peer (eg, after that peer disconnects)
Definition: txorphanage.cpp:96
void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Limit the orphanage to the given maximum.
size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
256-bit opaque blob.
Definition: uint256.h:106
BOOST_AUTO_TEST_SUITE_END()
@ SIGHASH_ALL
Definition: interpreter.h:28
int64_t NodeId
Definition: net.h:97
#define BOOST_CHECK(expr)
Definition: object.cpp:17
static void MakeNewKeyWithFastRandomContext(CKey &key)
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:422
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:421
@ OP_1
Definition: script.h:81
static constexpr CAmount CENT
Definition: setup_common.h:44
bool SignSignature(const SigningProvider &provider, const CScript &fromPubKey, CMutableTransaction &txTo, unsigned int nIn, const CAmount &amount, int nHashType, SignatureData &sig_data)
Produce a satisfying script (scriptSig or witness).
Definition: sign.cpp:666
A mutable version of CTransaction.
Definition: transaction.h:380
std::vector< CTxOut > vout
Definition: transaction.h:382
std::vector< CTxIn > vin
Definition: transaction.h:381
Testing setup that configures a complete environment.
Definition: setup_common.h:77
#define LOCK(cs)
Definition: sync.h:258
FastRandomContext g_insecure_rand_ctx
This global and the helpers that use it are not thread-safe.
Definition: random.cpp:14
static uint256 InsecureRand256()
Definition: random.h:50
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
assert(!tx.IsCoinBase())