LCOV - code coverage report
Current view: top level - src/wallet/test - spend_tests.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 54 54 100.0 %
Date: 2026-06-25 07:23:51 Functions: 21 21 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2021 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 <policy/fees.h>
       6             : #include <validation.h>
       7             : #include <wallet/coincontrol.h>
       8             : #include <wallet/spend.h>
       9             : #include <wallet/test/util.h>
      10             : #include <wallet/test/wallet_test_fixture.h>
      11             : 
      12             : #include <boost/test/unit_test.hpp>
      13             : 
      14             : namespace wallet {
      15         146 : BOOST_FIXTURE_TEST_SUITE(spend_tests, WalletTestingSetup)
      16             : 
      17         149 : BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
      18             : {
      19           1 :     CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
      20           1 :     auto wallet = CreateSyncedWallet(*m_node.chain, *m_node.coinjoin_loader, m_node.chainman->ActiveChain(), m_args, coinbaseKey);
      21             : 
      22             :     // Check that a subtract-from-recipient transaction slightly less than the
      23             :     // coinbase input amount does not create a change output (because it would
      24             :     // be uneconomical to add and spend the output), and make sure it pays the
      25             :     // leftover input amount which would have been change to the recipient
      26             :     // instead of the miner.
      27           5 :     auto check_tx = [&wallet](CAmount leftover_input_amount) {
      28           4 :         CRecipient recipient{GetScriptForRawPubKey({}), 500 * COIN - leftover_input_amount, true /* subtract fee */};
      29           4 :         bilingual_str error;
      30           4 :         CCoinControl coin_control;
      31           4 :         coin_control.m_feerate.emplace(10000);
      32           4 :         coin_control.fOverrideFeeRate = true;
      33           4 :         auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, coin_control);
      34           4 :         BOOST_CHECK(res);
      35           4 :         const auto& txr = *res;
      36           4 :         BOOST_CHECK_EQUAL(txr.tx->vout.size(), 1);
      37           4 :         BOOST_CHECK_EQUAL(txr.tx->vout[0].nValue, recipient.nAmount + leftover_input_amount - txr.fee);
      38           4 :         BOOST_CHECK_GT(txr.fee, 0);
      39           4 :         return txr.fee;
      40           4 :     };
      41             : 
      42             :     // Send full input amount to recipient, check that only nonzero fee is
      43             :     // subtracted (to_reduce == fee).
      44           1 :     const CAmount fee{check_tx(0)};
      45             : 
      46             :     // Send slightly less than full input amount to recipient, check leftover
      47             :     // input amount is paid to recipient not the miner (to_reduce == fee - 123)
      48           1 :     BOOST_CHECK_EQUAL(fee, check_tx(123));
      49             : 
      50             :     // Send full input minus fee amount to recipient, check leftover input
      51             :     // amount is paid to recipient not the miner (to_reduce == 0)
      52           1 :     BOOST_CHECK_EQUAL(fee, check_tx(fee));
      53             : 
      54             :     // Send full input minus more than the fee amount to recipient, check
      55             :     // leftover input amount is paid to recipient not the miner (to_reduce ==
      56             :     // -123). This overpays the recipient instead of overpaying the miner more
      57             :     // than double the neccesary fee.
      58           1 :     BOOST_CHECK_EQUAL(fee, check_tx(fee + 123));
      59           1 : }
      60             : 
      61           9 : static void TestFillInputToWeight(int64_t additional_weight, int64_t expected_scriptsig_size)
      62             : {
      63           9 :     static const int64_t EMPTY_INPUT_WEIGHT = ::GetSerializeSize(CTxIn());
      64             : 
      65           9 :     CTxIn input;
      66           9 :     int64_t target_weight = EMPTY_INPUT_WEIGHT + additional_weight;
      67           9 :     BOOST_CHECK(FillInputToWeight(input, target_weight));
      68             : 
      69           9 :     BOOST_CHECK_LE(::GetSerializeSize(input), target_weight);
      70           9 :     BOOST_CHECK_GE(::GetSerializeSize(input), target_weight - 2);
      71             : 
      72           9 :     BOOST_CHECK_EQUAL(input.scriptSig.size(), expected_scriptsig_size);
      73           9 : }
      74             : 
      75         149 : BOOST_FIXTURE_TEST_CASE(FillInputToWeightTest, BasicTestingSetup)
      76             : {
      77             :     {
      78             :         // Less than or equal minimum of 41 should not add any witness data
      79           1 :         CTxIn input;
      80           1 :         BOOST_CHECK(!FillInputToWeight(input, -1));
      81           1 :         BOOST_CHECK_EQUAL(::GetSerializeSize(input), 41);
      82           1 :         BOOST_CHECK(!FillInputToWeight(input, 0));
      83           1 :         BOOST_CHECK_EQUAL(::GetSerializeSize(input), 41);
      84           1 :         BOOST_CHECK(!FillInputToWeight(input, 40));
      85           1 :         BOOST_CHECK_EQUAL(::GetSerializeSize(input), 41);
      86           1 :         BOOST_CHECK(FillInputToWeight(input, 41));
      87           1 :         BOOST_CHECK_EQUAL(::GetSerializeSize(input), 41);
      88           1 :     }
      89             : 
      90             :     // Make sure we can add at least one weight
      91           1 :     TestFillInputToWeight(1, 1);
      92             : 
      93             :     // 1 byte compact size uint boundary
      94           1 :     TestFillInputToWeight(252, 252);
      95           1 :     TestFillInputToWeight(253, 251);
      96           1 :     TestFillInputToWeight(262, 260);
      97           1 :     TestFillInputToWeight(263, 261);
      98             : 
      99             :     // 3 byte compact size uint boundary
     100           1 :     TestFillInputToWeight(65535, 65533);
     101           1 :     TestFillInputToWeight(65536, 65532);
     102           1 :     TestFillInputToWeight(65545, 65541);
     103           1 :     TestFillInputToWeight(65546, 65542);
     104             : 
     105             :     // Note: We don't test the next boundary because of memory allocation constraints.
     106           1 : }
     107             : 
     108         146 : BOOST_AUTO_TEST_SUITE_END()
     109             : } // namespace wallet

Generated by: LCOV version 1.16