Bitcoin ABC  0.22.13
P2P Digital Currency
coin_selection.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2016 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 <chainparams.h>
7 #include <interfaces/chain.h>
8 #include <node/context.h>
9 #include <wallet/coinselection.h>
10 #include <wallet/wallet.h>
11 
12 #include <memory>
13 #include <set>
14 
15 static void addCoin(const Amount nValue, const CWallet &wallet,
16  std::vector<std::unique_ptr<CWalletTx>> &wtxs) {
17  static int nextLockTime = 0;
19  // so all transactions get different hashes
20  tx.nLockTime = nextLockTime++;
21  tx.vout.resize(1);
22  tx.vout[0].nValue = nValue;
23  wtxs.push_back(std::make_unique<CWalletTx>(
24  &wallet, MakeTransactionRef(std::move(tx))));
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) {
36 
37  NodeContext node;
38  auto chain = interfaces::MakeChain(node, Params());
39  CWallet wallet(chain.get(), WalletLocation(),
42  std::vector<std::unique_ptr<CWalletTx>> wtxs;
43  LOCK(wallet.cs_wallet);
44 
45  // Add coins.
46  for (int i = 0; i < 1000; ++i) {
47  addCoin(1000 * COIN, wallet, wtxs);
48  }
49  addCoin(3 * COIN, wallet, wtxs);
50 
51  // Create groups
52  std::vector<OutputGroup> groups;
53  for (const auto &wtx : wtxs) {
54  COutput output(wtx.get(), 0 /* iIn */, 6 * 24 /* nDepthIn */,
55  true /* spendable */, true /* solvable */,
56  true /* safe */);
57  groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
58  }
59 
62  true, 34, 148, CFeeRate(Amount::zero()), 0);
63  while (state.KeepRunning()) {
64  std::set<CInputCoin> setCoinsRet;
65  Amount nValueRet;
66  bool bnb_used;
67  bool success = wallet.SelectCoinsMinConf(
68  1003 * COIN, filter_standard, groups, setCoinsRet, nValueRet,
69  coin_selection_params, bnb_used);
70  assert(success);
71  assert(nValueRet == 1003 * COIN);
72  assert(setCoinsRet.size() == 2);
73  }
74 }
75 
76 typedef std::set<CInputCoin> CoinSet;
77 std::vector<std::unique_ptr<CWalletTx>> wtxn;
78 
79 // Copied from src/wallet/test/coinselector_tests.cpp
80 static void add_coin(const CWallet &wallet, const Amount nValue, int nInput,
81  std::vector<OutputGroup> &set) {
83  tx.vout.resize(nInput + 1);
84  tx.vout[nInput].nValue = nValue;
85  auto wtx =
86  std::make_unique<CWalletTx>(&wallet, MakeTransactionRef(std::move(tx)));
87  set.emplace_back(
88  COutput(wtx.get(), nInput, 0, true, true, true).GetInputCoin(), 0, true,
89  0, 0);
90  wtxn.emplace_back(std::move(wtx));
91 }
92 
93 // Copied from src/wallet/test/coinselector_tests.cpp
94 static Amount make_hard_case(const CWallet &wallet, int utxos,
95  std::vector<OutputGroup> &utxo_pool) {
96  utxo_pool.clear();
97  Amount target = Amount::zero();
98  for (int i = 0; i < utxos; ++i) {
99  const Amount base = (int64_t(1) << (utxos + i)) * SATOSHI;
100  target += base;
101  add_coin(wallet, base, 2 * i, utxo_pool);
102  add_coin(wallet, base + (int64_t(1) << (utxos - 1 - i)) * SATOSHI,
103  2 * i + 1, utxo_pool);
104  }
105  return target;
106 }
107 
108 static void BnBExhaustion(benchmark::State &state) {
110 
111  NodeContext node;
112  auto chain = interfaces::MakeChain(node, Params());
113  CWallet wallet(chain.get(), WalletLocation(),
115 
116  LOCK(wallet.cs_wallet);
117 
118  // Setup
119  wallet.SetupLegacyScriptPubKeyMan();
120  std::vector<OutputGroup> utxo_pool;
121  CoinSet selection;
122  Amount value_ret = Amount::zero();
123  Amount not_input_fees = Amount::zero();
124 
125  while (state.KeepRunning()) {
126  // Benchmark
127  Amount target = make_hard_case(wallet, 17, utxo_pool);
128  // Should exhaust
129  SelectCoinsBnB(utxo_pool, target, Amount::zero(), selection, value_ret,
130  not_input_fees);
131 
132  // Cleanup
133  utxo_pool.clear();
134  selection.clear();
135  }
136 }
137 
static std::unique_ptr< BerkeleyDatabase > CreateDummy()
Return object for accessing dummy database with no read/write capabilities.
Definition: bdb.h:135
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
Definition: wallet.cpp:4847
std::set< CInputCoin > CoinSet
static constexpr Amount zero()
Definition: amount.h:35
static const std::string REGTEST
static void BnBExhaustion(benchmark::State &state)
CoinSelectionParams coin_selection_params(false, 0, 0, CFeeRate(Amount::zero()), 0)
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:339
Definition: amount.h:17
CoinEligibilityFilter filter_standard(1, 6, 0)
bool KeepRunning()
Definition: bench.h:71
static constexpr Amount SATOSHI
Definition: amount.h:151
std::vector< CTxOut > vout
Definition: transaction.h:300
bool SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const Amount &target_value, const Amount &cost_of_change, std::set< CInputCoin > &out_set, Amount &value_ret, const Amount not_input_fees)
std::vector< std::unique_ptr< CWalletTx > > wtxn
static Amount make_hard_case(const CWallet &wallet, int utxos, std::vector< OutputGroup > &utxo_pool)
static void addCoin(const Amount nValue, const CWallet &wallet, std::vector< std::unique_ptr< CWalletTx >> &wtxs)
NodeContext struct containing references to chain state and connection state.
Definition: context.h:35
static constexpr Amount COIN
Definition: amount.h:153
static void add_coin(const CWallet &wallet, const Amount nValue, int nInput, std::vector< OutputGroup > &set)
#define LOCK(cs)
Definition: sync.h:230
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
const CChainParams & Params()
Return the currently selected parameters.
A mutable version of CTransaction.
Definition: transaction.h:297
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:679
Fee rate in satoshis per kilobyte: Amount / kB.
Definition: feerate.h:21
static void CoinSelection(benchmark::State &state)
The WalletLocation class provides wallet information.
Definition: walletutil.h:80
BENCHMARK(CoinSelection, 650)
std::unique_ptr< Chain > MakeChain(NodeContext &node, const CChainParams &params)
Return implementation of Chain interface.
Definition: chain.cpp:448