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