Line data Source code
1 : // Copyright (c) 2019-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 <chainparams.h> 6 : #include <coins.h> 7 : #include <consensus/tx_check.h> 8 : #include <consensus/tx_verify.h> 9 : #include <consensus/validation.h> 10 : #include <core_io.h> 11 : #include <core_memusage.h> 12 : #include <policy/policy.h> 13 : #include <policy/settings.h> 14 : #include <primitives/transaction.h> 15 : #include <streams.h> 16 : #include <test/fuzz/fuzz.h> 17 2 : #include <univalue.h> 18 2 : #include <util/chaintype.h> 19 : #include <util/rbf.h> 20 : #include <validation.h> 21 : #include <version.h> 22 : 23 : #include <cassert> 24 : 25 0 : void initialize_transaction() 26 : { 27 0 : SelectParams(ChainType::REGTEST); 28 0 : } 29 : 30 4 : FUZZ_TARGET(transaction, .init = initialize_transaction) 31 : { 32 0 : CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); 33 : try { 34 : int nVersion; 35 0 : ds >> nVersion; 36 0 : ds.SetVersion(nVersion); 37 0 : } catch (const std::ios_base::failure&) { 38 : return; 39 0 : } 40 0 : bool valid_tx = true; 41 0 : const CTransaction tx = [&] { 42 : try { 43 0 : return CTransaction(deserialize, ds); 44 0 : } catch (const std::ios_base::failure&) { 45 0 : valid_tx = false; 46 0 : return CTransaction{CMutableTransaction{}}; 47 0 : } 48 0 : }(); 49 0 : bool valid_mutable_tx = true; 50 0 : CDataStream ds_mtx(buffer, SER_NETWORK, INIT_PROTO_VERSION); 51 0 : CMutableTransaction mutable_tx; 52 : try { 53 : int nVersion; 54 0 : ds_mtx >> nVersion; 55 0 : ds_mtx.SetVersion(nVersion); 56 0 : ds_mtx >> mutable_tx; 57 0 : } catch (const std::ios_base::failure&) { 58 0 : valid_mutable_tx = false; 59 0 : } 60 0 : assert(valid_tx == valid_mutable_tx); 61 0 : if (!valid_tx) { 62 0 : return; 63 : } 64 : 65 : { 66 0 : TxValidationState state_with_dupe_check; 67 0 : const bool res{CheckTransaction(tx, state_with_dupe_check)}; 68 0 : Assert(res == state_with_dupe_check.IsValid()); 69 0 : } 70 : 71 0 : const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE}; 72 0 : std::string reason; 73 0 : const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason); 74 2 : const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason); 75 0 : if (is_standard_without_permit_bare_multisig) { 76 0 : assert(is_standard_with_permit_bare_multisig); 77 0 : } 78 : 79 0 : (void)tx.GetHash(); 80 0 : (void)tx.GetTotalSize(); 81 : try { 82 0 : (void)tx.GetValueOut(); 83 0 : } catch (const std::runtime_error&) { 84 0 : } 85 0 : (void)tx.GetWitnessHash(); 86 0 : (void)tx.HasWitness(); 87 0 : (void)tx.IsCoinBase(); 88 0 : (void)tx.IsNull(); 89 0 : (void)tx.ToString(); 90 : 91 0 : (void)EncodeHexTx(tx); 92 0 : (void)GetLegacySigOpCount(tx); 93 0 : (void)GetTransactionWeight(tx); 94 0 : (void)GetVirtualTransactionSize(tx); 95 0 : (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024); 96 0 : (void)RecursiveDynamicUsage(tx); 97 0 : (void)SignalsOptInRBF(tx); 98 : 99 0 : CCoinsView coins_view; 100 0 : const CCoinsViewCache coins_view_cache(&coins_view); 101 0 : (void)AreInputsStandard(tx, coins_view_cache); 102 0 : (void)IsWitnessStandard(tx, coins_view_cache); 103 : 104 0 : if (tx.GetTotalSize() < 250'000) { // Avoid high memory usage (with msan) due to json encoding 105 : { 106 0 : UniValue u{UniValue::VOBJ}; 107 0 : TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u); 108 0 : } 109 : { 110 0 : UniValue u{UniValue::VOBJ}; 111 0 : TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u); 112 0 : } 113 0 : } 114 0 : }