Remove most direct bitcoin calls from qt/walletmodel.cpp

This commit is contained in:
Russell Yanofsky 2017-04-17 18:56:44 -04:00 committed by John Newbery
parent 90d4640b7e
commit a0704a8996
18 changed files with 588 additions and 330 deletions

View file

@ -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));

View file

@ -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;

View file

@ -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;
};

View file

@ -5,15 +5,34 @@
#ifndef BITCOIN_INTERFACE_WALLET_H
#define BITCOIN_INTERFACE_WALLET_H
#include <functional>
#include <memory>
#include <string>
#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

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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)));
}

View file

@ -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;
}

View file

@ -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

View file

@ -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."));

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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();
}

View file

@ -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;
};

View file

@ -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);
}