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