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