orphanage_tests.cpp
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 <primitives/transaction.h> 7 #include <pubkey.h> 8 #include <script/sign.h> 9 #include <script/signingprovider.h> 10 #include <test/util/random.h> 11 #include <test/util/setup_common.h> 12 #include <txorphanage.h> 13 14 #include <array> 15 #include <cstdint> 16 17 #include <boost/test/unit_test.hpp> 18 19 BOOST_FIXTURE_TEST_SUITE(orphanage_tests, TestingSetup) 20 21 class TxOrphanageTest : public TxOrphanage 22 { 23 public: 24 inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) 25 { 26 LOCK(m_mutex); 27 return m_orphans.size(); 28 } 29 30 CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) 31 { 32 LOCK(m_mutex); 33 std::map<Txid, OrphanTx>::iterator it; 34 it = m_orphans.lower_bound(Txid::FromUint256(InsecureRand256())); 35 if (it == m_orphans.end()) 36 it = m_orphans.begin(); 37 return it->second.tx; 38 } 39 }; 40 41 static void MakeNewKeyWithFastRandomContext(CKey& key) 42 { 43 std::vector<unsigned char> keydata; 44 keydata = g_insecure_rand_ctx.randbytes(32); 45 key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn=*/true); 46 assert(key.IsValid()); 47 } 48 49 BOOST_AUTO_TEST_CASE(DoS_mapOrphans) 50 { 51 // This test had non-deterministic coverage due to 52 // randomly selected seeds. 53 // This seed is chosen so that all branches of the function 54 // ecdsa_signature_parse_der_lax are executed during this test. 55 // Specifically branches that run only when an ECDSA 56 // signature's R and S values have leading zeros. 57 g_insecure_rand_ctx = FastRandomContext{uint256{33}}; 58 59 TxOrphanageTest orphanage; 60 CKey key; 61 MakeNewKeyWithFastRandomContext(key); 62 FillableSigningProvider keystore; 63 BOOST_CHECK(keystore.AddKey(key)); 64 65 // 50 orphan transactions: 66 for (int i = 0; i < 50; i++) 67 { 68 CMutableTransaction tx; 69 tx.vin.resize(1); 70 tx.vin[0].prevout.n = 0; 71 tx.vin[0].prevout.hash = Txid::FromUint256(InsecureRand256()); 72 tx.vin[0].scriptSig << OP_1; 73 tx.vout.resize(1); 74 tx.vout[0].nValue = 1*CENT; 75 tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); 76 77 orphanage.AddTx(MakeTransactionRef(tx), i); 78 } 79 80 // ... and 50 that depend on other orphans: 81 for (int i = 0; i < 50; i++) 82 { 83 CTransactionRef txPrev = orphanage.RandomOrphan(); 84 85 CMutableTransaction tx; 86 tx.vin.resize(1); 87 tx.vin[0].prevout.n = 0; 88 tx.vin[0].prevout.hash = txPrev->GetHash(); 89 tx.vout.resize(1); 90 tx.vout[0].nValue = 1*CENT; 91 tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); 92 SignatureData empty; 93 BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty)); 94 95 orphanage.AddTx(MakeTransactionRef(tx), i); 96 } 97 98 // This really-big orphan should be ignored: 99 for (int i = 0; i < 10; i++) 100 { 101 CTransactionRef txPrev = orphanage.RandomOrphan(); 102 103 CMutableTransaction tx; 104 tx.vout.resize(1); 105 tx.vout[0].nValue = 1*CENT; 106 tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); 107 tx.vin.resize(2777); 108 for (unsigned int j = 0; j < tx.vin.size(); j++) 109 { 110 tx.vin[j].prevout.n = j; 111 tx.vin[j].prevout.hash = txPrev->GetHash(); 112 } 113 SignatureData empty; 114 BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty)); 115 // Reuse same signature for other inputs 116 // (they don't have to be valid for this test) 117 for (unsigned int j = 1; j < tx.vin.size(); j++) 118 tx.vin[j].scriptSig = tx.vin[0].scriptSig; 119 120 BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i)); 121 } 122 123 // Test EraseOrphansFor: 124 for (NodeId i = 0; i < 3; i++) 125 { 126 size_t sizeBefore = orphanage.CountOrphans(); 127 orphanage.EraseForPeer(i); 128 BOOST_CHECK(orphanage.CountOrphans() < sizeBefore); 129 } 130 131 // Test LimitOrphanTxSize() function: 132 FastRandomContext rng{/*fDeterministic=*/true}; 133 orphanage.LimitOrphans(40, rng); 134 BOOST_CHECK(orphanage.CountOrphans() <= 40); 135 orphanage.LimitOrphans(10, rng); 136 BOOST_CHECK(orphanage.CountOrphans() <= 10); 137 orphanage.LimitOrphans(0, rng); 138 BOOST_CHECK(orphanage.CountOrphans() == 0); 139 } 140 141 BOOST_AUTO_TEST_SUITE_END()