From 71d1d13627ccd27319f347e2d8167c8fe8a433f4 Mon Sep 17 00:00:00 2001 From: josibake Date: Sat, 7 May 2022 15:53:02 +0200 Subject: test: add unit test for AvailableCoins test that UTXOs are bucketed correctly after running AvailableCoins --- src/Makefile.test.include | 1 + src/wallet/test/availablecoins_tests.cpp | 105 +++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/wallet/test/availablecoins_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index d9195ad32e..e05cc7bdd6 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -167,6 +167,7 @@ BITCOIN_TESTS += \ wallet/test/wallet_crypto_tests.cpp \ wallet/test/wallet_transaction_tests.cpp \ wallet/test/coinselector_tests.cpp \ + wallet/test/availablecoins_tests.cpp \ wallet/test/init_tests.cpp \ wallet/test/ismine_tests.cpp \ wallet/test/scriptpubkeyman_tests.cpp diff --git a/src/wallet/test/availablecoins_tests.cpp b/src/wallet/test/availablecoins_tests.cpp new file mode 100644 index 0000000000..01d24da981 --- /dev/null +++ b/src/wallet/test/availablecoins_tests.cpp @@ -0,0 +1,105 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include + +#include + +namespace wallet { +BOOST_FIXTURE_TEST_SUITE(availablecoins_tests, WalletTestingSetup) +class AvailableCoinsTestingSetup : public TestChain100Setup +{ +public: + AvailableCoinsTestingSetup() + { + CreateAndProcessBlock({}, {}); + wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey); + } + + ~AvailableCoinsTestingSetup() + { + wallet.reset(); + } + CWalletTx& AddTx(CRecipient recipient) + { + CTransactionRef tx; + CCoinControl dummy; + { + constexpr int RANDOM_CHANGE_POSITION = -1; + auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, dummy); + BOOST_CHECK(res); + tx = res.GetObj().tx; + } + wallet->CommitTransaction(tx, {}, {}); + CMutableTransaction blocktx; + { + LOCK(wallet->cs_wallet); + blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx); + } + CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); + + LOCK(wallet->cs_wallet); + wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash()); + auto it = wallet->mapWallet.find(tx->GetHash()); + BOOST_CHECK(it != wallet->mapWallet.end()); + it->second.m_state = TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/1}; + return it->second; + } + + std::unique_ptr wallet; +}; + +BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, AvailableCoinsTestingSetup) +{ + CoinsResult available_coins; + BResult dest; + LOCK(wallet->cs_wallet); + + // Verify our wallet has one usable coinbase UTXO before starting + // This UTXO is a P2PK, so it should show up in the Other bucket + available_coins = AvailableCoins(*wallet); + BOOST_CHECK_EQUAL(available_coins.size(), 1U); + BOOST_CHECK_EQUAL(available_coins.other.size(), 1U); + + // We will create a self transfer for each of the OutputTypes and + // verify it is put in the correct bucket after running GetAvailablecoins + // + // For each OutputType, We expect 2 UTXOs in our wallet following the self transfer: + // 1. One UTXO as the recipient + // 2. One UTXO from the change, due to payment address matching logic + + // Bech32m + dest = wallet->GetNewDestination(OutputType::BECH32M, ""); + BOOST_ASSERT(dest.HasRes()); + AddTx(CRecipient{{GetScriptForDestination(dest.GetObj())}, 1 * COIN, /*fSubtractFeeFromAmount=*/true}); + available_coins = AvailableCoins(*wallet); + BOOST_CHECK_EQUAL(available_coins.bech32m.size(), 2U); + + // Bech32 + dest = wallet->GetNewDestination(OutputType::BECH32, ""); + BOOST_ASSERT(dest.HasRes()); + AddTx(CRecipient{{GetScriptForDestination(dest.GetObj())}, 2 * COIN, /*fSubtractFeeFromAmount=*/true}); + available_coins = AvailableCoins(*wallet); + BOOST_CHECK_EQUAL(available_coins.bech32.size(), 2U); + + // P2SH-SEGWIT + dest = wallet->GetNewDestination(OutputType::P2SH_SEGWIT, ""); + AddTx(CRecipient{{GetScriptForDestination(dest.GetObj())}, 3 * COIN, /*fSubtractFeeFromAmount=*/true}); + available_coins = AvailableCoins(*wallet); + BOOST_CHECK_EQUAL(available_coins.P2SH_segwit.size(), 2U); + + // Legacy (P2PKH) + dest = wallet->GetNewDestination(OutputType::LEGACY, ""); + BOOST_ASSERT(dest.HasRes()); + AddTx(CRecipient{{GetScriptForDestination(dest.GetObj())}, 4 * COIN, /*fSubtractFeeFromAmount=*/true}); + available_coins = AvailableCoins(*wallet); + BOOST_CHECK_EQUAL(available_coins.legacy.size(), 2U); +} + +BOOST_AUTO_TEST_SUITE_END() +} // namespace wallet -- cgit v1.2.3