Skip to content

Commit cae0608

Browse files
committed
Merge bitcoin/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/bitcoin@18fc71a Tree-SHA512: 82034f020e96b99b29da34dfdd7cfe58f8b7d2afed1409ea4a290c2cac69fc43e449e8b7b2afd874a9facf8f4cd6ebb80d17462317e60a6f011ed8f9eab5d4c5
2 parents 27dcc07 + 18fc71a commit cae0608

25 files changed

+233
-152
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
@@ -329,7 +329,6 @@ BITCOIN_CORE_H = \
329329
wallet/external_signer_scriptpubkeyman.h \
330330
wallet/feebumper.h \
331331
wallet/fees.h \
332-
wallet/ismine.h \
333332
wallet/load.h \
334333
wallet/receive.h \
335334
wallet/rpc/util.h \
@@ -339,6 +338,7 @@ BITCOIN_CORE_H = \
339338
wallet/spend.h \
340339
wallet/sqlite.h \
341340
wallet/transaction.h \
341+
wallet/types.h \
342342
wallet/wallet.h \
343343
wallet/walletdb.h \
344344
wallet/wallettool.h \

src/interfaces/wallet.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct bilingual_str;
3535
namespace wallet {
3636
class CCoinControl;
3737
class CWallet;
38+
enum class AddressPurpose;
3839
enum isminetype : unsigned int;
3940
struct CRecipient;
4041
struct WalletContext;
@@ -103,7 +104,7 @@ class Wallet
103104
virtual bool haveWatchOnly() = 0;
104105

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

108109
// Remove address.
109110
virtual bool delAddressBook(const CTxDestination& dest) = 0;
@@ -112,7 +113,7 @@ class Wallet
112113
virtual bool getAddress(const CTxDestination& dest,
113114
std::string* name,
114115
wallet::isminetype* is_mine,
115-
std::string* purpose) = 0;
116+
wallet::AddressPurpose* purpose) = 0;
116117

117118
//! Get wallet address list.
118119
virtual std::vector<WalletAddress> getAddresses() const = 0;
@@ -293,7 +294,7 @@ class Wallet
293294
using AddressBookChangedFn = std::function<void(const CTxDestination& address,
294295
const std::string& label,
295296
bool is_mine,
296-
const std::string& purpose,
297+
wallet::AddressPurpose purpose,
297298
ChangeType status)>;
298299
virtual std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) = 0;
299300

@@ -352,11 +353,11 @@ struct WalletAddress
352353
{
353354
CTxDestination dest;
354355
wallet::isminetype is_mine;
356+
wallet::AddressPurpose purpose;
355357
std::string name;
356-
std::string purpose;
357358

358-
WalletAddress(CTxDestination dest, wallet::isminetype is_mine, std::string name, std::string purpose)
359-
: dest(std::move(dest)), is_mine(is_mine), name(std::move(name)), purpose(std::move(purpose))
359+
WalletAddress(CTxDestination dest, wallet::isminetype is_mine, wallet::AddressPurpose purpose, std::string name)
360+
: dest(std::move(dest)), is_mine(is_mine), purpose(std::move(purpose)), name(std::move(name))
360361
{
361362
}
362363
};

src/qt/addresstablemodel.cpp

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

1010
#include <key_io.h>
11+
#include <wallet/types.h>
1112
#include <wallet/wallet.h>
1213

1314
#include <algorithm>
@@ -52,17 +53,16 @@ struct AddressTableEntryLessThan
5253
};
5354

5455
/* Determine address type from address purpose */
55-
static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
56+
static AddressTableEntry::Type translateTransactionType(wallet::AddressPurpose purpose, bool isMine)
5657
{
57-
AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
5858
// "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;
59+
switch (purpose) {
60+
case wallet::AddressPurpose::SEND: return AddressTableEntry::Sending;
61+
case wallet::AddressPurpose::RECEIVE: return AddressTableEntry::Receiving;
62+
case wallet::AddressPurpose::REFUND: return AddressTableEntry::Hidden;
63+
// No default case to allow for compiler to warn
64+
}
65+
assert(false);
6666
}
6767

6868
// Private implementation
@@ -85,7 +85,7 @@ class AddressTablePriv
8585
continue;
8686
}
8787
AddressTableEntry::Type addressType = translateTransactionType(
88-
QString::fromStdString(address.purpose), address.is_mine);
88+
address.purpose, address.is_mine);
8989
cachedAddressTable.append(AddressTableEntry(addressType,
9090
QString::fromStdString(address.name),
9191
QString::fromStdString(EncodeDestination(address.dest))));
@@ -97,7 +97,7 @@ class AddressTablePriv
9797
std::sort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
9898
}
9999

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

245245
if(role == Qt::EditRole)
@@ -253,7 +253,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
253253
editStatus = NO_CHANGES;
254254
return false;
255255
}
256-
walletModel->wallet().setAddressBook(curAddress, value.toString().toStdString(), strPurpose);
256+
walletModel->wallet().setAddressBook(curAddress, value.toString().toStdString(), purpose);
257257
} else if(index.column() == Address) {
258258
CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
259259
// Refuse to set invalid address, set error status and return false
@@ -282,7 +282,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
282282
// Remove old entry
283283
walletModel->wallet().delAddressBook(curAddress);
284284
// Add new entry with new address
285-
walletModel->wallet().setAddressBook(newAddress, value.toString().toStdString(), strPurpose);
285+
walletModel->wallet().setAddressBook(newAddress, value.toString().toStdString(), purpose);
286286
}
287287
}
288288
return true;
@@ -334,7 +334,7 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &par
334334
}
335335

336336
void AddressTableModel::updateEntry(const QString &address,
337-
const QString &label, bool isMine, const QString &purpose, int status)
337+
const QString &label, bool isMine, wallet::AddressPurpose purpose, int status)
338338
{
339339
// Update address book model from Bitcoin core
340340
priv->updateEntry(address, label, isMine, purpose, status);
@@ -365,7 +365,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
365365
}
366366

367367
// Add entry
368-
walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, "send");
368+
walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, wallet::AddressPurpose::SEND);
369369
}
370370
else if(type == Receive)
371371
{
@@ -416,18 +416,18 @@ QString AddressTableModel::labelForAddress(const QString &address) const
416416
return QString();
417417
}
418418

419-
QString AddressTableModel::purposeForAddress(const QString &address) const
419+
std::optional<wallet::AddressPurpose> AddressTableModel::purposeForAddress(const QString &address) const
420420
{
421-
std::string purpose;
421+
wallet::AddressPurpose purpose;
422422
if (getAddressData(address, /* name= */ nullptr, &purpose)) {
423-
return QString::fromStdString(purpose);
423+
return purpose;
424424
}
425-
return QString();
425+
return std::nullopt;
426426
}
427427

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

src/qt/addresstablemodel.h

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

8+
#include <optional>
9+
810
#include <QAbstractTableModel>
911
#include <QStringList>
1012

@@ -16,6 +18,9 @@ class WalletModel;
1618
namespace interfaces {
1719
class Wallet;
1820
}
21+
namespace wallet {
22+
enum class AddressPurpose;
23+
} // namespace wallet
1924

2025
/**
2126
Qt model of the address book in the core. This allows views to access and modify the address book.
@@ -71,7 +76,7 @@ class AddressTableModel : public QAbstractTableModel
7176
QString labelForAddress(const QString &address) const;
7277

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

7681
/* Look up row index of an address in the model.
7782
Return -1 if not found.
@@ -89,15 +94,15 @@ class AddressTableModel : public QAbstractTableModel
8994
EditStatus editStatus = OK;
9095

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

9499
/** Notify listeners that data changed. */
95100
void emitDataChanged(int index);
96101

97102
public Q_SLOTS:
98103
/* Update address list from core.
99104
*/
100-
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
105+
void updateEntry(const QString &address, const QString &label, bool isMine, wallet::AddressPurpose purpose, int status);
101106

102107
friend class AddressTablePriv;
103108
};

src/qt/editaddressdialog.cpp

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

11+
#include <wallet/types.h>
12+
1113
#include <QDataWidgetMapper>
1214
#include <QMessageBox>
1315

@@ -137,9 +139,9 @@ QString EditAddressDialog::getDuplicateAddressWarning() const
137139
{
138140
QString dup_address = ui->addressEdit->text();
139141
QString existing_label = model->labelForAddress(dup_address);
140-
QString existing_purpose = model->purposeForAddress(dup_address);
142+
auto existing_purpose = model->purposeForAddress(dup_address);
141143

142-
if (existing_purpose == "receive" &&
144+
if (existing_purpose == wallet::AddressPurpose::RECEIVE &&
143145
(mode == NewSendingAddress || mode == EditSendingAddress)) {
144146
return tr(
145147
"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
@@ -113,8 +113,8 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
113113

114114
{
115115
LOCK(wallet->cs_wallet);
116-
wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
117-
wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send");
116+
wallet->SetAddressBook(r_key_dest, r_label.toStdString(), wallet::AddressPurpose::RECEIVE);
117+
wallet->SetAddressBook(s_key_dest, s_label.toStdString(), wallet::AddressPurpose::SEND);
118118
}
119119

120120
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
@@ -221,7 +221,7 @@ std::shared_ptr<CWallet> SetupDescriptorsWallet(interfaces::Node& node, TestChai
221221
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
222222
if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
223223
CTxDestination dest = GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type);
224-
wallet->SetAddressBook(dest, "", "receive");
224+
wallet->SetAddressBook(dest, "", wallet::AddressPurpose::RECEIVE);
225225
wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash()));
226226
SyncUpWallet(wallet, node);
227227
wallet->SetBroadcastTransactions(true);

src/qt/transactiondesc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <policy/policy.h>
2121
#include <util/system.h>
2222
#include <validation.h>
23-
#include <wallet/ismine.h>
23+
#include <wallet/types.h>
2424

2525
#include <stdint.h>
2626
#include <string>

src/qt/transactionrecord.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <chain.h>
88
#include <interfaces/wallet.h>
99
#include <key_io.h>
10-
#include <wallet/ismine.h>
10+
#include <wallet/types.h>
1111

1212
#include <stdint.h>
1313

0 commit comments

Comments
 (0)