v30.3-roots.1 · Commit 50: [PATCH 50/68] qt: cleanse and release transient sweep cache
src/qt/test/wallettests.cpp
Before: src/qt/test/wallettests.cpp · After: src/qt/test/wallettests.cpp
File metadata
index b861a828c6ba30ad0e392e25f370970c687baf7f..54069ae8c61a7743cdb24b14a53c3e7d589c17ba 100644
Download original patch · Release notes
Diff rows 1–62 of 62. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
src/qt/test/wallettests.cpp
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
#include <qt/transactionview.h>
|
|
30
30
|
#include <qt/walletmodel.h>
|
|
31
31
|
#include <script/solver.h>
|
|
32
|
+
#include <support/lockedpool.h>
|
|
32
33
|
#include <test/util/setup_common.h>
|
|
33
34
|
#include <util/rbf.h>
|
|
34
35
|
#include <validation.h>
|
|
@@ -71,6 +72,12 @@ using wallet::WalletContext;
|
|
|
71
72
|
using wallet::WalletDescriptor;
|
|
72
73
|
using wallet::WalletRescanReserver;
|
|
73
74
|
|
|
75
|
+
struct SweepDialogTestAccess
|
|
76
|
+
{
|
|
77
|
+
static SecureString& Cache(SweepDialog& dialog) { return dialog.m_private_key_cache; }
|
|
78
|
+
static void ClearCache(SweepDialog& dialog) { dialog.clearPrivateKeyCache(); }
|
|
79
|
+
};
|
|
80
|
+
|
|
74
81
|
namespace
|
|
75
82
|
{
|
|
76
83
|
class LogCapture
|
|
@@ -312,6 +319,19 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
|
312
319
|
|
|
313
320
|
// Verify the guarded sweep dialog contract and asynchronous error path.
|
|
314
321
|
SweepDialog sweep_dialog(&walletModel);
|
|
322
|
+
auto& sweep_cache{SweepDialogTestAccess::Cache(sweep_dialog)};
|
|
323
|
+
// Disposal must release locked storage while the dialog stays alive;
|
|
324
|
+
// observe allocator accounting rather than dereferencing freed memory.
|
|
325
|
+
const auto locked_bytes_before{LockedPoolManager::Instance().stats().used};
|
|
326
|
+
sweep_cache.assign(52, 's');
|
|
327
|
+
QVERIFY(LockedPoolManager::Instance().stats().used > locked_bytes_before);
|
|
328
|
+
SweepDialogTestAccess::ClearCache(sweep_dialog);
|
|
329
|
+
QVERIFY(sweep_cache.empty());
|
|
330
|
+
QCOMPARE(LockedPoolManager::Instance().stats().used, locked_bytes_before);
|
|
331
|
+
sweep_cache.assign(4, 's');
|
|
332
|
+
SweepDialogTestAccess::ClearCache(sweep_dialog);
|
|
333
|
+
QVERIFY(sweep_cache.empty());
|
|
334
|
+
QCOMPARE(LockedPoolManager::Instance().stats().used, locked_bytes_before);
|
|
315
335
|
QLineEdit* sweep_key = sweep_dialog.findChild<QLineEdit*>("sweepPrivateKey");
|
|
316
336
|
QLineEdit* sweep_destination = sweep_dialog.findChild<QLineEdit*>("sweepDestination");
|
|
317
337
|
QPushButton* sweep_preview = sweep_dialog.findChild<QPushButton*>("sweepPreview");
|
|
@@ -356,6 +376,8 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
|
356
376
|
QVERIFY(!sweep_key->isEnabled());
|
|
357
377
|
QVERIFY(sweep_key->text().isEmpty());
|
|
358
378
|
QTRY_VERIFY(sweep_key->isEnabled());
|
|
379
|
+
QVERIFY(sweep_cache.empty());
|
|
380
|
+
QCOMPARE(sweep_cache.capacity(), SecureString{}.capacity());
|
|
359
381
|
QVERIFY(!sweep_result->text().contains(sweep_sentinel));
|
|
360
382
|
QVERIFY(!QString::fromStdString(sweep_logs.output).contains(sweep_sentinel));
|
|
361
383
|
|
|
@@ -366,6 +388,8 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
|
366
388
|
// A competing wallet update must discard the transient key and preview
|
|
367
389
|
// immediately, rather than relying on broadcast-time stale detection.
|
|
368
390
|
walletModel.updateTransaction();
|
|
391
|
+
QVERIFY(sweep_cache.empty());
|
|
392
|
+
QCOMPARE(sweep_cache.capacity(), SecureString{}.capacity());
|
|
369
393
|
QVERIFY(sweep_key->isEnabled());
|
|
370
394
|
QVERIFY(sweep_key->text().isEmpty());
|
|
371
395
|
QVERIFY(!sweep_broadcast->isEnabled());
|
|
@@ -375,6 +399,8 @@ void TestGUI(interfaces::Node& node, const std::shared_ptr<CWallet>& wallet)
|
|
|
375
399
|
QVERIFY(!sweep_broadcast->isEnabled());
|
|
376
400
|
sweep_dialog.reject();
|
|
377
401
|
QVERIFY(sweep_key->text().isEmpty());
|
|
402
|
+
QVERIFY(sweep_cache.empty());
|
|
403
|
+
QCOMPARE(sweep_cache.capacity(), SecureString{}.capacity());
|
|
378
404
|
|
|
379
405
|
const auto settings_contain_sentinel = [&] {
|
|
380
406
|
QSettings settings;
|