CPP   53

coin selection cpp

Guest on 6th July 2022 06:39:06 PM

  1. // Copyright (c)  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 <bench/bench.h>
  6. #include <wallet/wallet.h>
  7. #include <wallet/coinselection.h>
  8.  
  9. #include <set>
  10.  
  11. static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<OutputGroup>& groups)
  12. {
  13.     int nInput = 0;
  14.  
  15.     static int nextLockTime = 0;
  16.     CMutableTransaction tx;
  17.     tx.nLockTime = nextLockTime++; // so all transactions get different hashes
  18.     tx.vout.resize(nInput + 1);
  19.     tx.vout[nInput].nValue = nValue;
  20.     CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));
  21.  
  22.     int nAge = 6 * 24;
  23.     COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
  24.     groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
  25. }
  26.  
  27. // Simple benchmark for wallet coin selection. Note that it maybe be necessary
  28. // to build up more complicated scenarios in order to get meaningful
  29. // measurements of performance. From laanwj, "Wallet coin selection is probably
  30. // the hardest, as you need a wider selection of scenarios, just testing the
  31. // same one over and over isn't too useful. Generating random isn't useful
  32. // either for measurements."
  33. // (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
  34. static void CoinSelection(benchmark::State& state)
  35. {
  36.     const CWallet wallet("dummy", WalletDatabase::CreateDummy());
  37.     LOCK(wallet.cs_wallet);
  38.  
  39.     // Add coins.
  40.     std::vector<OutputGroup> groups;
  41.     for (int i = 0; i < 1000; ++i) {
  42.         addCoin(1000 * COIN, wallet, groups);
  43.     }
  44.     addCoin(3 * COIN, wallet, groups);
  45.  
  46.     const CoinEligibilityFilter filter_standard(1, 6, 0);
  47.     const CoinSelectionParams coin_selection_params(true, 34, 148, CFeeRate(0), 0);
  48.     while (state.KeepRunning()) {
  49.         std::set<CInputCoin> setCoinsRet;
  50.         CAmount nValueRet;
  51.         bool bnb_used;
  52.         bool success = wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used);
  53.         assert(success);
  54.         assert(nValueRet == 1003 * COIN);
  55.         assert(setCoinsRet.size() == 2);
  56.     }
  57. }
  58.  
  59. typedef std::set<CInputCoin> CoinSet;
  60. static const CWallet testWallet("dummy", WalletDatabase::CreateDummy());
  61. std::vector<std::unique_ptr<CWalletTx>> wtxn;
  62.  
  63. // Copied from src/wallet/test/coinselector_tests.cpp
  64. static void add_coin(const CAmount& nValue, int nInput, std::vector<OutputGroup>& set)
  65. {
  66.     CMutableTransaction tx;
  67.     tx.vout.resize(nInput + 1);
  68.     tx.vout[nInput].nValue = nValue;
  69.     std::unique_ptr<CWalletTx> wtx(new CWalletTx(&testWallet, MakeTransactionRef(std::move(tx))));
  70.     set.emplace_back(COutput(wtx.get(), nInput, 0, true, true, true).GetInputCoin(), 0, true, 0, 0);
  71.     wtxn.emplace_back(std::move(wtx));
  72. }
  73. // Copied from src/wallet/test/coinselector_tests.cpp
  74. static CAmount make_hard_case(int utxos, std::vector<OutputGroup>& utxo_pool)
  75. {
  76.     utxo_pool.clear();
  77.     CAmount target = 0;
  78.     for (int i = 0; i < utxos; ++i) {
  79.         target += (CAmount)1 << (utxos+i);
  80.         add_coin((CAmount)1 << (utxos+i), 2*i, utxo_pool);
  81.         add_coin(((CAmount)1 << (utxos+i)) + ((CAmount)1 << (utxos-1-i)), 2*i + 1, utxo_pool);
  82.     }
  83.     return target;
  84. }
  85.  
  86. static void BnBExhaustion(benchmark::State& state)
  87. {
  88.     // Setup
  89.     std::vector<OutputGroup> utxo_pool;
  90.     CoinSet selection;
  91.     CAmount value_ret = 0;
  92.     CAmount not_input_fees = 0;
  93.  
  94.     while (state.KeepRunning()) {
  95.         // Benchmark
  96.         CAmount target = make_hard_case(17, utxo_pool);
  97.         SelectCoinsBnB(utxo_pool, target, 0, selection, value_ret, not_input_fees); // Should exhaust
  98.  
  99.         // Cleanup
  100.         utxo_pool.clear();
  101.         selection.clear();
  102.     }
  103. }
  104.  
  105. BENCHMARK(CoinSelection, 650);
  106. BENCHMARK(BnBExhaustion, 650);

Raw Paste


Login or Register to edit or fork this paste. It's free.