Skip to content

Commit b35f9dc

Browse files
fanquakevijaydasmp
authored andcommitted
Merge bitcoin#27217: wallet: Replace use of purpose strings with an enum
18fc71a doc: Release note for purpose string restriction (Andrew Chow) e83babe wallet: Replace use of purpose strings with an enum (Andrew Chow) 2f80005 wallet: add AddressPurpose enum to replace string values (Ryan Ofsky) 8741522 wallet: Add wallet/types.h for simple public enum and struct types (Ryan Ofsky) Pull request description: Instead of storing and passing around fixed strings for the purpose of an address, use an enum. ACKs for top commit: josibake: reACK bitcoin@18fc71a Tree-SHA512: 82034f020e96b99b29da34dfdd7cfe58f8b7d2afed1409ea4a290c2cac69fc43e449e8b7b2afd874a9facf8f4cd6ebb80d17462317e60a6f011ed8f9eab5d4c5
1 parent d3c0730 commit b35f9dc

26 files changed

+229
-136
lines changed

doc/release-notes-27217.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Wallet
2+
------
3+
4+
* Address Purposes strings are now restricted to the currently known values of "send", "receive", and "refund".
5+
Wallets that have unrecognized purpose strings will have loading warnings, and the `listlabels`
6+
RPC will raise an error if an unrecognized purpose is requested.

src/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,6 @@ BITCOIN_CORE_H = \
448448
wallet/external_signer_scriptpubkeyman.h \
449449
wallet/fees.h \
450450
wallet/hdchain.h \
451-
wallet/ismine.h \
452451
wallet/load.h \
453452
wallet/receive.h \
454453
wallet/rpc/util.h \
@@ -458,6 +457,7 @@ BITCOIN_CORE_H = \
458457
wallet/spend.h \
459458
wallet/sqlite.h \
460459
wallet/transaction.h \
460+
wallet/types.h \
461461
wallet/wallet.h \
462462
wallet/walletdb.h \
463463
wallet/wallettool.h \

src/interfaces/wallet.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct NodeContext;
4242
namespace wallet {
4343
class CCoinControl;
4444
class CWallet;
45+
enum class AddressPurpose;
4546
enum isminetype : unsigned int;
4647
enum class RescanStatus : uint8_t;
4748
struct CRecipient;
@@ -138,7 +139,7 @@ class Wallet
138139
virtual bool haveWatchOnly() = 0;
139140

140141
//! Add or update address.
141-
virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::string& purpose) = 0;
142+
virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<wallet::AddressPurpose>& purpose) = 0;
142143

143144
// Remove address.
144145
virtual bool delAddressBook(const CTxDestination& dest) = 0;
@@ -147,7 +148,7 @@ class Wallet
147148
virtual bool getAddress(const CTxDestination& dest,
148149
std::string* name,
149150
wallet::isminetype* is_mine,
150-
std::string* purpose) = 0;
151+
wallet::AddressPurpose* purpose) = 0;
151152

152153
//! Get wallet address list.
153154
virtual std::vector<WalletAddress> getAddresses() const = 0;
@@ -335,7 +336,7 @@ class Wallet
335336
using AddressBookChangedFn = std::function<void(const CTxDestination& address,
336337
const std::string& label,
337338
bool is_mine,
338-
const std::string& purpose,
339+
wallet::AddressPurpose purpose,
339340
ChangeType status)>;
340341
virtual std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) = 0;
341342

@@ -421,11 +422,11 @@ struct WalletAddress
421422
{
422423
CTxDestination dest;
423424
wallet::isminetype is_mine;
425+
wallet::AddressPurpose purpose;
424426
std::string name;
425-
std::string purpose;
426427

427-
WalletAddress(CTxDestination dest, wallet::isminetype is_mine, std::string name, std::string purpose)
428-
: dest(std::move(dest)), is_mine(is_mine), name(std::move(name)), purpose(std::move(purpose))
428+
WalletAddress(CTxDestination dest, wallet::isminetype is_mine, wallet::AddressPurpose purpose, std::string name)
429+
: dest(std::move(dest)), is_mine(is_mine), purpose(std::move(purpose)), name(std::move(name))
429430
{
430431
}
431432
};

src/qt/addresstablemodel.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <qt/walletmodel.h>
1111

1212
#include <key_io.h>
13+
#include <wallet/types.h>
1314

1415
#include <algorithm>
1516

@@ -53,17 +54,16 @@ struct AddressTableEntryLessThan
5354
};
5455

5556
/* Determine address type from address purpose */
56-
static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
57+
static AddressTableEntry::Type translateTransactionType(wallet::AddressPurpose purpose, bool isMine)
5758
{
58-
AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
5959
// "refund" addresses aren't shown, and change addresses aren't returned by getAddresses at all.
60-
if (strPurpose == "send")
61-
addressType = AddressTableEntry::Sending;
62-
else if (strPurpose == "receive")
63-
addressType = AddressTableEntry::Receiving;
64-
else if (strPurpose == "unknown" || strPurpose == "") // if purpose not set, guess
65-
addressType = (isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
66-
return addressType;
60+
switch (purpose) {
61+
case wallet::AddressPurpose::SEND: return AddressTableEntry::Sending;
62+
case wallet::AddressPurpose::RECEIVE: return AddressTableEntry::Receiving;
63+
case wallet::AddressPurpose::REFUND: return AddressTableEntry::Hidden;
64+
// No default case to allow for compiler to warn
65+
}
66+
assert(false);
6767
}
6868

6969
// Private implementation
@@ -83,7 +83,7 @@ class AddressTablePriv
8383
for (const auto& address : wallet.getAddresses())
8484
{
8585
AddressTableEntry::Type addressType = translateTransactionType(
86-
QString::fromStdString(address.purpose), address.is_mine);
86+
address.purpose, address.is_mine);
8787
cachedAddressTable.append(AddressTableEntry(addressType,
8888
QString::fromStdString(address.name),
8989
QString::fromStdString(EncodeDestination(address.dest))));
@@ -95,7 +95,7 @@ class AddressTablePriv
9595
std::sort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
9696
}
9797

98-
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
98+
void updateEntry(const QString &address, const QString &label, bool isMine, wallet::AddressPurpose purpose, int status)
9999
{
100100
// Find address / label in model
101101
QList<AddressTableEntry>::iterator lower = std::lower_bound(
@@ -237,7 +237,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
237237
if(!index.isValid())
238238
return false;
239239
AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
240-
std::string strPurpose = (rec->type == AddressTableEntry::Sending ? "send" : "receive");
240+
wallet::AddressPurpose purpose = rec->type == AddressTableEntry::Sending ? wallet::AddressPurpose::SEND : wallet::AddressPurpose::RECEIVE;
241241
editStatus = OK;
242242

243243
if(role == Qt::EditRole)
@@ -251,7 +251,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
251251
editStatus = NO_CHANGES;
252252
return false;
253253
}
254-
walletModel->wallet().setAddressBook(curAddress, value.toString().toStdString(), strPurpose);
254+
walletModel->wallet().setAddressBook(curAddress, value.toString().toStdString(), purpose);
255255
} else if(index.column() == Address) {
256256
CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
257257
// Refuse to set invalid address, set error status and return false
@@ -280,7 +280,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
280280
// Remove old entry
281281
walletModel->wallet().delAddressBook(curAddress);
282282
// Add new entry with new address
283-
walletModel->wallet().setAddressBook(newAddress, value.toString().toStdString(), strPurpose);
283+
walletModel->wallet().setAddressBook(newAddress, value.toString().toStdString(), purpose);
284284
}
285285
}
286286
return true;
@@ -332,7 +332,7 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &par
332332
}
333333

334334
void AddressTableModel::updateEntry(const QString &address,
335-
const QString &label, bool isMine, const QString &purpose, int status)
335+
const QString &label, bool isMine, wallet::AddressPurpose purpose, int status)
336336
{
337337
// Update address book model from Dash core
338338
priv->updateEntry(address, label, isMine, purpose, status);
@@ -362,7 +362,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
362362
}
363363
}
364364
// Add entry
365-
walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, "send");
365+
walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, wallet::AddressPurpose::SEND);
366366
}
367367
else if(type == Receive)
368368
{
@@ -413,18 +413,18 @@ QString AddressTableModel::labelForAddress(const QString &address) const
413413
return QString();
414414
}
415415

416-
QString AddressTableModel::purposeForAddress(const QString &address) const
416+
std::optional<wallet::AddressPurpose> AddressTableModel::purposeForAddress(const QString &address) const
417417
{
418-
std::string purpose;
418+
wallet::AddressPurpose purpose;
419419
if (getAddressData(address, /* name= */ nullptr, &purpose)) {
420-
return QString::fromStdString(purpose);
420+
return purpose;
421421
}
422-
return QString();
422+
return std::nullopt;
423423
}
424424

425425
bool AddressTableModel::getAddressData(const QString &address,
426426
std::string* name,
427-
std::string* purpose) const {
427+
wallet::AddressPurpose* purpose) const {
428428
CTxDestination destination = DecodeDestination(address.toStdString());
429429
return walletModel->wallet().getAddress(destination, name, /* is_mine= */ nullptr, purpose);
430430
}

src/qt/addresstablemodel.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define BITCOIN_QT_ADDRESSTABLEMODEL_H
77

88
#include <script/standard.h>
9+
#include <optional>
910

1011
#include <QAbstractTableModel>
1112
#include <QStringList>
@@ -16,6 +17,9 @@ class WalletModel;
1617
namespace interfaces {
1718
class Wallet;
1819
}
20+
namespace wallet {
21+
enum class AddressPurpose;
22+
} // namespace wallet
1923

2024
/**
2125
Qt model of the address book in the core. This allows views to access and modify the address book.
@@ -71,7 +75,7 @@ class AddressTableModel : public QAbstractTableModel
7175
QString labelForAddress(const QString &address) const;
7276

7377
/** Look up purpose for address in address book, if not found return empty string. */
74-
QString purposeForAddress(const QString &address) const;
78+
std::optional<wallet::AddressPurpose> purposeForAddress(const QString &address) const;
7579

7680
/* Look up row index of an address in the model.
7781
Return -1 if not found.
@@ -89,15 +93,15 @@ class AddressTableModel : public QAbstractTableModel
8993
EditStatus editStatus = OK;
9094

9195
/** Look up address book data given an address string. */
92-
bool getAddressData(const QString &address, std::string* name, std::string* purpose) const;
96+
bool getAddressData(const QString &address, std::string* name, wallet::AddressPurpose* purpose) const;
9397

9498
/** Notify listeners that data changed. */
9599
void emitDataChanged(int index);
96100

97101
public Q_SLOTS:
98102
/* Update address list from core.
99103
*/
100-
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
104+
void updateEntry(const QString &address, const QString &label, bool isMine, wallet::AddressPurpose purpose, int status);
101105

102106
friend class AddressTablePriv;
103107
};

src/qt/editaddressdialog.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <qt/addresstablemodel.h>
1010
#include <qt/guiutil.h>
1111

12+
#include <wallet/types.h>
13+
1214
#include <QDataWidgetMapper>
1315
#include <QMessageBox>
1416

@@ -139,9 +141,9 @@ QString EditAddressDialog::getDuplicateAddressWarning() const
139141
{
140142
QString dup_address = ui->addressEdit->text();
141143
QString existing_label = model->labelForAddress(dup_address);
142-
QString existing_purpose = model->purposeForAddress(dup_address);
144+
auto existing_purpose = model->purposeForAddress(dup_address);
143145

144-
if (existing_purpose == "receive" &&
146+
if (existing_purpose == wallet::AddressPurpose::RECEIVE &&
145147
(mode == NewSendingAddress || mode == EditSendingAddress)) {
146148
return tr(
147149
"Address \"%1\" already exists as a receiving address with label "

src/qt/test/addressbooktests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
108108

109109
{
110110
LOCK(wallet->cs_wallet);
111-
wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
112-
wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send");
111+
wallet->SetAddressBook(r_key_dest, r_label.toStdString(), wallet::AddressPurpose::RECEIVE);
112+
wallet->SetAddressBook(s_key_dest, s_label.toStdString(), wallet::AddressPurpose::SEND);
113113
}
114114

115115
auto check_addbook_size = [wallet](int expected_size) {

src/qt/test/wallettests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void TestGUI(interfaces::Node& node)
137137
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
138138
if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
139139
CTxDestination dest = PKHash(test.coinbaseKey.GetPubKey());
140-
wallet->SetAddressBook(dest, "", "receive");
140+
wallet->SetAddressBook(dest, "", wallet::AddressPurpose::RECEIVE);
141141
wallet->SetLastBlockProcessed(105, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
142142
}
143143
{

src/qt/transactiondesc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <util/strencodings.h>
2323
#include <util/system.h>
2424
#include <validation.h>
25-
#include <wallet/ismine.h>
25+
#include <wallet/types.h>
2626

2727
#include <stdint.h>
2828
#include <string>

src/qt/transactionrecord.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <interfaces/wallet.h>
1010
#include <interfaces/node.h>
1111

12-
#include <wallet/ismine.h>
12+
#include <wallet/types.h>
1313

1414
#include <cstdint>
1515

0 commit comments

Comments
 (0)