Skip to content

Commit eca742a

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 927f603 commit eca742a

23 files changed

+200
-116
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
@@ -399,7 +399,6 @@ BITCOIN_CORE_H = \
399399
wallet/dump.h \
400400
wallet/fees.h \
401401
wallet/hdchain.h \
402-
wallet/ismine.h \
403402
wallet/load.h \
404403
wallet/receive.h \
405404
wallet/rpcwallet.h \
@@ -409,6 +408,7 @@ BITCOIN_CORE_H = \
409408
wallet/spend.h \
410409
wallet/sqlite.h \
411410
wallet/transaction.h \
411+
wallet/types.h \
412412
wallet/wallet.h \
413413
wallet/walletdb.h \
414414
wallet/wallettool.h \

src/interfaces/wallet.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ class CWallet;
3333
class UniValue;
3434
enum class FeeReason;
3535
enum class TransactionError;
36+
enum class AddressPurpose;
3637
enum isminetype : unsigned int;
3738
struct CRecipient;
3839
struct NodeContext;
3940
struct PartiallySignedTransaction;
40-
struct WalletContext;
4141
struct bilingual_str;
4242
using isminefilter = std::underlying_type<isminetype>::type;
4343

@@ -122,7 +122,7 @@ class Wallet
122122
virtual bool haveWatchOnly() = 0;
123123

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

127127
// Remove address.
128128
virtual bool delAddressBook(const CTxDestination& dest) = 0;
@@ -131,7 +131,7 @@ class Wallet
131131
virtual bool getAddress(const CTxDestination& dest,
132132
std::string* name,
133133
isminetype* is_mine,
134-
std::string* purpose) = 0;
134+
wallet::AddressPurpose* purpose) = 0;
135135

136136
//! Get wallet address list.
137137
virtual std::vector<WalletAddress> getAddresses() = 0;
@@ -305,7 +305,7 @@ class Wallet
305305
using AddressBookChangedFn = std::function<void(const CTxDestination& address,
306306
const std::string& label,
307307
bool is_mine,
308-
const std::string& purpose,
308+
wallet::AddressPurpose purpose,
309309
ChangeType status)>;
310310
virtual std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) = 0;
311311

@@ -375,11 +375,11 @@ struct WalletAddress
375375
{
376376
CTxDestination dest;
377377
isminetype is_mine;
378+
wallet::AddressPurpose purpose;
378379
std::string name;
379-
std::string purpose;
380380

381-
WalletAddress(CTxDestination dest, isminetype is_mine, std::string name, std::string purpose)
382-
: dest(std::move(dest)), is_mine(is_mine), name(std::move(name)), purpose(std::move(purpose))
381+
WalletAddress(CTxDestination dest, isminetype is_mine, wallet::AddressPurpose purpose, std::string name)
382+
: dest(std::move(dest)), is_mine(is_mine), purpose(std::move(purpose)), name(std::move(name))
383383
{
384384
}
385385
};

src/qt/addresstablemodel.cpp

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

1111
#include <key_io.h>
12-
12+
#include <wallet/types.h>
1313
#include <algorithm>
1414

1515
#include <QFont>
@@ -52,17 +52,16 @@ struct AddressTableEntryLessThan
5252
};
5353

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

6867
// Private implementation
@@ -82,7 +81,7 @@ class AddressTablePriv
8281
for (const auto& address : wallet.getAddresses())
8382
{
8483
AddressTableEntry::Type addressType = translateTransactionType(
85-
QString::fromStdString(address.purpose), address.is_mine);
84+
address.purpose, address.is_mine);
8685
cachedAddressTable.append(AddressTableEntry(addressType,
8786
QString::fromStdString(address.name),
8887
QString::fromStdString(EncodeDestination(address.dest))));
@@ -94,7 +93,7 @@ class AddressTablePriv
9493
std::sort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
9594
}
9695

97-
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
96+
void updateEntry(const QString &address, const QString &label, bool isMine, wallet::AddressPurpose purpose, int status)
9897
{
9998
// Find address / label in model
10099
QList<AddressTableEntry>::iterator lower = std::lower_bound(
@@ -236,7 +235,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
236235
if(!index.isValid())
237236
return false;
238237
AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
239-
std::string strPurpose = (rec->type == AddressTableEntry::Sending ? "send" : "receive");
238+
wallet::AddressPurpose purpose = rec->type == AddressTableEntry::Sending ? wallet::AddressPurpose::SEND : wallet::AddressPurpose::RECEIVE;
240239
editStatus = OK;
241240

242241
if(role == Qt::EditRole)
@@ -250,7 +249,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
250249
editStatus = NO_CHANGES;
251250
return false;
252251
}
253-
walletModel->wallet().setAddressBook(curAddress, value.toString().toStdString(), strPurpose);
252+
walletModel->wallet().setAddressBook(curAddress, value.toString().toStdString(), purpose);
254253
} else if(index.column() == Address) {
255254
CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
256255
// Refuse to set invalid address, set error status and return false
@@ -279,7 +278,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
279278
// Remove old entry
280279
walletModel->wallet().delAddressBook(curAddress);
281280
// Add new entry with new address
282-
walletModel->wallet().setAddressBook(newAddress, value.toString().toStdString(), strPurpose);
281+
walletModel->wallet().setAddressBook(newAddress, value.toString().toStdString(), purpose);
283282
}
284283
}
285284
return true;
@@ -331,7 +330,7 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &par
331330
}
332331

333332
void AddressTableModel::updateEntry(const QString &address,
334-
const QString &label, bool isMine, const QString &purpose, int status)
333+
const QString &label, bool isMine, wallet::AddressPurpose purpose, int status)
335334
{
336335
// Update address book model from Dash core
337336
priv->updateEntry(address, label, isMine, purpose, status);
@@ -361,7 +360,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
361360
}
362361
}
363362
// Add entry
364-
walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, "send");
363+
walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, wallet::AddressPurpose::SEND);
365364
}
366365
else if(type == Receive)
367366
{
@@ -414,18 +413,18 @@ QString AddressTableModel::labelForAddress(const QString &address) const
414413
return QString();
415414
}
416415

417-
QString AddressTableModel::purposeForAddress(const QString &address) const
416+
std::optional<wallet::AddressPurpose> AddressTableModel::purposeForAddress(const QString &address) const
418417
{
419-
std::string purpose;
418+
wallet::AddressPurpose purpose;
420419
if (getAddressData(address, /* name= */ nullptr, &purpose)) {
421-
return QString::fromStdString(purpose);
420+
return purpose;
422421
}
423-
return QString();
422+
return std::nullopt;
424423
}
425424

426425
bool AddressTableModel::getAddressData(const QString &address,
427426
std::string* name,
428-
std::string* purpose) const {
427+
wallet::AddressPurpose* purpose) const {
429428
CTxDestination destination = DecodeDestination(address.toStdString());
430429
return walletModel->wallet().getAddress(destination, name, /* is_mine= */ nullptr, purpose);
431430
}

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.
@@ -87,15 +91,15 @@ class AddressTableModel : public QAbstractTableModel
8791
EditStatus editStatus = OK;
8892

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

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

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

100104
friend class AddressTablePriv;
101105
};

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

@@ -140,9 +142,9 @@ QString EditAddressDialog::getDuplicateAddressWarning() const
140142
{
141143
QString dup_address = ui->addressEdit->text();
142144
QString existing_label = model->labelForAddress(dup_address);
143-
QString existing_purpose = model->purposeForAddress(dup_address);
145+
auto existing_purpose = model->purposeForAddress(dup_address);
144146

145-
if (existing_purpose == "receive" &&
147+
if (existing_purpose == wallet::AddressPurpose::RECEIVE &&
146148
(mode == NewSendingAddress || mode == EditSendingAddress)) {
147149
return tr(
148150
"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
@@ -99,8 +99,8 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
9999

100100
{
101101
LOCK(wallet->cs_wallet);
102-
wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
103-
wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send");
102+
wallet->SetAddressBook(r_key_dest, r_label.toStdString(), wallet::AddressPurpose::RECEIVE);
103+
wallet->SetAddressBook(s_key_dest, s_label.toStdString(), wallet::AddressPurpose::SEND);
104104
}
105105

106106
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
@@ -126,7 +126,7 @@ void TestGUI(interfaces::Node& node)
126126
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
127127
if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
128128
CTxDestination dest = PKHash(test.coinbaseKey.GetPubKey());
129-
wallet->SetAddressBook(dest, "", "receive");
129+
wallet->SetAddressBook(dest, "", wallet::AddressPurpose::RECEIVE);
130130
wallet->SetLastBlockProcessed(105, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
131131
}
132132
{

src/qt/transactiondesc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include <script/script.h>
2222
#include <util/system.h>
2323
#include <validation.h>
24-
#include <wallet/ismine.h>
24+
#include <wallet/types.h>
2525

2626
#include <stdint.h>
2727
#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 <stdint.h>
1515

0 commit comments

Comments
 (0)