aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Yanofsky <russ@yanofsky.org>2017-04-17 18:56:44 -0400
committerJohn Newbery <john@johnnewbery.com>2018-04-04 16:52:40 -0400
commita0704a8996bb950ae3c4d5b5a30e9dfe34cde1d3 (patch)
treed7dc5b382640f965bdff98baa1aa4e21a7af5d20
parent90d4640b7eff3154a0750c5acb52d39bd41e0bbb (diff)
Remove most direct bitcoin calls from qt/walletmodel.cpp
-rw-r--r--src/interface/node.cpp18
-rw-r--r--src/interface/node.h10
-rw-r--r--src/interface/wallet.cpp212
-rw-r--r--src/interface/wallet.h200
-rw-r--r--src/qt/bitcoin.cpp6
-rw-r--r--src/qt/bitcoingui.cpp4
-rw-r--r--src/qt/coincontroldialog.cpp12
-rw-r--r--src/qt/overviewpage.cpp8
-rw-r--r--src/qt/receivecoinsdialog.cpp6
-rw-r--r--src/qt/sendcoinsdialog.cpp16
-rw-r--r--src/qt/signverifymessagedialog.cpp2
-rw-r--r--src/qt/test/wallettests.cpp6
-rw-r--r--src/qt/transactionview.cpp10
-rw-r--r--src/qt/walletmodel.cpp306
-rw-r--r--src/qt/walletmodel.h59
-rw-r--r--src/qt/walletmodeltransaction.cpp20
-rw-r--r--src/qt/walletmodeltransaction.h15
-rw-r--r--src/qt/walletview.cpp2
18 files changed, 585 insertions, 327 deletions
diff --git a/src/interface/node.cpp b/src/interface/node.cpp
index 2f0114f5e4..db03cc0627 100644
--- a/src/interface/node.cpp
+++ b/src/interface/node.cpp
@@ -5,6 +5,7 @@
#include <interface/node.h>
#include <addrdb.h>
+#include <amount.h>
#include <chain.h>
#include <chainparams.h>
#include <init.h>
@@ -28,6 +29,7 @@
#include <config/bitcoin-config.h>
#endif
#ifdef ENABLE_WALLET
+#include <wallet/wallet.h>
#define CHECK_WALLET(x) x
#else
#define CHECK_WALLET(x) throw std::logic_error("Wallet function called in non-wallet build.")
@@ -37,8 +39,6 @@
#include <boost/thread/thread.hpp>
#include <univalue.h>
-class CWallet;
-
namespace interface {
namespace {
@@ -185,6 +185,8 @@ class NodeImpl : public Node
}
}
bool getNetworkActive() override { return g_connman && g_connman->GetNetworkActive(); }
+ unsigned int getTxConfirmTarget() override { CHECK_WALLET(return ::nTxConfirmTarget); }
+ CAmount getMaxTxFee() override { return ::maxTxFee; }
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
{
JSONRPCRequest req;
@@ -196,6 +198,18 @@ class NodeImpl : public Node
std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
+ std::vector<std::unique_ptr<Wallet>> getWallets() override
+ {
+#ifdef ENABLE_WALLET
+ std::vector<std::unique_ptr<Wallet>> wallets;
+ for (CWalletRef wallet : ::vpwallets) {
+ wallets.emplace_back(MakeWallet(*wallet));
+ }
+ return wallets;
+#else
+ throw std::logic_error("Node::getWallets() called in non-wallet build.");
+#endif
+ }
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
return MakeHandler(::uiInterface.InitMessage.connect(fn));
diff --git a/src/interface/node.h b/src/interface/node.h
index aeac1d6215..b0d435695e 100644
--- a/src/interface/node.h
+++ b/src/interface/node.h
@@ -6,6 +6,7 @@
#define BITCOIN_INTERFACE_NODE_H
#include <addrdb.h> // For banmap_t
+#include <amount.h> // For CAmount
#include <init.h> // For HelpMessageMode
#include <net.h> // For CConnman::NumConnections
#include <netaddress.h> // For Network
@@ -141,6 +142,12 @@ public:
//! Get network active.
virtual bool getNetworkActive() = 0;
+ //! Get tx confirm target.
+ virtual unsigned int getTxConfirmTarget() = 0;
+
+ //! Get max tx fee.
+ virtual CAmount getMaxTxFee() = 0;
+
//! Execute rpc command.
virtual UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) = 0;
@@ -153,6 +160,9 @@ public:
//! Unset RPC timer interface.
virtual void rpcUnsetTimerInterface(RPCTimerInterface* iface) = 0;
+ //! Return interfaces for accessing wallets (if any).
+ virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
+
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;
diff --git a/src/interface/wallet.cpp b/src/interface/wallet.cpp
index 01639aa37f..8dae7ac547 100644
--- a/src/interface/wallet.cpp
+++ b/src/interface/wallet.cpp
@@ -4,7 +4,21 @@
#include <interface/wallet.h>
+#include <amount.h>
+#include <chain.h>
+#include <consensus/validation.h>
#include <interface/handler.h>
+#include <net.h>
+#include <policy/policy.h>
+#include <primitives/transaction.h>
+#include <script/ismine.h>
+#include <script/standard.h>
+#include <support/allocators/secure.h>
+#include <sync.h>
+#include <ui_interface.h>
+#include <uint256.h>
+#include <validation.h>
+#include <wallet/feebumper.h>
#include <wallet/wallet.h>
#include <memory>
@@ -12,15 +26,213 @@
namespace interface {
namespace {
+class PendingWalletTxImpl : public PendingWalletTx
+{
+public:
+ PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet), m_key(&wallet) {}
+
+ const CTransaction& get() override { return *m_tx; }
+
+ int64_t getVirtualSize() override { return GetVirtualTransactionSize(*m_tx); }
+
+ bool commit(WalletValueMap value_map,
+ WalletOrderForm order_form,
+ std::string from_account,
+ std::string& reject_reason) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ CValidationState state;
+ if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), std::move(from_account), m_key, g_connman.get(), state)) {
+ reject_reason = state.GetRejectReason();
+ return false;
+ }
+ return true;
+ }
+
+ CTransactionRef m_tx;
+ CWallet& m_wallet;
+ CReserveKey m_key;
+};
+
class WalletImpl : public Wallet
{
public:
WalletImpl(CWallet& wallet) : m_wallet(wallet) {}
+ bool encryptWallet(const SecureString& wallet_passphrase) override
+ {
+ return m_wallet.EncryptWallet(wallet_passphrase);
+ }
+ bool isCrypted() override { return m_wallet.IsCrypted(); }
+ bool lock() override { return m_wallet.Lock(); }
+ bool unlock(const SecureString& wallet_passphrase) override { return m_wallet.Unlock(wallet_passphrase); }
+ bool isLocked() override { return m_wallet.IsLocked(); }
+ bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
+ const SecureString& new_wallet_passphrase) override
+ {
+ return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase);
+ }
+ bool backupWallet(const std::string& filename) override { return m_wallet.BackupWallet(filename); }
+ std::string getWalletName() override { return m_wallet.GetName(); }
+ bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet.GetPubKey(address, pub_key); }
+ bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet.GetKey(address, key); }
+ bool isSpendable(const CTxDestination& dest) override { return IsMine(m_wallet, dest) & ISMINE_SPENDABLE; }
+ bool haveWatchOnly() override { return m_wallet.HaveWatchOnly(); };
+ bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::string& purpose) override
+ {
+ return m_wallet.SetAddressBook(dest, name, purpose);
+ }
+ bool getAddress(const CTxDestination& dest, std::string* name, isminetype* is_mine) override
+ {
+ LOCK(m_wallet.cs_wallet);
+ auto it = m_wallet.mapAddressBook.find(dest);
+ if (it == m_wallet.mapAddressBook.end()) {
+ return false;
+ }
+ if (name) {
+ *name = it->second.name;
+ }
+ if (is_mine) {
+ *is_mine = IsMine(m_wallet, dest);
+ }
+ return true;
+ }
+ bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override
+ {
+ LOCK(m_wallet.cs_wallet);
+ return m_wallet.AddDestData(dest, key, value);
+ }
+ bool eraseDestData(const CTxDestination& dest, const std::string& key) override
+ {
+ LOCK(m_wallet.cs_wallet);
+ return m_wallet.EraseDestData(dest, key);
+ }
+ std::vector<std::string> getDestValues(const std::string& prefix) override
+ {
+ return m_wallet.GetDestValues(prefix);
+ }
+ void lockCoin(const COutPoint& output) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ return m_wallet.LockCoin(output);
+ }
+ void unlockCoin(const COutPoint& output) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ return m_wallet.UnlockCoin(output);
+ }
+ bool isLockedCoin(const COutPoint& output) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ return m_wallet.IsLockedCoin(output.hash, output.n);
+ }
+ void listLockedCoins(std::vector<COutPoint>& outputs) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ return m_wallet.ListLockedCoins(outputs);
+ }
+ std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
+ const CCoinControl& coin_control,
+ bool sign,
+ int& change_pos,
+ CAmount& fee,
+ std::string& fail_reason) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ auto pending = MakeUnique<PendingWalletTxImpl>(m_wallet);
+ if (!m_wallet.CreateTransaction(recipients, pending->m_tx, pending->m_key, fee, change_pos,
+ fail_reason, coin_control, sign)) {
+ return {};
+ }
+ return std::move(pending);
+ }
+ bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); }
+ bool abandonTransaction(const uint256& txid) override
+ {
+ LOCK2(cs_main, m_wallet.cs_wallet);
+ return m_wallet.AbandonTransaction(txid);
+ }
+ bool transactionCanBeBumped(const uint256& txid) override
+ {
+ return feebumper::TransactionCanBeBumped(&m_wallet, txid);
+ }
+ bool createBumpTransaction(const uint256& txid,
+ const CCoinControl& coin_control,
+ CAmount total_fee,
+ std::vector<std::string>& errors,
+ CAmount& old_fee,
+ CAmount& new_fee,
+ CMutableTransaction& mtx) override
+ {
+ return feebumper::CreateTransaction(&m_wallet, txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
+ feebumper::Result::OK;
+ }
+ bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(&m_wallet, mtx); }
+ bool commitBumpTransaction(const uint256& txid,
+ CMutableTransaction&& mtx,
+ std::vector<std::string>& errors,
+ uint256& bumped_txid) override
+ {
+ return feebumper::CommitTransaction(&m_wallet, txid, std::move(mtx), errors, bumped_txid) ==
+ feebumper::Result::OK;
+ }
+ WalletBalances getBalances() override
+ {
+ WalletBalances result;
+ result.balance = m_wallet.GetBalance();
+ result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance();
+ result.immature_balance = m_wallet.GetImmatureBalance();
+ result.have_watch_only = m_wallet.HaveWatchOnly();
+ if (result.have_watch_only) {
+ result.watch_only_balance = m_wallet.GetWatchOnlyBalance();
+ result.unconfirmed_watch_only_balance = m_wallet.GetUnconfirmedWatchOnlyBalance();
+ result.immature_watch_only_balance = m_wallet.GetImmatureWatchOnlyBalance();
+ }
+ return result;
+ }
+ bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
+ {
+ TRY_LOCK(cs_main, locked_chain);
+ if (!locked_chain) return false;
+ TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
+ if (!locked_wallet) {
+ return false;
+ }
+ balances = getBalances();
+ num_blocks = ::chainActive.Height();
+ return true;
+ }
+ CAmount getBalance() override { return m_wallet.GetBalance(); }
+ CAmount getAvailableBalance(const CCoinControl& coin_control) override
+ {
+ return m_wallet.GetAvailableBalance(&coin_control);
+ }
+ bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
+ OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
+ OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
return MakeHandler(m_wallet.ShowProgress.connect(fn));
}
+ std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); }));
+ }
+ std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyAddressBookChanged.connect(
+ [fn](CWallet*, const CTxDestination& address, const std::string& label, bool is_mine,
+ const std::string& purpose, ChangeType status) { fn(address, label, is_mine, purpose, status); }));
+ }
+ std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyTransactionChanged.connect(
+ [fn, this](CWallet*, const uint256& txid, ChangeType status) { fn(txid, status); }));
+ }
+ std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
+ }
CWallet& m_wallet;
};
diff --git a/src/interface/wallet.h b/src/interface/wallet.h
index bf68df4e7d..317b5c683c 100644
--- a/src/interface/wallet.h
+++ b/src/interface/wallet.h
@@ -5,15 +5,34 @@
#ifndef BITCOIN_INTERFACE_WALLET_H
#define BITCOIN_INTERFACE_WALLET_H
+#include <amount.h> // For CAmount
+#include <script/ismine.h> // For isminefilter, isminetype
+#include <script/standard.h> // For CTxDestination
+#include <support/allocators/secure.h> // For SecureString
+#include <ui_interface.h> // For ChangeType
+
#include <functional>
+#include <map>
#include <memory>
+#include <stdint.h>
#include <string>
+#include <utility>
+#include <vector>
+class CCoinControl;
+class CKey;
class CWallet;
+enum class OutputType;
+struct CRecipient;
namespace interface {
class Handler;
+class PendingWalletTx;
+struct WalletBalances;
+
+using WalletOrderForm = std::vector<std::pair<std::string, std::string>>;
+using WalletValueMap = std::map<std::string, std::string>;
//! Interface for accessing a wallet.
class Wallet
@@ -21,9 +40,190 @@ class Wallet
public:
virtual ~Wallet() {}
+ //! Encrypt wallet.
+ virtual bool encryptWallet(const SecureString& wallet_passphrase) = 0;
+
+ //! Return whether wallet is encrypted.
+ virtual bool isCrypted() = 0;
+
+ //! Lock wallet.
+ virtual bool lock() = 0;
+
+ //! Unlock wallet.
+ virtual bool unlock(const SecureString& wallet_passphrase) = 0;
+
+ //! Return whether wallet is locked.
+ virtual bool isLocked() = 0;
+
+ //! Change wallet passphrase.
+ virtual bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
+ const SecureString& new_wallet_passphrase) = 0;
+
+ //! Back up wallet.
+ virtual bool backupWallet(const std::string& filename) = 0;
+
+ //! Get wallet name.
+ virtual std::string getWalletName() = 0;
+
+ //! Get public key.
+ virtual bool getPubKey(const CKeyID& address, CPubKey& pub_key) = 0;
+
+ //! Get private key.
+ virtual bool getPrivKey(const CKeyID& address, CKey& key) = 0;
+
+ //! Return whether wallet has private key.
+ virtual bool isSpendable(const CTxDestination& dest) = 0;
+
+ //! Return whether wallet has watch only keys.
+ virtual bool haveWatchOnly() = 0;
+
+ //! Add or update address.
+ virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::string& purpose) = 0;
+
+ //! Look up address in wallet, return whether exists.
+ virtual bool getAddress(const CTxDestination& dest,
+ std::string* name = nullptr,
+ isminetype* is_mine = nullptr) = 0;
+
+ //! Add dest data.
+ virtual bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) = 0;
+
+ //! Erase dest data.
+ virtual bool eraseDestData(const CTxDestination& dest, const std::string& key) = 0;
+
+ //! Get dest values with prefix.
+ virtual std::vector<std::string> getDestValues(const std::string& prefix) = 0;
+
+ //! Lock coin.
+ virtual void lockCoin(const COutPoint& output) = 0;
+
+ //! Unlock coin.
+ virtual void unlockCoin(const COutPoint& output) = 0;
+
+ //! Return whether coin is locked.
+ virtual bool isLockedCoin(const COutPoint& output) = 0;
+
+ //! List locked coins.
+ virtual void listLockedCoins(std::vector<COutPoint>& outputs) = 0;
+
+ //! Create transaction.
+ virtual std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
+ const CCoinControl& coin_control,
+ bool sign,
+ int& change_pos,
+ CAmount& fee,
+ std::string& fail_reason) = 0;
+
+ //! Return whether transaction can be abandoned.
+ virtual bool transactionCanBeAbandoned(const uint256& txid) = 0;
+
+ //! Abandon transaction.
+ virtual bool abandonTransaction(const uint256& txid) = 0;
+
+ //! Return whether transaction can be bumped.
+ virtual bool transactionCanBeBumped(const uint256& txid) = 0;
+
+ //! Create bump transaction.
+ virtual bool createBumpTransaction(const uint256& txid,
+ const CCoinControl& coin_control,
+ CAmount total_fee,
+ std::vector<std::string>& errors,
+ CAmount& old_fee,
+ CAmount& new_fee,
+ CMutableTransaction& mtx) = 0;
+
+ //! Sign bump transaction.
+ virtual bool signBumpTransaction(CMutableTransaction& mtx) = 0;
+
+ //! Commit bump transaction.
+ virtual bool commitBumpTransaction(const uint256& txid,
+ CMutableTransaction&& mtx,
+ std::vector<std::string>& errors,
+ uint256& bumped_txid) = 0;
+
+ //! Get balances.
+ virtual WalletBalances getBalances() = 0;
+
+ //! Get balances if possible without blocking.
+ virtual bool tryGetBalances(WalletBalances& balances, int& num_blocks) = 0;
+
+ //! Get balance.
+ virtual CAmount getBalance() = 0;
+
+ //! Get available balance.
+ virtual CAmount getAvailableBalance(const CCoinControl& coin_control) = 0;
+
+ // Return whether HD enabled.
+ virtual bool hdEnabled() = 0;
+
+ // Get default address type.
+ virtual OutputType getDefaultAddressType() = 0;
+
+ // Get default change type.
+ virtual OutputType getDefaultChangeType() = 0;
+
//! Register handler for show progress messages.
using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
+
+ //! Register handler for status changed messages.
+ using StatusChangedFn = std::function<void()>;
+ virtual std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) = 0;
+
+ //! Register handler for address book changed messages.
+ using AddressBookChangedFn = std::function<void(const CTxDestination& address,
+ const std::string& label,
+ bool is_mine,
+ const std::string& purpose,
+ ChangeType status)>;
+ virtual std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) = 0;
+
+ //! Register handler for transaction changed messages.
+ using TransactionChangedFn = std::function<void(const uint256& txid, ChangeType status)>;
+ virtual std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) = 0;
+
+ //! Register handler for watchonly changed messages.
+ using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
+ virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
+};
+
+//! Tracking object returned by CreateTransaction and passed to CommitTransaction.
+class PendingWalletTx
+{
+public:
+ virtual ~PendingWalletTx() {}
+
+ //! Get transaction data.
+ virtual const CTransaction& get() = 0;
+
+ //! Get virtual transaction size.
+ virtual int64_t getVirtualSize() = 0;
+
+ //! Send pending transaction and commit to wallet.
+ virtual bool commit(WalletValueMap value_map,
+ WalletOrderForm order_form,
+ std::string from_account,
+ std::string& reject_reason) = 0;
+};
+
+//! Collection of wallet balances.
+struct WalletBalances
+{
+ CAmount balance = 0;
+ CAmount unconfirmed_balance = 0;
+ CAmount immature_balance = 0;
+ bool have_watch_only = false;
+ CAmount watch_only_balance = 0;
+ CAmount unconfirmed_watch_only_balance = 0;
+ CAmount immature_watch_only_balance = 0;
+
+ bool balanceChanged(const WalletBalances& prev) const
+ {
+ return balance != prev.balance || unconfirmed_balance != prev.unconfirmed_balance ||
+ immature_balance != prev.immature_balance || watch_only_balance != prev.watch_only_balance ||
+ unconfirmed_watch_only_balance != prev.unconfirmed_watch_only_balance ||
+ immature_watch_only_balance != prev.immature_watch_only_balance;
+ }
};
//! Return implementation of Wallet interface. This function will be undefined
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 279726d6df..33a5fe8015 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -465,8 +465,10 @@ void BitcoinApplication::initializeResult(bool success)
#ifdef ENABLE_WALLET
bool fFirstWallet = true;
- for (CWalletRef pwallet : vpwallets) {
- WalletModel * const walletModel = new WalletModel(platformStyle, pwallet, optionsModel);
+ auto wallets = m_node.getWallets();
+ auto cwallet = ::vpwallets.begin();
+ for (auto& wallet : wallets) {
+ WalletModel * const walletModel = new WalletModel(std::move(wallet), m_node, platformStyle, *cwallet++, optionsModel);
window->addWallet(walletModel);
if (fFirstWallet) {
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index aa9f1f0071..63a2a200b2 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1010,7 +1010,7 @@ void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmoun
// On new transaction, make an info balloon
QString msg = tr("Date: %1\n").arg(date) +
tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
- if (WalletModel::isMultiwallet() && !walletName.isEmpty()) {
+ if (m_node.getWallets().size() > 1 && !walletName.isEmpty()) {
msg += tr("Wallet: %1\n").arg(walletName);
}
msg += tr("Type: %1\n").arg(type);
@@ -1116,7 +1116,7 @@ void BitcoinGUI::updateWalletStatus()
}
WalletModel * const walletModel = walletView->getWalletModel();
setEncryptionStatus(walletModel->getEncryptionStatus());
- setHDStatus(walletModel->hdEnabled());
+ setHDStatus(walletModel->wallet().hdEnabled());
}
#endif // ENABLE_WALLET
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index a45e9f85c1..0a656a6f9b 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -209,7 +209,7 @@ void CoinControlDialog::showMenu(const QPoint &point)
if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode)
{
copyTransactionHashAction->setEnabled(true);
- if (model->isLockedCoin(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()))
+ if (model->wallet().isLockedCoin(COutPoint(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())))
{
lockAction->setEnabled(false);
unlockAction->setEnabled(true);
@@ -269,7 +269,7 @@ void CoinControlDialog::lockCoin()
contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt());
- model->lockCoin(outpt);
+ model->wallet().lockCoin(outpt);
contextMenuItem->setDisabled(true);
contextMenuItem->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed"));
updateLabelLocked();
@@ -279,7 +279,7 @@ void CoinControlDialog::lockCoin()
void CoinControlDialog::unlockCoin()
{
COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt());
- model->unlockCoin(outpt);
+ model->wallet().unlockCoin(outpt);
contextMenuItem->setDisabled(false);
contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon());
updateLabelLocked();
@@ -405,7 +405,7 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
void CoinControlDialog::updateLabelLocked()
{
std::vector<COutPoint> vOutpts;
- model->listLockedCoins(vOutpts);
+ model->wallet().listLockedCoins(vOutpts);
if (vOutpts.size() > 0)
{
ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size()));
@@ -479,7 +479,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
{
CPubKey pubkey;
CKeyID *keyid = boost::get<CKeyID>(&address);
- if (keyid && model->getPubKey(*keyid, pubkey))
+ if (keyid && model->wallet().getPubKey(*keyid, pubkey))
{
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
}
@@ -706,7 +706,7 @@ void CoinControlDialog::updateView()
itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i));
// disable locked coins
- if (model->isLockedCoin(txhash, out.i))
+ if (model->wallet().isLockedCoin(COutPoint(txhash, out.i)))
{
COutPoint outpt(txhash, out.i);
coinControl()->UnSelect(outpt); // just to be sure
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index d1c9f17961..aaea650141 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -231,13 +231,15 @@ void OverviewPage::setWalletModel(WalletModel *model)
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
// Keep up to date with wallet
- setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(),
- model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance());
+ interface::Wallet& wallet = model->wallet();
+ interface::WalletBalances balances = wallet.getBalances();
+ setBalance(balances.balance, balances.unconfirmed_balance, balances.immature_balance,
+ balances.watch_only_balance, balances.unconfirmed_watch_only_balance, balances.immature_watch_only_balance);
connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)));
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
- updateWatchOnlyLabels(model->haveWatchOnly());
+ updateWatchOnlyLabels(wallet.haveWatchOnly());
connect(model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyLabels(bool)));
}
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index c8b6366db0..70e11f0296 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -95,13 +95,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
// configure bech32 checkbox, disable if launched with legacy as default:
- if (model->getDefaultAddressType() == OutputType::BECH32) {
+ if (model->wallet().getDefaultAddressType() == OutputType::BECH32) {
ui->useBech32->setCheckState(Qt::Checked);
} else {
ui->useBech32->setCheckState(Qt::Unchecked);
}
- ui->useBech32->setVisible(model->getDefaultAddressType() != OutputType::LEGACY);
+ ui->useBech32->setVisible(model->wallet().getDefaultAddressType() != OutputType::LEGACY);
}
}
@@ -144,7 +144,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
QString address;
QString label = ui->reqLabel->text();
/* Generate new receiving address */
- OutputType address_type = model->getDefaultAddressType();
+ OutputType address_type = model->wallet().getDefaultAddressType();
if (address_type != OutputType::LEGACY) {
address_type = ui->useBech32->isChecked() ? OutputType::BECH32 : OutputType::P2SH_SEGWIT;
}
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 8a52aadbb0..98f08bbc59 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -15,6 +15,7 @@
#include <qt/sendcoinsentry.h>
#include <chainparams.h>
+#include <interface/node.h>
#include <key_io.h>
#include <wallet/coincontrol.h>
#include <validation.h> // mempool and minRelayTxFee
@@ -149,8 +150,9 @@ void SendCoinsDialog::setModel(WalletModel *_model)
}
}
- setBalance(_model->getBalance(), _model->getUnconfirmedBalance(), _model->getImmatureBalance(),
- _model->getWatchBalance(), _model->getWatchUnconfirmedBalance(), _model->getWatchImmatureBalance());
+ interface::WalletBalances balances = _model->wallet().getBalances();
+ setBalance(balances.balance, balances.unconfirmed_balance, balances.immature_balance,
+ balances.watch_only_balance, balances.unconfirmed_watch_only_balance, balances.immature_watch_only_balance);
connect(_model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)));
connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
updateDisplayUnit();
@@ -193,7 +195,7 @@ void SendCoinsDialog::setModel(WalletModel *_model)
settings.remove("nSmartFeeSliderPosition");
}
if (settings.value("nConfTarget").toInt() == 0)
- ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->getDefaultConfirmTarget()));
+ ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->node().getTxConfirmTarget()));
else
ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(settings.value("nConfTarget").toInt()));
}
@@ -372,7 +374,7 @@ void SendCoinsDialog::on_sendButton_clicked()
accept();
CoinControlDialog::coinControl()->UnSelectAll();
coinControlUpdateLabels();
- Q_EMIT coinsSent(currentTransaction.getTransaction()->GetHash());
+ Q_EMIT coinsSent(currentTransaction.getWtx()->get().GetHash());
}
fNewRecipientAllowed = true;
}
@@ -532,7 +534,7 @@ void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfir
void SendCoinsDialog::updateDisplayUnit()
{
- setBalance(model->getBalance(), 0, 0, 0, 0, 0);
+ setBalance(model->wallet().getBalance(), 0, 0, 0, 0, 0);
ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
updateMinFeeLabel();
updateSmartFeeLabel();
@@ -618,7 +620,7 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
}
// Calculate available amount to send.
- CAmount amount = model->getBalance(&coin_control);
+ CAmount amount = model->wallet().getAvailableBalance(coin_control);
for (int i = 0; i < ui->entries->count(); ++i) {
SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if (e && !e->isHidden() && e != entry) {
@@ -814,7 +816,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
}
else // Valid address
{
- if (!model->IsSpendable(dest)) {
+ if (!model->wallet().isSpendable(dest)) {
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
// confirmation dialog
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 8dade8df79..94a3ad7987 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -140,7 +140,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
}
CKey key;
- if (!model->getPrivKey(*keyID, key))
+ if (!model->wallet().getPrivKey(*keyID, key))
{
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index ebca4b6499..d28d4bd7e6 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -178,7 +178,9 @@ void TestGUI()
TransactionView transactionView(platformStyle.get());
auto node = interface::MakeNode();
OptionsModel optionsModel(*node);
- WalletModel walletModel(platformStyle.get(), &wallet, &optionsModel);
+ vpwallets.insert(vpwallets.begin(), &wallet);
+ WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &wallet, &optionsModel);
+ vpwallets.erase(vpwallets.begin());
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);
@@ -203,7 +205,7 @@ void TestGUI()
QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance");
QString balanceText = balanceLabel->text();
int unit = walletModel.getOptionsModel()->getDisplayUnit();
- CAmount balance = walletModel.getBalance();
+ CAmount balance = walletModel.wallet().getBalance();
QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::separatorAlways);
QCOMPARE(balanceText, balanceComparison);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 26391452da..aa6444245a 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -254,7 +254,7 @@ void TransactionView::setModel(WalletModel *_model)
}
// show/hide column Watch-only
- updateWatchOnlyColumn(_model->haveWatchOnly());
+ updateWatchOnlyColumn(_model->wallet().haveWatchOnly());
// Watch-only signal
connect(_model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool)));
@@ -364,7 +364,7 @@ void TransactionView::exportClicked()
// name, column, role
writer.setModel(transactionProxyModel);
writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
- if (model->haveWatchOnly())
+ if (model->wallet().haveWatchOnly())
writer.addColumn(tr("Watch-only"), TransactionTableModel::Watchonly);
writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
@@ -393,8 +393,8 @@ void TransactionView::contextualMenu(const QPoint &point)
// check if transaction can be abandoned, disable context menu action in case it doesn't
uint256 hash;
hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString());
- abandonAction->setEnabled(model->transactionCanBeAbandoned(hash));
- bumpFeeAction->setEnabled(model->transactionCanBeBumped(hash));
+ abandonAction->setEnabled(model->wallet().transactionCanBeAbandoned(hash));
+ bumpFeeAction->setEnabled(model->wallet().transactionCanBeBumped(hash));
if(index.isValid())
{
@@ -414,7 +414,7 @@ void TransactionView::abandonTx()
hash.SetHex(hashQStr.toStdString());
// Abandon the wallet transaction over the walletModel
- model->abandonTransaction(hash);
+ model->wallet().abandonTransaction(hash);
// Update the table
model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 795302be58..7a19773cf7 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -15,6 +15,8 @@
#include <qt/transactiontablemodel.h>
#include <chain.h>
+#include <interface/handler.h>
+#include <interface/node.h>
#include <key_io.h>
#include <keystore.h>
#include <validation.h>
@@ -37,21 +39,19 @@
#include <QTimer>
-WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) :
- QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
+WalletModel::WalletModel(std::unique_ptr<interface::Wallet> wallet, interface::Node& node, const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) :
+ QObject(parent), m_wallet(std::move(wallet)), m_node(node), cwallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
transactionTableModel(0),
recentRequestsTableModel(0),
- cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0),
- cachedWatchOnlyBalance{0}, cachedWatchUnconfBalance{0}, cachedWatchImmatureBalance{0},
cachedEncryptionStatus(Unencrypted),
cachedNumBlocks(0)
{
- fHaveWatchOnly = wallet->HaveWatchOnly();
+ fHaveWatchOnly = m_wallet->haveWatchOnly();
fForceCheckBalanceChanged = false;
- addressTableModel = new AddressTableModel(wallet, this);
- transactionTableModel = new TransactionTableModel(platformStyle, wallet, this);
- recentRequestsTableModel = new RecentRequestsTableModel(wallet, this);
+ addressTableModel = new AddressTableModel(cwallet, this);
+ transactionTableModel = new TransactionTableModel(platformStyle, cwallet, this);
+ recentRequestsTableModel = new RecentRequestsTableModel(cwallet, this);
// This timer will be fired repeatedly to update the balance
pollTimer = new QTimer(this);
@@ -66,46 +66,6 @@ WalletModel::~WalletModel()
unsubscribeFromCoreSignals();
}
-CAmount WalletModel::getBalance(const CCoinControl *coinControl) const
-{
- if (coinControl)
- {
- return wallet->GetAvailableBalance(coinControl);
- }
-
- return wallet->GetBalance();
-}
-
-CAmount WalletModel::getUnconfirmedBalance() const
-{
- return wallet->GetUnconfirmedBalance();
-}
-
-CAmount WalletModel::getImmatureBalance() const
-{
- return wallet->GetImmatureBalance();
-}
-
-bool WalletModel::haveWatchOnly() const
-{
- return fHaveWatchOnly;
-}
-
-CAmount WalletModel::getWatchBalance() const
-{
- return wallet->GetWatchOnlyBalance();
-}
-
-CAmount WalletModel::getWatchUnconfirmedBalance() const
-{
- return wallet->GetUnconfirmedWatchOnlyBalance();
-}
-
-CAmount WalletModel::getWatchImmatureBalance() const
-{
- return wallet->GetImmatureWatchOnlyBalance();
-}
-
void WalletModel::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
@@ -117,55 +77,34 @@ void WalletModel::updateStatus()
void WalletModel::pollBalanceChanged()
{
- // Get required locks upfront. This avoids the GUI from getting stuck on
- // periodical polls if the core is holding the locks for a longer time -
- // for example, during a wallet rescan.
- TRY_LOCK(cs_main, lockMain);
- if(!lockMain)
- return;
- TRY_LOCK(wallet->cs_wallet, lockWallet);
- if(!lockWallet)
+ // Try to get balances and return early if locks can't be acquired. This
+ // avoids the GUI from getting stuck on periodical polls if the core is
+ // holding the locks for a longer time - for example, during a wallet
+ // rescan.
+ interface::WalletBalances new_balances;
+ int numBlocks = -1;
+ if (!m_wallet->tryGetBalances(new_balances, numBlocks)) {
return;
+ }
- if(fForceCheckBalanceChanged || chainActive.Height() != cachedNumBlocks)
+ if(fForceCheckBalanceChanged || m_node.getNumBlocks() != cachedNumBlocks)
{
fForceCheckBalanceChanged = false;
// Balance and number of transactions might have changed
- cachedNumBlocks = chainActive.Height();
+ cachedNumBlocks = m_node.getNumBlocks();
- checkBalanceChanged();
+ checkBalanceChanged(new_balances);
if(transactionTableModel)
transactionTableModel->updateConfirmations();
}
}
-void WalletModel::checkBalanceChanged()
+void WalletModel::checkBalanceChanged(const interface::WalletBalances& new_balances)
{
- CAmount newBalance = getBalance();
- CAmount newUnconfirmedBalance = getUnconfirmedBalance();
- CAmount newImmatureBalance = getImmatureBalance();
- CAmount newWatchOnlyBalance = 0;
- CAmount newWatchUnconfBalance = 0;
- CAmount newWatchImmatureBalance = 0;
- if (haveWatchOnly())
- {
- newWatchOnlyBalance = getWatchBalance();
- newWatchUnconfBalance = getWatchUnconfirmedBalance();
- newWatchImmatureBalance = getWatchImmatureBalance();
- }
-
- if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance ||
- cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance)
- {
- cachedBalance = newBalance;
- cachedUnconfirmedBalance = newUnconfirmedBalance;
- cachedImmatureBalance = newImmatureBalance;
- cachedWatchOnlyBalance = newWatchOnlyBalance;
- cachedWatchUnconfBalance = newWatchUnconfBalance;
- cachedWatchImmatureBalance = newWatchImmatureBalance;
- Q_EMIT balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance,
- newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance);
+ if(new_balances.balanceChanged(m_cached_balances)) {
+ m_cached_balances = new_balances;
+ Q_EMIT balanceChanged(new_balances.balance, new_balances.unconfirmed_balance, new_balances.immature_balance, new_balances.watch_only_balance, new_balances.unconfirmed_watch_only_balance, new_balances.immature_watch_only_balance);
}
}
@@ -260,7 +199,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return DuplicateAddress;
}
- CAmount nBalance = getBalance(&coinControl);
+ CAmount nBalance = m_wallet->getAvailableBalance(coinControl);
if(total > nBalance)
{
@@ -268,22 +207,17 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
}
{
- LOCK2(cs_main, wallet->cs_wallet);
-
- transaction.newPossibleKeyChange(wallet);
-
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
std::string strFailReason;
- CTransactionRef& newTx = transaction.getTransaction();
- CReserveKey *keyChange = transaction.getPossibleKeyChange();
- bool fCreated = wallet->CreateTransaction(vecSend, newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl);
+ auto& newTx = transaction.getWtx();
+ newTx = m_wallet->createTransaction(vecSend, coinControl, true /* sign */, nChangePosRet, nFeeRequired, strFailReason);
transaction.setTransactionFee(nFeeRequired);
- if (fSubtractFeeFromAmount && fCreated)
+ if (fSubtractFeeFromAmount && newTx)
transaction.reassignAmounts(nChangePosRet);
- if(!fCreated)
+ if(!newTx)
{
if(!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance)
{
@@ -297,7 +231,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
// reject absurdly high fee. (This can never happen because the
// wallet caps the fee at maxTxFee. This merely serves as a
// belt-and-suspenders check)
- if (nFeeRequired > maxTxFee)
+ if (nFeeRequired > m_node.getMaxTxFee())
return AbsurdFee;
}
@@ -309,8 +243,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
QByteArray transaction_array; /* store serialized transaction */
{
- LOCK2(cs_main, wallet->cs_wallet);
-
std::vector<std::pair<std::string, std::string>> vOrderForm;
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{
@@ -330,14 +262,13 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
vOrderForm.emplace_back("Message", rcp.message.toStdString());
}
- CTransactionRef& newTx = transaction.getTransaction();
- CReserveKey *keyChange = transaction.getPossibleKeyChange();
- CValidationState state;
- if (!wallet->CommitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm), {} /* fromAccount */, *keyChange, g_connman.get(), state))
- return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(state.GetRejectReason()));
+ auto& newTx = transaction.getWtx();
+ std::string rejectReason;
+ if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), {} /* fromAccount */, rejectReason))
+ return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason));
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- ssTx << newTx;
+ ssTx << newTx->get();
transaction_array.append(&(ssTx[0]), ssTx.size());
}
@@ -352,24 +283,22 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
CTxDestination dest = DecodeDestination(strAddress);
std::string strLabel = rcp.label.toStdString();
{
- LOCK(wallet->cs_wallet);
-
- std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
-
// Check if we have a new address or an updated label
- if (mi == wallet->mapAddressBook.end())
+ std::string name;
+ if (!m_wallet->getAddress(dest, &name))
{
- wallet->SetAddressBook(dest, strLabel, "send");
+ m_wallet->setAddressBook(dest, strLabel, "send");
}
- else if (mi->second.name != strLabel)
+ else if (name != strLabel)
{
- wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ m_wallet->setAddressBook(dest, strLabel, ""); // "" means don't change purpose
}
}
}
- Q_EMIT coinsSent(wallet, rcp, transaction_array);
+ Q_EMIT coinsSent(cwallet, rcp, transaction_array);
}
- checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
+
+ checkBalanceChanged(m_wallet->getBalances()); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
return SendCoinsReturn(OK);
}
@@ -396,11 +325,11 @@ RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel()
WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
{
- if(!wallet->IsCrypted())
+ if(!m_wallet->isCrypted())
{
return Unencrypted;
}
- else if(wallet->IsLocked())
+ else if(m_wallet->isLocked())
{
return Locked;
}
@@ -415,7 +344,7 @@ bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphr
if(encrypted)
{
// Encrypt
- return wallet->EncryptWallet(passphrase);
+ return m_wallet->encryptWallet(passphrase);
}
else
{
@@ -429,39 +358,29 @@ bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
if(locked)
{
// Lock
- return wallet->Lock();
+ return m_wallet->lock();
}
else
{
// Unlock
- return wallet->Unlock(passPhrase);
+ return m_wallet->unlock(passPhrase);
}
}
bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
{
- bool retval;
- {
- LOCK(wallet->cs_wallet);
- wallet->Lock(); // Make sure wallet is locked before attempting pass change
- retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
- }
- return retval;
-}
-
-bool WalletModel::backupWallet(const QString &filename)
-{
- return wallet->BackupWallet(filename.toLocal8Bit().data());
+ m_wallet->lock(); // Make sure wallet is locked before attempting pass change
+ return m_wallet->changeWalletPassphrase(oldPass, newPass);
}
// Handlers for core signals
-static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
+static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
{
qDebug() << "NotifyKeyStoreStatusChanged";
QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
}
-static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
+static void NotifyAddressBookChanged(WalletModel *walletmodel,
const CTxDestination &address, const std::string &label, bool isMine,
const std::string &purpose, ChangeType status)
{
@@ -478,9 +397,8 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
Q_ARG(int, status));
}
-static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
+static void NotifyTransactionChanged(WalletModel *walletmodel, const uint256 &hash, ChangeType status)
{
- Q_UNUSED(wallet);
Q_UNUSED(hash);
Q_UNUSED(status);
QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection);
@@ -503,21 +421,21 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
- wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
- wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
- wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
- wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
- wallet->NotifyWatchonlyChanged.connect(boost::bind(NotifyWatchonlyChanged, this, _1));
+ m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
+ m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
+ m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
+ m_handler_show_progress = m_wallet->handleShowProgress(boost::bind(ShowProgress, this, _1, _2));
+ m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(boost::bind(NotifyWatchonlyChanged, this, _1));
}
void WalletModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from wallet
- wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
- wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
- wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
- wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
- wallet->NotifyWatchonlyChanged.disconnect(boost::bind(NotifyWatchonlyChanged, this, _1));
+ m_handler_status_changed->disconnect();
+ m_handler_address_book_changed->disconnect();
+ m_handler_transaction_changed->disconnect();
+ m_handler_show_progress->disconnect();
+ m_handler_watch_only_changed->disconnect();
}
// WalletModel::UnlockContext implementation
@@ -557,29 +475,14 @@ void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs)
rhs.relock = false;
}
-bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
-{
- return wallet->GetPubKey(address, vchPubKeyOut);
-}
-
-bool WalletModel::IsSpendable(const CTxDestination& dest) const
-{
- return IsMine(*wallet, dest) & ISMINE_SPENDABLE;
-}
-
-bool WalletModel::getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const
-{
- return wallet->GetKey(address, vchPrivKeyOut);
-}
-
// returns a list of COutputs from COutPoints
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ LOCK2(cs_main, cwallet->cs_wallet);
for (const COutPoint& outpoint : vOutpoints)
{
- auto it = wallet->mapWallet.find(outpoint.hash);
- if (it == wallet->mapWallet.end()) continue;
+ auto it = cwallet->mapWallet.find(outpoint.hash);
+ if (it == cwallet->mapWallet.end()) continue;
int nDepth = it->second.GetDepthInMainChain();
if (nDepth < 0) continue;
COutput out(&it->second, outpoint.n, nDepth, true /* spendable */, true /* solvable */, true /* safe */);
@@ -589,14 +492,14 @@ void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vect
bool WalletModel::isSpent(const COutPoint& outpoint) const
{
- LOCK2(cs_main, wallet->cs_wallet);
- return wallet->IsSpent(outpoint.hash, outpoint.n);
+ LOCK2(cs_main, cwallet->cs_wallet);
+ return cwallet->IsSpent(outpoint.hash, outpoint.n);
}
// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
{
- for (auto& group : wallet->ListCoins()) {
+ for (auto& group : cwallet->ListCoins()) {
auto& resultGroup = mapCoins[QString::fromStdString(EncodeDestination(group.first))];
for (auto& coin : group.second) {
resultGroup.emplace_back(std::move(coin));
@@ -604,33 +507,9 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
}
}
-bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
-{
- LOCK2(cs_main, wallet->cs_wallet);
- return wallet->IsLockedCoin(hash, n);
-}
-
-void WalletModel::lockCoin(COutPoint& output)
-{
- LOCK2(cs_main, wallet->cs_wallet);
- wallet->LockCoin(output);
-}
-
-void WalletModel::unlockCoin(COutPoint& output)
-{
- LOCK2(cs_main, wallet->cs_wallet);
- wallet->UnlockCoin(output);
-}
-
-void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
-{
- LOCK2(cs_main, wallet->cs_wallet);
- wallet->ListLockedCoins(vOutpts);
-}
-
void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
{
- vReceiveRequests = wallet->GetDestValues("rr"); // receive request
+ vReceiveRequests = m_wallet->getDestValues("rr"); // receive request
}
bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
@@ -641,27 +520,10 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t
ss << nId;
std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
- LOCK(wallet->cs_wallet);
if (sRequest.empty())
- return wallet->EraseDestData(dest, key);
+ return m_wallet->eraseDestData(dest, key);
else
- return wallet->AddDestData(dest, key, sRequest);
-}
-
-bool WalletModel::transactionCanBeAbandoned(uint256 hash) const
-{
- return wallet->TransactionCanBeAbandoned(hash);
-}
-
-bool WalletModel::abandonTransaction(uint256 hash) const
-{
- LOCK2(cs_main, wallet->cs_wallet);
- return wallet->AbandonTransaction(hash);
-}
-
-bool WalletModel::transactionCanBeBumped(uint256 hash) const
-{
- return feebumper::TransactionCanBeBumped(wallet, hash);
+ return m_wallet->addDestData(dest, key, sRequest);
}
bool WalletModel::bumpFee(uint256 hash)
@@ -672,7 +534,7 @@ bool WalletModel::bumpFee(uint256 hash)
CAmount old_fee;
CAmount new_fee;
CMutableTransaction mtx;
- if (feebumper::CreateTransaction(wallet, hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx) != feebumper::Result::OK) {
+ if (!m_wallet->createBumpTransaction(hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx)) {
QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
(errors.size() ? QString::fromStdString(errors[0]) : "") +")");
return false;
@@ -711,13 +573,13 @@ bool WalletModel::bumpFee(uint256 hash)
}
// sign bumped transaction
- if (!feebumper::SignTransaction(wallet, mtx)) {
+ if (!m_wallet->signBumpTransaction(mtx)) {
QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction."));
return false;
}
// commit the bumped transaction
uint256 txid;
- if (feebumper::CommitTransaction(wallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
+ if(!m_wallet->commitBumpTransaction(hash, std::move(mtx), errors, txid)) {
QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
QString::fromStdString(errors[0])+")");
return false;
@@ -730,28 +592,12 @@ bool WalletModel::isWalletEnabled()
return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
}
-bool WalletModel::hdEnabled() const
-{
- return wallet->IsHDEnabled();
-}
-
-OutputType WalletModel::getDefaultAddressType() const
-{
- return wallet->m_default_address_type;
-}
-
-int WalletModel::getDefaultConfirmTarget() const
-{
- return nTxConfirmTarget;
-}
-
QString WalletModel::getWalletName() const
{
- LOCK(wallet->cs_wallet);
- return QString::fromStdString(wallet->GetName());
+ return QString::fromStdString(m_wallet->getWalletName());
}
bool WalletModel::isMultiwallet()
{
- return gArgs.GetArgs("-wallet").size() > 1;
+ return m_node.getWallets().size() > 1;
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index ff4b38a804..8ff19f4ae5 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -13,6 +13,7 @@
#include <qt/paymentrequestplus.h>
#include <qt/walletmodeltransaction.h>
+#include <interface/wallet.h>
#include <support/allocators/secure.h>
#include <map>
@@ -34,9 +35,12 @@ class CKeyID;
class COutPoint;
class COutput;
class CPubKey;
-class CWallet;
class uint256;
+namespace interface {
+class Node;
+} // namespace interface
+
QT_BEGIN_NAMESPACE
class QTimer;
QT_END_NAMESPACE
@@ -107,7 +111,7 @@ class WalletModel : public QObject
Q_OBJECT
public:
- explicit WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0);
+ explicit WalletModel(std::unique_ptr<interface::Wallet> wallet, interface::Node& node, const PlatformStyle *platformStyle, CWallet *cwallet, OptionsModel *optionsModel, QObject *parent = 0);
~WalletModel();
enum StatusCode // Returned by sendCoins
@@ -136,15 +140,6 @@ public:
TransactionTableModel *getTransactionTableModel();
RecentRequestsTableModel *getRecentRequestsTableModel();
- CWallet *getWallet() const { return wallet; };
-
- CAmount getBalance(const CCoinControl *coinControl = nullptr) const;
- CAmount getUnconfirmedBalance() const;
- CAmount getImmatureBalance() const;
- bool haveWatchOnly() const;
- CAmount getWatchBalance() const;
- CAmount getWatchUnconfirmedBalance() const;
- CAmount getWatchImmatureBalance() const;
EncryptionStatus getEncryptionStatus() const;
// Check address for validity
@@ -173,8 +168,6 @@ public:
// Passphrase only needed when unlocking
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
- // Wallet backup
- bool backupWallet(const QString &filename);
// RAI object for unlocking wallet, returned by requestUnlock()
class UnlockContext
@@ -198,40 +191,33 @@ public:
UnlockContext requestUnlock();
- bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
- bool IsSpendable(const CTxDestination& dest) const;
- bool getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const;
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
bool isSpent(const COutPoint& outpoint) const;
void listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const;
- bool isLockedCoin(uint256 hash, unsigned int n) const;
- void lockCoin(COutPoint& output);
- void unlockCoin(COutPoint& output);
- void listLockedCoins(std::vector<COutPoint>& vOutpts);
-
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
- bool transactionCanBeAbandoned(uint256 hash) const;
- bool abandonTransaction(uint256 hash) const;
-
- bool transactionCanBeBumped(uint256 hash) const;
bool bumpFee(uint256 hash);
static bool isWalletEnabled();
- bool hdEnabled() const;
-
- OutputType getDefaultAddressType() const;
-
- int getDefaultConfirmTarget() const;
+ interface::Node& node() const { return m_node; }
+ interface::Wallet& wallet() const { return *m_wallet; }
QString getWalletName() const;
- static bool isMultiwallet();
+ bool isMultiwallet();
private:
- CWallet *wallet;
+ std::unique_ptr<interface::Wallet> m_wallet;
+ std::unique_ptr<interface::Handler> m_handler_status_changed;
+ std::unique_ptr<interface::Handler> m_handler_address_book_changed;
+ std::unique_ptr<interface::Handler> m_handler_transaction_changed;
+ std::unique_ptr<interface::Handler> m_handler_show_progress;
+ std::unique_ptr<interface::Handler> m_handler_watch_only_changed;
+ interface::Node& m_node;
+
+ CWallet *cwallet;
bool fHaveWatchOnly;
bool fForceCheckBalanceChanged;
@@ -244,12 +230,7 @@ private:
RecentRequestsTableModel *recentRequestsTableModel;
// Cache some values to be able to detect changes
- CAmount cachedBalance;
- CAmount cachedUnconfirmedBalance;
- CAmount cachedImmatureBalance;
- CAmount cachedWatchOnlyBalance;
- CAmount cachedWatchUnconfBalance;
- CAmount cachedWatchImmatureBalance;
+ interface::WalletBalances m_cached_balances;
EncryptionStatus cachedEncryptionStatus;
int cachedNumBlocks;
@@ -257,7 +238,7 @@ private:
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();
- void checkBalanceChanged();
+ void checkBalanceChanged(const interface::WalletBalances& new_balances);
Q_SIGNALS:
// Signal that balance in wallet changed
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index 4df8a5687e..21bdfe3818 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -4,12 +4,11 @@
#include <qt/walletmodeltransaction.h>
+#include <interface/node.h>
#include <policy/policy.h>
-#include <wallet/wallet.h>
WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &_recipients) :
recipients(_recipients),
- walletTransaction(0),
fee(0)
{
}
@@ -19,14 +18,14 @@ QList<SendCoinsRecipient> WalletModelTransaction::getRecipients() const
return recipients;
}
-CTransactionRef& WalletModelTransaction::getTransaction()
+std::unique_ptr<interface::PendingWalletTx>& WalletModelTransaction::getWtx()
{
- return walletTransaction;
+ return wtx;
}
unsigned int WalletModelTransaction::getTransactionSize()
{
- return (!walletTransaction ? 0 : ::GetVirtualTransactionSize(*walletTransaction));
+ return wtx ? wtx->getVirtualSize() : 0;
}
CAmount WalletModelTransaction::getTransactionFee() const
@@ -41,6 +40,7 @@ void WalletModelTransaction::setTransactionFee(const CAmount& newFee)
void WalletModelTransaction::reassignAmounts(int nChangePosRet)
{
+ const CTransaction* walletTransaction = &wtx->get();
int i = 0;
for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it)
{
@@ -80,13 +80,3 @@ CAmount WalletModelTransaction::getTotalTransactionAmount() const
}
return totalTransactionAmount;
}
-
-void WalletModelTransaction::newPossibleKeyChange(CWallet *wallet)
-{
- keyChange.reset(new CReserveKey(wallet));
-}
-
-CReserveKey *WalletModelTransaction::getPossibleKeyChange()
-{
- return keyChange.get();
-}
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
index 931e960d18..52efafaf62 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -11,9 +11,10 @@
class SendCoinsRecipient;
-class CReserveKey;
-class CWallet;
-class CWalletTx;
+namespace interface {
+class Node;
+class PendingWalletTx;
+}
/** Data model for a walletmodel transaction. */
class WalletModelTransaction
@@ -23,7 +24,7 @@ public:
QList<SendCoinsRecipient> getRecipients() const;
- CTransactionRef& getTransaction();
+ std::unique_ptr<interface::PendingWalletTx>& getWtx();
unsigned int getTransactionSize();
void setTransactionFee(const CAmount& newFee);
@@ -31,15 +32,11 @@ public:
CAmount getTotalTransactionAmount() const;
- void newPossibleKeyChange(CWallet *wallet);
- CReserveKey *getPossibleKeyChange();
-
void reassignAmounts(int nChangePosRet); // needed for the subtract-fee-from-amount feature
private:
QList<SendCoinsRecipient> recipients;
- CTransactionRef walletTransaction;
- std::unique_ptr<CReserveKey> keyChange;
+ std::unique_ptr<interface::PendingWalletTx> wtx;
CAmount fee;
};
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index e1c892f115..1505557244 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -258,7 +258,7 @@ void WalletView::backupWallet()
if (filename.isEmpty())
return;
- if (!walletModel->backupWallet(filename)) {
+ if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
Q_EMIT message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename),
CClientUIInterface::MSG_ERROR);
}