aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.qt_locale.include1
-rw-r--r--src/net_processing.cpp24
-rw-r--r--src/qt/bitcoin_locale.qrc1
-rw-r--r--src/qt/bitcoingui.cpp4
-rw-r--r--src/qt/locale/bitcoin_fa.ts100
-rw-r--r--src/qt/locale/bitcoin_mr_IN.ts97
-rw-r--r--src/qt/locale/bitcoin_nb.ts112
-rw-r--r--src/qt/locale/bitcoin_pa.ts448
-rw-r--r--src/qt/locale/bitcoin_th.ts16
-rw-r--r--src/qt/locale/bitcoin_tr.ts22
-rw-r--r--src/qt/walletframe.cpp2
-rw-r--r--src/script/sign.cpp21
-rw-r--r--src/wallet/rpc/spend.cpp6
-rw-r--r--src/wallet/rpc/wallet.cpp4
-rw-r--r--src/wallet/scriptpubkeyman.cpp35
-rw-r--r--src/wallet/spend.cpp14
-rw-r--r--src/wallet/spend.h2
-rw-r--r--src/wallet/test/coinselector_tests.cpp40
-rw-r--r--src/wallet/test/spend_tests.cpp45
-rw-r--r--src/wallet/wallet.cpp4
20 files changed, 920 insertions, 78 deletions
diff --git a/src/Makefile.qt_locale.include b/src/Makefile.qt_locale.include
index 63ef39d6b8..3ccbc4fd18 100644
--- a/src/Makefile.qt_locale.include
+++ b/src/Makefile.qt_locale.include
@@ -59,6 +59,7 @@ QT_TS = \
qt/locale/bitcoin_ne.ts \
qt/locale/bitcoin_nl.ts \
qt/locale/bitcoin_no.ts \
+ qt/locale/bitcoin_pa.ts \
qt/locale/bitcoin_pam.ts \
qt/locale/bitcoin_pl.ts \
qt/locale/bitcoin_pt.ts \
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index a6299be403..3edc051034 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -2007,8 +2007,15 @@ void PeerManagerImpl::RelayTransaction(const uint256& txid, const uint256& wtxid
auto tx_relay = peer.GetTxRelay();
if (!tx_relay) continue;
- const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
LOCK(tx_relay->m_tx_inventory_mutex);
+ // Only queue transactions for announcement once the version handshake
+ // is completed. The time of arrival for these transactions is
+ // otherwise at risk of leaking to a spy, if the spy is able to
+ // distinguish transactions received during the handshake from the rest
+ // in the announcement.
+ if (tx_relay->m_next_inv_send_time == 0s) continue;
+
+ const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
tx_relay->m_tx_inventory_to_send.insert(hash);
}
@@ -3396,6 +3403,21 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// they may wish to request compact blocks from us
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/false, /*version=*/CMPCTBLOCKS_VERSION));
}
+
+ if (auto tx_relay = peer->GetTxRelay()) {
+ // `TxRelay::m_tx_inventory_to_send` must be empty before the
+ // version handshake is completed as
+ // `TxRelay::m_next_inv_send_time` is first initialised in
+ // `SendMessages` after the verack is received. Any transactions
+ // received during the version handshake would otherwise
+ // immediately be advertised without random delay, potentially
+ // leaking the time of arrival to a spy.
+ Assume(WITH_LOCK(
+ tx_relay->m_tx_inventory_mutex,
+ return tx_relay->m_tx_inventory_to_send.empty() &&
+ tx_relay->m_next_inv_send_time == 0s));
+ }
+
pfrom.fSuccessfullyConnected = true;
return;
}
diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc
index 5edb4a08fe..e87cfe21e2 100644
--- a/src/qt/bitcoin_locale.qrc
+++ b/src/qt/bitcoin_locale.qrc
@@ -60,6 +60,7 @@
<file alias="ne">locale/bitcoin_ne.qm</file>
<file alias="nl">locale/bitcoin_nl.qm</file>
<file alias="no">locale/bitcoin_no.qm</file>
+ <file alias="pa">locale/bitcoin_pa.qm</file>
<file alias="pam">locale/bitcoin_pam.qm</file>
<file alias="pl">locale/bitcoin_pl.qm</file>
<file alias="pt">locale/bitcoin_pt.qm</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 894a401e56..18d374311a 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -512,7 +512,7 @@ void BitcoinGUI::createMenuBar()
connect(minimize_action, &QAction::triggered, [] {
QApplication::activeWindow()->showMinimized();
});
- connect(qApp, &QApplication::focusWindowChanged, [minimize_action] (QWindow* window) {
+ connect(qApp, &QApplication::focusWindowChanged, this, [minimize_action] (QWindow* window) {
minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
});
@@ -527,7 +527,7 @@ void BitcoinGUI::createMenuBar()
}
});
- connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) {
+ connect(qApp, &QApplication::focusWindowChanged, this, [zoom_action] (QWindow* window) {
zoom_action->setEnabled(window != nullptr);
});
#endif
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 8f4d7a6d10..5c4fba8ac1 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -259,6 +259,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">فایل تنظیمات %1 ممکن است خراب یا نامعتبر باشد.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">استثناء فراری (این استثناء نشان دهنده این است که هسته بیتکوین نتوانست چیزی را در کیف(والت) بنویسد.)</translation>
</message>
@@ -1013,7 +1017,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>سابقه تراکنش بلوک(های) %n پردازش شد.</numerusform>
</translation>
</message>
<message>
@@ -1087,6 +1091,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">کیف پول را ببندید</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">بازیابی کیف پول…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">بازیابی یک کیف پول از یک فایل پشتیبان</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">همه‌ی کیف پول‌ها را ببند</translation>
</message>
@@ -1105,6 +1119,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">داده های کیف پول</translation>
</message>
<message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">بارگیری پشتیبان‌گیری کیف پول</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">بازیابی کیف پول</translation>
+ </message>
+ <message>
<source>Wallet Name</source>
<extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
<translation type="unfinished">نام کیف پول</translation>
@@ -1133,7 +1157,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n اتصال(های) فعال به شبکه بیت کوین.</numerusform>
</translation>
</message>
<message>
@@ -1157,6 +1181,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">فعال‌سازی فعالیت شبکه</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">پیش‌همگام‌سازی سرصفحه‌ها (%1%)…</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">خطا: %1</translation>
</message>
@@ -1414,7 +1442,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">نمی‌توان امضاکنندگان را فهرست کرد</translation>
</message>
- </context>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">تعداد زیادی امضاکننده خارجی پیدا شد</translation>
+ </message>
+</context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1456,6 +1488,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">بازیابی کیف پول</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">بازیابی کیف پول &lt;b&gt;%1&lt;/b&gt; ...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">بازیابی کیف پول انجام نشد</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">هشدار بازیابی کیف پول</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">بازیابی پیام کیف پول</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1611,19 +1671,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n GB of space available</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n گیگابایت فضای موجود</numerusform>
</translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(از %n گیگابایت مورد نیاز)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>(%n GB needed for full chain)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(%n گیگابایت برای زنجیره کامل مورد نیاز است)</numerusform>
</translation>
</message>
<message>
@@ -1638,7 +1698,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(برای بازیابی نسخه‌های پشتیبان %n روز (های) قدیمی کافی است)</numerusform>
</translation>
</message>
<message>
@@ -1674,6 +1734,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">گیگابایت</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">وقتی تأیید را کلیک می‌کنید، %1 شروع به دانلود و پردازش زنجیره بلاک %4 کامل (%2 گیگابایت) می‌کند که با اولین تراکنش‌ها در %3 شروع می‌شود که %4 در ابتدا راه‌اندازی می شود.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">اگر تصمیم بگیرید که فضای ذخیره سازی زنجیره بلوک (هرس) را محدود کنید ، داده های تاریخی باید بارگیری و پردازش شود ، اما اگر آن را حذف کنید ، اگر شما دیسک کم استفاده کنید.
 </translation>
@@ -1765,7 +1829,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">ناشناخته. هماهنگ‌سازی سربرگ‌ها (%1، %2%) </translation>
</message>
- </context>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">ناشناس. پیش‌همگام‌سازی سرصفحه‌ها (%1، %2% )…</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -1801,6 +1869,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">اندازه کش پایگاه داده.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">گزینه های تنظیم شده در این گفتگو توسط خط فرمان لغو می شوند:</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation type="unfinished">بازکردن فایل پیکربندی</translation>
</message>
@@ -2039,6 +2111,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">کلاینت نیازمند ریست شدن است برای فعال کردن تغییرات</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">تنظیمات فعلی در "%1" پشتیبان گیری خواهد شد.</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
<extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">کلاینت خاموش خواهد شد.آیا میخواهید ادامه دهید؟</translation>
@@ -2081,6 +2158,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">نمی توان تنظیم "%1"، %2 را خواند.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
diff --git a/src/qt/locale/bitcoin_mr_IN.ts b/src/qt/locale/bitcoin_mr_IN.ts
index f1b84c27ea..2641e4586a 100644
--- a/src/qt/locale/bitcoin_mr_IN.ts
+++ b/src/qt/locale/bitcoin_mr_IN.ts
@@ -86,6 +86,11 @@
<translation type="unfinished">पत्त्याची निर्यात करा</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">कॉमा सेपरेटेड फ़ाइल</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation type="unfinished">निर्यात अयशस्वी</translation>
</message>
@@ -106,7 +111,22 @@
</message>
</context>
<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">एक गंभीर त्रुटी आली. %1यापुढे सुरक्षितपणे सुरू ठेवू शकत नाही आणि संपेल.</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">अंतर्गत त्रुटी</translation>
+ </message>
+ </context>
+<context>
<name>QObject</name>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1अजून सुरक्षितपणे बाहेर पडलो नाही...</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
@@ -151,7 +171,79 @@
</message>
</context>
<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">सेटिंग्ज फाइल वाचता आली नाही</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">सेटिंग्ज फाइल लिहिता आली नाही</translation>
+ </message>
+ </context>
+<context>
<name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;मिनीमाइज़</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;पर्याय</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;एनक्रिप्ट वॉलेट</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;बॅकअप वॉलेट…
+ </translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;पासफ्रेज बदला...</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">स्वाक्षरी आणि संदेश...</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;संदेश सत्यापित करा...</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">फाइलमधून PSBT &amp;लोड करा...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">वॉलेट बंद करा...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">वॉलेट तयार करा...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">सर्व वॉलेट बंद करा...</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">शीर्षलेख समक्रमित करत आहे (%1%)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">नेटवर्कसह सिंक्रोनाइझ करत आहे...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">डिस्कवर ब्लॉक अनुक्रमित करत आहे...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">डिस्कवर ब्लॉक्सवर प्रक्रिया करत आहे...</translation>
+ </message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
@@ -264,6 +356,11 @@
<context>
<name>TransactionView</name>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">कॉमा सेपरेटेड फ़ाइल</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">लेबल</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts
index 777c1157df..c58017288f 100644
--- a/src/qt/locale/bitcoin_nb.ts
+++ b/src/qt/locale/bitcoin_nb.ts
@@ -269,6 +269,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Vil du tilbakestille innstillingene til utgangsverdiene, eller vil du avbryte uten å gjøre endringer?</translation>
</message>
<message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">En fatal feil har oppstått. Sjekk at filen med innstillinger er skrivbar eller prøv å kjøre med -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Feil: Den spesifiserte datamappen "%1" finnes ikke.</translation>
</message>
@@ -350,36 +355,36 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n sekund</numerusform>
+ <numerusform>%n sekunder</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n minutt</numerusform>
+ <numerusform>%n minutter</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n time</numerusform>
+ <numerusform>%n timer</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n dag</numerusform>
+ <numerusform>%n dager</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n uke</numerusform>
+ <numerusform>%n uker</numerusform>
</translation>
</message>
<message>
@@ -389,8 +394,8 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n år</numerusform>
+ <numerusform>%n år</numerusform>
</translation>
</message>
</context>
@@ -553,6 +558,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kan ikke sette -peerblockfilters uten -blockfilterindex</translation>
</message>
<message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Kunne ikke gjenopprette sikkerhetskopi av lommebok.</translation>
+ </message>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation type="unfinished">Kopirett © %i-%i</translation>
</message>
@@ -749,6 +760,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Må oppgi en port med -whitebind: '%s'</translation>
</message>
<message>
+ <source>No addresses available</source>
+ <translation type="unfinished">Ingen adresser tilgjengelig</translation>
+ </message>
+ <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">For få fildeskriptorer tilgjengelig.</translation>
</message>
@@ -1188,6 +1203,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Lukk lommebok</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Gjenopprett lommebok...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Gjenopprett en lommebok fra en sikkerhetskopi</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Lukk alle lommebøker</translation>
</message>
@@ -1217,6 +1242,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Lommebokdata</translation>
</message>
<message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Last lommebok sikkerhetskopi</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Gjenopprett lommebok</translation>
+ </message>
+ <message>
<source>Wallet Name</source>
<extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
<translation type="unfinished">Lommeboknavn</translation>
@@ -1262,6 +1297,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Klikk for å aktivere nettverksaktivitet.</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Synkroniserer blokkhoder (%1%)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Feil: %1</translation>
</message>
@@ -1550,6 +1589,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Gjenopprett lommebok</translation>
+ </message>
+ </context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1730,15 +1777,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>(of %n GB needed)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>(av %n GB som trengs)</numerusform>
+ <numerusform>(av %n GB som trengs)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>(%n GB needed for full chain)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>(%n GB kreves for hele kjeden)</numerusform>
+ <numerusform>(%n GB kreves for hele kjeden)</numerusform>
</translation>
</message>
<message>
@@ -1890,7 +1937,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished">%1 synkroniseres for øyeblikket. Den vil laste ned blokkhoder og blokker fra likemenn og validere dem til de når enden av blokkjeden.</translation>
</message>
- </context>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Ukjent.Synkroniser blokkhoder (%1,%2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -1942,6 +1993,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Minimer i stedet for å avslutte applikasjonen når vinduet lukkes. Når dette er valgt, vil applikasjonen avsluttes kun etter at Avslutte er valgt i menyen.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Alternativer som er satt i denne dialogboksen overstyres av kommandolinjen:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Åpne %1-oppsettsfila fra arbeidsmappen.</translation>
</message>
@@ -2351,6 +2406,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaksjonen trenger signatur(er).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Men ingen lommebok er lastet.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Men denne lommeboken kan ikke signere transaksjoner.)</translation>
</message>
@@ -2420,6 +2479,11 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Likemann</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Alder</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Retning</translation>
@@ -2602,6 +2666,11 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Kartlagt AS</translation>
</message>
<message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Adresser Prosessert</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Brukeragent</translation>
</message>
@@ -3272,6 +3341,11 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Se over ditt transaksjonsforslag. Dette kommer til å produsere en Delvis Signert Bitcoin Transaksjon (PSBT) som du kan lagre eller kopiere og så signere med f.eks. en offline %1 lommebok, eller en PSBT kompatibel hardware lommebok.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Vil du lage denne transaksjonen?</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Vennligst se over transaksjonen din.</translation>
@@ -3637,8 +3711,8 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>modner om %n blokk</numerusform>
+ <numerusform>modner om %n blokker</numerusform>
</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_pa.ts b/src/qt/locale/bitcoin_pa.ts
new file mode 100644
index 0000000000..e72f6a4bf0
--- /dev/null
+++ b/src/qt/locale/bitcoin_pa.ts
@@ -0,0 +1,448 @@
+<TS version="2.1" language="pa">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">ਪਤੇ ਜਾਂ ਲੇਬਲ ਦਾ ਸੰਪਾਦਨ ਕਰਨ ਲਈ ਸੱਜਾ-ਕਲਿੱਕ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">ਨਵਾਂ ਪਤਾ ਬਣਾਓ</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">&amp;ਨਵਾਂ</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">ਚੁਣੇ ਪਤੇ ਦੀ ਸਿਸਟਮ ਦੀ ਚੂੰਢੀ-ਤਖਤੀ 'ਤੇ ਨਕਲ ਲਾਹੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">&amp;ਨਕਲ ਲਾਹੋ</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">ਬੰ&amp;ਦ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">ਚੁਣੇ ਪਤੇ ਨੂੰ ਸੂਚੀ ਵਿੱਚੋਂ ਮਿਟਾਓ</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">ਖੋਜਣ ਲਈ ਪਤਾ ਜਾਂ ਲੇਬਲ ਦਾਖਲ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">ਮੌਜੂਦਾ ਟੈਬ ਵਿੱਚ ਡੇਟਾ ਨੂੰ ਫਾਈਲ ਵਿੱਚ ਐਕਸਪੋਰਟ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;ਨਿਰਯਾਤ</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">&amp;ਮਿਟਾਓ</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">ਸਿੱਕੇ ਭੇਜਣ ਲਈ ਪਤਾ ਚੁਣੋ</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">ਸਿੱਕੇ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ ਪਤਾ ਚੁਣੋ</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">ਇਹ ਭੁਗਤਾਨ ਭੇਜਣ ਲਈ ਤੁਹਾਡੇ ਬਿਟਕੋਇਨ ਪਤੇ ਹਨ। ਸਿੱਕੇ ਭੇਜਣ ਤੋਂ ਪਹਿਲਾਂ ਹਮੇਸ਼ਾਂ ਰਕਮ ਅਤੇ ਪ੍ਰਾਪਤ ਕਰਨ ਵਾਲੇ ਪਤੇ ਦੀ ਜਾਂਚ ਕਰੋ।</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">&amp;ਕਾਪੀ ਪਤਾ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">&amp;ਲੇਬਲ ਕਾਪੀ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;ਸੋਧੋ</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">ਪਤਾ ਸੂਚੀ ਨਿਰਯਾਤ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">ਕਾਮੇ ਨਾਲ ਵੱਖ ਕੀਤੀ ਫਾਈਲ</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">ਨਿਰਯਾਤ ਅਸਫਲ ਰਿਹਾ</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">ਪਤਾ</translation>
+ </message>
+ </context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਡਾਇਲਾਗ</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਲਿਖੋ</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation type="unfinished">ਨਵਾਂ ਪਾਸਫਰੇਜ</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation type="unfinished">ਨਵਾਂ ਪਾਸਫਰੇਜ ਦੁਹਰਾਓ</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਦਿਖਾਓ</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਐਨਕ੍ਰਿਪਟ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਨੂੰ ਅਨਲੌਕ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਬਦਲੋ</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਇਨਕ੍ਰਿਪਸ਼ਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ 'ਤੇ ਆਪਣੇ ਵਾਲਿਟ ਨੂੰ ਐਨਕ੍ਰਿਪਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਨੂੰ ਐਨਕ੍ਰਿਪਟ ਕੀਤਾ ਗਿਆ</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">ਇਨਕ੍ਰਿਪਟਡ ਹੋਣ ਲਈ ਵਾਲਿਟ</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">ਤੁਹਾਡਾ ਵਾਲਿਟ ਐਨਕ੍ਰਿਪਟ ਹੋਣ ਵਾਲਾ ਹੈ।</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">ਤੁਹਾਡਾ ਵਾਲਿਟ ਹੁਣ ਏਨਕ੍ਰਿਪਟ ਹੋ ਗਿਆ ਹੈ।</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਇਨਕ੍ਰਿਪਸ਼ਨ ਅਸਫਲ</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">ਸਪਲਾਈ ਕੀਤੇ ਪਾਸਫਰੇਜ਼ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ।</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਅਨਲੌਕ ਅਸਫਲ ਰਿਹਾ</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਪਾਸਫਰੇਜ ਸਫਲਤਾਪੂਰਵਕ ਬਦਲਿਆ ਗਿਆ।</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">ਚੇਤਾਵਨੀ: Caps Lock ਕੁੰਜੀ ਚਾਲੂ ਹੈ!</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">ਇੱਕ ਘਾਤਕ ਗਲਤੀ ਆਈ ਹੈ। %1ਹੁਣ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਜਾਰੀ ਨਹੀਂ ਰਹਿ ਸਕਦਾ ਹੈ ਅਤੇ ਛੱਡ ਦੇਵੇਗਾ।</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">ਅੰਦਰੂਨੀ ਗੜਬੜ</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">ਗਲਤੀ: %1</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">ਸੈਟਿੰਗ ਫਾਈਲ ਨੂੰ ਪੜ੍ਹਨ ਵਿੱਚ ਅਸਫਲ</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">ਸੈਟਿੰਗ ਫਾਈਲ ਲਿਖਣ ਵਿੱਚ ਅਸਫਲ</translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">&amp;ਓਵਰਵਿਊ</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">&amp;ਲੈਣ-ਦੇਣ</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">ਲੈਣ-ਦੇਣ ਦਾ ਇਤਿਹਾਸ ਬ੍ਰਾਊਜ਼ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">ਐਪਲੀਕੇਸ਼ਨ ਛੱਡੋ</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">ਨਵਾਂ ਵਾਲਿਟ ਬਣਾਓ</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">ਬਟੂਆ: </translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished">ਬਿਟਕੋਇਨ ਪਤੇ 'ਤੇ ਸਿੱਕੇ ਭੇਜੋ</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਨੂੰ ਕਿਸੇ ਹੋਰ ਥਾਂ 'ਤੇ ਬੈਕਅੱਪ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਇਨਕ੍ਰਿਪਸ਼ਨ ਲਈ ਵਰਤਿਆ ਜਾਣ ਵਾਲਾ ਪਾਸਫਰੇਜ ਬਦਲੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">&amp;ਭੇਜੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">&amp;ਪ੍ਰਾਪਤ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;ਵਾਲਿਟ ਇਨਕ੍ਰਿਪਟ ਕਰੋ...</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">ਨਿੱਜੀ ਕੁੰਜੀਆਂ ਨੂੰ ਐਨਕ੍ਰਿਪਟ ਕਰੋ ਜੋ ਤੁਹਾਡੇ ਵਾਲਿਟ ਨਾਲ ਸਬੰਧਤ ਹਨ</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;ਬੈਕਅੱਪ ਵਾਲਿਟ…</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ &amp;ਬਦਲੋ...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">ਗਲਤੀ: %1</translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>Address</source>
+ <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
+ <translation type="unfinished">ਪਤਾ</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">ਬਟੂਆ: </translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">ਕਾਮੇ ਨਾਲ ਵੱਖ ਕੀਤੀ ਫਾਈਲ</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">ਪਤਾ</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">ਨਿਰਯਾਤ ਅਸਫਲ ਰਿਹਾ</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">ਨਵਾਂ ਵਾਲਿਟ ਬਣਾਓ</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;ਨਿਰਯਾਤ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">ਮੌਜੂਦਾ ਟੈਬ ਵਿੱਚ ਡੇਟਾ ਨੂੰ ਫਾਈਲ ਵਿੱਚ ਐਕਸਪੋਰਟ ਕਰੋ</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_th.ts b/src/qt/locale/bitcoin_th.ts
index b98dac68f5..44052c6b24 100644
--- a/src/qt/locale/bitcoin_th.ts
+++ b/src/qt/locale/bitcoin_th.ts
@@ -312,31 +312,31 @@ Signing is only possible with addresses of the type 'legacy'</translation>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nวินาที</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nนาที</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nชั่วโมง</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nวัน</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nสัปดาห์</numerusform>
</translation>
</message>
<message>
@@ -346,7 +346,7 @@ Signing is only possible with addresses of the type 'legacy'</translation>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nปี</numerusform>
</translation>
</message>
<message>
@@ -1526,13 +1526,13 @@ Signing is only possible with addresses of the type 'legacy'</translation>
<message numerus="yes">
<source>%n GB of space available</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>มีพื้นที่ว่าง %n GB ที่ใช้งานได้</numerusform>
</translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(ต้องการพื้นที่ %n GB )</numerusform>
</translation>
</message>
<message numerus="yes">
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
index fc64a8b14b..f7c86ecd4f 100644
--- a/src/qt/locale/bitcoin_tr.ts
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -248,6 +248,10 @@ Cüzdan kilidini aç.</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">%1 ayar dosyası bozuk veya geçersiz olabilir.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Sızıntı istisnası</translation>
</message>
@@ -985,7 +989,7 @@ Cüzdan kilidini aç.</translation>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>İşlem geçmişinin %n bloğu işlendi.</numerusform>
</translation>
</message>
<message>
@@ -1403,7 +1407,11 @@ Cüzdan kilidini aç.</translation>
<source>Create wallet warning</source>
<translation type="unfinished">Cüzdan oluşturma uyarısı</translation>
</message>
- </context>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Çok fazla harici imzalayan bulundu</translation>
+ </message>
+</context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1449,6 +1457,16 @@ Cüzdan kilidini aç.</translation>
<extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
<translation type="unfinished">Cüzdanı Geri Yükle</translation>
</message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Cüzdan geri yüklenemedi</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Cüzdan uyarısını geri yükle</translation>
+ </message>
</context>
<context>
<name>WalletController</name>
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 8dc97e66a2..adc7793916 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -212,7 +212,7 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
return;
}
std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
- data.assign(std::istream_iterator<unsigned char>{in}, {});
+ data.assign(std::istreambuf_iterator<char>{in}, {});
// Some psbt files may be base64 strings in the file rather than binary data
std::string b64_str{data.begin(), data.end()};
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 5da0d076d8..0d74a661a5 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -146,6 +146,16 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
static bool CreateTaprootScriptSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const XOnlyPubKey& pubkey, const uint256& leaf_hash, SigVersion sigversion)
{
+ KeyOriginInfo info;
+ if (provider.GetKeyOriginByXOnly(pubkey, info)) {
+ auto it = sigdata.taproot_misc_pubkeys.find(pubkey);
+ if (it == sigdata.taproot_misc_pubkeys.end()) {
+ sigdata.taproot_misc_pubkeys.emplace(pubkey, std::make_pair(std::set<uint256>({leaf_hash}), info));
+ } else {
+ it->second.first.insert(leaf_hash);
+ }
+ }
+
auto lookup_key = std::make_pair(pubkey, leaf_hash);
auto it = sigdata.taproot_script_sigs.find(lookup_key);
if (it != sigdata.taproot_script_sigs.end()) {
@@ -170,17 +180,6 @@ static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatu
// <xonly pubkey> OP_CHECKSIG
if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {
XOnlyPubKey pubkey{Span{script}.subspan(1, 32)};
-
- KeyOriginInfo info;
- if (provider.GetKeyOriginByXOnly(pubkey, info)) {
- auto it = sigdata.taproot_misc_pubkeys.find(pubkey);
- if (it == sigdata.taproot_misc_pubkeys.end()) {
- sigdata.taproot_misc_pubkeys.emplace(pubkey, std::make_pair(std::set<uint256>({leaf_hash}), info));
- } else {
- it->second.first.insert(leaf_hash);
- }
- }
-
std::vector<unsigned char> sig;
if (CreateTaprootScriptSig(creator, sigdata, provider, sig, pubkey, leaf_hash, sigversion)) {
result = Vector(std::move(sig));
diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
index bc65cbf7bf..7064a50937 100644
--- a/src/wallet/rpc/spend.cpp
+++ b/src/wallet/rpc/spend.cpp
@@ -747,7 +747,7 @@ RPCHelpMan fundrawtransaction()
"If that happens, you will need to fund the transaction with different inputs and republish it."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
- {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
@@ -1144,7 +1144,7 @@ RPCHelpMan send()
{"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns a serialized transaction which will not be added to the wallet or broadcast"},
{"change_address", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"change_position", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
- {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\" and \"bech32m\"."},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
@@ -1597,7 +1597,7 @@ RPCHelpMan walletcreatefundedpsbt()
"If that happens, you will need to fund the transaction with different inputs and republish it."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
- {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only"},
{"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 675c4a759d..971814e9cd 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -730,7 +730,9 @@ static RPCHelpMan migratewallet()
std::shared_ptr<CWallet> wallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue;
- EnsureWalletIsUnlocked(*wallet);
+ if (wallet->IsCrypted()) {
+ throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: migratewallet on encrypted wallets is currently unsupported.");
+ }
WalletContext& context = EnsureWalletContext(request.context);
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 41654579c6..3bcc6b4bdc 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -2499,14 +2499,23 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction&
keys->Merge(std::move(*script_keys));
} else {
// Maybe there are pubkeys listed that we can sign for
- script_keys = std::make_unique<FlatSigningProvider>();
- for (const auto& pk_pair : input.hd_keypaths) {
- const CPubKey& pubkey = pk_pair.first;
- std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);
- if (pk_keys) {
- keys->Merge(std::move(*pk_keys));
- }
+ std::vector<CPubKey> pubkeys;
+
+ // ECDSA Pubkeys
+ for (const auto& [pk, _] : input.hd_keypaths) {
+ pubkeys.push_back(pk);
+ }
+
+ // Taproot output pubkey
+ std::vector<std::vector<unsigned char>> sols;
+ if (Solver(script, sols) == TxoutType::WITNESS_V1_TAPROOT) {
+ sols[0].insert(sols[0].begin(), 0x02);
+ pubkeys.emplace_back(sols[0]);
+ sols[0][0] = 0x03;
+ pubkeys.emplace_back(sols[0]);
}
+
+ // Taproot pubkeys
for (const auto& pk_pair : input.m_tap_bip32_paths) {
const XOnlyPubKey& pubkey = pk_pair.first;
for (unsigned char prefix : {0x02, 0x03}) {
@@ -2514,10 +2523,14 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction&
std::copy(pubkey.begin(), pubkey.end(), b + 1);
CPubKey fullpubkey;
fullpubkey.Set(b, b + 33);
- std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(fullpubkey);
- if (pk_keys) {
- keys->Merge(std::move(*pk_keys));
- }
+ pubkeys.push_back(fullpubkey);
+ }
+ }
+
+ for (const auto& pubkey : pubkeys) {
+ std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);
+ if (pk_keys) {
+ keys->Merge(std::move(*pk_keys));
}
}
}
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index ce41a4e954..f534e10799 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -102,15 +102,13 @@ void CoinsResult::Clear() {
coins.clear();
}
-void CoinsResult::Erase(std::set<COutPoint>& preset_coins)
+void CoinsResult::Erase(const std::set<COutPoint>& coins_to_remove)
{
- for (auto& it : coins) {
- auto& vec = it.second;
- auto i = std::find_if(vec.begin(), vec.end(), [&](const COutput &c) { return preset_coins.count(c.outpoint);});
- if (i != vec.end()) {
- vec.erase(i);
- break;
- }
+ for (auto& [type, vec] : coins) {
+ auto remove_it = std::remove_if(vec.begin(), vec.end(), [&](const COutput& coin) {
+ return coins_to_remove.count(coin.outpoint) == 1;
+ });
+ vec.erase(remove_it, vec.end());
}
}
diff --git a/src/wallet/spend.h b/src/wallet/spend.h
index c29e5be5c7..009e680627 100644
--- a/src/wallet/spend.h
+++ b/src/wallet/spend.h
@@ -47,7 +47,7 @@ struct CoinsResult {
* i.e., methods can work with individual OutputType vectors or on the entire object */
size_t Size() const;
void Clear();
- void Erase(std::set<COutPoint>& preset_coins);
+ void Erase(const std::set<COutPoint>& coins_to_remove);
void Shuffle(FastRandomContext& rng_fast);
void Add(OutputType type, const COutput& out);
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 23f024247d..9bc6fafae7 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -969,5 +969,45 @@ BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test)
BOOST_CHECK(!result);
}
+BOOST_FIXTURE_TEST_CASE(wallet_coinsresult_test, BasicTestingSetup)
+{
+ // Test case to verify CoinsResult object sanity.
+ CoinsResult available_coins;
+ {
+ std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", m_args, CreateMockWalletDatabase());
+ BOOST_CHECK_EQUAL(dummyWallet->LoadWallet(), DBErrors::LOAD_OK);
+ LOCK(dummyWallet->cs_wallet);
+ dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ dummyWallet->SetupDescriptorScriptPubKeyMans();
+
+ // Add some coins to 'available_coins'
+ for (int i=0; i<10; i++) {
+ add_coin(available_coins, *dummyWallet, 1 * COIN);
+ }
+ }
+
+ {
+ // First test case, check that 'CoinsResult::Erase' function works as expected.
+ // By trying to erase two elements from the 'available_coins' object.
+ std::set<COutPoint> outs_to_remove;
+ const auto& coins = available_coins.All();
+ for (int i = 0; i < 2; i++) {
+ outs_to_remove.emplace(coins[i].outpoint);
+ }
+ available_coins.Erase(outs_to_remove);
+
+ // Check that the elements were actually removed.
+ const auto& updated_coins = available_coins.All();
+ for (const auto& out: outs_to_remove) {
+ auto it = std::find_if(updated_coins.begin(), updated_coins.end(), [&out](const COutput &coin) {
+ return coin.outpoint == out;
+ });
+ BOOST_CHECK(it == updated_coins.end());
+ }
+ // And verify that no extra element were removed
+ BOOST_CHECK_EQUAL(available_coins.Size(), 8);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp
index a75b014870..81a8883f85 100644
--- a/src/wallet/test/spend_tests.cpp
+++ b/src/wallet/test/spend_tests.cpp
@@ -112,5 +112,50 @@ BOOST_FIXTURE_TEST_CASE(FillInputToWeightTest, BasicTestingSetup)
// Note: We don't test the next boundary because of memory allocation constraints.
}
+BOOST_FIXTURE_TEST_CASE(wallet_duplicated_preset_inputs_test, TestChain100Setup)
+{
+ // Verify that the wallet's Coin Selection process does not include pre-selected inputs twice in a transaction.
+
+ // Add 4 spendable UTXO, 50 BTC each, to the wallet (total balance 200 BTC)
+ for (int i = 0; i < 4; i++) CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+ auto wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), m_args, coinbaseKey);
+
+ LOCK(wallet->cs_wallet);
+ auto available_coins = AvailableCoins(*wallet);
+ std::vector<COutput> coins = available_coins.All();
+ // Preselect the first 3 UTXO (150 BTC total)
+ std::set<COutPoint> preset_inputs = {coins[0].outpoint, coins[1].outpoint, coins[2].outpoint};
+
+ // Try to create a tx that spends more than what preset inputs + wallet selected inputs are covering for.
+ // The wallet can cover up to 200 BTC, and the tx target is 299 BTC.
+ std::vector<CRecipient> recipients = {{GetScriptForDestination(*Assert(wallet->GetNewDestination(OutputType::BECH32, "dummy"))),
+ /*nAmount=*/299 * COIN, /*fSubtractFeeFromAmount=*/true}};
+ CCoinControl coin_control;
+ coin_control.m_allow_other_inputs = true;
+ for (const auto& outpoint : preset_inputs) {
+ coin_control.Select(outpoint);
+ }
+
+ // Attempt to send 299 BTC from a wallet that only has 200 BTC. The wallet should exclude
+ // the preset inputs from the pool of available coins, realize that there is not enough
+ // money to fund the 299 BTC payment, and fail with "Insufficient funds".
+ //
+ // Even with SFFO, the wallet can only afford to send 200 BTC.
+ // If the wallet does not properly exclude preset inputs from the pool of available coins
+ // prior to coin selection, it may create a transaction that does not fund the full payment
+ // amount or, through SFFO, incorrectly reduce the recipient's amount by the difference
+ // between the original target and the wrongly counted inputs (in this case 99 BTC)
+ // so that the recipient's amount is no longer equal to the user's selected target of 299 BTC.
+
+ // First case, use 'subtract_fee_from_outputs=true'
+ util::Result<CreatedTransactionResult> res_tx = CreateTransaction(*wallet, recipients, /*change_pos*/-1, coin_control);
+ BOOST_CHECK(!res_tx.has_value());
+
+ // Second case, don't use 'subtract_fee_from_outputs'.
+ recipients[0].fSubtractFeeFromAmount = false;
+ res_tx = CreateTransaction(*wallet, recipients, /*change_pos*/-1, coin_control);
+ BOOST_CHECK(!res_tx.has_value());
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ac7bf46a14..36fe32e54d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -4102,8 +4102,8 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
// Make list of wallets to cleanup
std::vector<std::shared_ptr<CWallet>> created_wallets;
- created_wallets.push_back(std::move(res.watchonly_wallet));
- created_wallets.push_back(std::move(res.solvables_wallet));
+ if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
+ if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
// Get the directories to remove after unloading
for (std::shared_ptr<CWallet>& w : created_wallets) {