Branch data Line data Source code
1 : : // Copyright (c) 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 <consensus/amount.h> 6 : : #include <consensus/validation.h> 7 : : #include <net_processing.h> 8 : : #include <node/eviction.h> 9 : : #include <policy/policy.h> 10 : : #include <primitives/transaction.h> 11 : : #include <script/script.h> 12 : : #include <sync.h> 13 : : #include <test/fuzz/FuzzedDataProvider.h> 14 : : #include <test/fuzz/fuzz.h> 15 : : #include <test/fuzz/util.h> 16 : : #include <test/util/setup_common.h> 17 [ + - ]: 173 : #include <txorphanage.h> 18 [ + - ]: 173 : #include <uint256.h> 19 : : #include <util/check.h> 20 : : #include <util/time.h> 21 : : 22 : : #include <cstdint> 23 : : #include <memory> 24 : : #include <set> 25 : : #include <utility> 26 : : #include <vector> 27 : : 28 : 1 : void initialize_orphanage() 29 : : { 30 [ + - - + : 1 : static const auto testing_setup = MakeNoLogFileContext(); + - ] 31 : 1 : } 32 : : 33 [ + - - + ]: 638 : FUZZ_TARGET(txorphan, .init = initialize_orphanage) 34 : : { 35 : 292 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 36 : 292 : SetMockTime(ConsumeTime(fuzzed_data_provider)); 37 : : 38 : 292 : TxOrphanage orphanage; 39 : 292 : std::vector<COutPoint> outpoints; 40 : : // initial outpoints used to construct transactions later 41 [ + + ]: 1460 : for (uint8_t i = 0; i < 4; i++) { 42 [ + - + - ]: 1168 : outpoints.emplace_back(uint256{i}, 0); 43 : 1168 : } 44 : : // if true, allow duplicate input when constructing tx 45 [ + - ]: 292 : const bool duplicate_input = fuzzed_data_provider.ConsumeBool(); 46 : : 47 [ + + + - : 7849 : LIMITED_WHILE(outpoints.size() < 200'000 && fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS) + + + + ] 48 : : { 49 : : // construct transaction 50 [ + - ]: 15114 : const CTransactionRef tx = [&] { 51 : 7557 : CMutableTransaction tx_mut; 52 [ + - ]: 7557 : const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size()); 53 [ + - ]: 7557 : const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size()); 54 : : // pick unique outpoints from outpoints as input 55 [ + + ]: 3155493 : for (uint32_t i = 0; i < num_in; i++) { 56 [ + - ]: 3147936 : auto& prevout = PickValue(fuzzed_data_provider, outpoints); 57 [ + - ]: 3147936 : tx_mut.vin.emplace_back(prevout); 58 : : // pop the picked outpoint if duplicate input is not allowed 59 [ + + ]: 3147936 : if (!duplicate_input) { 60 : 2073229 : std::swap(prevout, outpoints.back()); 61 : 2073229 : outpoints.pop_back(); 62 : 2073229 : } 63 : 3147936 : } 64 : : // output amount will not affect txorphanage 65 [ + + ]: 4135802 : for (uint32_t i = 0; i < num_out; i++) { 66 [ + - + - ]: 4128245 : tx_mut.vout.emplace_back(CAmount{0}, CScript{}); 67 : 4128245 : } 68 : : // restore previously popped outpoints 69 [ + + ]: 3155493 : for (auto& in : tx_mut.vin) { 70 [ + - ]: 3147936 : outpoints.push_back(in.prevout); 71 : : } 72 [ + - ]: 7557 : auto new_tx = MakeTransactionRef(tx_mut); 73 : : // add newly constructed transaction to outpoints 74 [ + + ]: 4135975 : for (uint32_t i = 0; i < num_out; i++) { 75 [ + - + - ]: 4128245 : outpoints.emplace_back(new_tx->GetHash(), i); 76 : 4128245 : } 77 : 7557 : return new_tx; 78 [ + - ]: 7557 : }(); 79 : : 80 : : // trigger orphanage functions 81 [ + - + + : 36917 : LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS) + + ] 82 : : { 83 [ + - + - ]: 29533 : NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<NodeId>(); 84 : : 85 [ + - ]: 29360 : CallOneOf( 86 : : fuzzed_data_provider, 87 : 33567 : [&] { 88 : 4207 : orphanage.AddChildrenToWorkSet(*tx); 89 : 4207 : }, 90 : 35423 : [&] { 91 : : { 92 : 6063 : CTransactionRef ref = orphanage.GetTxToReconsider(peer_id); 93 [ + - + + ]: 6063 : if (ref) { 94 [ + - + - : 615 : bool have_tx = orphanage.HaveTx(GenTxid::Txid(ref->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(ref->GetHash())); - + # # # # ] 95 [ + - ]: 615 : Assert(have_tx); 96 : 615 : } 97 : 6063 : } 98 : 6063 : }, 99 : 37646 : [&] { 100 [ + + ]: 8286 : bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 101 : : // AddTx should return false if tx is too big or already have it 102 : : // tx weight is unknown, we only check when tx is already in orphanage 103 : : { 104 : 8286 : bool add_tx = orphanage.AddTx(tx, peer_id); 105 : : // have_tx == true -> add_tx == false 106 [ + + ]: 8286 : Assert(!have_tx || !add_tx); 107 : : } 108 [ + + ]: 8286 : have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 109 : : { 110 : 8286 : bool add_tx = orphanage.AddTx(tx, peer_id); 111 : : // if have_tx is still false, it must be too big 112 : 8286 : Assert(!have_tx == (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT)); 113 [ + + ]: 8286 : Assert(!have_tx || !add_tx); 114 : : } 115 : 8286 : }, 116 : 35548 : [&] { 117 [ + + ]: 6188 : bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 118 : : // EraseTx should return 0 if m_orphans doesn't have the tx 119 : : { 120 : 6188 : Assert(have_tx == orphanage.EraseTx(tx->GetHash())); 121 : : } 122 [ - + ]: 6188 : have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash())); 123 : : // have_tx should be false and EraseTx should fail 124 : : { 125 [ - + ]: 6188 : Assert(!have_tx && !orphanage.EraseTx(tx->GetHash())); 126 : : } 127 : 6188 : }, 128 : 32176 : [&] { 129 : 2816 : orphanage.EraseForPeer(peer_id); 130 : 2816 : }, 131 : 31160 : [&] { 132 : : // test mocktime and expiry 133 : 1800 : SetMockTime(ConsumeTime(fuzzed_data_provider)); 134 : 1800 : auto limit = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); 135 : 1800 : orphanage.LimitOrphans(limit); 136 : 1800 : Assert(orphanage.Size() <= limit); 137 : 1800 : }); 138 : 29360 : } 139 : 7557 : } 140 : 292 : }