Bitcoin Core  26.1.0
P2P Digital Currency
interfaces.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2022 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 <interfaces/wallet.h>
6 
7 #include <common/args.h>
8 #include <consensus/amount.h>
9 #include <interfaces/chain.h>
10 #include <interfaces/handler.h>
11 #include <policy/fees.h>
12 #include <primitives/transaction.h>
13 #include <rpc/server.h>
15 #include <sync.h>
16 #include <uint256.h>
17 #include <util/check.h>
18 #include <util/translation.h>
19 #include <util/ui_change_type.h>
20 #include <wallet/coincontrol.h>
21 #include <wallet/context.h>
22 #include <wallet/feebumper.h>
23 #include <wallet/fees.h>
24 #include <wallet/types.h>
25 #include <wallet/load.h>
26 #include <wallet/receive.h>
27 #include <wallet/rpc/wallet.h>
28 #include <wallet/spend.h>
29 #include <wallet/wallet.h>
30 
31 #include <memory>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 using interfaces::Chain;
40 using interfaces::Wallet;
50 
51 namespace wallet {
52 // All members of the classes in this namespace are intentionally public, as the
53 // classes themselves are private.
54 namespace {
56 WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
57 {
58  LOCK(wallet.cs_wallet);
59  WalletTx result;
60  result.tx = wtx.tx;
61  result.txin_is_mine.reserve(wtx.tx->vin.size());
62  for (const auto& txin : wtx.tx->vin) {
63  result.txin_is_mine.emplace_back(InputIsMine(wallet, txin));
64  }
65  result.txout_is_mine.reserve(wtx.tx->vout.size());
66  result.txout_address.reserve(wtx.tx->vout.size());
67  result.txout_address_is_mine.reserve(wtx.tx->vout.size());
68  for (const auto& txout : wtx.tx->vout) {
69  result.txout_is_mine.emplace_back(wallet.IsMine(txout));
70  result.txout_is_change.push_back(OutputIsChange(wallet, txout));
71  result.txout_address.emplace_back();
72  result.txout_address_is_mine.emplace_back(ExtractDestination(txout.scriptPubKey, result.txout_address.back()) ?
73  wallet.IsMine(result.txout_address.back()) :
74  ISMINE_NO);
75  }
76  result.credit = CachedTxGetCredit(wallet, wtx, ISMINE_ALL);
77  result.debit = CachedTxGetDebit(wallet, wtx, ISMINE_ALL);
78  result.change = CachedTxGetChange(wallet, wtx);
79  result.time = wtx.GetTxTime();
80  result.value_map = wtx.mapValue;
81  result.is_coinbase = wtx.IsCoinBase();
82  return result;
83 }
84 
86 WalletTxStatus MakeWalletTxStatus(const CWallet& wallet, const CWalletTx& wtx)
88 {
89  AssertLockHeld(wallet.cs_wallet);
90 
91  WalletTxStatus result;
92  result.block_height =
93  wtx.state<TxStateConfirmed>() ? wtx.state<TxStateConfirmed>()->confirmed_block_height :
94  wtx.state<TxStateConflicted>() ? wtx.state<TxStateConflicted>()->conflicting_block_height :
95  std::numeric_limits<int>::max();
96  result.blocks_to_maturity = wallet.GetTxBlocksToMaturity(wtx);
97  result.depth_in_main_chain = wallet.GetTxDepthInMainChain(wtx);
98  result.time_received = wtx.nTimeReceived;
99  result.lock_time = wtx.tx->nLockTime;
100  result.is_trusted = CachedTxIsTrusted(wallet, wtx);
101  result.is_abandoned = wtx.isAbandoned();
102  result.is_coinbase = wtx.IsCoinBase();
103  result.is_in_main_chain = wallet.IsTxInMainChain(wtx);
104  return result;
105 }
106 
108 WalletTxOut MakeWalletTxOut(const CWallet& wallet,
109  const CWalletTx& wtx,
110  int n,
111  int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
112 {
113  WalletTxOut result;
114  result.txout = wtx.tx->vout[n];
115  result.time = wtx.GetTxTime();
116  result.depth_in_main_chain = depth;
117  result.is_spent = wallet.IsSpent(COutPoint(wtx.GetHash(), n));
118  return result;
119 }
120 
121 WalletTxOut MakeWalletTxOut(const CWallet& wallet,
122  const COutput& output) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
123 {
124  WalletTxOut result;
125  result.txout = output.txout;
126  result.time = output.time;
127  result.depth_in_main_chain = output.depth;
128  result.is_spent = wallet.IsSpent(output.outpoint);
129  return result;
130 }
131 
132 class WalletImpl : public Wallet
133 {
134 public:
135  explicit WalletImpl(WalletContext& context, const std::shared_ptr<CWallet>& wallet) : m_context(context), m_wallet(wallet) {}
136 
137  bool encryptWallet(const SecureString& wallet_passphrase) override
138  {
139  return m_wallet->EncryptWallet(wallet_passphrase);
140  }
141  bool isCrypted() override { return m_wallet->IsCrypted(); }
142  bool lock() override { return m_wallet->Lock(); }
143  bool unlock(const SecureString& wallet_passphrase) override { return m_wallet->Unlock(wallet_passphrase); }
144  bool isLocked() override { return m_wallet->IsLocked(); }
145  bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
146  const SecureString& new_wallet_passphrase) override
147  {
148  return m_wallet->ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase);
149  }
150  void abortRescan() override { m_wallet->AbortRescan(); }
151  bool backupWallet(const std::string& filename) override { return m_wallet->BackupWallet(filename); }
152  std::string getWalletName() override { return m_wallet->GetName(); }
153  util::Result<CTxDestination> getNewDestination(const OutputType type, const std::string& label) override
154  {
155  LOCK(m_wallet->cs_wallet);
156  return m_wallet->GetNewDestination(type, label);
157  }
158  bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override
159  {
160  std::unique_ptr<SigningProvider> provider = m_wallet->GetSolvingProvider(script);
161  if (provider) {
162  return provider->GetPubKey(address, pub_key);
163  }
164  return false;
165  }
166  SigningResult signMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) override
167  {
168  return m_wallet->SignMessage(message, pkhash, str_sig);
169  }
170  bool isSpendable(const CTxDestination& dest) override
171  {
172  LOCK(m_wallet->cs_wallet);
173  return m_wallet->IsMine(dest) & ISMINE_SPENDABLE;
174  }
175  bool haveWatchOnly() override
176  {
177  auto spk_man = m_wallet->GetLegacyScriptPubKeyMan();
178  if (spk_man) {
179  return spk_man->HaveWatchOnly();
180  }
181  return false;
182  };
183  bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<AddressPurpose>& purpose) override
184  {
185  return m_wallet->SetAddressBook(dest, name, purpose);
186  }
187  bool delAddressBook(const CTxDestination& dest) override
188  {
189  return m_wallet->DelAddressBook(dest);
190  }
191  bool getAddress(const CTxDestination& dest,
192  std::string* name,
193  isminetype* is_mine,
194  AddressPurpose* purpose) override
195  {
196  LOCK(m_wallet->cs_wallet);
197  const auto& entry = m_wallet->FindAddressBookEntry(dest, /*allow_change=*/false);
198  if (!entry) return false; // addr not found
199  if (name) {
200  *name = entry->GetLabel();
201  }
202  std::optional<isminetype> dest_is_mine;
203  if (is_mine || purpose) {
204  dest_is_mine = m_wallet->IsMine(dest);
205  }
206  if (is_mine) {
207  *is_mine = *dest_is_mine;
208  }
209  if (purpose) {
210  // In very old wallets, address purpose may not be recorded so we derive it from IsMine
211  *purpose = entry->purpose.value_or(*dest_is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND);
212  }
213  return true;
214  }
215  std::vector<WalletAddress> getAddresses() const override
216  {
217  LOCK(m_wallet->cs_wallet);
218  std::vector<WalletAddress> result;
219  m_wallet->ForEachAddrBookEntry([&](const CTxDestination& dest, const std::string& label, bool is_change, const std::optional<AddressPurpose>& purpose) EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet) {
220  if (is_change) return;
221  isminetype is_mine = m_wallet->IsMine(dest);
222  // In very old wallets, address purpose may not be recorded so we derive it from IsMine
223  result.emplace_back(dest, is_mine, purpose.value_or(is_mine ? AddressPurpose::RECEIVE : AddressPurpose::SEND), label);
224  });
225  return result;
226  }
227  std::vector<std::string> getAddressReceiveRequests() override {
228  LOCK(m_wallet->cs_wallet);
229  return m_wallet->GetAddressReceiveRequests();
230  }
231  bool setAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& value) override {
232  // Note: The setAddressReceiveRequest interface used by the GUI to store
233  // receive requests is a little awkward and could be improved in the
234  // future:
235  //
236  // - The same method is used to save requests and erase them, but
237  // having separate methods could be clearer and prevent bugs.
238  //
239  // - Request ids are passed as strings even though they are generated as
240  // integers.
241  //
242  // - Multiple requests can be stored for the same address, but it might
243  // be better to only allow one request or only keep the current one.
244  LOCK(m_wallet->cs_wallet);
245  WalletBatch batch{m_wallet->GetDatabase()};
246  return value.empty() ? m_wallet->EraseAddressReceiveRequest(batch, dest, id)
247  : m_wallet->SetAddressReceiveRequest(batch, dest, id, value);
248  }
249  bool displayAddress(const CTxDestination& dest) override
250  {
251  LOCK(m_wallet->cs_wallet);
252  return m_wallet->DisplayAddress(dest);
253  }
254  bool lockCoin(const COutPoint& output, const bool write_to_db) override
255  {
256  LOCK(m_wallet->cs_wallet);
257  std::unique_ptr<WalletBatch> batch = write_to_db ? std::make_unique<WalletBatch>(m_wallet->GetDatabase()) : nullptr;
258  return m_wallet->LockCoin(output, batch.get());
259  }
260  bool unlockCoin(const COutPoint& output) override
261  {
262  LOCK(m_wallet->cs_wallet);
263  std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(m_wallet->GetDatabase());
264  return m_wallet->UnlockCoin(output, batch.get());
265  }
266  bool isLockedCoin(const COutPoint& output) override
267  {
268  LOCK(m_wallet->cs_wallet);
269  return m_wallet->IsLockedCoin(output);
270  }
271  void listLockedCoins(std::vector<COutPoint>& outputs) override
272  {
273  LOCK(m_wallet->cs_wallet);
274  return m_wallet->ListLockedCoins(outputs);
275  }
276  util::Result<CTransactionRef> createTransaction(const std::vector<CRecipient>& recipients,
277  const CCoinControl& coin_control,
278  bool sign,
279  int& change_pos,
280  CAmount& fee) override
281  {
282  LOCK(m_wallet->cs_wallet);
283  auto res = CreateTransaction(*m_wallet, recipients, change_pos,
284  coin_control, sign);
285  if (!res) return util::Error{util::ErrorString(res)};
286  const auto& txr = *res;
287  fee = txr.fee;
288  change_pos = txr.change_pos;
289 
290  return txr.tx;
291  }
292  void commitTransaction(CTransactionRef tx,
293  WalletValueMap value_map,
294  WalletOrderForm order_form) override
295  {
296  LOCK(m_wallet->cs_wallet);
297  m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form));
298  }
299  bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); }
300  bool abandonTransaction(const uint256& txid) override
301  {
302  LOCK(m_wallet->cs_wallet);
303  return m_wallet->AbandonTransaction(txid);
304  }
305  bool transactionCanBeBumped(const uint256& txid) override
306  {
307  return feebumper::TransactionCanBeBumped(*m_wallet.get(), txid);
308  }
309  bool createBumpTransaction(const uint256& txid,
310  const CCoinControl& coin_control,
311  std::vector<bilingual_str>& errors,
312  CAmount& old_fee,
313  CAmount& new_fee,
314  CMutableTransaction& mtx) override
315  {
316  std::vector<CTxOut> outputs; // just an empty list of new recipients for now
317  return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx, /* require_mine= */ true, outputs) == feebumper::Result::OK;
318  }
319  bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(*m_wallet.get(), mtx); }
320  bool commitBumpTransaction(const uint256& txid,
321  CMutableTransaction&& mtx,
322  std::vector<bilingual_str>& errors,
323  uint256& bumped_txid) override
324  {
325  return feebumper::CommitTransaction(*m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) ==
327  }
328  CTransactionRef getTx(const uint256& txid) override
329  {
330  LOCK(m_wallet->cs_wallet);
331  auto mi = m_wallet->mapWallet.find(txid);
332  if (mi != m_wallet->mapWallet.end()) {
333  return mi->second.tx;
334  }
335  return {};
336  }
337  WalletTx getWalletTx(const uint256& txid) override
338  {
339  LOCK(m_wallet->cs_wallet);
340  auto mi = m_wallet->mapWallet.find(txid);
341  if (mi != m_wallet->mapWallet.end()) {
342  return MakeWalletTx(*m_wallet, mi->second);
343  }
344  return {};
345  }
346  std::set<WalletTx> getWalletTxs() override
347  {
348  LOCK(m_wallet->cs_wallet);
349  std::set<WalletTx> result;
350  for (const auto& entry : m_wallet->mapWallet) {
351  result.emplace(MakeWalletTx(*m_wallet, entry.second));
352  }
353  return result;
354  }
355  bool tryGetTxStatus(const uint256& txid,
356  interfaces::WalletTxStatus& tx_status,
357  int& num_blocks,
358  int64_t& block_time) override
359  {
360  TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
361  if (!locked_wallet) {
362  return false;
363  }
364  auto mi = m_wallet->mapWallet.find(txid);
365  if (mi == m_wallet->mapWallet.end()) {
366  return false;
367  }
368  num_blocks = m_wallet->GetLastBlockHeight();
369  block_time = -1;
370  CHECK_NONFATAL(m_wallet->chain().findBlock(m_wallet->GetLastBlockHash(), FoundBlock().time(block_time)));
371  tx_status = MakeWalletTxStatus(*m_wallet, mi->second);
372  return true;
373  }
374  WalletTx getWalletTxDetails(const uint256& txid,
375  WalletTxStatus& tx_status,
376  WalletOrderForm& order_form,
377  bool& in_mempool,
378  int& num_blocks) override
379  {
380  LOCK(m_wallet->cs_wallet);
381  auto mi = m_wallet->mapWallet.find(txid);
382  if (mi != m_wallet->mapWallet.end()) {
383  num_blocks = m_wallet->GetLastBlockHeight();
384  in_mempool = mi->second.InMempool();
385  order_form = mi->second.vOrderForm;
386  tx_status = MakeWalletTxStatus(*m_wallet, mi->second);
387  return MakeWalletTx(*m_wallet, mi->second);
388  }
389  return {};
390  }
391  TransactionError fillPSBT(int sighash_type,
392  bool sign,
393  bool bip32derivs,
394  size_t* n_signed,
396  bool& complete) override
397  {
398  return m_wallet->FillPSBT(psbtx, complete, sighash_type, sign, bip32derivs, n_signed);
399  }
400  WalletBalances getBalances() override
401  {
402  const auto bal = GetBalance(*m_wallet);
403  WalletBalances result;
404  result.balance = bal.m_mine_trusted;
405  result.unconfirmed_balance = bal.m_mine_untrusted_pending;
406  result.immature_balance = bal.m_mine_immature;
407  result.have_watch_only = haveWatchOnly();
408  if (result.have_watch_only) {
409  result.watch_only_balance = bal.m_watchonly_trusted;
410  result.unconfirmed_watch_only_balance = bal.m_watchonly_untrusted_pending;
411  result.immature_watch_only_balance = bal.m_watchonly_immature;
412  }
413  return result;
414  }
415  bool tryGetBalances(WalletBalances& balances, uint256& block_hash) override
416  {
417  TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
418  if (!locked_wallet) {
419  return false;
420  }
421  block_hash = m_wallet->GetLastBlockHash();
422  balances = getBalances();
423  return true;
424  }
425  CAmount getBalance() override { return GetBalance(*m_wallet).m_mine_trusted; }
426  CAmount getAvailableBalance(const CCoinControl& coin_control) override
427  {
428  LOCK(m_wallet->cs_wallet);
429  CAmount total_amount = 0;
430  // Fetch selected coins total amount
431  if (coin_control.HasSelected()) {
432  FastRandomContext rng{};
433  CoinSelectionParams params(rng);
434  // Note: for now, swallow any error.
435  if (auto res = FetchSelectedInputs(*m_wallet, coin_control, params)) {
436  total_amount += res->total_amount;
437  }
438  }
439 
440  // And fetch the wallet available coins
441  if (coin_control.m_allow_other_inputs) {
442  total_amount += AvailableCoins(*m_wallet, &coin_control).GetTotalAmount();
443  }
444 
445  return total_amount;
446  }
447  isminetype txinIsMine(const CTxIn& txin) override
448  {
449  LOCK(m_wallet->cs_wallet);
450  return InputIsMine(*m_wallet, txin);
451  }
452  isminetype txoutIsMine(const CTxOut& txout) override
453  {
454  LOCK(m_wallet->cs_wallet);
455  return m_wallet->IsMine(txout);
456  }
457  CAmount getDebit(const CTxIn& txin, isminefilter filter) override
458  {
459  LOCK(m_wallet->cs_wallet);
460  return m_wallet->GetDebit(txin, filter);
461  }
462  CAmount getCredit(const CTxOut& txout, isminefilter filter) override
463  {
464  LOCK(m_wallet->cs_wallet);
465  return OutputGetCredit(*m_wallet, txout, filter);
466  }
467  CoinsList listCoins() override
468  {
469  LOCK(m_wallet->cs_wallet);
470  CoinsList result;
471  for (const auto& entry : ListCoins(*m_wallet)) {
472  auto& group = result[entry.first];
473  for (const auto& coin : entry.second) {
474  group.emplace_back(coin.outpoint,
475  MakeWalletTxOut(*m_wallet, coin));
476  }
477  }
478  return result;
479  }
480  std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
481  {
482  LOCK(m_wallet->cs_wallet);
483  std::vector<WalletTxOut> result;
484  result.reserve(outputs.size());
485  for (const auto& output : outputs) {
486  result.emplace_back();
487  auto it = m_wallet->mapWallet.find(output.hash);
488  if (it != m_wallet->mapWallet.end()) {
489  int depth = m_wallet->GetTxDepthInMainChain(it->second);
490  if (depth >= 0) {
491  result.back() = MakeWalletTxOut(*m_wallet, it->second, output.n, depth);
492  }
493  }
494  }
495  return result;
496  }
497  CAmount getRequiredFee(unsigned int tx_bytes) override { return GetRequiredFee(*m_wallet, tx_bytes); }
498  CAmount getMinimumFee(unsigned int tx_bytes,
499  const CCoinControl& coin_control,
500  int* returned_target,
501  FeeReason* reason) override
502  {
503  FeeCalculation fee_calc;
504  CAmount result;
505  result = GetMinimumFee(*m_wallet, tx_bytes, coin_control, &fee_calc);
506  if (returned_target) *returned_target = fee_calc.returnedTarget;
507  if (reason) *reason = fee_calc.reason;
508  return result;
509  }
510  unsigned int getConfirmTarget() override { return m_wallet->m_confirm_target; }
511  bool hdEnabled() override { return m_wallet->IsHDEnabled(); }
512  bool canGetAddresses() override { return m_wallet->CanGetAddresses(); }
513  bool hasExternalSigner() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER); }
514  bool privateKeysDisabled() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); }
515  bool taprootEnabled() override {
516  if (m_wallet->IsLegacy()) return false;
517  auto spk_man = m_wallet->GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/false);
518  return spk_man != nullptr;
519  }
520  OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; }
521  CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; }
522  void remove() override
523  {
524  RemoveWallet(m_context, m_wallet, /*load_on_start=*/false);
525  }
526  bool isLegacy() override { return m_wallet->IsLegacy(); }
527  std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
528  {
529  return MakeSignalHandler(m_wallet->NotifyUnload.connect(fn));
530  }
531  std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
532  {
533  return MakeSignalHandler(m_wallet->ShowProgress.connect(fn));
534  }
535  std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override
536  {
537  return MakeSignalHandler(m_wallet->NotifyStatusChanged.connect([fn](CWallet*) { fn(); }));
538  }
539  std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override
540  {
541  return MakeSignalHandler(m_wallet->NotifyAddressBookChanged.connect(
542  [fn](const CTxDestination& address, const std::string& label, bool is_mine,
543  AddressPurpose purpose, ChangeType status) { fn(address, label, is_mine, purpose, status); }));
544  }
545  std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) override
546  {
547  return MakeSignalHandler(m_wallet->NotifyTransactionChanged.connect(
548  [fn](const uint256& txid, ChangeType status) { fn(txid, status); }));
549  }
550  std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) override
551  {
552  return MakeSignalHandler(m_wallet->NotifyWatchonlyChanged.connect(fn));
553  }
554  std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override
555  {
556  return MakeSignalHandler(m_wallet->NotifyCanGetAddressesChanged.connect(fn));
557  }
558  CWallet* wallet() override { return m_wallet.get(); }
559 
560  WalletContext& m_context;
561  std::shared_ptr<CWallet> m_wallet;
562 };
563 
564 class WalletLoaderImpl : public WalletLoader
565 {
566 public:
567  WalletLoaderImpl(Chain& chain, ArgsManager& args)
568  {
569  m_context.chain = &chain;
570  m_context.args = &args;
571  }
572  ~WalletLoaderImpl() override { UnloadWallets(m_context); }
573 
575  void registerRpcs() override
576  {
577  for (const CRPCCommand& command : GetWalletRPCCommands()) {
578  m_rpc_commands.emplace_back(command.category, command.name, [this, &command](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
579  JSONRPCRequest wallet_request = request;
580  wallet_request.context = &m_context;
581  return command.actor(wallet_request, result, last_handler);
582  }, command.argNames, command.unique_id);
583  m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));
584  }
585  }
586  bool verify() override { return VerifyWallets(m_context); }
587  bool load() override { return LoadWallets(m_context); }
588  void start(CScheduler& scheduler) override { return StartWallets(m_context, scheduler); }
589  void flush() override { return FlushWallets(m_context); }
590  void stop() override { return StopWallets(m_context); }
591  void setMockTime(int64_t time) override { return SetMockTime(time); }
592 
594  util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) override
595  {
596  DatabaseOptions options;
597  DatabaseStatus status;
598  ReadDatabaseArgs(*m_context.args, options);
599  options.require_create = true;
600  options.create_flags = wallet_creation_flags;
601  options.create_passphrase = passphrase;
603  std::unique_ptr<Wallet> wallet{MakeWallet(m_context, CreateWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};
604  if (wallet) {
605  return {std::move(wallet)};
606  } else {
607  return util::Error{error};
608  }
609  }
610  util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) override
611  {
612  DatabaseOptions options;
613  DatabaseStatus status;
614  ReadDatabaseArgs(*m_context.args, options);
615  options.require_existing = true;
617  std::unique_ptr<Wallet> wallet{MakeWallet(m_context, LoadWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};
618  if (wallet) {
619  return {std::move(wallet)};
620  } else {
621  return util::Error{error};
622  }
623  }
624  util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) override
625  {
626  DatabaseStatus status;
628  std::unique_ptr<Wallet> wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings))};
629  if (wallet) {
630  return {std::move(wallet)};
631  } else {
632  return util::Error{error};
633  }
634  }
635  util::Result<WalletMigrationResult> migrateWallet(const std::string& name, const SecureString& passphrase) override
636  {
637  auto res = wallet::MigrateLegacyToDescriptor(name, passphrase, m_context);
638  if (!res) return util::Error{util::ErrorString(res)};
640  .wallet = MakeWallet(m_context, res->wallet),
641  .watchonly_wallet_name = res->watchonly_wallet ? std::make_optional(res->watchonly_wallet->GetName()) : std::nullopt,
642  .solvables_wallet_name = res->solvables_wallet ? std::make_optional(res->solvables_wallet->GetName()) : std::nullopt,
643  .backup_path = res->backup_path,
644  };
645  return {std::move(out)}; // std::move to work around clang bug
646  }
647  std::string getWalletDir() override
648  {
649  return fs::PathToString(GetWalletDir());
650  }
651  std::vector<std::string> listWalletDir() override
652  {
653  std::vector<std::string> paths;
654  for (auto& path : ListDatabases(GetWalletDir())) {
655  paths.push_back(fs::PathToString(path));
656  }
657  return paths;
658  }
659  std::vector<std::unique_ptr<Wallet>> getWallets() override
660  {
661  std::vector<std::unique_ptr<Wallet>> wallets;
662  for (const auto& wallet : GetWallets(m_context)) {
663  wallets.emplace_back(MakeWallet(m_context, wallet));
664  }
665  return wallets;
666  }
667  std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
668  {
669  return HandleLoadWallet(m_context, std::move(fn));
670  }
671  WalletContext* context() override { return &m_context; }
672 
673  WalletContext m_context;
674  const std::vector<std::string> m_wallet_filenames;
675  std::vector<std::unique_ptr<Handler>> m_rpc_handlers;
676  std::list<CRPCCommand> m_rpc_commands;
677 };
678 } // namespace
679 } // namespace wallet
680 
681 namespace interfaces {
682 std::unique_ptr<Wallet> MakeWallet(wallet::WalletContext& context, const std::shared_ptr<wallet::CWallet>& wallet) { return wallet ? std::make_unique<wallet::WalletImpl>(context, wallet) : nullptr; }
683 
684 std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args)
685 {
686  return std::make_unique<wallet::WalletLoaderImpl>(chain, args);
687 }
688 } // namespace interfaces
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:421
Helper for findBlock to selectively return pieces of block data.
Definition: chain.h:52
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:142
isminetype InputIsMine(const CWallet &wallet, const CTxIn &txin)
Definition: receive.cpp:12
AssertLockHeld(pool.cs)
std::vector< CTxDestination > txout_address
Definition: wallet.h:397
const std::vector< std::string > m_wallet_filenames
Definition: interfaces.cpp:674
void FlushWallets(WalletContext &context)
Flush all wallets in preparation for shutdown.
Definition: load.cpp:157
int returnedTarget
Definition: fees.h:95
std::function< void(std::unique_ptr< interfaces::Wallet > wallet)> LoadWalletFn
Definition: wallet.h:77
bool OutputIsChange(const CWallet &wallet, const CTxOut &txout)
Definition: receive.cpp:73
#define TRY_LOCK(cs, name)
Definition: sync.h:262
std::vector< wallet::isminetype > txin_is_mine
Definition: wallet.h:394
unsigned int time_received
Definition: wallet.h:415
Bilingual messages:
Definition: translation.h:18
SigningResult
Definition: message.h:43
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:360
std::shared_ptr< CWallet > m_wallet
Definition: interfaces.cpp:561
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:46
FeeReason reason
Definition: fees.h:93
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:58
std::unique_ptr< Wallet > MakeWallet(wallet::WalletContext &context, const std::shared_ptr< wallet::CWallet > &wallet)
Return implementation of Wallet interface.
Definition: interfaces.cpp:682
CTransactionRef tx
Definition: wallet.h:393
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:293
A version of CTransaction with the PSBT format.
Definition: psbt.h:946
Result CreateRateBumpTransaction(CWallet &wallet, const uint256 &txid, const CCoinControl &coin_control, std::vector< bilingual_str > &errors, CAmount &old_fee, CAmount &new_fee, CMutableTransaction &mtx, bool require_mine, const std::vector< CTxOut > &outputs, std::optional< uint32_t > original_change_index)
Create bumpfee transaction based on feerate estimates.
Definition: feebumper.cpp:164
CAmount CachedTxGetChange(const CWallet &wallet, const CWalletTx &wtx)
Definition: receive.cpp:139
CTxDestination getNewDestination(CWallet &w, OutputType output_type)
Returns a new destination, of an specific type, from the wallet.
Definition: util.cpp:91
std::map< std::string, std::string > WalletValueMap
Definition: wallet.h:57
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:11
OutputType
Definition: outputtype.h:17
bool TransactionCanBeBumped(const CWallet &wallet, const uint256 &txid)
Return whether transaction can be bumped.
Definition: feebumper.cpp:153
bool LoadWallets(WalletContext &context)
Load wallet databases.
Definition: load.cpp:105
Result CommitTransaction(CWallet &wallet, const uint256 &txid, CMutableTransaction &&mtx, std::vector< bilingual_str > &errors, uint256 &bumped_txid)
Commit the bumpfee transaction.
Definition: feebumper.cpp:357
void StopWallets(WalletContext &context)
Stop all wallets. Wallets will be flushed first.
Definition: load.cpp:164
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
std::vector< bool > txout_is_change
Definition: wallet.h:396
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:81
std::vector< wallet::isminetype > txout_is_mine
Definition: wallet.h:395
bool VerifyWallets(WalletContext &context)
Responsible for reading and validating the -wallet arguments and verifying the wallet database...
Definition: load.cpp:25
AddressPurpose
Address purpose field that has been been stored with wallet sending and receiving addresses since BIP...
Definition: types.h:60
Indicates that the wallet needs an external signer.
Definition: walletutil.h:77
std::unique_ptr< WalletLoader > MakeWalletLoader(Chain &chain, ArgsManager &args)
Return implementation of ChainClient interface for a wallet loader.
Definition: dummywallet.cpp:63
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:43
CAmount CachedTxGetCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:109
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:150
ArgsManager & args
Definition: bitcoind.cpp:269
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
void StartWallets(WalletContext &context, CScheduler &scheduler)
Complete startup of wallets.
Definition: load.cpp:144
Collection of wallet balances.
Definition: wallet.h:371
An input of a transaction.
Definition: transaction.h:74
#define LOCK(cs)
Definition: sync.h:258
const char * name
Definition: rest.cpp:45
bool CachedTxIsTrusted(const CWallet &wallet, const CWalletTx &wtx, std::set< uint256 > &trusted_parents)
Definition: receive.cpp:256
Fast randomness source.
Definition: random.h:143
An encapsulated public key.
Definition: pubkey.h:33
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:40
uint32_t n
Definition: transaction.h:39
Interface for accessing a wallet.
Definition: wallet.h:60
WalletContext context
CAmount GetTotalAmount()
Definition: spend.h:56
static bool verify(const CScriptNum10 &bignum, const CScriptNum &scriptnum)
NodeContext * m_context
Definition: interfaces.cpp:401
An output of a transaction.
Definition: transaction.h:157
std::vector< wallet::isminetype > txout_address_is_mine
Definition: wallet.h:398
CAmount immature_watch_only_balance
Definition: wallet.h:379
FeeReason
Definition: fees.h:58
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:35
static RPCHelpMan stop()
Definition: server.cpp:165
Wallet chain client that in addition to having chain client methods for starting up, shutting down, and registering RPCs, also has additional methods (called by the GUI) to load and create wallets.
Definition: wallet.h:322
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
Definition: wallet.cpp:4193
bool SignTransaction(CWallet &wallet, CMutableTransaction &mtx)
Sign the new transaction,.
Definition: feebumper.cpp:337
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:152
Generic interface for managing an event handler or callback function registered with another interfac...
Definition: handler.h:22
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:129
util::Result< PreSelectedInputs > FetchSelectedInputs(const CWallet &wallet, const CCoinControl &coin_control, const CoinSelectionParams &coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Fetch and validate coin control selected inputs.
Definition: spend.cpp:257
DatabaseStatus
Definition: db.h:197
256-bit opaque blob.
Definition: uint256.h:106
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:178
const auto command
CAmount unconfirmed_watch_only_balance
Definition: wallet.h:378
Migrated wallet info.
Definition: wallet.h:433
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:122
bool error(const char *fmt, const Args &... args)
Definition: logging.h:262
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:412
std::vector< std::unique_ptr< Handler > > m_rpc_handlers
Definition: interfaces.cpp:675
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
CoinsResult AvailableCoins(const CWallet &wallet, const CCoinControl *coinControl, std::optional< CFeeRate > feerate, const CoinFilterParams &params)
Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
Definition: spend.cpp:304
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
Definition: wallet.cpp:200
WalletContext struct containing references to state shared between CWallet instances, like the reference to the chain interface, and the list of opened wallets.
Definition: context.h:35
TransactionError
Definition: error.h:22
CAmount m_mine_trusted
Trusted, at depth=GetBalance.min_depth or more.
Definition: receive.h:52
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, int change_pos, const CCoinControl &coin_control, bool sign)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: spend.cpp:1278
std::vector< std::pair< std::string, std::string > > WalletOrderForm
Definition: wallet.h:56
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:81
Information about one wallet address.
Definition: wallet.h:357
A mutable version of CTransaction.
Definition: transaction.h:379
std::unique_ptr< Handler > MakeSignalHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
Definition: interfaces.cpp:47
std::vector< fs::path > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
Definition: db.cpp:19
void UnloadWallets(WalletContext &context)
Close all wallets.
Definition: load.cpp:171
std::map< std::string, std::string > value_map
Definition: wallet.h:403
CAmount GetRequiredFee(const CWallet &wallet, unsigned int nTxBytes)
Return the minimum required absolute fee for this size based on the required fee rate.
Definition: fees.cpp:13
Span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:888
std::shared_ptr< CWallet > wallet
Simple class for background tasks that should be run periodically or once "after a while"...
Definition: scheduler.h:38
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:373
ChangeType
General change type (added, updated, removed).
Definition: ui_change_type.h:9
CAmount GetMinimumFee(const CWallet &wallet, unsigned int nTxBytes, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee considering user set parameters and the required fee.
Definition: fees.cpp:19
std::shared_ptr< CWallet > RestoreWallet(WalletContext &context, const fs::path &backup_file, const std::string &wallet_name, std::optional< bool > load_on_start, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:478
std::list< CRPCCommand > m_rpc_commands
Definition: interfaces.cpp:676
Wallet transaction output.
Definition: wallet.h:424
CAmount OutputGetCredit(const CWallet &wallet, const CTxOut &txout, const isminefilter &filter)
Definition: receive.cpp:31
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
Updated transaction status.
Definition: wallet.h:410
FoundBlock & time(int64_t &time)
Definition: chain.h:57
std::map< CTxDestination, std::vector< COutput > > ListCoins(const CWallet &wallet)
Return list of available coins and locked coins grouped by non-change output address.
Definition: spend.cpp:494
CAmount CachedTxGetDebit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
filter decides which addresses will count towards the debit
Definition: receive.cpp:126
uint256 hash
Definition: transaction.h:38