diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -7,6 +7,7 @@ #include <amount.h> // For Amount #include <primitives/transaction.h> // For CTxOut +#include <pubkey.h> // For CTxDestination (CKeyID and CScriptID) #include <script/ismine.h> // For isminefilter, isminetype #include <script/standard.h> // For CTxDestination #include <support/allocators/secure.h> // For SecureString @@ -36,6 +37,7 @@ class Handler; class PendingWalletTx; +struct WalletAddress; struct WalletBalances; struct WalletTxOut; @@ -76,6 +78,9 @@ //! Get chainparams. virtual const CChainParams &getChainParams() = 0; + // Get key from pool. + virtual bool getKeyFromPool(bool internal, CPubKey &pub_key) = 0; + //! Get public key. virtual bool getPubKey(const CKeyID &address, CPubKey &pub_key) = 0; @@ -93,11 +98,17 @@ const std::string &name, const std::string &purpose) = 0; + // Remove address. + virtual bool delAddressBook(const CTxDestination &dest) = 0; + //! Look up address in wallet, return whether exists. virtual bool getAddress(const CTxDestination &dest, std::string *name = nullptr, isminetype *is_mine = nullptr) = 0; + //! Get wallet address list. + virtual std::vector<WalletAddress> getAddresses() = 0; + //! Add dest data. virtual bool addDestData(const CTxDestination &dest, const std::string &key, const std::string &value) = 0; @@ -204,6 +215,19 @@ std::string &reject_reason) = 0; }; +//! Information about one wallet address. +struct WalletAddress { + CTxDestination dest; + isminetype is_mine; + std::string name; + std::string purpose; + + WalletAddress(CTxDestination destIn, isminetype isMineIn, + std::string nameIn, std::string purposeIn) + : dest(std::move(destIn)), is_mine(isMineIn), name(std::move(nameIn)), + purpose(std::move(purposeIn)) {} +}; + //! Collection of wallet balances. struct WalletBalances { Amount balance = Amount::zero(); diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -84,6 +84,9 @@ return m_wallet.BackupWallet(filename); } std::string getWalletName() override { return m_wallet.GetName(); } + bool getKeyFromPool(bool internal, CPubKey &pub_key) override { + return m_wallet.GetKeyFromPool(pub_key, internal); + } const CChainParams &getChainParams() override { return m_wallet.chainParams; } @@ -101,6 +104,9 @@ const std::string &purpose) override { return m_wallet.SetAddressBook(dest, name, purpose); } + bool delAddressBook(const CTxDestination &dest) override { + return m_wallet.DelAddressBook(dest); + } bool getAddress(const CTxDestination &dest, std::string *name, isminetype *is_mine) override { LOCK(m_wallet.cs_wallet); @@ -116,6 +122,15 @@ } return true; } + std::vector<WalletAddress> getAddresses() override { + LOCK(m_wallet.cs_wallet); + std::vector<WalletAddress> result; + for (const auto &item : m_wallet.mapAddressBook) { + result.emplace_back(item.first, IsMine(m_wallet, item.first), + item.second.name, item.second.purpose); + } + return result; + } bool addDestData(const CTxDestination &dest, const std::string &key, const std::string &value) override { LOCK(m_wallet.cs_wallet); diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -11,7 +11,9 @@ class AddressTablePriv; class WalletModel; -class CWallet; +namespace interfaces { +class Wallet; +} /** * Qt model of the address book in the core. This allows views to access and @@ -21,7 +23,7 @@ Q_OBJECT public: - explicit AddressTableModel(CWallet *wallet, WalletModel *parent = 0); + explicit AddressTableModel(WalletModel *parent = 0); ~AddressTableModel(); enum ColumnIndex { @@ -93,7 +95,6 @@ private: WalletModel *walletModel; - CWallet *wallet; AddressTablePriv *priv; QStringList columns; EditStatus editStatus; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "addresstablemodel.h" +#include <qt/addresstablemodel.h> -#include "guiutil.h" -#include "walletmodel.h" - -#include "dstencode.h" -#include "wallet/wallet.h" +#include <dstencode.h> +#include <interfaces/node.h> +#include <qt/guiutil.h> +#include <qt/walletmodel.h> +#include <wallet/wallet.h> #include <QDebug> #include <QFont> @@ -68,28 +68,19 @@ // Private implementation class AddressTablePriv { public: - CWallet *wallet; QList<AddressTableEntry> cachedAddressTable; AddressTableModel *parent; - AddressTablePriv(CWallet *_wallet, AddressTableModel *_parent) - : wallet(_wallet), parent(_parent) {} + AddressTablePriv(AddressTableModel *_parent) : parent(_parent) {} - void refreshAddressTable() { + void refreshAddressTable(interfaces::Wallet &wallet) { cachedAddressTable.clear(); - { - LOCK(wallet->cs_wallet); - for (const std::pair<CTxDestination, CAddressBookData> &item : - wallet->mapAddressBook) { - const CTxDestination &address = item.first; - bool fMine = IsMine(*wallet, address); - AddressTableEntry::Type addressType = translateTransactionType( - QString::fromStdString(item.second.purpose), fMine); - const std::string &strName = item.second.name; - cachedAddressTable.append(AddressTableEntry( - addressType, QString::fromStdString(strName), - QString::fromStdString(EncodeDestination(address)))); - } + for (const auto &address : wallet.getAddresses()) { + AddressTableEntry::Type addressType = translateTransactionType( + QString::fromStdString(address.purpose), address.is_mine); + cachedAddressTable.append(AddressTableEntry( + addressType, QString::fromStdString(address.name), + QString::fromStdString(EncodeDestination(address.dest)))); } // qLowerBound() and qUpperBound() require our cachedAddressTable list // to be sorted in asc order. Even though the map is already sorted this @@ -162,12 +153,11 @@ } }; -AddressTableModel::AddressTableModel(CWallet *_wallet, WalletModel *parent) - : QAbstractTableModel(parent), walletModel(parent), wallet(_wallet), - priv(0) { +AddressTableModel::AddressTableModel(WalletModel *parent) + : QAbstractTableModel(parent), walletModel(parent), priv(0) { columns << tr("Label") << tr("Address"); - priv = new AddressTablePriv(wallet, this); - priv->refreshAddressTable(); + priv = new AddressTablePriv(this); + priv->refreshAddressTable(parent->wallet()); } AddressTableModel::~AddressTableModel() { @@ -230,20 +220,19 @@ editStatus = OK; if (role == Qt::EditRole) { - LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */ - CTxDestination curAddress = - DecodeDestination(rec->address.toStdString(), wallet->chainParams); + CTxDestination curAddress = DecodeDestination( + rec->address.toStdString(), walletModel->getChainParams()); if (index.column() == Label) { // Do nothing, if old label == new label if (rec->label == value.toString()) { editStatus = NO_CHANGES; return false; } - wallet->SetAddressBook(curAddress, value.toString().toStdString(), - strPurpose); + walletModel->wallet().setAddressBook( + curAddress, value.toString().toStdString(), strPurpose); } else if (index.column() == Address) { CTxDestination newAddress = DecodeDestination( - value.toString().toStdString(), wallet->chainParams); + value.toString().toStdString(), walletModel->getChainParams()); // Refuse to set invalid address, set error status and return false if (boost::get<CNoDestination>(&newAddress)) { editStatus = INVALID_ADDRESS; @@ -257,17 +246,17 @@ // Check for duplicate addresses to prevent accidental deletion of // addresses, if you try to paste an existing address over another // address (with a different label) - else if (wallet->mapAddressBook.count(newAddress)) { + if (walletModel->wallet().getAddress(newAddress)) { editStatus = DUPLICATE_ADDRESS; return false; } // Double-check that we're not overwriting a receiving address else if (rec->type == AddressTableEntry::Sending) { // Remove old entry - wallet->DelAddressBook(curAddress); + walletModel->wallet().delAddressBook(curAddress); // Add new entry with new address - wallet->SetAddressBook(newAddress, rec->label.toStdString(), - strPurpose); + walletModel->wallet().setAddressBook( + newAddress, value.toString().toStdString(), strPurpose); } } return true; @@ -332,25 +321,24 @@ return QString(); } // Check for duplicate addresses - { - LOCK(wallet->cs_wallet); - if (wallet->mapAddressBook.count( - DecodeDestination(strAddress, wallet->chainParams))) { - editStatus = DUPLICATE_ADDRESS; - return QString(); - } + if (walletModel->wallet().getAddress( + DecodeDestination(strAddress, walletModel->getChainParams()))) { + editStatus = DUPLICATE_ADDRESS; + return QString(); } } else if (type == Receive) { // Generate a new address to associate with given label CPubKey newKey; - if (!wallet->GetKeyFromPool(newKey)) { + if (!walletModel->wallet().getKeyFromPool(false /* internal */, + newKey)) { WalletModel::UnlockContext ctx(walletModel->requestUnlock()); if (!ctx.isValid()) { // Unlock wallet failed or was cancelled editStatus = WALLET_UNLOCK_FAILURE; return QString(); } - if (!wallet->GetKeyFromPool(newKey)) { + if (!walletModel->wallet().getKeyFromPool(false /* internal */, + newKey)) { editStatus = KEY_GENERATION_FAILURE; return QString(); } @@ -361,8 +349,9 @@ } // Add entry - wallet->SetAddressBook(DecodeDestination(strAddress, wallet->chainParams), - strLabel, (type == Send ? "send" : "receive")); + walletModel->wallet().setAddressBook( + DecodeDestination(strAddress, walletModel->getChainParams()), strLabel, + (type == Send ? "send" : "receive")); return QString::fromStdString(strAddress); } @@ -376,23 +365,19 @@ // Also refuse to remove receiving addresses. return false; } - wallet->DelAddressBook( - DecodeDestination(rec->address.toStdString(), wallet->chainParams)); + walletModel->wallet().delAddressBook(DecodeDestination( + rec->address.toStdString(), walletModel->getChainParams())); return true; } /* Look up label for address in address book, if not found return empty string. */ QString AddressTableModel::labelForAddress(const QString &address) const { - { - LOCK(wallet->cs_wallet); - CTxDestination destination = - DecodeDestination(address.toStdString(), wallet->chainParams); - std::map<CTxDestination, CAddressBookData>::iterator mi = - wallet->mapAddressBook.find(destination); - if (mi != wallet->mapAddressBook.end()) { - return QString::fromStdString(mi->second.name); - } + CTxDestination destination = + DecodeDestination(address.toStdString(), walletModel->getChainParams()); + std::string name; + if (walletModel->wallet().getAddress(destination, &name)) { + return QString::fromStdString(name); } return QString(); } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -43,7 +43,7 @@ fHaveWatchOnly = m_wallet->haveWatchOnly(); fForceCheckBalanceChanged = false; - addressTableModel = new AddressTableModel(cwallet, this); + addressTableModel = new AddressTableModel(this); transactionTableModel = new TransactionTableModel(platformStyle, cwallet, this); recentRequestsTableModel = new RecentRequestsTableModel(cwallet, this);