| 16 | BOOST_FIXTURE_TEST_SUITE(spend_tests, WalletTestingSetup) |
| 17 | |
| 18 | BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup) |
| 19 | { |
| 20 | CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); |
| 21 | auto wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey); |
| 22 | |
| 23 | // Check that a subtract-from-recipient transaction slightly less than the |
| 24 | // coinbase input amount does not create a change output (because it would |
| 25 | // be uneconomical to add and spend the output), and make sure it pays the |
| 26 | // leftover input amount which would have been change to the recipient |
| 27 | // instead of the miner. |
| 28 | auto check_tx = [&wallet](CAmount leftover_input_amount) { |
| 29 | CRecipient recipient{GetScriptForRawPubKey({}), 50 * COIN - leftover_input_amount, CAsset(), CPubKey(), true /* subtract fee */}; |
| 30 | CTransactionRef tx; |
| 31 | CAmount fee; |
| 32 | int change_pos = -1; |
| 33 | bilingual_str error; |
| 34 | CCoinControl coin_control; |
| 35 | coin_control.m_feerate.emplace(10000); |
| 36 | coin_control.fOverrideFeeRate = true; |
| 37 | // We need to use a change type with high cost of change so that the leftover amount will be dropped to fee instead of added as a change output |
| 38 | coin_control.m_change_type = OutputType::LEGACY; |
| 39 | FeeCalculation fee_calc; |
| 40 | BOOST_CHECK(CreateTransaction(*wallet, {recipient}, tx, fee, change_pos, error, coin_control, fee_calc)); |
| 41 | BOOST_CHECK_EQUAL(tx->vout.size(), 1); |
| 42 | BOOST_CHECK_EQUAL(tx->vout[0].nValue.GetAmount(), recipient.nAmount + leftover_input_amount - fee); |
| 43 | BOOST_CHECK_GT(fee, 0); |
| 44 | return fee; |
| 45 | }; |
| 46 | |
| 47 | // Send full input amount to recipient, check that only nonzero fee is |
| 48 | // subtracted (to_reduce == fee). |
| 49 | const CAmount fee{check_tx(0)}; |
| 50 | |
| 51 | // Send slightly less than full input amount to recipient, check leftover |
| 52 | // input amount is paid to recipient not the miner (to_reduce == fee - 123) |
| 53 | BOOST_CHECK_EQUAL(fee, check_tx(123)); |
| 54 | |
| 55 | // Send full input minus fee amount to recipient, check leftover input |
| 56 | // amount is paid to recipient not the miner (to_reduce == 0) |
| 57 | BOOST_CHECK_EQUAL(fee, check_tx(fee)); |
| 58 | |
| 59 | // Send full input minus more than the fee amount to recipient, check |
| 60 | // leftover input amount is paid to recipient not the miner (to_reduce == |
| 61 | // -123). This overpays the recipient instead of overpaying the miner more |
| 62 | // than double the necessary fee. |
| 63 | BOOST_CHECK_EQUAL(fee, check_tx(fee + 123)); |
| 64 | } |
| 65 | |
| 66 | static void TestFillInputToWeight(int64_t additional_weight, std::vector<int64_t> expected_stack_sizes) |
| 67 | { |
nothing calls this directly
no test coverage detected