Skip to content

Commit 26ff28a

Browse files
laanwjPastaPastaPasta
authored andcommitted
Merge bitcoin#21353: interfaces: Stop exposing wallet destdata to gui
f5ba424 wallet: Add IsAddressUsed / SetAddressUsed methods (Russell Yanofsky) 62252c9 interfaces: Stop exposing wallet destdata to gui (Russell Yanofsky) 985430d test: Add gui test for wallet receive requests (Russell Yanofsky) Pull request description: Stop giving GUI access to destdata rows in database. Replace with narrow API just for saving and reading receive request information. This simplifies code and should prevent the GUI from interfering with other destdata like address-used status. It also adds some more GUI test coverage. There are no changes in behavior. ACKs for top commit: jarolrod: tACK f5ba424 laanwj: Code review ACK f5ba424 Tree-SHA512: 5423df4786e537a59013cb5bfb9e1bc29a7ca4b8835360c00cc2165a59f925fdc355907a4ceb8bca0285bb4946ba235bffa7645537a951ad03fd3b4cee17b6b0
1 parent 348f4a8 commit 26ff28a

File tree

9 files changed

+78
-79
lines changed

9 files changed

+78
-79
lines changed

src/interfaces/wallet.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,11 @@ class Wallet
128128
//! Get wallet address list.
129129
virtual std::vector<WalletAddress> getAddresses() = 0;
130130

131-
//! Add dest data.
132-
virtual bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) = 0;
131+
//! Get receive requests.
132+
virtual std::vector<std::string> getAddressReceiveRequests() = 0;
133133

134-
//! Erase dest data.
135-
virtual bool eraseDestData(const CTxDestination& dest, const std::string& key) = 0;
136-
137-
//! Get dest values with prefix.
138-
virtual std::vector<std::string> getDestValues(const std::string& prefix) = 0;
134+
//! Save or remove receive request.
135+
virtual bool setAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& value) = 0;
139136

140137
//! Lock coin.
141138
virtual void lockCoin(const COutPoint& output) = 0;

src/qt/recentrequeststablemodel.cpp

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

1212
#include <clientversion.h>
13+
#include <interfaces/wallet.h>
14+
#include <key_io.h>
1315
#include <streams.h>
16+
#include <util/string.h>
1417

1518
#include <utility>
1619

1720
RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) :
1821
QAbstractTableModel(parent), walletModel(parent)
1922
{
2023
// Load entries from wallet
21-
std::vector<std::string> vReceiveRequests;
22-
parent->loadReceiveRequests(vReceiveRequests);
23-
for (const std::string& request : vReceiveRequests)
24+
for (const std::string& request : parent->wallet().getAddressReceiveRequests()) {
2425
addNewRequest(request);
26+
}
2527

2628
/* These columns must match the indices in the ColumnIndex enumeration */
2729
columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle();
@@ -143,7 +145,7 @@ bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex
143145
for (int i = 0; i < count; ++i)
144146
{
145147
const RecentRequestEntry* rec = &list[row+i];
146-
if (!walletModel->saveReceiveRequest(rec->recipient.address.toStdString(), rec->id, ""))
148+
if (!walletModel->wallet().setAddressReceiveRequest(DecodeDestination(rec->recipient.address.toStdString()), ToString(rec->id), ""))
147149
return false;
148150
}
149151

@@ -172,7 +174,7 @@ void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient
172174
CDataStream ss(SER_DISK, CLIENT_VERSION);
173175
ss << newEntry;
174176

175-
if (!walletModel->saveReceiveRequest(recipient.address.toStdString(), newEntry.id, ss.str()))
177+
if (!walletModel->wallet().setAddressReceiveRequest(DecodeDestination(recipient.address.toStdString()), ToString(newEntry.id), ss.str()))
176178
return;
177179

178180
addNewRequest(newEntry);

src/qt/test/wallettests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ void TestGUI(interfaces::Node& node)
187187
int initialRowCount = requestTableModel->rowCount({});
188188
QPushButton* requestPaymentButton = receiveCoinsDialog.findChild<QPushButton*>("receiveButton");
189189
requestPaymentButton->click();
190+
QString address;
190191
for (QWidget* widget : QApplication::topLevelWidgets()) {
191192
if (widget->inherits("ReceiveRequestDialog")) {
192193
ReceiveRequestDialog* receiveRequestDialog = qobject_cast<ReceiveRequestDialog*>(widget);
@@ -195,6 +196,9 @@ void TestGUI(interfaces::Node& node)
195196
QString uri = receiveRequestDialog->QObject::findChild<QLabel*>("uri_content")->text();
196197
QCOMPARE(uri.count("dash:"), 2);
197198
QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("address_tag")->text(), QString("Address:"));
199+
QVERIFY(address.isEmpty());
200+
address = receiveRequestDialog->QObject::findChild<QLabel*>("address_content")->text();
201+
QVERIFY(!address.isEmpty());
198202

199203
QCOMPARE(uri.count("amount=0.00000001"), 2);
200204
QCOMPARE(receiveRequestDialog->QObject::findChild<QLabel*>("amount_tag")->text(), QString("Amount:"));
@@ -221,13 +225,31 @@ void TestGUI(interfaces::Node& node)
221225
int currentRowCount = requestTableModel->rowCount({});
222226
QCOMPARE(currentRowCount, initialRowCount+1);
223227

228+
// Check addition to wallet
229+
std::vector<std::string> requests = walletModel.wallet().getAddressReceiveRequests();
230+
QCOMPARE(requests.size(), size_t{1});
231+
RecentRequestEntry entry;
232+
CDataStream{MakeUCharSpan(requests[0]), SER_DISK, CLIENT_VERSION} >> entry;
233+
QCOMPARE(entry.nVersion, int{1});
234+
QCOMPARE(entry.id, int64_t{1});
235+
QVERIFY(entry.date.isValid());
236+
QCOMPARE(entry.recipient.address, address);
237+
QCOMPARE(entry.recipient.label, QString{"TEST_LABEL_1"});
238+
QCOMPARE(entry.recipient.amount, CAmount{1});
239+
QCOMPARE(entry.recipient.message, QString{"TEST_MESSAGE_1"});
240+
QCOMPARE(entry.recipient.sPaymentRequest, std::string{});
241+
QCOMPARE(entry.recipient.authenticatedMerchant, QString{});
242+
224243
// Check Remove button
225244
QTableView* table = receiveCoinsDialog.findChild<QTableView*>("recentRequestsView");
226245
table->selectRow(currentRowCount-1);
227246
QPushButton* removeRequestButton = receiveCoinsDialog.findChild<QPushButton*>("removeRequestButton");
228247
removeRequestButton->click();
229248
QCOMPARE(requestTableModel->rowCount({}), currentRowCount-1);
230249
RemoveWallet(wallet, std::nullopt);
250+
251+
// Check removal from wallet
252+
QCOMPARE(walletModel.wallet().getAddressReceiveRequests().size(), size_t{0});
231253
}
232254

233255
} // namespace

src/qt/walletmodel.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -571,25 +571,6 @@ void WalletModel::UnlockContext::CopyFrom(UnlockContext&& rhs)
571571
rhs.was_mixing = false;
572572
}
573573

574-
void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
575-
{
576-
vReceiveRequests = m_wallet->getDestValues("rr"); // receive request
577-
}
578-
579-
bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
580-
{
581-
CTxDestination dest = DecodeDestination(sAddress);
582-
583-
std::stringstream ss;
584-
ss << nId;
585-
std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
586-
587-
if (sRequest.empty())
588-
return m_wallet->eraseDestData(dest, key);
589-
else
590-
return m_wallet->addDestData(dest, key, sRequest);
591-
}
592-
593574
bool WalletModel::isWalletEnabled()
594575
{
595576
return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);

src/qt/walletmodel.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,6 @@ class WalletModel : public QObject
140140

141141
UnlockContext requestUnlock(bool fForMixingOnly=false);
142142

143-
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
144-
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
145-
146143
static bool isWalletEnabled();
147144

148145
int getNumISLocks() const;

src/wallet/interfaces.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -227,22 +227,14 @@ class WalletImpl : public Wallet
227227
}
228228
return result;
229229
}
230-
bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override
231-
{
230+
std::vector<std::string> getAddressReceiveRequests() override {
232231
LOCK(m_wallet->cs_wallet);
233-
WalletBatch batch{m_wallet->GetDatabase()};
234-
return m_wallet->AddDestData(batch, dest, key, value);
232+
return m_wallet->GetAddressReceiveRequests();
235233
}
236-
bool eraseDestData(const CTxDestination& dest, const std::string& key) override
237-
{
234+
bool setAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& value) override {
238235
LOCK(m_wallet->cs_wallet);
239236
WalletBatch batch{m_wallet->GetDatabase()};
240-
return m_wallet->EraseDestData(batch, dest, key);
241-
}
242-
std::vector<std::string> getDestValues(const std::string& prefix) override
243-
{
244-
LOCK(m_wallet->cs_wallet);
245-
return m_wallet->GetDestValues(prefix);
237+
return m_wallet->SetAddressReceiveRequest(batch, dest, id, value);
246238
}
247239
void lockCoin(const COutPoint& output) override
248240
{

src/wallet/test/wallet_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,11 @@ BOOST_AUTO_TEST_CASE(LoadReceiveRequests)
478478
CTxDestination dest = PKHash();
479479
LOCK(m_wallet.cs_wallet);
480480
WalletBatch batch{m_wallet.GetDatabase()};
481-
m_wallet.AddDestData(batch, dest, "misc", "val_misc");
482-
m_wallet.AddDestData(batch, dest, "rr0", "val_rr0");
483-
m_wallet.AddDestData(batch, dest, "rr1", "val_rr1");
481+
m_wallet.SetAddressUsed(batch, dest, true);
482+
m_wallet.SetAddressReceiveRequest(batch, dest, "0", "val_rr0");
483+
m_wallet.SetAddressReceiveRequest(batch, dest, "1", "val_rr1");
484484

485-
auto values = m_wallet.GetDestValues("rr");
485+
auto values = m_wallet.GetAddressReceiveRequests();
486486
BOOST_CHECK_EQUAL(values.size(), 2U);
487487
BOOST_CHECK_EQUAL(values[0], "val_rr0");
488488
BOOST_CHECK_EQUAL(values[1], "val_rr1");

src/wallet/wallet.cpp

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -803,12 +803,11 @@ void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned
803803
CTxDestination dst;
804804
if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
805805
if (IsMine(dst)) {
806-
if (used && !GetDestData(dst, "used", nullptr)) {
807-
if (AddDestData(batch, dst, "used", "p")) { // p for "present", opposite of absent (null)
806+
if (used != IsAddressUsed(dst)) {
807+
if (used) {
808808
tx_destinations.insert(dst);
809809
}
810-
} else if (!used && GetDestData(dst, "used", nullptr)) {
811-
EraseDestData(batch, dst, "used");
810+
SetAddressUsed(batch, dst, used);
812811
}
813812
}
814813
}
@@ -824,14 +823,14 @@ bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
824823
if (!ExtractDestination(srctx->tx->vout[n].scriptPubKey, dest)) {
825824
return false;
826825
}
827-
if (GetDestData(dest, "used", nullptr)) {
826+
if (IsAddressUsed(dest)) {
828827
return true;
829828
}
830829
if (IsLegacy()) {
831830
LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
832831
assert(spk_man != nullptr);
833832
for (const auto& keyid : GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
834-
if (GetDestData(PKHash(keyid), "used", nullptr)) {
833+
if (IsAddressUsed(PKHash(keyid))) {
835834
return true;
836835
}
837836
}
@@ -4441,45 +4440,45 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
44414440
return nTimeSmart;
44424441
}
44434442

4444-
bool CWallet::AddDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key, const std::string &value)
4443+
bool CWallet::SetAddressUsed(WalletBatch& batch, const CTxDestination& dest, bool used)
44454444
{
4445+
const std::string key{"used"};
44464446
if (std::get_if<CNoDestination>(&dest))
44474447
return false;
44484448

4449+
if (!used) {
4450+
if (auto* data = util::FindKey(m_address_book, dest)) data->destdata.erase(key);
4451+
return batch.EraseDestData(EncodeDestination(dest), key);
4452+
}
4453+
4454+
const std::string value{"1"};
44494455
m_address_book[dest].destdata.insert(std::make_pair(key, value));
44504456
return batch.WriteDestData(EncodeDestination(dest), key, value);
44514457
}
44524458

4453-
bool CWallet::EraseDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key)
4454-
{
4455-
if (!m_address_book[dest].destdata.erase(key))
4456-
return false;
4457-
return batch.EraseDestData(EncodeDestination(dest), key);
4458-
}
4459-
44604459
void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
44614460
{
44624461
m_address_book[dest].destdata.insert(std::make_pair(key, value));
44634462
}
44644463

4465-
bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
4464+
bool CWallet::IsAddressUsed(const CTxDestination& dest) const
44664465
{
4466+
const std::string key{"used"};
44674467
std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
44684468
if(i != m_address_book.end())
44694469
{
44704470
CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
44714471
if(j != i->second.destdata.end())
44724472
{
4473-
if(value)
4474-
*value = j->second;
44754473
return true;
44764474
}
44774475
}
44784476
return false;
44794477
}
44804478

4481-
std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
4479+
std::vector<std::string> CWallet::GetAddressReceiveRequests() const
44824480
{
4481+
const std::string prefix{"rr"};
44834482
std::vector<std::string> values;
44844483
for (const auto& address : m_address_book) {
44854484
for (const auto& data : address.second.destdata) {
@@ -4491,6 +4490,20 @@ std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
44914490
return values;
44924491
}
44934492

4493+
bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
4494+
{
4495+
const std::string key{"rr" + id}; // "rr" prefix = "receive request" in destdata
4496+
CAddressBookData& data = m_address_book.at(dest);
4497+
if (value.empty()) {
4498+
if (!batch.EraseDestData(EncodeDestination(dest), key)) return false;
4499+
data.destdata.erase(key);
4500+
} else {
4501+
if (!batch.WriteDestData(EncodeDestination(dest), key, value)) return false;
4502+
data.destdata[key] = value;
4503+
}
4504+
return true;
4505+
}
4506+
44944507
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
44954508
{
44964509
// Do some checking on wallet path. It should be either a:

src/wallet/wallet.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -983,19 +983,8 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
983983

984984
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
985985

986-
/**
987-
* Adds a destination data tuple to the store, and saves it to disk
988-
* When adding new fields, take care to consider how DelAddressBook should handle it!
989-
*/
990-
bool AddDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
991-
//! Erases a destination data tuple in the store and on disk
992-
bool EraseDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
993986
//! Adds a destination data tuple to the store, without saving it to disk
994987
void LoadDestData(const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
995-
//! Look up a destination data tuple in the store, return true if found false otherwise
996-
bool GetDestData(const CTxDestination& dest, const std::string& key, std::string* value) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
997-
//! Get all destination values matching a prefix.
998-
std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
999988

1000989
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
1001990
int64_t nRelockTime GUARDED_BY(cs_wallet){0};
@@ -1201,6 +1190,12 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
12011190

12021191
bool DelAddressBook(const CTxDestination& address);
12031192

1193+
bool IsAddressUsed(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
1194+
bool SetAddressUsed(WalletBatch& batch, const CTxDestination& dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
1195+
1196+
std::vector<std::string> GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
1197+
bool SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
1198+
12041199
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
12051200

12061201
//! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower

0 commit comments

Comments
 (0)