diff options
60 files changed, 1693 insertions, 1265 deletions
diff --git a/Makefile.am b/Makefile.am index 011faa62c7..8b61763ae4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,6 +23,7 @@ endif BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT) BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT) +BITCOIN_TEST_BIN=$(top_builddir)/src/test/$(BITCOIN_TEST_NAME)$(EXEEXT) BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT) BITCOIN_TX_BIN=$(top_builddir)/src/$(BITCOIN_TX_NAME)$(EXEEXT) BITCOIN_UTIL_BIN=$(top_builddir)/src/$(BITCOIN_UTIL_NAME)$(EXEEXT) @@ -78,6 +79,7 @@ $(BITCOIN_WIN_INSTALLER): all-recursive $(MKDIR_P) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_QT_BIN) $(top_builddir)/release + STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_TEST_BIN) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_CLI_BIN) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_TX_BIN) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_WALLET_BIN) $(top_builddir)/release diff --git a/SECURITY.md b/SECURITY.md index 25b6175c95..c6a496edf1 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,7 +13,6 @@ The following keys may be used to communicate sensitive information to developer | Name | Fingerprint | |------|-------------| -| Wladimir van der Laan | 71A3 B167 3540 5025 D447 E8F2 7481 0B01 2346 C9A6 | | Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 | | Michael Ford | E777 299F C265 DD04 7930 70EB 944D 35F9 AC3D B76A | diff --git a/configure.ac b/configure.ac index 766c33bba3..1752fda344 100644 --- a/configure.ac +++ b/configure.ac @@ -31,6 +31,7 @@ fi BITCOIN_DAEMON_NAME=bitcoind BITCOIN_GUI_NAME=bitcoin-qt +BITCOIN_TEST_NAME=test_bitcoin BITCOIN_CLI_NAME=bitcoin-cli BITCOIN_TX_NAME=bitcoin-tx BITCOIN_UTIL_NAME=bitcoin-util @@ -1917,6 +1918,7 @@ AC_SUBST(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION") AC_SUBST(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL") AC_SUBST(BITCOIN_DAEMON_NAME) AC_SUBST(BITCOIN_GUI_NAME) +AC_SUBST(BITCOIN_TEST_NAME) AC_SUBST(BITCOIN_CLI_NAME) AC_SUBST(BITCOIN_TX_NAME) AC_SUBST(BITCOIN_UTIL_NAME) diff --git a/contrib/guix/INSTALL.md b/contrib/guix/INSTALL.md index 68aae18731..a9a41ddff6 100644 --- a/contrib/guix/INSTALL.md +++ b/contrib/guix/INSTALL.md @@ -72,11 +72,11 @@ writing (July 2021). Guix is expected to be more widely packaged over time. For an up-to-date view on Guix's package status/version across distros, please see: https://repology.org/project/guix/versions -### Debian 11 (Bullseye)/Ubuntu 21.04 (Hirsute Hippo) +### Debian / Ubuntu Guix v1.2.0 is available as a distribution package starting in [Debian 11](https://packages.debian.org/bullseye/guix) and [Ubuntu -21.04](https://packages.ubuntu.com/hirsute/guix). +21.04](https://packages.ubuntu.com/search?keywords=guix). Note that if you intend on using Guix without using any substitutes (more details [here][security-model]), v1.2.0 has a known problem when building GnuTLS diff --git a/contrib/guix/README.md b/contrib/guix/README.md index af5607c710..ed6ac8d589 100644 --- a/contrib/guix/README.md +++ b/contrib/guix/README.md @@ -382,7 +382,7 @@ https://ci.guix.gnu.org is automatically used unless the `--no-substitutes` flag is supplied. This default list of substitute servers is overridable both on a `guix-daemon` level and when you invoke `guix` commands. See examples below for the various ways of adding dongcarl's substitute server after having [authorized -his signing key](#authorize-the-signing-keys). +his signing key](#step-1-authorize-the-signing-keys). Change the **default list** of substitute servers by starting `guix-daemon` with the `--substitute-urls` option (you will likely need to edit your init script): diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index 28cad05013..2795a90036 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -369,6 +369,8 @@ mkdir -p "$DISTSRC" # has not been run before buildling, this file will be a stub cp "${DISTSRC}/share/examples/bitcoin.conf" "${DISTNAME}/" + cp -r "${DISTSRC}/share/rpcauth" "${DISTNAME}/share/" + # Finally, deterministically produce {non-,}debug binary tarballs ready # for release case "$HOST" in diff --git a/doc/release-notes-25504.md b/doc/release-notes-25504.md new file mode 100644 index 0000000000..bf80f18031 --- /dev/null +++ b/doc/release-notes-25504.md @@ -0,0 +1,6 @@ +Updated RPCs +------------ + +- The `listsinceblock`, `listtransactions` and `gettransaction` output now contain a new + `parent_descs` field for every "receive" entry. +- A new optional `include_change` parameter was added to the `listsinceblock` command. diff --git a/share/setup.nsi.in b/share/setup.nsi.in index b31ba7a5b4..2ce798bd2d 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -75,13 +75,15 @@ Section -Main SEC0000 File @abs_top_builddir@/release/@BITCOIN_GUI_NAME@@EXEEXT@ File /oname=COPYING.txt @abs_top_srcdir@/COPYING File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt + File @abs_top_srcdir@/share/examples/bitcoin.conf + SetOutPath $INSTDIR\share\rpcauth + File @abs_top_srcdir@/share/rpcauth/*.* SetOutPath $INSTDIR\daemon File @abs_top_builddir@/release/@BITCOIN_DAEMON_NAME@@EXEEXT@ File @abs_top_builddir@/release/@BITCOIN_CLI_NAME@@EXEEXT@ File @abs_top_builddir@/release/@BITCOIN_TX_NAME@@EXEEXT@ File @abs_top_builddir@/release/@BITCOIN_WALLET_TOOL_NAME@@EXEEXT@ - SetOutPath $INSTDIR\doc - File /r /x Makefile* @abs_top_srcdir@/doc\*.* + File @abs_top_builddir@/release/@BITCOIN_TEST_NAME@@EXEEXT@ SetOutPath $INSTDIR WriteRegStr HKCU "${REGKEY}\Components" Main 1 SectionEnd @@ -128,8 +130,9 @@ Section /o -un.Main UNSEC0000 Delete /REBOOTOK $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ Delete /REBOOTOK $INSTDIR\COPYING.txt Delete /REBOOTOK $INSTDIR\readme.txt + Delete /REBOOTOK $INSTDIR\bitcoin.conf + RMDir /r /REBOOTOK $INSTDIR\share RMDir /r /REBOOTOK $INSTDIR\daemon - RMDir /r /REBOOTOK $INSTDIR\doc DeleteRegValue HKCU "${REGKEY}\Components" Main SectionEnd diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index a80ec3703c..6ada28115e 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -59,7 +59,7 @@ static void CoinSelection(benchmark::Bench& bench) wallet::CoinsResult available_coins; for (const auto& wtx : wtxs) { const auto txout = wtx->tx->vout.at(0); - available_coins.bech32.emplace_back(COutPoint(wtx->GetHash(), 0), txout, /*depth=*/6 * 24, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/true, /*solvable=*/true, /*safe=*/true, wtx->GetTxTime(), /*from_me=*/true, /*fees=*/ 0); + available_coins.coins[OutputType::BECH32].emplace_back(COutPoint(wtx->GetHash(), 0), txout, /*depth=*/6 * 24, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/true, /*solvable=*/true, /*safe=*/true, wtx->GetTxTime(), /*from_me=*/true, /*fees=*/ 0); } const CoinEligibilityFilter filter_standard(1, 6, 0); diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index fc3f91d492..87f18371b1 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -115,12 +115,14 @@ int main(int argc, char* argv[]) // Main program logic starts here std::cout << "Hello! I'm going to print out some information about your datadir." << std::endl - << "\t" << "Path: " << gArgs.GetDataDirNet() << std::endl + << "\t" << "Path: " << gArgs.GetDataDirNet() << std::endl; + { + LOCK(chainman.GetMutex()); + std::cout << "\t" << "Reindexing: " << std::boolalpha << node::fReindex.load() << std::noboolalpha << std::endl << "\t" << "Snapshot Active: " << std::boolalpha << chainman.IsSnapshotActive() << std::noboolalpha << std::endl << "\t" << "Active Height: " << chainman.ActiveHeight() << std::endl << "\t" << "Active IBD: " << std::boolalpha << chainman.ActiveChainstate().IsInitialBlockDownload() << std::noboolalpha << std::endl; - { CBlockIndex* tip = chainman.ActiveTip(); if (tip) { std::cout << "\t" << tip->ToString() << std::endl; diff --git a/src/init.cpp b/src/init.cpp index 4606b77e9f..488c754e95 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1547,7 +1547,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly. // No locking, as this happens before any background thread is started. boost::signals2::connection block_notify_genesis_wait_connection; - if (chainman.ActiveChain().Tip() == nullptr) { + if (WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip() == nullptr)) { block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2)); } else { fHaveGenesis = true; @@ -1751,12 +1751,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // At this point, the RPC is "started", but still in warmup, which means it // cannot yet be called. Before we make it callable, we need to make sure // that the RPC's view of the best block is valid and consistent with - // ChainstateManager's ActiveTip. + // ChainstateManager's active tip. // // If we do not do this, RPC's view of the best block will be height=0 and // hash=0x0. This will lead to erroroneous responses for things like // waitforblockheight. - RPCNotifyBlockChange(chainman.ActiveTip()); + RPCNotifyBlockChange(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip())); SetRPCWarmupFinished(); uiInterface.InitMessage(_("Done loading").translated); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 64c2a29245..b39412158f 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -370,6 +370,9 @@ struct Peer { /** Set of txids to reconsider once their parent transactions have been accepted **/ std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans); + /** Whether we've sent this peer a getheaders in response to an inv prior to initial-headers-sync completing */ + bool m_inv_triggered_getheaders_before_sync{false}; + /** Protects m_getdata_requests **/ Mutex m_getdata_requests_mutex; /** Work queue of items requested by this peer **/ @@ -682,6 +685,9 @@ private: /** Number of nodes with fSyncStarted. */ int nSyncStarted GUARDED_BY(cs_main) = 0; + /** Hash of the last block we received via INV */ + uint256 m_last_block_inv_triggering_headers_sync{}; + /** * Sources of received blocks, saved to be able punish them when processing * happens afterwards. @@ -2504,7 +2510,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer, // Consider fetching more headers. if (nCount == MAX_HEADERS_RESULTS) { // Headers message had its maximum size; the peer may have more headers. - if (MaybeSendGetHeaders(pfrom, m_chainman.ActiveChain().GetLocator(pindexLast), peer)) { + if (MaybeSendGetHeaders(pfrom, WITH_LOCK(m_chainman.GetMutex(), return m_chainman.ActiveChain().GetLocator(pindexLast)), peer)) { LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height); } @@ -3240,8 +3246,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, UpdateBlockAvailability(pfrom.GetId(), inv.hash); if (!fAlreadyHave && !fImporting && !fReindex && !IsBlockRequested(inv.hash)) { // Headers-first is the primary method of announcement on - // the network. If a node fell back to sending blocks by inv, - // it's probably for a re-org. The final block hash + // the network. If a node fell back to sending blocks by + // inv, it may be for a re-org, or because we haven't + // completed initial headers sync. The final block hash // provided should be the highest, so send a getheaders and // then fetch the blocks we need to catch up. best_block = &inv.hash; @@ -3266,10 +3273,30 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, } if (best_block != nullptr) { - if (MaybeSendGetHeaders(pfrom, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), *peer)) { - LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", - m_chainman.m_best_header->nHeight, best_block->ToString(), - pfrom.GetId()); + // If we haven't started initial headers-sync with this peer, then + // consider sending a getheaders now. On initial startup, there's a + // reliability vs bandwidth tradeoff, where we are only trying to do + // initial headers sync with one peer at a time, with a long + // timeout (at which point, if the sync hasn't completed, we will + // disconnect the peer and then choose another). In the meantime, + // as new blocks are found, we are willing to add one new peer per + // block to sync with as well, to sync quicker in the case where + // our initial peer is unresponsive (but less bandwidth than we'd + // use if we turned on sync with all peers). + CNodeState& state{*Assert(State(pfrom.GetId()))}; + if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) { + if (MaybeSendGetHeaders(pfrom, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), *peer)) { + LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", + m_chainman.m_best_header->nHeight, best_block->ToString(), + pfrom.GetId()); + } + if (!state.fSyncStarted) { + peer->m_inv_triggered_getheaders_before_sync = true; + // Update the last block hash that triggered a new headers + // sync, so that we don't turn on headers sync with more + // than 1 new peer every new block. + m_last_block_inv_triggering_headers_sync = *best_block; + } } } diff --git a/src/outputtype.cpp b/src/outputtype.cpp index 5be9942d7d..9ab2902256 100644 --- a/src/outputtype.cpp +++ b/src/outputtype.cpp @@ -20,6 +20,7 @@ static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy"; static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit"; static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32"; static const std::string OUTPUT_TYPE_STRING_BECH32M = "bech32m"; +static const std::string OUTPUT_TYPE_STRING_UNKNOWN = "unknown"; std::optional<OutputType> ParseOutputType(const std::string& type) { @@ -31,6 +32,8 @@ std::optional<OutputType> ParseOutputType(const std::string& type) return OutputType::BECH32; } else if (type == OUTPUT_TYPE_STRING_BECH32M) { return OutputType::BECH32M; + } else if (type == OUTPUT_TYPE_STRING_UNKNOWN) { + return OutputType::UNKNOWN; } return std::nullopt; } @@ -42,6 +45,7 @@ const std::string& FormatOutputType(OutputType type) case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT; case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32; case OutputType::BECH32M: return OUTPUT_TYPE_STRING_BECH32M; + case OutputType::UNKNOWN: return OUTPUT_TYPE_STRING_UNKNOWN; } // no default case, so the compiler can warn about missing cases assert(false); } @@ -61,7 +65,8 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type) return witdest; } } - case OutputType::BECH32M: {} // This function should never be used with BECH32M, so let it assert + case OutputType::BECH32M: + case OutputType::UNKNOWN: {} // This function should never be used with BECH32M or UNKNOWN, so let it assert } // no default case, so the compiler can warn about missing cases assert(false); } @@ -99,7 +104,8 @@ CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore, return ScriptHash(witprog); } } - case OutputType::BECH32M: {} // This function should not be used for BECH32M, so let it assert + case OutputType::BECH32M: + case OutputType::UNKNOWN: {} // This function should not be used for BECH32M or UNKNOWN, so let it assert } // no default case, so the compiler can warn about missing cases assert(false); } diff --git a/src/outputtype.h b/src/outputtype.h index 6b4e695760..be5fd62b80 100644 --- a/src/outputtype.h +++ b/src/outputtype.h @@ -19,6 +19,7 @@ enum class OutputType { P2SH_SEGWIT, BECH32, BECH32M, + UNKNOWN, }; static constexpr auto OUTPUT_TYPES = std::array{ @@ -26,6 +27,7 @@ static constexpr auto OUTPUT_TYPES = std::array{ OutputType::P2SH_SEGWIT, OutputType::BECH32, OutputType::BECH32M, + OutputType::UNKNOWN, }; std::optional<OutputType> ParseOutputType(const std::string& str); diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 57fd88483e..0fe69051a4 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1124,7 +1124,7 @@ Signing is only possible with addresses of the type 'legacy'.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+29"/> + <location line="+33"/> <source>Create wallet failed</source> <translation type="unfinished"></translation> </message> @@ -1138,6 +1138,11 @@ Signing is only possible with addresses of the type 'legacy'.</source> <source>Can't list signers</source> <translation type="unfinished"></translation> </message> + <message> + <location line="+3"/> + <source>Too many external signers found</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>CreateWalletDialog</name> @@ -1471,7 +1476,7 @@ Signing is only possible with addresses of the type 'legacy'.</source> <context> <name>LoadWalletsActivity</name> <message> - <location filename="../walletcontroller.cpp" line="+69"/> + <location filename="../walletcontroller.cpp" line="+74"/> <source>Load Wallets</source> <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment> <translation type="unfinished"></translation> @@ -1581,7 +1586,7 @@ Signing is only possible with addresses of the type 'legacy'.</source> <context> <name>OpenWalletActivity</name> <message> - <location filename="../walletcontroller.cpp" line="-42"/> + <location filename="../walletcontroller.cpp" line="-46"/> <source>Open wallet failed</source> <translation type="unfinished"></translation> </message> @@ -3584,7 +3589,7 @@ For more information on using this console, type %6. <context> <name>RestoreWalletActivity</name> <message> - <location filename="../walletcontroller.cpp" line="+45"/> + <location filename="../walletcontroller.cpp" line="+49"/> <source>Restore Wallet</source> <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment> <translation type="unfinished"></translation> @@ -3596,7 +3601,7 @@ For more information on using this console, type %6. <translation type="unfinished"></translation> </message> <message> - <location line="+16"/> + <location line="+19"/> <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> @@ -4962,7 +4967,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 <context> <name>WalletController</name> <message> - <location filename="../walletcontroller.cpp" line="-329"/> + <location filename="../walletcontroller.cpp" line="-344"/> <source>Close wallet</source> <translation type="unfinished"></translation> </message> diff --git a/src/qt/locale/bitcoin_en.xlf b/src/qt/locale/bitcoin_en.xlf index 8e5cb5f21f..c5f0c933f4 100644 --- a/src/qt/locale/bitcoin_en.xlf +++ b/src/qt/locale/bitcoin_en.xlf @@ -979,98 +979,102 @@ Signing is only possible with addresses of the type 'legacy'.</source> </trans-unit> <trans-unit id="_msg222"> <source xml:space="preserve">Create wallet failed</source> - <context-group purpose="location"><context context-type="linenumber">276</context></context-group> + <context-group purpose="location"><context context-type="linenumber">280</context></context-group> </trans-unit> <trans-unit id="_msg223"> <source xml:space="preserve">Create wallet warning</source> - <context-group purpose="location"><context context-type="linenumber">278</context></context-group> + <context-group purpose="location"><context context-type="linenumber">282</context></context-group> </trans-unit> <trans-unit id="_msg224"> <source xml:space="preserve">Can't list signers</source> - <context-group purpose="location"><context context-type="linenumber">294</context></context-group> + <context-group purpose="location"><context context-type="linenumber">298</context></context-group> + </trans-unit> + <trans-unit id="_msg225"> + <source xml:space="preserve">Too many external signers found</source> + <context-group purpose="location"><context context-type="linenumber">301</context></context-group> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="LoadWalletsActivity"> - <trans-unit id="_msg225"> + <trans-unit id="_msg226"> <source xml:space="preserve">Load Wallets</source> - <context-group purpose="location"><context context-type="linenumber">363</context></context-group> + <context-group purpose="location"><context context-type="linenumber">375</context></context-group> <note annotates="source" from="developer">Title of progress window which is displayed when wallets are being loaded.</note> </trans-unit> - <trans-unit id="_msg226"> + <trans-unit id="_msg227"> <source xml:space="preserve">Loading wallets…</source> - <context-group purpose="location"><context context-type="linenumber">366</context></context-group> + <context-group purpose="location"><context context-type="linenumber">378</context></context-group> <note annotates="source" from="developer">Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</note> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="OpenWalletActivity"> - <trans-unit id="_msg227"> + <trans-unit id="_msg228"> <source xml:space="preserve">Open wallet failed</source> - <context-group purpose="location"><context context-type="linenumber">324</context></context-group> + <context-group purpose="location"><context context-type="linenumber">332</context></context-group> </trans-unit> - <trans-unit id="_msg228"> + <trans-unit id="_msg229"> <source xml:space="preserve">Open wallet warning</source> - <context-group purpose="location"><context context-type="linenumber">326</context></context-group> + <context-group purpose="location"><context context-type="linenumber">334</context></context-group> </trans-unit> - <trans-unit id="_msg229"> + <trans-unit id="_msg230"> <source xml:space="preserve">default wallet</source> - <context-group purpose="location"><context context-type="linenumber">336</context></context-group> + <context-group purpose="location"><context context-type="linenumber">344</context></context-group> </trans-unit> - <trans-unit id="_msg230"> + <trans-unit id="_msg231"> <source xml:space="preserve">Open Wallet</source> - <context-group purpose="location"><context context-type="linenumber">340</context></context-group> + <context-group purpose="location"><context context-type="linenumber">348</context></context-group> <note annotates="source" from="developer">Title of window indicating the progress of opening of a wallet.</note> </trans-unit> - <trans-unit id="_msg231"> + <trans-unit id="_msg232"> <source xml:space="preserve">Opening Wallet <b>%1</b>…</source> - <context-group purpose="location"><context context-type="linenumber">343</context></context-group> + <context-group purpose="location"><context context-type="linenumber">351</context></context-group> <note annotates="source" from="developer">Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</note> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="RestoreWalletActivity"> - <trans-unit id="_msg232"> + <trans-unit id="_msg233"> <source xml:space="preserve">Restore Wallet</source> - <context-group purpose="location"><context context-type="linenumber">388</context></context-group> + <context-group purpose="location"><context context-type="linenumber">400</context></context-group> <note annotates="source" from="developer">Title of progress window which is displayed when wallets are being restored.</note> </trans-unit> - <trans-unit id="_msg233"> + <trans-unit id="_msg234"> <source xml:space="preserve">Restoring Wallet <b>%1</b>…</source> - <context-group purpose="location"><context context-type="linenumber">391</context></context-group> + <context-group purpose="location"><context context-type="linenumber">403</context></context-group> <note annotates="source" from="developer">Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</note> </trans-unit> - <trans-unit id="_msg234"> + <trans-unit id="_msg235"> <source xml:space="preserve">Restore wallet failed</source> - <context-group purpose="location"><context context-type="linenumber">407</context></context-group> + <context-group purpose="location"><context context-type="linenumber">422</context></context-group> <note annotates="source" from="developer">Title of message box which is displayed when the wallet could not be restored.</note> </trans-unit> - <trans-unit id="_msg235"> + <trans-unit id="_msg236"> <source xml:space="preserve">Restore wallet warning</source> - <context-group purpose="location"><context context-type="linenumber">410</context></context-group> + <context-group purpose="location"><context context-type="linenumber">425</context></context-group> <note annotates="source" from="developer">Title of message box which is displayed when the wallet is restored with some warning.</note> </trans-unit> - <trans-unit id="_msg236"> + <trans-unit id="_msg237"> <source xml:space="preserve">Restore wallet message</source> - <context-group purpose="location"><context context-type="linenumber">413</context></context-group> + <context-group purpose="location"><context context-type="linenumber">428</context></context-group> <note annotates="source" from="developer">Title of message box which is displayed when the wallet is successfully restored.</note> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="WalletController"> - <trans-unit id="_msg237"> + <trans-unit id="_msg238"> <source xml:space="preserve">Close wallet</source> <context-group purpose="location"><context context-type="linenumber">84</context></context-group> </trans-unit> - <trans-unit id="_msg238"> + <trans-unit id="_msg239"> <source xml:space="preserve">Are you sure you wish to close the wallet <i>%1</i>?</source> <context-group purpose="location"><context context-type="linenumber">85</context></context-group> </trans-unit> - <trans-unit id="_msg239"> + <trans-unit id="_msg240"> <source xml:space="preserve">Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source> <context-group purpose="location"><context context-type="linenumber">86</context></context-group> </trans-unit> - <trans-unit id="_msg240"> + <trans-unit id="_msg241"> <source xml:space="preserve">Close all wallets</source> <context-group purpose="location"><context context-type="linenumber">99</context></context-group> </trans-unit> - <trans-unit id="_msg241"> + <trans-unit id="_msg242"> <source xml:space="preserve">Are you sure you wish to close all wallets?</source> <context-group purpose="location"><context context-type="linenumber">100</context></context-group> </trans-unit> @@ -1078,59 +1082,59 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/createwalletdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="CreateWalletDialog"> - <trans-unit id="_msg242"> + <trans-unit id="_msg243"> <source xml:space="preserve">Create Wallet</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg243"> + <trans-unit id="_msg244"> <source xml:space="preserve">Wallet Name</source> <context-group purpose="location"><context context-type="linenumber">25</context></context-group> </trans-unit> - <trans-unit id="_msg244"> + <trans-unit id="_msg245"> <source xml:space="preserve">Wallet</source> <context-group purpose="location"><context context-type="linenumber">38</context></context-group> </trans-unit> - <trans-unit id="_msg245"> + <trans-unit id="_msg246"> <source xml:space="preserve">Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source> <context-group purpose="location"><context context-type="linenumber">47</context></context-group> </trans-unit> - <trans-unit id="_msg246"> + <trans-unit id="_msg247"> <source xml:space="preserve">Encrypt Wallet</source> <context-group purpose="location"><context context-type="linenumber">50</context></context-group> </trans-unit> - <trans-unit id="_msg247"> + <trans-unit id="_msg248"> <source xml:space="preserve">Advanced Options</source> <context-group purpose="location"><context context-type="linenumber">76</context></context-group> </trans-unit> - <trans-unit id="_msg248"> + <trans-unit id="_msg249"> <source xml:space="preserve">Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets.</source> <context-group purpose="location"><context context-type="linenumber">85</context></context-group> </trans-unit> - <trans-unit id="_msg249"> + <trans-unit id="_msg250"> <source xml:space="preserve">Disable Private Keys</source> <context-group purpose="location"><context context-type="linenumber">88</context></context-group> </trans-unit> - <trans-unit id="_msg250"> + <trans-unit id="_msg251"> <source xml:space="preserve">Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</source> <context-group purpose="location"><context context-type="linenumber">95</context></context-group> </trans-unit> - <trans-unit id="_msg251"> + <trans-unit id="_msg252"> <source xml:space="preserve">Make Blank Wallet</source> <context-group purpose="location"><context context-type="linenumber">98</context></context-group> </trans-unit> - <trans-unit id="_msg252"> + <trans-unit id="_msg253"> <source xml:space="preserve">Use descriptors for scriptPubKey management</source> <context-group purpose="location"><context context-type="linenumber">105</context></context-group> </trans-unit> - <trans-unit id="_msg253"> + <trans-unit id="_msg254"> <source xml:space="preserve">Descriptor Wallet</source> <context-group purpose="location"><context context-type="linenumber">108</context></context-group> </trans-unit> - <trans-unit id="_msg254"> + <trans-unit id="_msg255"> <source xml:space="preserve">Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source> <context-group purpose="location"><context context-type="linenumber">118</context></context-group> </trans-unit> - <trans-unit id="_msg255"> + <trans-unit id="_msg256"> <source xml:space="preserve">External signer</source> <context-group purpose="location"><context context-type="linenumber">121</context></context-group> </trans-unit> @@ -1138,15 +1142,15 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../createwalletdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="CreateWalletDialog"> - <trans-unit id="_msg256"> + <trans-unit id="_msg257"> <source xml:space="preserve">Create</source> <context-group purpose="location"><context context-type="linenumber">22</context></context-group> </trans-unit> - <trans-unit id="_msg257"> + <trans-unit id="_msg258"> <source xml:space="preserve">Compiled without sqlite support (required for descriptor wallets)</source> <context-group purpose="location"><context context-type="linenumber">90</context></context-group> </trans-unit> - <trans-unit id="_msg258"> + <trans-unit id="_msg259"> <source xml:space="preserve">Compiled without external signing support (required for external signing)</source> <context-group purpose="location"><context context-type="linenumber">104</context></context-group> <note annotates="source" from="developer">"External signing" means using devices such as hardware wallets.</note> @@ -1155,23 +1159,23 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/editaddressdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="EditAddressDialog"> - <trans-unit id="_msg259"> + <trans-unit id="_msg260"> <source xml:space="preserve">Edit Address</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg260"> + <trans-unit id="_msg261"> <source xml:space="preserve">&Label</source> <context-group purpose="location"><context context-type="linenumber">25</context></context-group> </trans-unit> - <trans-unit id="_msg261"> + <trans-unit id="_msg262"> <source xml:space="preserve">The label associated with this address list entry</source> <context-group purpose="location"><context context-type="linenumber">35</context></context-group> </trans-unit> - <trans-unit id="_msg262"> + <trans-unit id="_msg263"> <source xml:space="preserve">The address associated with this address list entry. This can only be modified for sending addresses.</source> <context-group purpose="location"><context context-type="linenumber">52</context></context-group> </trans-unit> - <trans-unit id="_msg263"> + <trans-unit id="_msg264"> <source xml:space="preserve">&Address</source> <context-group purpose="location"><context context-type="linenumber">42</context></context-group> </trans-unit> @@ -1179,35 +1183,35 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../editaddressdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="EditAddressDialog"> - <trans-unit id="_msg264"> + <trans-unit id="_msg265"> <source xml:space="preserve">New sending address</source> <context-group purpose="location"><context context-type="linenumber">29</context></context-group> </trans-unit> - <trans-unit id="_msg265"> + <trans-unit id="_msg266"> <source xml:space="preserve">Edit receiving address</source> <context-group purpose="location"><context context-type="linenumber">32</context></context-group> </trans-unit> - <trans-unit id="_msg266"> + <trans-unit id="_msg267"> <source xml:space="preserve">Edit sending address</source> <context-group purpose="location"><context context-type="linenumber">36</context></context-group> </trans-unit> - <trans-unit id="_msg267"> + <trans-unit id="_msg268"> <source xml:space="preserve">The entered address "%1" is not a valid Bitcoin address.</source> <context-group purpose="location"><context context-type="linenumber">113</context></context-group> </trans-unit> - <trans-unit id="_msg268"> + <trans-unit id="_msg269"> <source xml:space="preserve">Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source> <context-group purpose="location"><context context-type="linenumber">146</context></context-group> </trans-unit> - <trans-unit id="_msg269"> + <trans-unit id="_msg270"> <source xml:space="preserve">The entered address "%1" is already in the address book with label "%2".</source> <context-group purpose="location"><context context-type="linenumber">151</context></context-group> </trans-unit> - <trans-unit id="_msg270"> + <trans-unit id="_msg271"> <source xml:space="preserve">Could not unlock wallet.</source> <context-group purpose="location"><context context-type="linenumber">123</context></context-group> </trans-unit> - <trans-unit id="_msg271"> + <trans-unit id="_msg272"> <source xml:space="preserve">New key generation failed.</source> <context-group purpose="location"><context context-type="linenumber">128</context></context-group> </trans-unit> @@ -1215,90 +1219,90 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../intro.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="FreespaceChecker"> - <trans-unit id="_msg272"> + <trans-unit id="_msg273"> <source xml:space="preserve">A new data directory will be created.</source> <context-group purpose="location"><context context-type="linenumber">73</context></context-group> </trans-unit> - <trans-unit id="_msg273"> + <trans-unit id="_msg274"> <source xml:space="preserve">name</source> <context-group purpose="location"><context context-type="linenumber">95</context></context-group> </trans-unit> - <trans-unit id="_msg274"> + <trans-unit id="_msg275"> <source xml:space="preserve">Directory already exists. Add %1 if you intend to create a new directory here.</source> <context-group purpose="location"><context context-type="linenumber">97</context></context-group> </trans-unit> - <trans-unit id="_msg275"> + <trans-unit id="_msg276"> <source xml:space="preserve">Path already exists, and is not a directory.</source> <context-group purpose="location"><context context-type="linenumber">100</context></context-group> </trans-unit> - <trans-unit id="_msg276"> + <trans-unit id="_msg277"> <source xml:space="preserve">Cannot create data directory here.</source> <context-group purpose="location"><context context-type="linenumber">107</context></context-group> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="Intro"> - <trans-unit id="_msg277"> + <trans-unit id="_msg278"> <source xml:space="preserve">Bitcoin</source> <context-group purpose="location"><context context-type="linenumber">139</context></context-group> </trans-unit> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">301</context></context-group> - <trans-unit id="_msg278[0]"> + <trans-unit id="_msg279[0]"> <source xml:space="preserve">%n GB of space available</source> </trans-unit> - <trans-unit id="_msg278[1]"> + <trans-unit id="_msg279[1]"> <source xml:space="preserve">%n GB of space available</source> </trans-unit> </group> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">303</context></context-group> - <trans-unit id="_msg279[0]"> + <trans-unit id="_msg280[0]"> <source xml:space="preserve">(of %n GB needed)</source> </trans-unit> - <trans-unit id="_msg279[1]"> + <trans-unit id="_msg280[1]"> <source xml:space="preserve">(of %n GB needed)</source> </trans-unit> </group> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">306</context></context-group> - <trans-unit id="_msg280[0]"> + <trans-unit id="_msg281[0]"> <source xml:space="preserve">(%n GB needed for full chain)</source> </trans-unit> - <trans-unit id="_msg280[1]"> + <trans-unit id="_msg281[1]"> <source xml:space="preserve">(%n GB needed for full chain)</source> </trans-unit> </group> - <trans-unit id="_msg281"> + <trans-unit id="_msg282"> <source xml:space="preserve">At least %1 GB of data will be stored in this directory, and it will grow over time.</source> <context-group purpose="location"><context context-type="linenumber">378</context></context-group> </trans-unit> - <trans-unit id="_msg282"> + <trans-unit id="_msg283"> <source xml:space="preserve">Approximately %1 GB of data will be stored in this directory.</source> <context-group purpose="location"><context context-type="linenumber">381</context></context-group> </trans-unit> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">390</context></context-group> <note annotates="source" from="developer">Explanatory text on the capability of the current prune target.</note> - <trans-unit id="_msg283[0]"> + <trans-unit id="_msg284[0]"> <source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source> </trans-unit> - <trans-unit id="_msg283[1]"> + <trans-unit id="_msg284[1]"> <source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source> </trans-unit> </group> - <trans-unit id="_msg284"> + <trans-unit id="_msg285"> <source xml:space="preserve">%1 will download and store a copy of the Bitcoin block chain.</source> <context-group purpose="location"><context context-type="linenumber">392</context></context-group> </trans-unit> - <trans-unit id="_msg285"> + <trans-unit id="_msg286"> <source xml:space="preserve">The wallet will also be stored in this directory.</source> <context-group purpose="location"><context context-type="linenumber">394</context></context-group> </trans-unit> - <trans-unit id="_msg286"> + <trans-unit id="_msg287"> <source xml:space="preserve">Error: Specified data directory "%1" cannot be created.</source> <context-group purpose="location"><context context-type="linenumber">250</context></context-group> </trans-unit> - <trans-unit id="_msg287"> + <trans-unit id="_msg288"> <source xml:space="preserve">Error</source> <context-group purpose="location"><context context-type="linenumber">280</context></context-group> </trans-unit> @@ -1306,25 +1310,25 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../utilitydialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="HelpMessageDialog"> - <trans-unit id="_msg288"> + <trans-unit id="_msg289"> <source xml:space="preserve">version</source> <context-group purpose="location"><context context-type="linenumber">38</context></context-group> </trans-unit> - <trans-unit id="_msg289"> + <trans-unit id="_msg290"> <source xml:space="preserve">About %1</source> <context-group purpose="location"><context context-type="linenumber">42</context></context-group> </trans-unit> - <trans-unit id="_msg290"> + <trans-unit id="_msg291"> <source xml:space="preserve">Command-line options</source> <context-group purpose="location"><context context-type="linenumber">60</context></context-group> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="ShutdownWindow"> - <trans-unit id="_msg291"> + <trans-unit id="_msg292"> <source xml:space="preserve">%1 is shutting down…</source> <context-group purpose="location"><context context-type="linenumber">145</context></context-group> </trans-unit> - <trans-unit id="_msg292"> + <trans-unit id="_msg293"> <source xml:space="preserve">Do not shut down the computer until this window disappears.</source> <context-group purpose="location"><context context-type="linenumber">146</context></context-group> </trans-unit> @@ -1332,47 +1336,47 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/intro.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="Intro"> - <trans-unit id="_msg293"> + <trans-unit id="_msg294"> <source xml:space="preserve">Welcome</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg294"> + <trans-unit id="_msg295"> <source xml:space="preserve">Welcome to %1.</source> <context-group purpose="location"><context context-type="linenumber">23</context></context-group> </trans-unit> - <trans-unit id="_msg295"> + <trans-unit id="_msg296"> <source xml:space="preserve">As this is the first time the program is launched, you can choose where %1 will store its data.</source> <context-group purpose="location"><context context-type="linenumber">49</context></context-group> </trans-unit> - <trans-unit id="_msg296"> + <trans-unit id="_msg297"> <source xml:space="preserve">When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source> <context-group purpose="location"><context context-type="linenumber">206</context></context-group> </trans-unit> - <trans-unit id="_msg297"> + <trans-unit id="_msg298"> <source xml:space="preserve">Limit block chain storage to</source> <context-group purpose="location"><context context-type="linenumber">238</context></context-group> </trans-unit> - <trans-unit id="_msg298"> + <trans-unit id="_msg299"> <source xml:space="preserve">Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source> <context-group purpose="location"><context context-type="linenumber">241</context></context-group> </trans-unit> - <trans-unit id="_msg299"> + <trans-unit id="_msg300"> <source xml:space="preserve"> GB</source> <context-group purpose="location"><context context-type="linenumber">248</context></context-group> </trans-unit> - <trans-unit id="_msg300"> + <trans-unit id="_msg301"> <source xml:space="preserve">This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source> <context-group purpose="location"><context context-type="linenumber">216</context></context-group> </trans-unit> - <trans-unit id="_msg301"> + <trans-unit id="_msg302"> <source xml:space="preserve">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> <context-group purpose="location"><context context-type="linenumber">226</context></context-group> </trans-unit> - <trans-unit id="_msg302"> + <trans-unit id="_msg303"> <source xml:space="preserve">Use the default data directory</source> <context-group purpose="location"><context context-type="linenumber">66</context></context-group> </trans-unit> - <trans-unit id="_msg303"> + <trans-unit id="_msg304"> <source xml:space="preserve">Use a custom data directory:</source> <context-group purpose="location"><context context-type="linenumber">73</context></context-group> </trans-unit> @@ -1380,54 +1384,54 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/modaloverlay.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="ModalOverlay"> - <trans-unit id="_msg304"> + <trans-unit id="_msg305"> <source xml:space="preserve">Form</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg305"> + <trans-unit id="_msg306"> <source xml:space="preserve">Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source> <context-group purpose="location"><context context-type="linenumber">133</context></context-group> </trans-unit> - <trans-unit id="_msg306"> + <trans-unit id="_msg307"> <source xml:space="preserve">Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source> <context-group purpose="location"><context context-type="linenumber">152</context></context-group> </trans-unit> - <trans-unit id="_msg307"> + <trans-unit id="_msg308"> <source xml:space="preserve">Number of blocks left</source> <context-group purpose="location"><context context-type="linenumber">215</context></context-group> </trans-unit> - <trans-unit id="_msg308"> + <trans-unit id="_msg309"> <source xml:space="preserve">Unknown…</source> <context-group purpose="location"><context context-type="linenumber">222</context></context-group> <context-group purpose="location"><context context-type="linenumber">248</context></context-group> <context-group purpose="location"><context context-type="sourcefile">../modaloverlay.cpp</context><context context-type="linenumber">152</context></context-group> </trans-unit> - <trans-unit id="_msg309"> + <trans-unit id="_msg310"> <source xml:space="preserve">calculating…</source> <context-group purpose="location"><context context-type="linenumber">292</context></context-group> <context-group purpose="location"><context context-type="linenumber">312</context></context-group> </trans-unit> - <trans-unit id="_msg310"> + <trans-unit id="_msg311"> <source xml:space="preserve">Last block time</source> <context-group purpose="location"><context context-type="linenumber">235</context></context-group> </trans-unit> - <trans-unit id="_msg311"> + <trans-unit id="_msg312"> <source xml:space="preserve">Progress</source> <context-group purpose="location"><context context-type="linenumber">261</context></context-group> </trans-unit> - <trans-unit id="_msg312"> + <trans-unit id="_msg313"> <source xml:space="preserve">Progress increase per hour</source> <context-group purpose="location"><context context-type="linenumber">285</context></context-group> </trans-unit> - <trans-unit id="_msg313"> + <trans-unit id="_msg314"> <source xml:space="preserve">Estimated time left until synced</source> <context-group purpose="location"><context context-type="linenumber">305</context></context-group> </trans-unit> - <trans-unit id="_msg314"> + <trans-unit id="_msg315"> <source xml:space="preserve">Hide</source> <context-group purpose="location"><context context-type="linenumber">342</context></context-group> </trans-unit> - <trans-unit id="_msg315"> + <trans-unit id="_msg316"> <source xml:space="preserve">Esc</source> <context-group purpose="location"><context context-type="linenumber">345</context></context-group> </trans-unit> @@ -1435,17 +1439,17 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../modaloverlay.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="ModalOverlay"> - <trans-unit id="_msg316"> + <trans-unit id="_msg317"> <source xml:space="preserve">%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source> <context-group purpose="location"><context context-type="linenumber">34</context></context-group> </trans-unit> - <trans-unit id="_msg317"> + <trans-unit id="_msg318"> <source xml:space="preserve">Unknown. Syncing Headers (%1, %2%)…</source> <context-group purpose="location"><context context-type="linenumber">158</context></context-group> </trans-unit> </group> <group restype="x-trolltech-linguist-context" resname="QObject"> - <trans-unit id="_msg318"> + <trans-unit id="_msg319"> <source xml:space="preserve">unknown</source> <context-group purpose="location"><context context-type="linenumber">123</context></context-group> </trans-unit> @@ -1453,15 +1457,15 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/openuridialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="OpenURIDialog"> - <trans-unit id="_msg319"> + <trans-unit id="_msg320"> <source xml:space="preserve">Open bitcoin URI</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg320"> + <trans-unit id="_msg321"> <source xml:space="preserve">URI:</source> <context-group purpose="location"><context context-type="linenumber">22</context></context-group> </trans-unit> - <trans-unit id="_msg321"> + <trans-unit id="_msg322"> <source xml:space="preserve">Paste address from clipboard</source> <context-group purpose="location"><context context-type="linenumber">36</context></context-group> <note annotates="source" from="developer">Tooltip text for button that allows you to paste an address that is in your clipboard.</note> @@ -1470,310 +1474,310 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/optionsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="OptionsDialog"> - <trans-unit id="_msg322"> + <trans-unit id="_msg323"> <source xml:space="preserve">Options</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg323"> + <trans-unit id="_msg324"> <source xml:space="preserve">&Main</source> <context-group purpose="location"><context context-type="linenumber">27</context></context-group> </trans-unit> - <trans-unit id="_msg324"> + <trans-unit id="_msg325"> <source xml:space="preserve">Automatically start %1 after logging in to the system.</source> <context-group purpose="location"><context context-type="linenumber">33</context></context-group> </trans-unit> - <trans-unit id="_msg325"> + <trans-unit id="_msg326"> <source xml:space="preserve">&Start %1 on system login</source> <context-group purpose="location"><context context-type="linenumber">36</context></context-group> </trans-unit> - <trans-unit id="_msg326"> + <trans-unit id="_msg327"> <source xml:space="preserve">Enabling pruning significantly reduces the disk space required to store transactions. All blocks are still fully validated. Reverting this setting requires re-downloading the entire blockchain.</source> <context-group purpose="location"><context context-type="linenumber">58</context></context-group> </trans-unit> - <trans-unit id="_msg327"> + <trans-unit id="_msg328"> <source xml:space="preserve">Size of &database cache</source> <context-group purpose="location"><context context-type="linenumber">111</context></context-group> </trans-unit> - <trans-unit id="_msg328"> + <trans-unit id="_msg329"> <source xml:space="preserve">Number of script &verification threads</source> <context-group purpose="location"><context context-type="linenumber">157</context></context-group> </trans-unit> - <trans-unit id="_msg329"> + <trans-unit id="_msg330"> <source xml:space="preserve">IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <context-group purpose="location"><context context-type="linenumber">388</context></context-group> <context-group purpose="location"><context context-type="linenumber">575</context></context-group> </trans-unit> - <trans-unit id="_msg330"> + <trans-unit id="_msg331"> <source xml:space="preserve">Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source> <context-group purpose="location"><context context-type="linenumber">457</context></context-group> <context-group purpose="location"><context context-type="linenumber">480</context></context-group> <context-group purpose="location"><context context-type="linenumber">503</context></context-group> </trans-unit> - <trans-unit id="_msg331"> + <trans-unit id="_msg332"> <source xml:space="preserve">Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source> <context-group purpose="location"><context context-type="linenumber">672</context></context-group> </trans-unit> - <trans-unit id="_msg332"> + <trans-unit id="_msg333"> <source xml:space="preserve">Options set in this dialog are overridden by the command line:</source> <context-group purpose="location"><context context-type="linenumber">899</context></context-group> </trans-unit> - <trans-unit id="_msg333"> + <trans-unit id="_msg334"> <source xml:space="preserve">Open the %1 configuration file from the working directory.</source> <context-group purpose="location"><context context-type="linenumber">944</context></context-group> </trans-unit> - <trans-unit id="_msg334"> + <trans-unit id="_msg335"> <source xml:space="preserve">Open Configuration File</source> <context-group purpose="location"><context context-type="linenumber">947</context></context-group> </trans-unit> - <trans-unit id="_msg335"> + <trans-unit id="_msg336"> <source xml:space="preserve">Reset all client options to default.</source> <context-group purpose="location"><context context-type="linenumber">957</context></context-group> </trans-unit> - <trans-unit id="_msg336"> + <trans-unit id="_msg337"> <source xml:space="preserve">&Reset Options</source> <context-group purpose="location"><context context-type="linenumber">960</context></context-group> </trans-unit> - <trans-unit id="_msg337"> + <trans-unit id="_msg338"> <source xml:space="preserve">&Network</source> <context-group purpose="location"><context context-type="linenumber">315</context></context-group> </trans-unit> - <trans-unit id="_msg338"> + <trans-unit id="_msg339"> <source xml:space="preserve">Prune &block storage to</source> <context-group purpose="location"><context context-type="linenumber">61</context></context-group> </trans-unit> - <trans-unit id="_msg339"> + <trans-unit id="_msg340"> <source xml:space="preserve">GB</source> <context-group purpose="location"><context context-type="linenumber">71</context></context-group> </trans-unit> - <trans-unit id="_msg340"> + <trans-unit id="_msg341"> <source xml:space="preserve">Reverting this setting requires re-downloading the entire blockchain.</source> <context-group purpose="location"><context context-type="linenumber">96</context></context-group> </trans-unit> - <trans-unit id="_msg341"> + <trans-unit id="_msg342"> <source xml:space="preserve">Maximum database cache size. A larger cache can contribute to faster sync, after which the benefit is less pronounced for most use cases. Lowering the cache size will reduce memory usage. Unused mempool memory is shared for this cache.</source> <context-group purpose="location"><context context-type="linenumber">108</context></context-group> <note annotates="source" from="developer">Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</note> </trans-unit> - <trans-unit id="_msg342"> + <trans-unit id="_msg343"> <source xml:space="preserve">MiB</source> <context-group purpose="location"><context context-type="linenumber">127</context></context-group> </trans-unit> - <trans-unit id="_msg343"> + <trans-unit id="_msg344"> <source xml:space="preserve">Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source> <context-group purpose="location"><context context-type="linenumber">154</context></context-group> <note annotates="source" from="developer">Tooltip text for Options window setting that sets the number of script verification threads. Explains that negative values mean to leave these many cores free to the system.</note> </trans-unit> - <trans-unit id="_msg344"> + <trans-unit id="_msg345"> <source xml:space="preserve">(0 = auto, <0 = leave that many cores free)</source> <context-group purpose="location"><context context-type="linenumber">170</context></context-group> </trans-unit> - <trans-unit id="_msg345"> + <trans-unit id="_msg346"> <source xml:space="preserve">This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source> <context-group purpose="location"><context context-type="linenumber">192</context></context-group> <note annotates="source" from="developer">Tooltip text for Options window setting that enables the RPC server.</note> </trans-unit> - <trans-unit id="_msg346"> + <trans-unit id="_msg347"> <source xml:space="preserve">Enable R&PC server</source> <context-group purpose="location"><context context-type="linenumber">195</context></context-group> <note annotates="source" from="developer">An Options window setting to enable the RPC server.</note> </trans-unit> - <trans-unit id="_msg347"> + <trans-unit id="_msg348"> <source xml:space="preserve">W&allet</source> <context-group purpose="location"><context context-type="linenumber">216</context></context-group> </trans-unit> - <trans-unit id="_msg348"> + <trans-unit id="_msg349"> <source xml:space="preserve">Whether to set subtract fee from amount as default or not.</source> <context-group purpose="location"><context context-type="linenumber">222</context></context-group> <note annotates="source" from="developer">Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</note> </trans-unit> - <trans-unit id="_msg349"> + <trans-unit id="_msg350"> <source xml:space="preserve">Subtract &fee from amount by default</source> <context-group purpose="location"><context context-type="linenumber">225</context></context-group> <note annotates="source" from="developer">An Options window setting to set subtracting the fee from a sending amount as default.</note> </trans-unit> - <trans-unit id="_msg350"> + <trans-unit id="_msg351"> <source xml:space="preserve">Expert</source> <context-group purpose="location"><context context-type="linenumber">232</context></context-group> </trans-unit> - <trans-unit id="_msg351"> + <trans-unit id="_msg352"> <source xml:space="preserve">Enable coin &control features</source> <context-group purpose="location"><context context-type="linenumber">241</context></context-group> </trans-unit> - <trans-unit id="_msg352"> + <trans-unit id="_msg353"> <source xml:space="preserve">If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source> <context-group purpose="location"><context context-type="linenumber">248</context></context-group> </trans-unit> - <trans-unit id="_msg353"> + <trans-unit id="_msg354"> <source xml:space="preserve">&Spend unconfirmed change</source> <context-group purpose="location"><context context-type="linenumber">251</context></context-group> </trans-unit> - <trans-unit id="_msg354"> + <trans-unit id="_msg355"> <source xml:space="preserve">Enable &PSBT controls</source> <context-group purpose="location"><context context-type="linenumber">258</context></context-group> <note annotates="source" from="developer">An options window setting to enable PSBT controls.</note> </trans-unit> - <trans-unit id="_msg355"> + <trans-unit id="_msg356"> <source xml:space="preserve">Whether to show PSBT controls.</source> <context-group purpose="location"><context context-type="linenumber">261</context></context-group> <note annotates="source" from="developer">Tooltip text for options window setting that enables PSBT controls.</note> </trans-unit> - <trans-unit id="_msg356"> + <trans-unit id="_msg357"> <source xml:space="preserve">External Signer (e.g. hardware wallet)</source> <context-group purpose="location"><context context-type="linenumber">271</context></context-group> </trans-unit> - <trans-unit id="_msg357"> + <trans-unit id="_msg358"> <source xml:space="preserve">&External signer script path</source> <context-group purpose="location"><context context-type="linenumber">279</context></context-group> </trans-unit> - <trans-unit id="_msg358"> + <trans-unit id="_msg359"> <source xml:space="preserve">Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source> <context-group purpose="location"><context context-type="linenumber">289</context></context-group> </trans-unit> - <trans-unit id="_msg359"> + <trans-unit id="_msg360"> <source xml:space="preserve">Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source> <context-group purpose="location"><context context-type="linenumber">321</context></context-group> </trans-unit> - <trans-unit id="_msg360"> + <trans-unit id="_msg361"> <source xml:space="preserve">Map port using &UPnP</source> <context-group purpose="location"><context context-type="linenumber">324</context></context-group> </trans-unit> - <trans-unit id="_msg361"> + <trans-unit id="_msg362"> <source xml:space="preserve">Automatically open the Bitcoin client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random.</source> <context-group purpose="location"><context context-type="linenumber">331</context></context-group> </trans-unit> - <trans-unit id="_msg362"> + <trans-unit id="_msg363"> <source xml:space="preserve">Map port using NA&T-PMP</source> <context-group purpose="location"><context context-type="linenumber">334</context></context-group> </trans-unit> - <trans-unit id="_msg363"> + <trans-unit id="_msg364"> <source xml:space="preserve">Accept connections from outside.</source> <context-group purpose="location"><context context-type="linenumber">341</context></context-group> </trans-unit> - <trans-unit id="_msg364"> + <trans-unit id="_msg365"> <source xml:space="preserve">Allow incomin&g connections</source> <context-group purpose="location"><context context-type="linenumber">344</context></context-group> </trans-unit> - <trans-unit id="_msg365"> + <trans-unit id="_msg366"> <source xml:space="preserve">Connect to the Bitcoin network through a SOCKS5 proxy.</source> <context-group purpose="location"><context context-type="linenumber">351</context></context-group> </trans-unit> - <trans-unit id="_msg366"> + <trans-unit id="_msg367"> <source xml:space="preserve">&Connect through SOCKS5 proxy (default proxy):</source> <context-group purpose="location"><context context-type="linenumber">354</context></context-group> </trans-unit> - <trans-unit id="_msg367"> + <trans-unit id="_msg368"> <source xml:space="preserve">Proxy &IP:</source> <context-group purpose="location"><context context-type="linenumber">363</context></context-group> <context-group purpose="location"><context context-type="linenumber">550</context></context-group> </trans-unit> - <trans-unit id="_msg368"> + <trans-unit id="_msg369"> <source xml:space="preserve">&Port:</source> <context-group purpose="location"><context context-type="linenumber">395</context></context-group> <context-group purpose="location"><context context-type="linenumber">582</context></context-group> </trans-unit> - <trans-unit id="_msg369"> + <trans-unit id="_msg370"> <source xml:space="preserve">Port of the proxy (e.g. 9050)</source> <context-group purpose="location"><context context-type="linenumber">420</context></context-group> <context-group purpose="location"><context context-type="linenumber">607</context></context-group> </trans-unit> - <trans-unit id="_msg370"> + <trans-unit id="_msg371"> <source xml:space="preserve">Used for reaching peers via:</source> <context-group purpose="location"><context context-type="linenumber">444</context></context-group> </trans-unit> - <trans-unit id="_msg371"> + <trans-unit id="_msg372"> <source xml:space="preserve">IPv4</source> <context-group purpose="location"><context context-type="linenumber">467</context></context-group> </trans-unit> - <trans-unit id="_msg372"> + <trans-unit id="_msg373"> <source xml:space="preserve">IPv6</source> <context-group purpose="location"><context context-type="linenumber">490</context></context-group> </trans-unit> - <trans-unit id="_msg373"> + <trans-unit id="_msg374"> <source xml:space="preserve">Tor</source> <context-group purpose="location"><context context-type="linenumber">513</context></context-group> </trans-unit> - <trans-unit id="_msg374"> + <trans-unit id="_msg375"> <source xml:space="preserve">&Window</source> <context-group purpose="location"><context context-type="linenumber">643</context></context-group> </trans-unit> - <trans-unit id="_msg375"> + <trans-unit id="_msg376"> <source xml:space="preserve">Show the icon in the system tray.</source> <context-group purpose="location"><context context-type="linenumber">649</context></context-group> </trans-unit> - <trans-unit id="_msg376"> + <trans-unit id="_msg377"> <source xml:space="preserve">&Show tray icon</source> <context-group purpose="location"><context context-type="linenumber">652</context></context-group> </trans-unit> - <trans-unit id="_msg377"> + <trans-unit id="_msg378"> <source xml:space="preserve">Show only a tray icon after minimizing the window.</source> <context-group purpose="location"><context context-type="linenumber">662</context></context-group> </trans-unit> - <trans-unit id="_msg378"> + <trans-unit id="_msg379"> <source xml:space="preserve">&Minimize to the tray instead of the taskbar</source> <context-group purpose="location"><context context-type="linenumber">665</context></context-group> </trans-unit> - <trans-unit id="_msg379"> + <trans-unit id="_msg380"> <source xml:space="preserve">M&inimize on close</source> <context-group purpose="location"><context context-type="linenumber">675</context></context-group> </trans-unit> - <trans-unit id="_msg380"> + <trans-unit id="_msg381"> <source xml:space="preserve">&Display</source> <context-group purpose="location"><context context-type="linenumber">696</context></context-group> </trans-unit> - <trans-unit id="_msg381"> + <trans-unit id="_msg382"> <source xml:space="preserve">User Interface &language:</source> <context-group purpose="location"><context context-type="linenumber">704</context></context-group> </trans-unit> - <trans-unit id="_msg382"> + <trans-unit id="_msg383"> <source xml:space="preserve">The user interface language can be set here. This setting will take effect after restarting %1.</source> <context-group purpose="location"><context context-type="linenumber">717</context></context-group> </trans-unit> - <trans-unit id="_msg383"> + <trans-unit id="_msg384"> <source xml:space="preserve">&Unit to show amounts in:</source> <context-group purpose="location"><context context-type="linenumber">728</context></context-group> </trans-unit> - <trans-unit id="_msg384"> + <trans-unit id="_msg385"> <source xml:space="preserve">Choose the default subdivision unit to show in the interface and when sending coins.</source> <context-group purpose="location"><context context-type="linenumber">741</context></context-group> </trans-unit> - <trans-unit id="_msg385"> + <trans-unit id="_msg386"> <source xml:space="preserve">Third-party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source> <context-group purpose="location"><context context-type="linenumber">752</context></context-group> <context-group purpose="location"><context context-type="linenumber">765</context></context-group> </trans-unit> - <trans-unit id="_msg386"> + <trans-unit id="_msg387"> <source xml:space="preserve">&Third-party transaction URLs</source> <context-group purpose="location"><context context-type="linenumber">755</context></context-group> </trans-unit> - <trans-unit id="_msg387"> + <trans-unit id="_msg388"> <source xml:space="preserve">Whether to show coin control features or not.</source> <context-group purpose="location"><context context-type="linenumber">238</context></context-group> </trans-unit> - <trans-unit id="_msg388"> + <trans-unit id="_msg389"> <source xml:space="preserve">Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source> <context-group purpose="location"><context context-type="linenumber">538</context></context-group> </trans-unit> - <trans-unit id="_msg389"> + <trans-unit id="_msg390"> <source xml:space="preserve">Use separate SOCKS&5 proxy to reach peers via Tor onion services:</source> <context-group purpose="location"><context context-type="linenumber">541</context></context-group> </trans-unit> - <trans-unit id="_msg390"> + <trans-unit id="_msg391"> <source xml:space="preserve">Monospaced font in the Overview tab:</source> <context-group purpose="location"><context context-type="linenumber">777</context></context-group> </trans-unit> - <trans-unit id="_msg391"> + <trans-unit id="_msg392"> <source xml:space="preserve">embedded "%1"</source> <context-group purpose="location"><context context-type="linenumber">785</context></context-group> </trans-unit> - <trans-unit id="_msg392"> + <trans-unit id="_msg393"> <source xml:space="preserve">closest matching "%1"</source> <context-group purpose="location"><context context-type="linenumber">834</context></context-group> </trans-unit> - <trans-unit id="_msg393"> + <trans-unit id="_msg394"> <source xml:space="preserve">&OK</source> <context-group purpose="location"><context context-type="linenumber">1040</context></context-group> </trans-unit> - <trans-unit id="_msg394"> + <trans-unit id="_msg395"> <source xml:space="preserve">&Cancel</source> <context-group purpose="location"><context context-type="linenumber">1053</context></context-group> </trans-unit> @@ -1781,71 +1785,71 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../optionsdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="OptionsDialog"> - <trans-unit id="_msg395"> + <trans-unit id="_msg396"> <source xml:space="preserve">Compiled without external signing support (required for external signing)</source> <context-group purpose="location"><context context-type="linenumber">96</context></context-group> <note annotates="source" from="developer">"External signing" means using devices such as hardware wallets.</note> </trans-unit> - <trans-unit id="_msg396"> + <trans-unit id="_msg397"> <source xml:space="preserve">default</source> <context-group purpose="location"><context context-type="linenumber">108</context></context-group> </trans-unit> - <trans-unit id="_msg397"> + <trans-unit id="_msg398"> <source xml:space="preserve">none</source> <context-group purpose="location"><context context-type="linenumber">194</context></context-group> </trans-unit> - <trans-unit id="_msg398"> + <trans-unit id="_msg399"> <source xml:space="preserve">Confirm options reset</source> <context-group purpose="location"><context context-type="linenumber">301</context></context-group> <note annotates="source" from="developer">Window title text of pop-up window shown when the user has chosen to reset options.</note> </trans-unit> - <trans-unit id="_msg399"> + <trans-unit id="_msg400"> <source xml:space="preserve">Client restart required to activate changes.</source> <context-group purpose="location"><context context-type="linenumber">292</context></context-group> <context-group purpose="location"><context context-type="linenumber">371</context></context-group> <note annotates="source" from="developer">Text explaining that the settings changed will not come into effect until the client is restarted.</note> </trans-unit> - <trans-unit id="_msg400"> + <trans-unit id="_msg401"> <source xml:space="preserve">Current settings will be backed up at "%1".</source> <context-group purpose="location"><context context-type="linenumber">296</context></context-group> <note annotates="source" from="developer">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.</note> </trans-unit> - <trans-unit id="_msg401"> + <trans-unit id="_msg402"> <source xml:space="preserve">Client will be shut down. Do you want to proceed?</source> <context-group purpose="location"><context context-type="linenumber">299</context></context-group> <note annotates="source" from="developer">Text asking the user to confirm if they would like to proceed with a client shutdown.</note> </trans-unit> - <trans-unit id="_msg402"> + <trans-unit id="_msg403"> <source xml:space="preserve">Configuration options</source> <context-group purpose="location"><context context-type="linenumber">319</context></context-group> <note annotates="source" from="developer">Window title text of pop-up box that allows opening up of configuration file.</note> </trans-unit> - <trans-unit id="_msg403"> + <trans-unit id="_msg404"> <source xml:space="preserve">The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source> <context-group purpose="location"><context context-type="linenumber">322</context></context-group> <note annotates="source" from="developer">Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</note> </trans-unit> - <trans-unit id="_msg404"> + <trans-unit id="_msg405"> <source xml:space="preserve">Continue</source> <context-group purpose="location"><context context-type="linenumber">325</context></context-group> </trans-unit> - <trans-unit id="_msg405"> + <trans-unit id="_msg406"> <source xml:space="preserve">Cancel</source> <context-group purpose="location"><context context-type="linenumber">326</context></context-group> </trans-unit> - <trans-unit id="_msg406"> + <trans-unit id="_msg407"> <source xml:space="preserve">Error</source> <context-group purpose="location"><context context-type="linenumber">335</context></context-group> </trans-unit> - <trans-unit id="_msg407"> + <trans-unit id="_msg408"> <source xml:space="preserve">The configuration file could not be opened.</source> <context-group purpose="location"><context context-type="linenumber">335</context></context-group> </trans-unit> - <trans-unit id="_msg408"> + <trans-unit id="_msg409"> <source xml:space="preserve">This change would require a client restart.</source> <context-group purpose="location"><context context-type="linenumber">375</context></context-group> </trans-unit> - <trans-unit id="_msg409"> + <trans-unit id="_msg410"> <source xml:space="preserve">The supplied proxy address is invalid.</source> <context-group purpose="location"><context context-type="linenumber">403</context></context-group> </trans-unit> @@ -1853,7 +1857,7 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../optionsmodel.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="OptionsModel"> - <trans-unit id="_msg410"> + <trans-unit id="_msg411"> <source xml:space="preserve">Could not read setting "%1", %2.</source> <context-group purpose="location"><context context-type="linenumber">204</context></context-group> </trans-unit> @@ -1861,76 +1865,76 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/overviewpage.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="OverviewPage"> - <trans-unit id="_msg411"> + <trans-unit id="_msg412"> <source xml:space="preserve">Form</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg412"> + <trans-unit id="_msg413"> <source xml:space="preserve">The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source> <context-group purpose="location"><context context-type="linenumber">76</context></context-group> <context-group purpose="location"><context context-type="linenumber">411</context></context-group> </trans-unit> - <trans-unit id="_msg413"> + <trans-unit id="_msg414"> <source xml:space="preserve">Watch-only:</source> <context-group purpose="location"><context context-type="linenumber">284</context></context-group> </trans-unit> - <trans-unit id="_msg414"> + <trans-unit id="_msg415"> <source xml:space="preserve">Available:</source> <context-group purpose="location"><context context-type="linenumber">294</context></context-group> </trans-unit> - <trans-unit id="_msg415"> + <trans-unit id="_msg416"> <source xml:space="preserve">Your current spendable balance</source> <context-group purpose="location"><context context-type="linenumber">304</context></context-group> </trans-unit> - <trans-unit id="_msg416"> + <trans-unit id="_msg417"> <source xml:space="preserve">Pending:</source> <context-group purpose="location"><context context-type="linenumber">339</context></context-group> </trans-unit> - <trans-unit id="_msg417"> + <trans-unit id="_msg418"> <source xml:space="preserve">Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source> <context-group purpose="location"><context context-type="linenumber">139</context></context-group> </trans-unit> - <trans-unit id="_msg418"> + <trans-unit id="_msg419"> <source xml:space="preserve">Immature:</source> <context-group purpose="location"><context context-type="linenumber">239</context></context-group> </trans-unit> - <trans-unit id="_msg419"> + <trans-unit id="_msg420"> <source xml:space="preserve">Mined balance that has not yet matured</source> <context-group purpose="location"><context context-type="linenumber">210</context></context-group> </trans-unit> - <trans-unit id="_msg420"> + <trans-unit id="_msg421"> <source xml:space="preserve">Balances</source> <context-group purpose="location"><context context-type="linenumber">60</context></context-group> </trans-unit> - <trans-unit id="_msg421"> + <trans-unit id="_msg422"> <source xml:space="preserve">Total:</source> <context-group purpose="location"><context context-type="linenumber">200</context></context-group> </trans-unit> - <trans-unit id="_msg422"> + <trans-unit id="_msg423"> <source xml:space="preserve">Your current total balance</source> <context-group purpose="location"><context context-type="linenumber">249</context></context-group> </trans-unit> - <trans-unit id="_msg423"> + <trans-unit id="_msg424"> <source xml:space="preserve">Your current balance in watch-only addresses</source> <context-group purpose="location"><context context-type="linenumber">323</context></context-group> </trans-unit> - <trans-unit id="_msg424"> + <trans-unit id="_msg425"> <source xml:space="preserve">Spendable:</source> <context-group purpose="location"><context context-type="linenumber">346</context></context-group> </trans-unit> - <trans-unit id="_msg425"> + <trans-unit id="_msg426"> <source xml:space="preserve">Recent transactions</source> <context-group purpose="location"><context context-type="linenumber">395</context></context-group> </trans-unit> - <trans-unit id="_msg426"> + <trans-unit id="_msg427"> <source xml:space="preserve">Unconfirmed transactions to watch-only addresses</source> <context-group purpose="location"><context context-type="linenumber">120</context></context-group> </trans-unit> - <trans-unit id="_msg427"> + <trans-unit id="_msg428"> <source xml:space="preserve">Mined balance in watch-only addresses that has not yet matured</source> <context-group purpose="location"><context context-type="linenumber">158</context></context-group> </trans-unit> - <trans-unit id="_msg428"> + <trans-unit id="_msg429"> <source xml:space="preserve">Current total balance in watch-only addresses</source> <context-group purpose="location"><context context-type="linenumber">268</context></context-group> </trans-unit> @@ -1938,7 +1942,7 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../overviewpage.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="OverviewPage"> - <trans-unit id="_msg429"> + <trans-unit id="_msg430"> <source xml:space="preserve">Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.</source> <context-group purpose="location"><context context-type="linenumber">186</context></context-group> </trans-unit> @@ -1946,27 +1950,27 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../forms/psbtoperationsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="PSBTOperationsDialog"> - <trans-unit id="_msg430"> + <trans-unit id="_msg431"> <source xml:space="preserve">Dialog</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg431"> + <trans-unit id="_msg432"> <source xml:space="preserve">Sign Tx</source> <context-group purpose="location"><context context-type="linenumber">86</context></context-group> </trans-unit> - <trans-unit id="_msg432"> + <trans-unit id="_msg433"> <source xml:space="preserve">Broadcast Tx</source> <context-group purpose="location"><context context-type="linenumber">102</context></context-group> </trans-unit> - <trans-unit id="_msg433"> + <trans-unit id="_msg434"> <source xml:space="preserve">Copy to Clipboard</source> <context-group purpose="location"><context context-type="linenumber">122</context></context-group> </trans-unit> - <trans-unit id="_msg434"> + <trans-unit id="_msg435"> <source xml:space="preserve">Save…</source> <context-group purpose="location"><context context-type="linenumber">129</context></context-group> </trans-unit> - <trans-unit id="_msg435"> + <trans-unit id="_msg436"> <source xml:space="preserve">Close</source> <context-group purpose="location"><context context-type="linenumber">136</context></context-group> </trans-unit> @@ -1974,108 +1978,108 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../psbtoperationsdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="PSBTOperationsDialog"> - <trans-unit id="_msg436"> + <trans-unit id="_msg437"> <source xml:space="preserve">Failed to load transaction: %1</source> <context-group purpose="location"><context context-type="linenumber">61</context></context-group> </trans-unit> - <trans-unit id="_msg437"> + <trans-unit id="_msg438"> <source xml:space="preserve">Failed to sign transaction: %1</source> <context-group purpose="location"><context context-type="linenumber">86</context></context-group> </trans-unit> - <trans-unit id="_msg438"> + <trans-unit id="_msg439"> <source xml:space="preserve">Cannot sign inputs while wallet is locked.</source> <context-group purpose="location"><context context-type="linenumber">94</context></context-group> </trans-unit> - <trans-unit id="_msg439"> + <trans-unit id="_msg440"> <source xml:space="preserve">Could not sign any more inputs.</source> <context-group purpose="location"><context context-type="linenumber">96</context></context-group> </trans-unit> - <trans-unit id="_msg440"> + <trans-unit id="_msg441"> <source xml:space="preserve">Signed %1 inputs, but more signatures are still required.</source> <context-group purpose="location"><context context-type="linenumber">98</context></context-group> </trans-unit> - <trans-unit id="_msg441"> + <trans-unit id="_msg442"> <source xml:space="preserve">Signed transaction successfully. Transaction is ready to broadcast.</source> <context-group purpose="location"><context context-type="linenumber">101</context></context-group> </trans-unit> - <trans-unit id="_msg442"> + <trans-unit id="_msg443"> <source xml:space="preserve">Unknown error processing transaction.</source> <context-group purpose="location"><context context-type="linenumber">113</context></context-group> </trans-unit> - <trans-unit id="_msg443"> + <trans-unit id="_msg444"> <source xml:space="preserve">Transaction broadcast successfully! Transaction ID: %1</source> <context-group purpose="location"><context context-type="linenumber">123</context></context-group> </trans-unit> - <trans-unit id="_msg444"> + <trans-unit id="_msg445"> <source xml:space="preserve">Transaction broadcast failed: %1</source> <context-group purpose="location"><context context-type="linenumber">126</context></context-group> </trans-unit> - <trans-unit id="_msg445"> + <trans-unit id="_msg446"> <source xml:space="preserve">PSBT copied to clipboard.</source> <context-group purpose="location"><context context-type="linenumber">135</context></context-group> </trans-unit> - <trans-unit id="_msg446"> + <trans-unit id="_msg447"> <source xml:space="preserve">Save Transaction Data</source> <context-group purpose="location"><context context-type="linenumber">158</context></context-group> </trans-unit> - <trans-unit id="_msg447"> + <trans-unit id="_msg448"> <source xml:space="preserve">Partially Signed Transaction (Binary)</source> <context-group purpose="location"><context context-type="linenumber">160</context></context-group> <note annotates="source" from="developer">Expanded name of the binary PSBT file format. See: BIP 174.</note> </trans-unit> - <trans-unit id="_msg448"> + <trans-unit id="_msg449"> <source xml:space="preserve">PSBT saved to disk.</source> <context-group purpose="location"><context context-type="linenumber">167</context></context-group> </trans-unit> - <trans-unit id="_msg449"> + <trans-unit id="_msg450"> <source xml:space="preserve"> * Sends %1 to %2</source> <context-group purpose="location"><context context-type="linenumber">183</context></context-group> </trans-unit> - <trans-unit id="_msg450"> + <trans-unit id="_msg451"> <source xml:space="preserve">Unable to calculate transaction fee or total transaction amount.</source> <context-group purpose="location"><context context-type="linenumber">193</context></context-group> </trans-unit> - <trans-unit id="_msg451"> + <trans-unit id="_msg452"> <source xml:space="preserve">Pays transaction fee: </source> <context-group purpose="location"><context context-type="linenumber">195</context></context-group> </trans-unit> - <trans-unit id="_msg452"> + <trans-unit id="_msg453"> <source xml:space="preserve">Total Amount</source> <context-group purpose="location"><context context-type="linenumber">207</context></context-group> </trans-unit> - <trans-unit id="_msg453"> + <trans-unit id="_msg454"> <source xml:space="preserve">or</source> <context-group purpose="location"><context context-type="linenumber">210</context></context-group> </trans-unit> - <trans-unit id="_msg454"> + <trans-unit id="_msg455"> <source xml:space="preserve">Transaction has %1 unsigned inputs.</source> <context-group purpose="location"><context context-type="linenumber">216</context></context-group> </trans-unit> - <trans-unit id="_msg455"> + <trans-unit id="_msg456"> <source xml:space="preserve">Transaction is missing some information about inputs.</source> <context-group purpose="location"><context context-type="linenumber">262</context></context-group> </trans-unit> - <trans-unit id="_msg456"> + <trans-unit id="_msg457"> <source xml:space="preserve">Transaction still needs signature(s).</source> <context-group purpose="location"><context context-type="linenumber">266</context></context-group> </trans-unit> - <trans-unit id="_msg457"> + <trans-unit id="_msg458"> <source xml:space="preserve">(But no wallet is loaded.)</source> <context-group purpose="location"><context context-type="linenumber">269</context></context-group> </trans-unit> - <trans-unit id="_msg458"> + <trans-unit id="_msg459"> <source xml:space="preserve">(But this wallet cannot sign transactions.)</source> <context-group purpose="location"><context context-type="linenumber">272</context></context-group> </trans-unit> - <trans-unit id="_msg459"> + <trans-unit id="_msg460"> <source xml:space="preserve">(But this wallet does not have the right keys.)</source> <context-group purpose="location"><context context-type="linenumber">275</context></context-group> </trans-unit> - <trans-unit id="_msg460"> + <trans-unit id="_msg461"> <source xml:space="preserve">Transaction is fully signed and ready for broadcast.</source> <context-group purpose="location"><context context-type="linenumber">283</context></context-group> </trans-unit> - <trans-unit id="_msg461"> + <trans-unit id="_msg462"> <source xml:space="preserve">Transaction status is unknown.</source> <context-group purpose="location"><context context-type="linenumber">287</context></context-group> </trans-unit> @@ -2083,37 +2087,37 @@ Signing is only possible with addresses of the type 'legacy'.</source> </body></file> <file original="../paymentserver.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="PaymentServer"> - <trans-unit id="_msg462"> + <trans-unit id="_msg463"> <source xml:space="preserve">Payment request error</source> <context-group purpose="location"><context context-type="linenumber">152</context></context-group> </trans-unit> - <trans-unit id="_msg463"> + <trans-unit id="_msg464"> <source xml:space="preserve">Cannot start bitcoin: click-to-pay handler</source> <context-group purpose="location"><context context-type="linenumber">153</context></context-group> </trans-unit> - <trans-unit id="_msg464"> + <trans-unit id="_msg465"> <source xml:space="preserve">URI handling</source> <context-group purpose="location"><context context-type="linenumber">201</context></context-group> <context-group purpose="location"><context context-type="linenumber">217</context></context-group> <context-group purpose="location"><context context-type="linenumber">223</context></context-group> <context-group purpose="location"><context context-type="linenumber">230</context></context-group> </trans-unit> - <trans-unit id="_msg465"> + <trans-unit id="_msg466"> <source xml:space="preserve">'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source> <context-group purpose="location"><context context-type="linenumber">201</context></context-group> </trans-unit> - <trans-unit id="_msg466"> + <trans-unit id="_msg467"> <source xml:space="preserve">Cannot process payment request because BIP70 is not supported. Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored. If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source> <context-group purpose="location"><context context-type="linenumber">218</context></context-group> <context-group purpose="location"><context context-type="linenumber">241</context></context-group> </trans-unit> - <trans-unit id="_msg467"> + <trans-unit id="_msg468"> <source xml:space="preserve">URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source> <context-group purpose="location"><context context-type="linenumber">231</context></context-group> </trans-unit> - <trans-unit id="_msg468"> + <trans-unit id="_msg469"> <source xml:space="preserve">Payment request file handling</source> <context-group purpose="location"><context context-type="linenumber">240</context></context-group> </trans-unit> @@ -2121,52 +2125,52 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../peertablemodel.h" datatype="c" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="PeerTableModel"> - <trans-unit id="_msg469"> + <trans-unit id="_msg470"> <source xml:space="preserve">User Agent</source> <context-group purpose="location"><context context-type="linenumber">112</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which contains the peer's User Agent string.</note> </trans-unit> - <trans-unit id="_msg470"> + <trans-unit id="_msg471"> <source xml:space="preserve">Ping</source> <context-group purpose="location"><context context-type="linenumber">103</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which indicates the current latency of the connection with the peer.</note> </trans-unit> - <trans-unit id="_msg471"> + <trans-unit id="_msg472"> <source xml:space="preserve">Peer</source> <context-group purpose="location"><context context-type="linenumber">85</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which contains a unique number used to identify a connection.</note> </trans-unit> - <trans-unit id="_msg472"> + <trans-unit id="_msg473"> <source xml:space="preserve">Age</source> <context-group purpose="location"><context context-type="linenumber">88</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</note> </trans-unit> - <trans-unit id="_msg473"> + <trans-unit id="_msg474"> <source xml:space="preserve">Direction</source> <context-group purpose="location"><context context-type="linenumber">94</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which indicates the direction the peer connection was initiated from.</note> </trans-unit> - <trans-unit id="_msg474"> + <trans-unit id="_msg475"> <source xml:space="preserve">Sent</source> <context-group purpose="location"><context context-type="linenumber">106</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</note> </trans-unit> - <trans-unit id="_msg475"> + <trans-unit id="_msg476"> <source xml:space="preserve">Received</source> <context-group purpose="location"><context context-type="linenumber">109</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which indicates the total amount of network information we have received from the peer.</note> </trans-unit> - <trans-unit id="_msg476"> + <trans-unit id="_msg477"> <source xml:space="preserve">Address</source> <context-group purpose="location"><context context-type="linenumber">91</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</note> </trans-unit> - <trans-unit id="_msg477"> + <trans-unit id="_msg478"> <source xml:space="preserve">Type</source> <context-group purpose="location"><context context-type="linenumber">97</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</note> </trans-unit> - <trans-unit id="_msg478"> + <trans-unit id="_msg479"> <source xml:space="preserve">Network</source> <context-group purpose="location"><context context-type="linenumber">100</context></context-group> <note annotates="source" from="developer">Title of Peers Table column which states the network the peer connected through.</note> @@ -2175,12 +2179,12 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../peertablemodel.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="PeerTableModel"> - <trans-unit id="_msg479"> + <trans-unit id="_msg480"> <source xml:space="preserve">Inbound</source> <context-group purpose="location"><context context-type="linenumber">78</context></context-group> <note annotates="source" from="developer">An Inbound Connection from a Peer.</note> </trans-unit> - <trans-unit id="_msg480"> + <trans-unit id="_msg481"> <source xml:space="preserve">Outbound</source> <context-group purpose="location"><context context-type="linenumber">80</context></context-group> <note annotates="source" from="developer">An Outbound Connection to a Peer.</note> @@ -2189,7 +2193,7 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../bitcoinunits.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="QObject"> - <trans-unit id="_msg481"> + <trans-unit id="_msg482"> <source xml:space="preserve">Amount</source> <context-group purpose="location"><context context-type="linenumber">197</context></context-group> </trans-unit> @@ -2197,162 +2201,162 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../guiutil.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="QObject"> - <trans-unit id="_msg482"> + <trans-unit id="_msg483"> <source xml:space="preserve">Enter a Bitcoin address (e.g. %1)</source> <context-group purpose="location"><context context-type="linenumber">129</context></context-group> </trans-unit> - <trans-unit id="_msg483"> + <trans-unit id="_msg484"> <source xml:space="preserve">Ctrl+W</source> <context-group purpose="location"><context context-type="linenumber">417</context></context-group> </trans-unit> - <trans-unit id="_msg484"> + <trans-unit id="_msg485"> <source xml:space="preserve">Unroutable</source> <context-group purpose="location"><context context-type="linenumber">673</context></context-group> </trans-unit> - <trans-unit id="_msg485"> + <trans-unit id="_msg486"> <source xml:space="preserve">Internal</source> <context-group purpose="location"><context context-type="linenumber">679</context></context-group> </trans-unit> - <trans-unit id="_msg486"> + <trans-unit id="_msg487"> <source xml:space="preserve">Inbound</source> <context-group purpose="location"><context context-type="linenumber">692</context></context-group> <note annotates="source" from="developer">An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</note> </trans-unit> - <trans-unit id="_msg487"> + <trans-unit id="_msg488"> <source xml:space="preserve">Outbound</source> <context-group purpose="location"><context context-type="linenumber">695</context></context-group> <note annotates="source" from="developer">An outbound connection to a peer. An outbound connection is a connection initiated by us.</note> </trans-unit> - <trans-unit id="_msg488"> + <trans-unit id="_msg489"> <source xml:space="preserve">Full Relay</source> <context-group purpose="location"><context context-type="linenumber">700</context></context-group> <note annotates="source" from="developer">Peer connection type that relays all network information.</note> </trans-unit> - <trans-unit id="_msg489"> + <trans-unit id="_msg490"> <source xml:space="preserve">Block Relay</source> <context-group purpose="location"><context context-type="linenumber">703</context></context-group> <note annotates="source" from="developer">Peer connection type that relays network information about blocks and not transactions or addresses.</note> </trans-unit> - <trans-unit id="_msg490"> + <trans-unit id="_msg491"> <source xml:space="preserve">Manual</source> <context-group purpose="location"><context context-type="linenumber">705</context></context-group> <note annotates="source" from="developer">Peer connection type established manually through one of several methods.</note> </trans-unit> - <trans-unit id="_msg491"> + <trans-unit id="_msg492"> <source xml:space="preserve">Feeler</source> <context-group purpose="location"><context context-type="linenumber">707</context></context-group> <note annotates="source" from="developer">Short-lived peer connection type that tests the aliveness of known addresses.</note> </trans-unit> - <trans-unit id="_msg492"> + <trans-unit id="_msg493"> <source xml:space="preserve">Address Fetch</source> <context-group purpose="location"><context context-type="linenumber">709</context></context-group> <note annotates="source" from="developer">Short-lived peer connection type that solicits known addresses from a peer.</note> </trans-unit> - <trans-unit id="_msg493"> + <trans-unit id="_msg494"> <source xml:space="preserve">%1 d</source> <context-group purpose="location"><context context-type="linenumber">722</context></context-group> <context-group purpose="location"><context context-type="linenumber">734</context></context-group> </trans-unit> - <trans-unit id="_msg494"> + <trans-unit id="_msg495"> <source xml:space="preserve">%1 h</source> <context-group purpose="location"><context context-type="linenumber">723</context></context-group> <context-group purpose="location"><context context-type="linenumber">735</context></context-group> </trans-unit> - <trans-unit id="_msg495"> + <trans-unit id="_msg496"> <source xml:space="preserve">%1 m</source> <context-group purpose="location"><context context-type="linenumber">724</context></context-group> <context-group purpose="location"><context context-type="linenumber">736</context></context-group> </trans-unit> - <trans-unit id="_msg496"> + <trans-unit id="_msg497"> <source xml:space="preserve">%1 s</source> <context-group purpose="location"><context context-type="linenumber">726</context></context-group> <context-group purpose="location"><context context-type="linenumber">737</context></context-group> <context-group purpose="location"><context context-type="linenumber">763</context></context-group> </trans-unit> - <trans-unit id="_msg497"> + <trans-unit id="_msg498"> <source xml:space="preserve">None</source> <context-group purpose="location"><context context-type="linenumber">751</context></context-group> </trans-unit> - <trans-unit id="_msg498"> + <trans-unit id="_msg499"> <source xml:space="preserve">N/A</source> <context-group purpose="location"><context context-type="linenumber">757</context></context-group> </trans-unit> - <trans-unit id="_msg499"> + <trans-unit id="_msg500"> <source xml:space="preserve">%1 ms</source> <context-group purpose="location"><context context-type="linenumber">758</context></context-group> </trans-unit> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">776</context></context-group> - <trans-unit id="_msg500[0]"> + <trans-unit id="_msg501[0]"> <source xml:space="preserve">%n second(s)</source> </trans-unit> - <trans-unit id="_msg500[1]"> + <trans-unit id="_msg501[1]"> <source xml:space="preserve">%n second(s)</source> </trans-unit> </group> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">780</context></context-group> - <trans-unit id="_msg501[0]"> + <trans-unit id="_msg502[0]"> <source xml:space="preserve">%n minute(s)</source> </trans-unit> - <trans-unit id="_msg501[1]"> + <trans-unit id="_msg502[1]"> <source xml:space="preserve">%n minute(s)</source> </trans-unit> </group> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">784</context></context-group> - <trans-unit id="_msg502[0]"> + <trans-unit id="_msg503[0]"> <source xml:space="preserve">%n hour(s)</source> </trans-unit> - <trans-unit id="_msg502[1]"> + <trans-unit id="_msg503[1]"> <source xml:space="preserve">%n hour(s)</source> </trans-unit> </group> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">788</context></context-group> - <trans-unit id="_msg503[0]"> + <trans-unit id="_msg504[0]"> <source xml:space="preserve">%n day(s)</source> </trans-unit> - <trans-unit id="_msg503[1]"> + <trans-unit id="_msg504[1]"> <source xml:space="preserve">%n day(s)</source> </trans-unit> </group> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">792</context></context-group> <context-group purpose="location"><context context-type="linenumber">798</context></context-group> - <trans-unit id="_msg504[0]"> + <trans-unit id="_msg505[0]"> <source xml:space="preserve">%n week(s)</source> </trans-unit> - <trans-unit id="_msg504[1]"> + <trans-unit id="_msg505[1]"> <source xml:space="preserve">%n week(s)</source> </trans-unit> </group> - <trans-unit id="_msg505"> + <trans-unit id="_msg506"> <source xml:space="preserve">%1 and %2</source> <context-group purpose="location"><context context-type="linenumber">798</context></context-group> </trans-unit> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">798</context></context-group> - <trans-unit id="_msg506[0]"> + <trans-unit id="_msg507[0]"> <source xml:space="preserve">%n year(s)</source> </trans-unit> - <trans-unit id="_msg506[1]"> + <trans-unit id="_msg507[1]"> <source xml:space="preserve">%n year(s)</source> </trans-unit> </group> - <trans-unit id="_msg507"> + <trans-unit id="_msg508"> <source xml:space="preserve">%1 B</source> <context-group purpose="location"><context context-type="linenumber">806</context></context-group> </trans-unit> - <trans-unit id="_msg508"> + <trans-unit id="_msg509"> <source xml:space="preserve">%1 kB</source> <context-group purpose="location"><context context-type="linenumber">808</context></context-group> </trans-unit> - <trans-unit id="_msg509"> + <trans-unit id="_msg510"> <source xml:space="preserve">%1 MB</source> <context-group purpose="location"><context context-type="linenumber">810</context></context-group> </trans-unit> - <trans-unit id="_msg510"> + <trans-unit id="_msg511"> <source xml:space="preserve">%1 GB</source> <context-group purpose="location"><context context-type="linenumber">812</context></context-group> </trans-unit> @@ -2360,31 +2364,31 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../qrimagewidget.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="QRImageWidget"> - <trans-unit id="_msg511"> + <trans-unit id="_msg512"> <source xml:space="preserve">&Save Image…</source> <context-group purpose="location"><context context-type="linenumber">30</context></context-group> </trans-unit> - <trans-unit id="_msg512"> + <trans-unit id="_msg513"> <source xml:space="preserve">&Copy Image</source> <context-group purpose="location"><context context-type="linenumber">31</context></context-group> </trans-unit> - <trans-unit id="_msg513"> + <trans-unit id="_msg514"> <source xml:space="preserve">Resulting URI too long, try to reduce the text for label / message.</source> <context-group purpose="location"><context context-type="linenumber">42</context></context-group> </trans-unit> - <trans-unit id="_msg514"> + <trans-unit id="_msg515"> <source xml:space="preserve">Error encoding URI into QR Code.</source> <context-group purpose="location"><context context-type="linenumber">49</context></context-group> </trans-unit> - <trans-unit id="_msg515"> + <trans-unit id="_msg516"> <source xml:space="preserve">QR code support not available.</source> <context-group purpose="location"><context context-type="linenumber">90</context></context-group> </trans-unit> - <trans-unit id="_msg516"> + <trans-unit id="_msg517"> <source xml:space="preserve">Save QR Code</source> <context-group purpose="location"><context context-type="linenumber">120</context></context-group> </trans-unit> - <trans-unit id="_msg517"> + <trans-unit id="_msg518"> <source xml:space="preserve">PNG Image</source> <context-group purpose="location"><context context-type="linenumber">123</context></context-group> <note annotates="source" from="developer">Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</note> @@ -2393,7 +2397,7 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../forms/debugwindow.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="RPCConsole"> - <trans-unit id="_msg518"> + <trans-unit id="_msg519"> <source xml:space="preserve">N/A</source> <context-group purpose="location"><context context-type="linenumber">75</context></context-group> <context-group purpose="location"><context context-type="linenumber">101</context></context-group> @@ -2434,291 +2438,291 @@ If you are receiving this error you should request the merchant provide a BIP21 <context-group purpose="location"><context context-type="linenumber">1662</context></context-group> <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.h</context><context context-type="linenumber">143</context></context-group> </trans-unit> - <trans-unit id="_msg519"> + <trans-unit id="_msg520"> <source xml:space="preserve">Client version</source> <context-group purpose="location"><context context-type="linenumber">65</context></context-group> </trans-unit> - <trans-unit id="_msg520"> + <trans-unit id="_msg521"> <source xml:space="preserve">&Information</source> <context-group purpose="location"><context context-type="linenumber">43</context></context-group> </trans-unit> - <trans-unit id="_msg521"> + <trans-unit id="_msg522"> <source xml:space="preserve">General</source> <context-group purpose="location"><context context-type="linenumber">58</context></context-group> </trans-unit> - <trans-unit id="_msg522"> + <trans-unit id="_msg523"> <source xml:space="preserve">Datadir</source> <context-group purpose="location"><context context-type="linenumber">114</context></context-group> </trans-unit> - <trans-unit id="_msg523"> + <trans-unit id="_msg524"> <source xml:space="preserve">To specify a non-default location of the data directory use the '%1' option.</source> <context-group purpose="location"><context context-type="linenumber">124</context></context-group> </trans-unit> - <trans-unit id="_msg524"> + <trans-unit id="_msg525"> <source xml:space="preserve">Blocksdir</source> <context-group purpose="location"><context context-type="linenumber">143</context></context-group> </trans-unit> - <trans-unit id="_msg525"> + <trans-unit id="_msg526"> <source xml:space="preserve">To specify a non-default location of the blocks directory use the '%1' option.</source> <context-group purpose="location"><context context-type="linenumber">153</context></context-group> </trans-unit> - <trans-unit id="_msg526"> + <trans-unit id="_msg527"> <source xml:space="preserve">Startup time</source> <context-group purpose="location"><context context-type="linenumber">172</context></context-group> </trans-unit> - <trans-unit id="_msg527"> + <trans-unit id="_msg528"> <source xml:space="preserve">Network</source> <context-group purpose="location"><context context-type="linenumber">201</context></context-group> <context-group purpose="location"><context context-type="linenumber">1093</context></context-group> </trans-unit> - <trans-unit id="_msg528"> + <trans-unit id="_msg529"> <source xml:space="preserve">Name</source> <context-group purpose="location"><context context-type="linenumber">208</context></context-group> </trans-unit> - <trans-unit id="_msg529"> + <trans-unit id="_msg530"> <source xml:space="preserve">Number of connections</source> <context-group purpose="location"><context context-type="linenumber">231</context></context-group> </trans-unit> - <trans-unit id="_msg530"> + <trans-unit id="_msg531"> <source xml:space="preserve">Block chain</source> <context-group purpose="location"><context context-type="linenumber">260</context></context-group> </trans-unit> - <trans-unit id="_msg531"> + <trans-unit id="_msg532"> <source xml:space="preserve">Memory Pool</source> <context-group purpose="location"><context context-type="linenumber">319</context></context-group> </trans-unit> - <trans-unit id="_msg532"> + <trans-unit id="_msg533"> <source xml:space="preserve">Current number of transactions</source> <context-group purpose="location"><context context-type="linenumber">326</context></context-group> </trans-unit> - <trans-unit id="_msg533"> + <trans-unit id="_msg534"> <source xml:space="preserve">Memory usage</source> <context-group purpose="location"><context context-type="linenumber">349</context></context-group> </trans-unit> - <trans-unit id="_msg534"> + <trans-unit id="_msg535"> <source xml:space="preserve">Wallet: </source> <context-group purpose="location"><context context-type="linenumber">443</context></context-group> </trans-unit> - <trans-unit id="_msg535"> + <trans-unit id="_msg536"> <source xml:space="preserve">(none)</source> <context-group purpose="location"><context context-type="linenumber">454</context></context-group> </trans-unit> - <trans-unit id="_msg536"> + <trans-unit id="_msg537"> <source xml:space="preserve">&Reset</source> <context-group purpose="location"><context context-type="linenumber">665</context></context-group> </trans-unit> - <trans-unit id="_msg537"> + <trans-unit id="_msg538"> <source xml:space="preserve">Received</source> <context-group purpose="location"><context context-type="linenumber">745</context></context-group> <context-group purpose="location"><context context-type="linenumber">1453</context></context-group> </trans-unit> - <trans-unit id="_msg538"> + <trans-unit id="_msg539"> <source xml:space="preserve">Sent</source> <context-group purpose="location"><context context-type="linenumber">825</context></context-group> <context-group purpose="location"><context context-type="linenumber">1430</context></context-group> </trans-unit> - <trans-unit id="_msg539"> + <trans-unit id="_msg540"> <source xml:space="preserve">&Peers</source> <context-group purpose="location"><context context-type="linenumber">866</context></context-group> </trans-unit> - <trans-unit id="_msg540"> + <trans-unit id="_msg541"> <source xml:space="preserve">Banned peers</source> <context-group purpose="location"><context context-type="linenumber">942</context></context-group> </trans-unit> - <trans-unit id="_msg541"> + <trans-unit id="_msg542"> <source xml:space="preserve">Select a peer to view detailed information.</source> <context-group purpose="location"><context context-type="linenumber">1010</context></context-group> <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">1155</context></context-group> </trans-unit> - <trans-unit id="_msg542"> + <trans-unit id="_msg543"> <source xml:space="preserve">Version</source> <context-group purpose="location"><context context-type="linenumber">1116</context></context-group> </trans-unit> - <trans-unit id="_msg543"> + <trans-unit id="_msg544"> <source xml:space="preserve">Starting Block</source> <context-group purpose="location"><context context-type="linenumber">1240</context></context-group> </trans-unit> - <trans-unit id="_msg544"> + <trans-unit id="_msg545"> <source xml:space="preserve">Synced Headers</source> <context-group purpose="location"><context context-type="linenumber">1263</context></context-group> </trans-unit> - <trans-unit id="_msg545"> + <trans-unit id="_msg546"> <source xml:space="preserve">Synced Blocks</source> <context-group purpose="location"><context context-type="linenumber">1286</context></context-group> </trans-unit> - <trans-unit id="_msg546"> + <trans-unit id="_msg547"> <source xml:space="preserve">Last Transaction</source> <context-group purpose="location"><context context-type="linenumber">1361</context></context-group> </trans-unit> - <trans-unit id="_msg547"> + <trans-unit id="_msg548"> <source xml:space="preserve">The mapped Autonomous System used for diversifying peer selection.</source> <context-group purpose="location"><context context-type="linenumber">1571</context></context-group> </trans-unit> - <trans-unit id="_msg548"> + <trans-unit id="_msg549"> <source xml:space="preserve">Mapped AS</source> <context-group purpose="location"><context context-type="linenumber">1574</context></context-group> </trans-unit> - <trans-unit id="_msg549"> + <trans-unit id="_msg550"> <source xml:space="preserve">Whether we relay addresses to this peer.</source> <context-group purpose="location"><context context-type="linenumber">1597</context></context-group> <note annotates="source" from="developer">Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</note> </trans-unit> - <trans-unit id="_msg550"> + <trans-unit id="_msg551"> <source xml:space="preserve">Address Relay</source> <context-group purpose="location"><context context-type="linenumber">1600</context></context-group> <note annotates="source" from="developer">Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</note> </trans-unit> - <trans-unit id="_msg551"> + <trans-unit id="_msg552"> <source xml:space="preserve">The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source> <context-group purpose="location"><context context-type="linenumber">1623</context></context-group> <note annotates="source" from="developer">Tooltip text 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).</note> </trans-unit> - <trans-unit id="_msg552"> + <trans-unit id="_msg553"> <source xml:space="preserve">The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source> <context-group purpose="location"><context context-type="linenumber">1649</context></context-group> <note annotates="source" from="developer">Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</note> </trans-unit> - <trans-unit id="_msg553"> + <trans-unit id="_msg554"> <source xml:space="preserve">Addresses Processed</source> <context-group purpose="location"><context context-type="linenumber">1626</context></context-group> <note annotates="source" from="developer">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).</note> </trans-unit> - <trans-unit id="_msg554"> + <trans-unit id="_msg555"> <source xml:space="preserve">Addresses Rate-Limited</source> <context-group purpose="location"><context context-type="linenumber">1652</context></context-group> <note annotates="source" from="developer">Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</note> </trans-unit> - <trans-unit id="_msg555"> + <trans-unit id="_msg556"> <source xml:space="preserve">User Agent</source> <context-group purpose="location"><context context-type="linenumber">88</context></context-group> <context-group purpose="location"><context context-type="linenumber">1139</context></context-group> </trans-unit> - <trans-unit id="_msg556"> + <trans-unit id="_msg557"> <source xml:space="preserve">Node window</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg557"> + <trans-unit id="_msg558"> <source xml:space="preserve">Current block height</source> <context-group purpose="location"><context context-type="linenumber">267</context></context-group> </trans-unit> - <trans-unit id="_msg558"> + <trans-unit id="_msg559"> <source xml:space="preserve">Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source> <context-group purpose="location"><context context-type="linenumber">397</context></context-group> </trans-unit> - <trans-unit id="_msg559"> + <trans-unit id="_msg560"> <source xml:space="preserve">Decrease font size</source> <context-group purpose="location"><context context-type="linenumber">475</context></context-group> </trans-unit> - <trans-unit id="_msg560"> + <trans-unit id="_msg561"> <source xml:space="preserve">Increase font size</source> <context-group purpose="location"><context context-type="linenumber">495</context></context-group> </trans-unit> - <trans-unit id="_msg561"> + <trans-unit id="_msg562"> <source xml:space="preserve">Permissions</source> <context-group purpose="location"><context context-type="linenumber">1041</context></context-group> </trans-unit> - <trans-unit id="_msg562"> + <trans-unit id="_msg563"> <source xml:space="preserve">The direction and type of peer connection: %1</source> <context-group purpose="location"><context context-type="linenumber">1064</context></context-group> </trans-unit> - <trans-unit id="_msg563"> + <trans-unit id="_msg564"> <source xml:space="preserve">Direction/Type</source> <context-group purpose="location"><context context-type="linenumber">1067</context></context-group> </trans-unit> - <trans-unit id="_msg564"> + <trans-unit id="_msg565"> <source xml:space="preserve">The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source> <context-group purpose="location"><context context-type="linenumber">1090</context></context-group> </trans-unit> - <trans-unit id="_msg565"> + <trans-unit id="_msg566"> <source xml:space="preserve">Services</source> <context-group purpose="location"><context context-type="linenumber">1162</context></context-group> </trans-unit> - <trans-unit id="_msg566"> + <trans-unit id="_msg567"> <source xml:space="preserve">Whether the peer requested us to relay transactions.</source> <context-group purpose="location"><context context-type="linenumber">1188</context></context-group> </trans-unit> - <trans-unit id="_msg567"> + <trans-unit id="_msg568"> <source xml:space="preserve">Wants Tx Relay</source> <context-group purpose="location"><context context-type="linenumber">1191</context></context-group> </trans-unit> - <trans-unit id="_msg568"> + <trans-unit id="_msg569"> <source xml:space="preserve">High bandwidth BIP152 compact block relay: %1</source> <context-group purpose="location"><context context-type="linenumber">1214</context></context-group> </trans-unit> - <trans-unit id="_msg569"> + <trans-unit id="_msg570"> <source xml:space="preserve">High Bandwidth</source> <context-group purpose="location"><context context-type="linenumber">1217</context></context-group> </trans-unit> - <trans-unit id="_msg570"> + <trans-unit id="_msg571"> <source xml:space="preserve">Connection Time</source> <context-group purpose="location"><context context-type="linenumber">1309</context></context-group> </trans-unit> - <trans-unit id="_msg571"> + <trans-unit id="_msg572"> <source xml:space="preserve">Elapsed time since a novel block passing initial validity checks was received from this peer.</source> <context-group purpose="location"><context context-type="linenumber">1332</context></context-group> </trans-unit> - <trans-unit id="_msg572"> + <trans-unit id="_msg573"> <source xml:space="preserve">Last Block</source> <context-group purpose="location"><context context-type="linenumber">1335</context></context-group> </trans-unit> - <trans-unit id="_msg573"> + <trans-unit id="_msg574"> <source xml:space="preserve">Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source> <context-group purpose="location"><context context-type="linenumber">1358</context></context-group> <note annotates="source" from="developer">Tooltip text for the Last Transaction field in the peer details area.</note> </trans-unit> - <trans-unit id="_msg574"> + <trans-unit id="_msg575"> <source xml:space="preserve">Last Send</source> <context-group purpose="location"><context context-type="linenumber">1384</context></context-group> </trans-unit> - <trans-unit id="_msg575"> + <trans-unit id="_msg576"> <source xml:space="preserve">Last Receive</source> <context-group purpose="location"><context context-type="linenumber">1407</context></context-group> </trans-unit> - <trans-unit id="_msg576"> + <trans-unit id="_msg577"> <source xml:space="preserve">Ping Time</source> <context-group purpose="location"><context context-type="linenumber">1476</context></context-group> </trans-unit> - <trans-unit id="_msg577"> + <trans-unit id="_msg578"> <source xml:space="preserve">The duration of a currently outstanding ping.</source> <context-group purpose="location"><context context-type="linenumber">1499</context></context-group> </trans-unit> - <trans-unit id="_msg578"> + <trans-unit id="_msg579"> <source xml:space="preserve">Ping Wait</source> <context-group purpose="location"><context context-type="linenumber">1502</context></context-group> </trans-unit> - <trans-unit id="_msg579"> + <trans-unit id="_msg580"> <source xml:space="preserve">Min Ping</source> <context-group purpose="location"><context context-type="linenumber">1525</context></context-group> </trans-unit> - <trans-unit id="_msg580"> + <trans-unit id="_msg581"> <source xml:space="preserve">Time Offset</source> <context-group purpose="location"><context context-type="linenumber">1548</context></context-group> </trans-unit> - <trans-unit id="_msg581"> + <trans-unit id="_msg582"> <source xml:space="preserve">Last block time</source> <context-group purpose="location"><context context-type="linenumber">290</context></context-group> </trans-unit> - <trans-unit id="_msg582"> + <trans-unit id="_msg583"> <source xml:space="preserve">&Open</source> <context-group purpose="location"><context context-type="linenumber">400</context></context-group> </trans-unit> - <trans-unit id="_msg583"> + <trans-unit id="_msg584"> <source xml:space="preserve">&Console</source> <context-group purpose="location"><context context-type="linenumber">426</context></context-group> </trans-unit> - <trans-unit id="_msg584"> + <trans-unit id="_msg585"> <source xml:space="preserve">&Network Traffic</source> <context-group purpose="location"><context context-type="linenumber">613</context></context-group> </trans-unit> - <trans-unit id="_msg585"> + <trans-unit id="_msg586"> <source xml:space="preserve">Totals</source> <context-group purpose="location"><context context-type="linenumber">681</context></context-group> </trans-unit> - <trans-unit id="_msg586"> + <trans-unit id="_msg587"> <source xml:space="preserve">Debug log file</source> <context-group purpose="location"><context context-type="linenumber">390</context></context-group> </trans-unit> - <trans-unit id="_msg587"> + <trans-unit id="_msg588"> <source xml:space="preserve">Clear console</source> <context-group purpose="location"><context context-type="linenumber">515</context></context-group> </trans-unit> @@ -2726,139 +2730,139 @@ If you are receiving this error you should request the merchant provide a BIP21 </body></file> <file original="../rpcconsole.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="RPCConsole"> - <trans-unit id="_msg588"> + <trans-unit id="_msg589"> <source xml:space="preserve">In:</source> <context-group purpose="location"><context context-type="linenumber">953</context></context-group> </trans-unit> - <trans-unit id="_msg589"> + <trans-unit id="_msg590"> <source xml:space="preserve">Out:</source> <context-group purpose="location"><context context-type="linenumber">954</context></context-group> </trans-unit> - <trans-unit id="_msg590"> + <trans-unit id="_msg591"> <source xml:space="preserve">Inbound: initiated by peer</source> <context-group purpose="location"><context context-type="linenumber">496</context></context-group> <note annotates="source" from="developer">Explanatory text for an inbound peer connection.</note> </trans-unit> - <trans-unit id="_msg591"> + <trans-unit id="_msg592"> <source xml:space="preserve">Outbound Full Relay: default</source> <context-group purpose="location"><context context-type="linenumber">500</context></context-group> <note annotates="source" from="developer">Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</note> </trans-unit> - <trans-unit id="_msg592"> + <trans-unit id="_msg593"> <source xml:space="preserve">Outbound Block Relay: does not relay transactions or addresses</source> <context-group purpose="location"><context context-type="linenumber">503</context></context-group> <note annotates="source" from="developer">Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</note> </trans-unit> - <trans-unit id="_msg593"> + <trans-unit id="_msg594"> <source xml:space="preserve">Outbound Manual: added using RPC %1 or %2/%3 configuration options</source> <context-group purpose="location"><context context-type="linenumber">508</context></context-group> <note annotates="source" from="developer">Explanatory text for an outbound peer connection that was established manually through one of several methods. The numbered arguments are stand-ins for the methods available to establish manual connections.</note> </trans-unit> - <trans-unit id="_msg594"> + <trans-unit id="_msg595"> <source xml:space="preserve">Outbound Feeler: short-lived, for testing addresses</source> <context-group purpose="location"><context context-type="linenumber">514</context></context-group> <note annotates="source" from="developer">Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</note> </trans-unit> - <trans-unit id="_msg595"> + <trans-unit id="_msg596"> <source xml:space="preserve">Outbound Address Fetch: short-lived, for soliciting addresses</source> <context-group purpose="location"><context context-type="linenumber">517</context></context-group> <note annotates="source" from="developer">Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</note> </trans-unit> - <trans-unit id="_msg596"> + <trans-unit id="_msg597"> <source xml:space="preserve">we selected the peer for high bandwidth relay</source> <context-group purpose="location"><context context-type="linenumber">521</context></context-group> </trans-unit> - <trans-unit id="_msg597"> + <trans-unit id="_msg598"> <source xml:space="preserve">the peer selected us for high bandwidth relay</source> <context-group purpose="location"><context context-type="linenumber">522</context></context-group> </trans-unit> - <trans-unit id="_msg598"> + <trans-unit id="_msg599"> <source xml:space="preserve">no high bandwidth relay selected</source> <context-group purpose="location"><context context-type="linenumber">523</context></context-group> </trans-unit> - <trans-unit id="_msg599"> + <trans-unit id="_msg600"> <source xml:space="preserve">Ctrl++</source> <context-group purpose="location"><context context-type="linenumber">536</context></context-group> <note annotates="source" from="developer">Main shortcut to increase the RPC console font size.</note> </trans-unit> - <trans-unit id="_msg600"> + <trans-unit id="_msg601"> <source xml:space="preserve">Ctrl+=</source> <context-group purpose="location"><context context-type="linenumber">538</context></context-group> <note annotates="source" from="developer">Secondary shortcut to increase the RPC console font size.</note> </trans-unit> - <trans-unit id="_msg601"> + <trans-unit id="_msg602"> <source xml:space="preserve">Ctrl+-</source> <context-group purpose="location"><context context-type="linenumber">542</context></context-group> <note annotates="source" from="developer">Main shortcut to decrease the RPC console font size.</note> </trans-unit> - <trans-unit id="_msg602"> + <trans-unit id="_msg603"> <source xml:space="preserve">Ctrl+_</source> <context-group purpose="location"><context context-type="linenumber">544</context></context-group> <note annotates="source" from="developer">Secondary shortcut to decrease the RPC console font size.</note> </trans-unit> - <trans-unit id="_msg603"> + <trans-unit id="_msg604"> <source xml:space="preserve">&Copy address</source> <context-group purpose="location"><context context-type="linenumber">695</context></context-group> <note annotates="source" from="developer">Context menu action to copy the address of a peer.</note> </trans-unit> - <trans-unit id="_msg604"> + <trans-unit id="_msg605"> <source xml:space="preserve">&Disconnect</source> <context-group purpose="location"><context context-type="linenumber">699</context></context-group> </trans-unit> - <trans-unit id="_msg605"> + <trans-unit id="_msg606"> <source xml:space="preserve">1 &hour</source> <context-group purpose="location"><context context-type="linenumber">700</context></context-group> </trans-unit> - <trans-unit id="_msg606"> + <trans-unit id="_msg607"> <source xml:space="preserve">1 d&ay</source> <context-group purpose="location"><context context-type="linenumber">701</context></context-group> </trans-unit> - <trans-unit id="_msg607"> + <trans-unit id="_msg608"> <source xml:space="preserve">1 &week</source> <context-group purpose="location"><context context-type="linenumber">702</context></context-group> </trans-unit> - <trans-unit id="_msg608"> + <trans-unit id="_msg609"> <source xml:space="preserve">1 &year</source> <context-group purpose="location"><context context-type="linenumber">703</context></context-group> </trans-unit> - <trans-unit id="_msg609"> + <trans-unit id="_msg610"> <source xml:space="preserve">&Copy IP/Netmask</source> <context-group purpose="location"><context context-type="linenumber">729</context></context-group> <note annotates="source" from="developer">Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</note> </trans-unit> - <trans-unit id="_msg610"> + <trans-unit id="_msg611"> <source xml:space="preserve">&Unban</source> <context-group purpose="location"><context context-type="linenumber">733</context></context-group> </trans-unit> - <trans-unit id="_msg611"> + <trans-unit id="_msg612"> <source xml:space="preserve">Network activity disabled</source> <context-group purpose="location"><context context-type="linenumber">957</context></context-group> </trans-unit> - <trans-unit id="_msg612"> + <trans-unit id="_msg613"> <source xml:space="preserve">Executing command without any wallet</source> <context-group purpose="location"><context context-type="linenumber">1035</context></context-group> </trans-unit> - <trans-unit id="_msg613"> + <trans-unit id="_msg614"> <source xml:space="preserve">Ctrl+I</source> <context-group purpose="location"><context context-type="linenumber">1351</context></context-group> </trans-unit> - <trans-unit id="_msg614"> + <trans-unit id="_msg615"> <source xml:space="preserve">Ctrl+T</source> <context-group purpose="location"><context context-type="linenumber">1352</context></context-group> </trans-unit> - <trans-unit id="_msg615"> + <trans-unit id="_msg616"> <source xml:space="preserve">Ctrl+N</source> <context-group purpose="location"><context context-type="linenumber">1353</context></context-group> </trans-unit> - <trans-unit id="_msg616"> + <trans-unit id="_msg617"> <source xml:space="preserve">Ctrl+P</source> <context-group purpose="location"><context context-type="linenumber">1354</context></context-group> </trans-unit> - <trans-unit id="_msg617"> + <trans-unit id="_msg618"> <source xml:space="preserve">Executing command using "%1" wallet</source> <context-group purpose="location"><context context-type="linenumber">1033</context></context-group> </trans-unit> - <trans-unit id="_msg618"> + <trans-unit id="_msg619"> <source xml:space="preserve">Welcome to the %1 RPC console. Use up and down arrows to navigate history, and %2 to clear screen. Use %3 and %4 to increase or decrease the font size. @@ -2869,16 +2873,16 @@ For more information on using this console, type %6. <context-group purpose="location"><context context-type="linenumber">887</context></context-group> <note annotates="source" from="developer">RPC console welcome message. Placeholders %7 and %8 are style tags for the warning content, and they are not space separated from the rest of the text intentionally.</note> </trans-unit> - <trans-unit id="_msg619"> + <trans-unit id="_msg620"> <source xml:space="preserve">Executing…</source> <context-group purpose="location"><context context-type="linenumber">1043</context></context-group> <note annotates="source" from="developer">A console message indicating an entered command is currently being executed.</note> </trans-unit> - <trans-unit id="_msg620"> + <trans-unit id="_msg621"> <source xml:space="preserve">(peer: %1)</source> <context-group purpose="location"><context context-type="linenumber">1161</context></context-group> </trans-unit> - <trans-unit id="_msg621"> + <trans-unit id="_msg622"> <source xml:space="preserve">via %1</source> <context-group purpose="location"><context context-type="linenumber">1163</context></context-group> </trans-unit> @@ -2886,31 +2890,31 @@ For more information on using this console, type %6. </body></file> <file original="../rpcconsole.h" datatype="c" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="RPCConsole"> - <trans-unit id="_msg622"> + <trans-unit id="_msg623"> <source xml:space="preserve">Yes</source> <context-group purpose="location"><context context-type="linenumber">142</context></context-group> </trans-unit> - <trans-unit id="_msg623"> + <trans-unit id="_msg624"> <source xml:space="preserve">No</source> <context-group purpose="location"><context context-type="linenumber">142</context></context-group> </trans-unit> - <trans-unit id="_msg624"> + <trans-unit id="_msg625"> <source xml:space="preserve">To</source> <context-group purpose="location"><context context-type="linenumber">142</context></context-group> </trans-unit> - <trans-unit id="_msg625"> + <trans-unit id="_msg626"> <source xml:space="preserve">From</source> <context-group purpose="location"><context context-type="linenumber">142</context></context-group> </trans-unit> - <trans-unit id="_msg626"> + <trans-unit id="_msg627"> <source xml:space="preserve">Ban for</source> <context-group purpose="location"><context context-type="linenumber">143</context></context-group> </trans-unit> - <trans-unit id="_msg627"> + <trans-unit id="_msg628"> <source xml:space="preserve">Never</source> <context-group purpose="location"><context context-type="linenumber">185</context></context-group> </trans-unit> - <trans-unit id="_msg628"> + <trans-unit id="_msg629"> <source xml:space="preserve">Unknown</source> <context-group purpose="location"><context context-type="linenumber">143</context></context-group> </trans-unit> @@ -2918,72 +2922,72 @@ For more information on using this console, type %6. </body></file> <file original="../forms/receivecoinsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="ReceiveCoinsDialog"> - <trans-unit id="_msg629"> + <trans-unit id="_msg630"> <source xml:space="preserve">&Amount:</source> <context-group purpose="location"><context context-type="linenumber">37</context></context-group> </trans-unit> - <trans-unit id="_msg630"> + <trans-unit id="_msg631"> <source xml:space="preserve">&Label:</source> <context-group purpose="location"><context context-type="linenumber">83</context></context-group> </trans-unit> - <trans-unit id="_msg631"> + <trans-unit id="_msg632"> <source xml:space="preserve">&Message:</source> <context-group purpose="location"><context context-type="linenumber">53</context></context-group> </trans-unit> - <trans-unit id="_msg632"> + <trans-unit id="_msg633"> <source xml:space="preserve">An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source> <context-group purpose="location"><context context-type="linenumber">50</context></context-group> </trans-unit> - <trans-unit id="_msg633"> + <trans-unit id="_msg634"> <source xml:space="preserve">An optional label to associate with the new receiving address.</source> <context-group purpose="location"><context context-type="linenumber">80</context></context-group> </trans-unit> - <trans-unit id="_msg634"> + <trans-unit id="_msg635"> <source xml:space="preserve">Use this form to request payments. All fields are <b>optional</b>.</source> <context-group purpose="location"><context context-type="linenumber">73</context></context-group> </trans-unit> - <trans-unit id="_msg635"> + <trans-unit id="_msg636"> <source xml:space="preserve">An optional amount to request. Leave this empty or zero to not request a specific amount.</source> <context-group purpose="location"><context context-type="linenumber">34</context></context-group> <context-group purpose="location"><context context-type="linenumber">193</context></context-group> </trans-unit> - <trans-unit id="_msg636"> + <trans-unit id="_msg637"> <source xml:space="preserve">An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source> <context-group purpose="location"><context context-type="linenumber">66</context></context-group> </trans-unit> - <trans-unit id="_msg637"> + <trans-unit id="_msg638"> <source xml:space="preserve">An optional message that is attached to the payment request and may be displayed to the sender.</source> <context-group purpose="location"><context context-type="linenumber">96</context></context-group> </trans-unit> - <trans-unit id="_msg638"> + <trans-unit id="_msg639"> <source xml:space="preserve">&Create new receiving address</source> <context-group purpose="location"><context context-type="linenumber">111</context></context-group> </trans-unit> - <trans-unit id="_msg639"> + <trans-unit id="_msg640"> <source xml:space="preserve">Clear all fields of the form.</source> <context-group purpose="location"><context context-type="linenumber">134</context></context-group> </trans-unit> - <trans-unit id="_msg640"> + <trans-unit id="_msg641"> <source xml:space="preserve">Clear</source> <context-group purpose="location"><context context-type="linenumber">137</context></context-group> </trans-unit> - <trans-unit id="_msg641"> + <trans-unit id="_msg642"> <source xml:space="preserve">Requested payments history</source> <context-group purpose="location"><context context-type="linenumber">273</context></context-group> </trans-unit> - <trans-unit id="_msg642"> + <trans-unit id="_msg643"> <source xml:space="preserve">Show the selected request (does the same as double clicking an entry)</source> <context-group purpose="location"><context context-type="linenumber">298</context></context-group> </trans-unit> - <trans-unit id="_msg643"> + <trans-unit id="_msg644"> <source xml:space="preserve">Show</source> <context-group purpose="location"><context context-type="linenumber">301</context></context-group> </trans-unit> - <trans-unit id="_msg644"> + <trans-unit id="_msg645"> <source xml:space="preserve">Remove the selected entries from the list</source> <context-group purpose="location"><context context-type="linenumber">318</context></context-group> </trans-unit> - <trans-unit id="_msg645"> + <trans-unit id="_msg646"> <source xml:space="preserve">Remove</source> <context-group purpose="location"><context context-type="linenumber">321</context></context-group> </trans-unit> @@ -2991,31 +2995,31 @@ For more information on using this console, type %6. </body></file> <file original="../receivecoinsdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="ReceiveCoinsDialog"> - <trans-unit id="_msg646"> + <trans-unit id="_msg647"> <source xml:space="preserve">Copy &URI</source> <context-group purpose="location"><context context-type="linenumber">47</context></context-group> </trans-unit> - <trans-unit id="_msg647"> + <trans-unit id="_msg648"> <source xml:space="preserve">&Copy address</source> <context-group purpose="location"><context context-type="linenumber">48</context></context-group> </trans-unit> - <trans-unit id="_msg648"> + <trans-unit id="_msg649"> <source xml:space="preserve">Copy &label</source> <context-group purpose="location"><context context-type="linenumber">49</context></context-group> </trans-unit> - <trans-unit id="_msg649"> + <trans-unit id="_msg650"> <source xml:space="preserve">Copy &message</source> <context-group purpose="location"><context context-type="linenumber">50</context></context-group> </trans-unit> - <trans-unit id="_msg650"> + <trans-unit id="_msg651"> <source xml:space="preserve">Copy &amount</source> <context-group purpose="location"><context context-type="linenumber">51</context></context-group> </trans-unit> - <trans-unit id="_msg651"> + <trans-unit id="_msg652"> <source xml:space="preserve">Could not unlock wallet.</source> <context-group purpose="location"><context context-type="linenumber">176</context></context-group> </trans-unit> - <trans-unit id="_msg652"> + <trans-unit id="_msg653"> <source xml:space="preserve">Could not generate new %1 address</source> <context-group purpose="location"><context context-type="linenumber">181</context></context-group> </trans-unit> @@ -3023,51 +3027,51 @@ For more information on using this console, type %6. </body></file> <file original="../forms/receiverequestdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="ReceiveRequestDialog"> - <trans-unit id="_msg653"> + <trans-unit id="_msg654"> <source xml:space="preserve">Request payment to …</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg654"> + <trans-unit id="_msg655"> <source xml:space="preserve">Address:</source> <context-group purpose="location"><context context-type="linenumber">90</context></context-group> </trans-unit> - <trans-unit id="_msg655"> + <trans-unit id="_msg656"> <source xml:space="preserve">Amount:</source> <context-group purpose="location"><context context-type="linenumber">119</context></context-group> </trans-unit> - <trans-unit id="_msg656"> + <trans-unit id="_msg657"> <source xml:space="preserve">Label:</source> <context-group purpose="location"><context context-type="linenumber">148</context></context-group> </trans-unit> - <trans-unit id="_msg657"> + <trans-unit id="_msg658"> <source xml:space="preserve">Message:</source> <context-group purpose="location"><context context-type="linenumber">180</context></context-group> </trans-unit> - <trans-unit id="_msg658"> + <trans-unit id="_msg659"> <source xml:space="preserve">Wallet:</source> <context-group purpose="location"><context context-type="linenumber">212</context></context-group> </trans-unit> - <trans-unit id="_msg659"> + <trans-unit id="_msg660"> <source xml:space="preserve">Copy &URI</source> <context-group purpose="location"><context context-type="linenumber">240</context></context-group> </trans-unit> - <trans-unit id="_msg660"> + <trans-unit id="_msg661"> <source xml:space="preserve">Copy &Address</source> <context-group purpose="location"><context context-type="linenumber">250</context></context-group> </trans-unit> - <trans-unit id="_msg661"> + <trans-unit id="_msg662"> <source xml:space="preserve">&Verify</source> <context-group purpose="location"><context context-type="linenumber">260</context></context-group> </trans-unit> - <trans-unit id="_msg662"> + <trans-unit id="_msg663"> <source xml:space="preserve">Verify this address on e.g. a hardware wallet screen</source> <context-group purpose="location"><context context-type="linenumber">263</context></context-group> </trans-unit> - <trans-unit id="_msg663"> + <trans-unit id="_msg664"> <source xml:space="preserve">&Save Image…</source> <context-group purpose="location"><context context-type="linenumber">273</context></context-group> </trans-unit> - <trans-unit id="_msg664"> + <trans-unit id="_msg665"> <source xml:space="preserve">Payment information</source> <context-group purpose="location"><context context-type="linenumber">39</context></context-group> </trans-unit> @@ -3075,7 +3079,7 @@ For more information on using this console, type %6. </body></file> <file original="../receiverequestdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="ReceiveRequestDialog"> - <trans-unit id="_msg665"> + <trans-unit id="_msg666"> <source xml:space="preserve">Request payment to %1</source> <context-group purpose="location"><context context-type="linenumber">49</context></context-group> </trans-unit> @@ -3083,31 +3087,31 @@ For more information on using this console, type %6. </body></file> <file original="../recentrequeststablemodel.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="RecentRequestsTableModel"> - <trans-unit id="_msg666"> + <trans-unit id="_msg667"> <source xml:space="preserve">Date</source> <context-group purpose="location"><context context-type="linenumber">32</context></context-group> </trans-unit> - <trans-unit id="_msg667"> + <trans-unit id="_msg668"> <source xml:space="preserve">Label</source> <context-group purpose="location"><context context-type="linenumber">32</context></context-group> </trans-unit> - <trans-unit id="_msg668"> + <trans-unit id="_msg669"> <source xml:space="preserve">Message</source> <context-group purpose="location"><context context-type="linenumber">32</context></context-group> </trans-unit> - <trans-unit id="_msg669"> + <trans-unit id="_msg670"> <source xml:space="preserve">(no label)</source> <context-group purpose="location"><context context-type="linenumber">70</context></context-group> </trans-unit> - <trans-unit id="_msg670"> + <trans-unit id="_msg671"> <source xml:space="preserve">(no message)</source> <context-group purpose="location"><context context-type="linenumber">79</context></context-group> </trans-unit> - <trans-unit id="_msg671"> + <trans-unit id="_msg672"> <source xml:space="preserve">(no amount requested)</source> <context-group purpose="location"><context context-type="linenumber">87</context></context-group> </trans-unit> - <trans-unit id="_msg672"> + <trans-unit id="_msg673"> <source xml:space="preserve">Requested</source> <context-group purpose="location"><context context-type="linenumber">130</context></context-group> </trans-unit> @@ -3115,154 +3119,154 @@ For more information on using this console, type %6. </body></file> <file original="../forms/sendcoinsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SendCoinsDialog"> - <trans-unit id="_msg673"> + <trans-unit id="_msg674"> <source xml:space="preserve">Send Coins</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> <context-group purpose="location"><context context-type="sourcefile">../sendcoinsdialog.cpp</context><context context-type="linenumber">759</context></context-group> </trans-unit> - <trans-unit id="_msg674"> + <trans-unit id="_msg675"> <source xml:space="preserve">Coin Control Features</source> <context-group purpose="location"><context context-type="linenumber">90</context></context-group> </trans-unit> - <trans-unit id="_msg675"> + <trans-unit id="_msg676"> <source xml:space="preserve">automatically selected</source> <context-group purpose="location"><context context-type="linenumber">120</context></context-group> </trans-unit> - <trans-unit id="_msg676"> + <trans-unit id="_msg677"> <source xml:space="preserve">Insufficient funds!</source> <context-group purpose="location"><context context-type="linenumber">139</context></context-group> </trans-unit> - <trans-unit id="_msg677"> + <trans-unit id="_msg678"> <source xml:space="preserve">Quantity:</source> <context-group purpose="location"><context context-type="linenumber">228</context></context-group> </trans-unit> - <trans-unit id="_msg678"> + <trans-unit id="_msg679"> <source xml:space="preserve">Bytes:</source> <context-group purpose="location"><context context-type="linenumber">263</context></context-group> </trans-unit> - <trans-unit id="_msg679"> + <trans-unit id="_msg680"> <source xml:space="preserve">Amount:</source> <context-group purpose="location"><context context-type="linenumber">311</context></context-group> </trans-unit> - <trans-unit id="_msg680"> + <trans-unit id="_msg681"> <source xml:space="preserve">Fee:</source> <context-group purpose="location"><context context-type="linenumber">391</context></context-group> </trans-unit> - <trans-unit id="_msg681"> + <trans-unit id="_msg682"> <source xml:space="preserve">After Fee:</source> <context-group purpose="location"><context context-type="linenumber">442</context></context-group> </trans-unit> - <trans-unit id="_msg682"> + <trans-unit id="_msg683"> <source xml:space="preserve">Change:</source> <context-group purpose="location"><context context-type="linenumber">474</context></context-group> </trans-unit> - <trans-unit id="_msg683"> + <trans-unit id="_msg684"> <source xml:space="preserve">If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source> <context-group purpose="location"><context context-type="linenumber">518</context></context-group> </trans-unit> - <trans-unit id="_msg684"> + <trans-unit id="_msg685"> <source xml:space="preserve">Custom change address</source> <context-group purpose="location"><context context-type="linenumber">521</context></context-group> </trans-unit> - <trans-unit id="_msg685"> + <trans-unit id="_msg686"> <source xml:space="preserve">Transaction Fee:</source> <context-group purpose="location"><context context-type="linenumber">727</context></context-group> </trans-unit> - <trans-unit id="_msg686"> + <trans-unit id="_msg687"> <source xml:space="preserve">Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source> <context-group purpose="location"><context context-type="linenumber">765</context></context-group> </trans-unit> - <trans-unit id="_msg687"> + <trans-unit id="_msg688"> <source xml:space="preserve">Warning: Fee estimation is currently not possible.</source> <context-group purpose="location"><context context-type="linenumber">774</context></context-group> </trans-unit> - <trans-unit id="_msg688"> + <trans-unit id="_msg689"> <source xml:space="preserve">per kilobyte</source> <context-group purpose="location"><context context-type="linenumber">856</context></context-group> </trans-unit> - <trans-unit id="_msg689"> + <trans-unit id="_msg690"> <source xml:space="preserve">Hide</source> <context-group purpose="location"><context context-type="linenumber">803</context></context-group> </trans-unit> - <trans-unit id="_msg690"> + <trans-unit id="_msg691"> <source xml:space="preserve">Recommended:</source> <context-group purpose="location"><context context-type="linenumber">915</context></context-group> </trans-unit> - <trans-unit id="_msg691"> + <trans-unit id="_msg692"> <source xml:space="preserve">Custom:</source> <context-group purpose="location"><context context-type="linenumber">945</context></context-group> </trans-unit> - <trans-unit id="_msg692"> + <trans-unit id="_msg693"> <source xml:space="preserve">Send to multiple recipients at once</source> <context-group purpose="location"><context context-type="linenumber">1160</context></context-group> </trans-unit> - <trans-unit id="_msg693"> + <trans-unit id="_msg694"> <source xml:space="preserve">Add &Recipient</source> <context-group purpose="location"><context context-type="linenumber">1163</context></context-group> </trans-unit> - <trans-unit id="_msg694"> + <trans-unit id="_msg695"> <source xml:space="preserve">Clear all fields of the form.</source> <context-group purpose="location"><context context-type="linenumber">1143</context></context-group> </trans-unit> - <trans-unit id="_msg695"> + <trans-unit id="_msg696"> <source xml:space="preserve">Inputs…</source> <context-group purpose="location"><context context-type="linenumber">110</context></context-group> </trans-unit> - <trans-unit id="_msg696"> + <trans-unit id="_msg697"> <source xml:space="preserve">Dust:</source> <context-group purpose="location"><context context-type="linenumber">343</context></context-group> </trans-unit> - <trans-unit id="_msg697"> + <trans-unit id="_msg698"> <source xml:space="preserve">Choose…</source> <context-group purpose="location"><context context-type="linenumber">741</context></context-group> </trans-unit> - <trans-unit id="_msg698"> + <trans-unit id="_msg699"> <source xml:space="preserve">Hide transaction fee settings</source> <context-group purpose="location"><context context-type="linenumber">800</context></context-group> </trans-unit> - <trans-unit id="_msg699"> + <trans-unit id="_msg700"> <source xml:space="preserve">Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size. Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source> <context-group purpose="location"><context context-type="linenumber">851</context></context-group> </trans-unit> - <trans-unit id="_msg700"> + <trans-unit id="_msg701"> <source xml:space="preserve">When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> <context-group purpose="location"><context context-type="linenumber">886</context></context-group> </trans-unit> - <trans-unit id="_msg701"> + <trans-unit id="_msg702"> <source xml:space="preserve">A too low fee might result in a never confirming transaction (read the tooltip)</source> <context-group purpose="location"><context context-type="linenumber">889</context></context-group> </trans-unit> - <trans-unit id="_msg702"> + <trans-unit id="_msg703"> <source xml:space="preserve">(Smart fee not initialized yet. This usually takes a few blocks…)</source> <context-group purpose="location"><context context-type="linenumber">994</context></context-group> </trans-unit> - <trans-unit id="_msg703"> + <trans-unit id="_msg704"> <source xml:space="preserve">Confirmation time target:</source> <context-group purpose="location"><context context-type="linenumber">1020</context></context-group> </trans-unit> - <trans-unit id="_msg704"> + <trans-unit id="_msg705"> <source xml:space="preserve">Enable Replace-By-Fee</source> <context-group purpose="location"><context context-type="linenumber">1078</context></context-group> </trans-unit> - <trans-unit id="_msg705"> + <trans-unit id="_msg706"> <source xml:space="preserve">With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source> <context-group purpose="location"><context context-type="linenumber">1081</context></context-group> </trans-unit> - <trans-unit id="_msg706"> + <trans-unit id="_msg707"> <source xml:space="preserve">Clear &All</source> <context-group purpose="location"><context context-type="linenumber">1146</context></context-group> </trans-unit> - <trans-unit id="_msg707"> + <trans-unit id="_msg708"> <source xml:space="preserve">Balance:</source> <context-group purpose="location"><context context-type="linenumber">1201</context></context-group> </trans-unit> - <trans-unit id="_msg708"> + <trans-unit id="_msg709"> <source xml:space="preserve">Confirm the send action</source> <context-group purpose="location"><context context-type="linenumber">1117</context></context-group> </trans-unit> - <trans-unit id="_msg709"> + <trans-unit id="_msg710"> <source xml:space="preserve">S&end</source> <context-group purpose="location"><context context-type="linenumber">1120</context></context-group> </trans-unit> @@ -3270,209 +3274,209 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../sendcoinsdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SendCoinsDialog"> - <trans-unit id="_msg710"> + <trans-unit id="_msg711"> <source xml:space="preserve">Copy quantity</source> <context-group purpose="location"><context context-type="linenumber">99</context></context-group> </trans-unit> - <trans-unit id="_msg711"> + <trans-unit id="_msg712"> <source xml:space="preserve">Copy amount</source> <context-group purpose="location"><context context-type="linenumber">100</context></context-group> </trans-unit> - <trans-unit id="_msg712"> + <trans-unit id="_msg713"> <source xml:space="preserve">Copy fee</source> <context-group purpose="location"><context context-type="linenumber">101</context></context-group> </trans-unit> - <trans-unit id="_msg713"> + <trans-unit id="_msg714"> <source xml:space="preserve">Copy after fee</source> <context-group purpose="location"><context context-type="linenumber">102</context></context-group> </trans-unit> - <trans-unit id="_msg714"> + <trans-unit id="_msg715"> <source xml:space="preserve">Copy bytes</source> <context-group purpose="location"><context context-type="linenumber">103</context></context-group> </trans-unit> - <trans-unit id="_msg715"> + <trans-unit id="_msg716"> <source xml:space="preserve">Copy dust</source> <context-group purpose="location"><context context-type="linenumber">104</context></context-group> </trans-unit> - <trans-unit id="_msg716"> + <trans-unit id="_msg717"> <source xml:space="preserve">Copy change</source> <context-group purpose="location"><context context-type="linenumber">105</context></context-group> </trans-unit> - <trans-unit id="_msg717"> + <trans-unit id="_msg718"> <source xml:space="preserve">%1 (%2 blocks)</source> <context-group purpose="location"><context context-type="linenumber">181</context></context-group> </trans-unit> - <trans-unit id="_msg718"> + <trans-unit id="_msg719"> <source xml:space="preserve">Sign on device</source> <context-group purpose="location"><context context-type="linenumber">211</context></context-group> <note annotates="source" from="developer">"device" usually means a hardware wallet.</note> </trans-unit> - <trans-unit id="_msg719"> + <trans-unit id="_msg720"> <source xml:space="preserve">Connect your hardware wallet first.</source> <context-group purpose="location"><context context-type="linenumber">214</context></context-group> </trans-unit> - <trans-unit id="_msg720"> + <trans-unit id="_msg721"> <source xml:space="preserve">Set external signer script path in Options -> Wallet</source> <context-group purpose="location"><context context-type="linenumber">218</context></context-group> <note annotates="source" from="developer">"External signer" means using devices such as hardware wallets.</note> </trans-unit> - <trans-unit id="_msg721"> + <trans-unit id="_msg722"> <source xml:space="preserve">Cr&eate Unsigned</source> <context-group purpose="location"><context context-type="linenumber">221</context></context-group> </trans-unit> - <trans-unit id="_msg722"> + <trans-unit id="_msg723"> <source xml:space="preserve">Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> <context-group purpose="location"><context context-type="linenumber">222</context></context-group> </trans-unit> - <trans-unit id="_msg723"> + <trans-unit id="_msg724"> <source xml:space="preserve"> from wallet '%1'</source> <context-group purpose="location"><context context-type="linenumber">312</context></context-group> </trans-unit> - <trans-unit id="_msg724"> + <trans-unit id="_msg725"> <source xml:space="preserve">%1 to '%2'</source> <context-group purpose="location"><context context-type="linenumber">323</context></context-group> </trans-unit> - <trans-unit id="_msg725"> + <trans-unit id="_msg726"> <source xml:space="preserve">%1 to %2</source> <context-group purpose="location"><context context-type="linenumber">328</context></context-group> </trans-unit> - <trans-unit id="_msg726"> + <trans-unit id="_msg727"> <source xml:space="preserve">To review recipient list click "Show Details…"</source> <context-group purpose="location"><context context-type="linenumber">394</context></context-group> </trans-unit> - <trans-unit id="_msg727"> + <trans-unit id="_msg728"> <source xml:space="preserve">Sign failed</source> <context-group purpose="location"><context context-type="linenumber">454</context></context-group> </trans-unit> - <trans-unit id="_msg728"> + <trans-unit id="_msg729"> <source xml:space="preserve">External signer not found</source> <context-group purpose="location"><context context-type="linenumber">459</context></context-group> <note annotates="source" from="developer">"External signer" means using devices such as hardware wallets.</note> </trans-unit> - <trans-unit id="_msg729"> + <trans-unit id="_msg730"> <source xml:space="preserve">External signer failure</source> <context-group purpose="location"><context context-type="linenumber">464</context></context-group> <note annotates="source" from="developer">"External signer" means using devices such as hardware wallets.</note> </trans-unit> - <trans-unit id="_msg730"> + <trans-unit id="_msg731"> <source xml:space="preserve">Save Transaction Data</source> <context-group purpose="location"><context context-type="linenumber">430</context></context-group> </trans-unit> - <trans-unit id="_msg731"> + <trans-unit id="_msg732"> <source xml:space="preserve">Partially Signed Transaction (Binary)</source> <context-group purpose="location"><context context-type="linenumber">432</context></context-group> <note annotates="source" from="developer">Expanded name of the binary PSBT file format. See: BIP 174.</note> </trans-unit> - <trans-unit id="_msg732"> + <trans-unit id="_msg733"> <source xml:space="preserve">PSBT saved</source> <context-group purpose="location"><context context-type="linenumber">439</context></context-group> </trans-unit> - <trans-unit id="_msg733"> + <trans-unit id="_msg734"> <source xml:space="preserve">External balance:</source> <context-group purpose="location"><context context-type="linenumber">705</context></context-group> </trans-unit> - <trans-unit id="_msg734"> + <trans-unit id="_msg735"> <source xml:space="preserve">or</source> <context-group purpose="location"><context context-type="linenumber">390</context></context-group> </trans-unit> - <trans-unit id="_msg735"> + <trans-unit id="_msg736"> <source xml:space="preserve">You can increase the fee later (signals Replace-By-Fee, BIP-125).</source> <context-group purpose="location"><context context-type="linenumber">372</context></context-group> </trans-unit> - <trans-unit id="_msg736"> + <trans-unit id="_msg737"> <source xml:space="preserve">Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> <context-group purpose="location"><context context-type="linenumber">342</context></context-group> <note annotates="source" from="developer">Text to inform a user attempting to create a transaction of their current options. At this stage, a user can only create a PSBT. This string is displayed when private keys are disabled and an external signer is not available.</note> </trans-unit> - <trans-unit id="_msg737"> + <trans-unit id="_msg738"> <source xml:space="preserve">Do you want to create this transaction?</source> <context-group purpose="location"><context context-type="linenumber">336</context></context-group> <note annotates="source" from="developer">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.</note> </trans-unit> - <trans-unit id="_msg738"> + <trans-unit id="_msg739"> <source xml:space="preserve">Please, review your transaction. You can create and send this transaction or create a Partially Signed Bitcoin Transaction (PSBT), which you can save or copy and then sign with, e.g., an offline %1 wallet, or a PSBT-compatible hardware wallet.</source> <context-group purpose="location"><context context-type="linenumber">347</context></context-group> <note annotates="source" from="developer">Text to inform a user attempting to create a transaction of their current options. At this stage, a user can send their transaction or create a PSBT. This string is displayed when both private keys and PSBT controls are enabled.</note> </trans-unit> - <trans-unit id="_msg739"> + <trans-unit id="_msg740"> <source xml:space="preserve">Please, review your transaction.</source> <context-group purpose="location"><context context-type="linenumber">350</context></context-group> <note annotates="source" from="developer">Text to prompt a user to review the details of the transaction they are attempting to send.</note> </trans-unit> - <trans-unit id="_msg740"> + <trans-unit id="_msg741"> <source xml:space="preserve">Transaction fee</source> <context-group purpose="location"><context context-type="linenumber">358</context></context-group> </trans-unit> - <trans-unit id="_msg741"> + <trans-unit id="_msg742"> <source xml:space="preserve">Not signalling Replace-By-Fee, BIP-125.</source> <context-group purpose="location"><context context-type="linenumber">374</context></context-group> </trans-unit> - <trans-unit id="_msg742"> + <trans-unit id="_msg743"> <source xml:space="preserve">Total Amount</source> <context-group purpose="location"><context context-type="linenumber">387</context></context-group> </trans-unit> - <trans-unit id="_msg743"> + <trans-unit id="_msg744"> <source xml:space="preserve">Confirm send coins</source> <context-group purpose="location"><context context-type="linenumber">486</context></context-group> </trans-unit> - <trans-unit id="_msg744"> + <trans-unit id="_msg745"> <source xml:space="preserve">Watch-only balance:</source> <context-group purpose="location"><context context-type="linenumber">708</context></context-group> </trans-unit> - <trans-unit id="_msg745"> + <trans-unit id="_msg746"> <source xml:space="preserve">The recipient address is not valid. Please recheck.</source> <context-group purpose="location"><context context-type="linenumber">732</context></context-group> </trans-unit> - <trans-unit id="_msg746"> + <trans-unit id="_msg747"> <source xml:space="preserve">The amount to pay must be larger than 0.</source> <context-group purpose="location"><context context-type="linenumber">735</context></context-group> </trans-unit> - <trans-unit id="_msg747"> + <trans-unit id="_msg748"> <source xml:space="preserve">The amount exceeds your balance.</source> <context-group purpose="location"><context context-type="linenumber">738</context></context-group> </trans-unit> - <trans-unit id="_msg748"> + <trans-unit id="_msg749"> <source xml:space="preserve">The total exceeds your balance when the %1 transaction fee is included.</source> <context-group purpose="location"><context context-type="linenumber">741</context></context-group> </trans-unit> - <trans-unit id="_msg749"> + <trans-unit id="_msg750"> <source xml:space="preserve">Duplicate address found: addresses should only be used once each.</source> <context-group purpose="location"><context context-type="linenumber">744</context></context-group> </trans-unit> - <trans-unit id="_msg750"> + <trans-unit id="_msg751"> <source xml:space="preserve">Transaction creation failed!</source> <context-group purpose="location"><context context-type="linenumber">747</context></context-group> </trans-unit> - <trans-unit id="_msg751"> + <trans-unit id="_msg752"> <source xml:space="preserve">A fee higher than %1 is considered an absurdly high fee.</source> <context-group purpose="location"><context context-type="linenumber">751</context></context-group> </trans-unit> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">874</context></context-group> - <trans-unit id="_msg752[0]"> + <trans-unit id="_msg753[0]"> <source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source> </trans-unit> - <trans-unit id="_msg752[1]"> + <trans-unit id="_msg753[1]"> <source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source> </trans-unit> </group> - <trans-unit id="_msg753"> + <trans-unit id="_msg754"> <source xml:space="preserve">Warning: Invalid Bitcoin address</source> <context-group purpose="location"><context context-type="linenumber">975</context></context-group> </trans-unit> - <trans-unit id="_msg754"> + <trans-unit id="_msg755"> <source xml:space="preserve">Warning: Unknown change address</source> <context-group purpose="location"><context context-type="linenumber">980</context></context-group> </trans-unit> - <trans-unit id="_msg755"> + <trans-unit id="_msg756"> <source xml:space="preserve">Confirm custom change address</source> <context-group purpose="location"><context context-type="linenumber">983</context></context-group> </trans-unit> - <trans-unit id="_msg756"> + <trans-unit id="_msg757"> <source xml:space="preserve">The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source> <context-group purpose="location"><context context-type="linenumber">983</context></context-group> </trans-unit> - <trans-unit id="_msg757"> + <trans-unit id="_msg758"> <source xml:space="preserve">(no label)</source> <context-group purpose="location"><context context-type="linenumber">1004</context></context-group> </trans-unit> @@ -3480,68 +3484,68 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../forms/sendcoinsentry.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SendCoinsEntry"> - <trans-unit id="_msg758"> + <trans-unit id="_msg759"> <source xml:space="preserve">A&mount:</source> <context-group purpose="location"><context context-type="linenumber">151</context></context-group> </trans-unit> - <trans-unit id="_msg759"> + <trans-unit id="_msg760"> <source xml:space="preserve">Pay &To:</source> <context-group purpose="location"><context context-type="linenumber">35</context></context-group> </trans-unit> - <trans-unit id="_msg760"> + <trans-unit id="_msg761"> <source xml:space="preserve">&Label:</source> <context-group purpose="location"><context context-type="linenumber">128</context></context-group> </trans-unit> - <trans-unit id="_msg761"> + <trans-unit id="_msg762"> <source xml:space="preserve">Choose previously used address</source> <context-group purpose="location"><context context-type="linenumber">60</context></context-group> </trans-unit> - <trans-unit id="_msg762"> + <trans-unit id="_msg763"> <source xml:space="preserve">The Bitcoin address to send the payment to</source> <context-group purpose="location"><context context-type="linenumber">53</context></context-group> </trans-unit> - <trans-unit id="_msg763"> + <trans-unit id="_msg764"> <source xml:space="preserve">Alt+A</source> <context-group purpose="location"><context context-type="linenumber">76</context></context-group> </trans-unit> - <trans-unit id="_msg764"> + <trans-unit id="_msg765"> <source xml:space="preserve">Paste address from clipboard</source> <context-group purpose="location"><context context-type="linenumber">83</context></context-group> </trans-unit> - <trans-unit id="_msg765"> + <trans-unit id="_msg766"> <source xml:space="preserve">Alt+P</source> <context-group purpose="location"><context context-type="linenumber">99</context></context-group> </trans-unit> - <trans-unit id="_msg766"> + <trans-unit id="_msg767"> <source xml:space="preserve">Remove this entry</source> <context-group purpose="location"><context context-type="linenumber">106</context></context-group> </trans-unit> - <trans-unit id="_msg767"> + <trans-unit id="_msg768"> <source xml:space="preserve">The amount to send in the selected unit</source> <context-group purpose="location"><context context-type="linenumber">166</context></context-group> </trans-unit> - <trans-unit id="_msg768"> + <trans-unit id="_msg769"> <source xml:space="preserve">The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source> <context-group purpose="location"><context context-type="linenumber">173</context></context-group> </trans-unit> - <trans-unit id="_msg769"> + <trans-unit id="_msg770"> <source xml:space="preserve">S&ubtract fee from amount</source> <context-group purpose="location"><context context-type="linenumber">176</context></context-group> </trans-unit> - <trans-unit id="_msg770"> + <trans-unit id="_msg771"> <source xml:space="preserve">Use available balance</source> <context-group purpose="location"><context context-type="linenumber">183</context></context-group> </trans-unit> - <trans-unit id="_msg771"> + <trans-unit id="_msg772"> <source xml:space="preserve">Message:</source> <context-group purpose="location"><context context-type="linenumber">192</context></context-group> </trans-unit> - <trans-unit id="_msg772"> + <trans-unit id="_msg773"> <source xml:space="preserve">Enter a label for this address to add it to the list of used addresses</source> <context-group purpose="location"><context context-type="linenumber">141</context></context-group> <context-group purpose="location"><context context-type="linenumber">144</context></context-group> </trans-unit> - <trans-unit id="_msg773"> + <trans-unit id="_msg774"> <source xml:space="preserve">A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source> <context-group purpose="location"><context context-type="linenumber">202</context></context-group> </trans-unit> @@ -3549,11 +3553,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../sendcoinsdialog.h" datatype="c" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SendConfirmationDialog"> - <trans-unit id="_msg774"> + <trans-unit id="_msg775"> <source xml:space="preserve">Send</source> <context-group purpose="location"><context context-type="linenumber">144</context></context-group> </trans-unit> - <trans-unit id="_msg775"> + <trans-unit id="_msg776"> <source xml:space="preserve">Create Unsigned</source> <context-group purpose="location"><context context-type="linenumber">146</context></context-group> </trans-unit> @@ -3561,105 +3565,105 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../forms/signverifymessagedialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SignVerifyMessageDialog"> - <trans-unit id="_msg776"> + <trans-unit id="_msg777"> <source xml:space="preserve">Signatures - Sign / Verify a Message</source> <context-group purpose="location"><context context-type="linenumber">14</context></context-group> </trans-unit> - <trans-unit id="_msg777"> + <trans-unit id="_msg778"> <source xml:space="preserve">&Sign Message</source> <context-group purpose="location"><context context-type="linenumber">27</context></context-group> </trans-unit> - <trans-unit id="_msg778"> + <trans-unit id="_msg779"> <source xml:space="preserve">You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source> <context-group purpose="location"><context context-type="linenumber">33</context></context-group> </trans-unit> - <trans-unit id="_msg779"> + <trans-unit id="_msg780"> <source xml:space="preserve">The Bitcoin address to sign the message with</source> <context-group purpose="location"><context context-type="linenumber">51</context></context-group> </trans-unit> - <trans-unit id="_msg780"> + <trans-unit id="_msg781"> <source xml:space="preserve">Choose previously used address</source> <context-group purpose="location"><context context-type="linenumber">58</context></context-group> <context-group purpose="location"><context context-type="linenumber">274</context></context-group> </trans-unit> - <trans-unit id="_msg781"> + <trans-unit id="_msg782"> <source xml:space="preserve">Alt+A</source> <context-group purpose="location"><context context-type="linenumber">68</context></context-group> <context-group purpose="location"><context context-type="linenumber">284</context></context-group> </trans-unit> - <trans-unit id="_msg782"> + <trans-unit id="_msg783"> <source xml:space="preserve">Paste address from clipboard</source> <context-group purpose="location"><context context-type="linenumber">78</context></context-group> </trans-unit> - <trans-unit id="_msg783"> + <trans-unit id="_msg784"> <source xml:space="preserve">Alt+P</source> <context-group purpose="location"><context context-type="linenumber">88</context></context-group> </trans-unit> - <trans-unit id="_msg784"> + <trans-unit id="_msg785"> <source xml:space="preserve">Enter the message you want to sign here</source> <context-group purpose="location"><context context-type="linenumber">100</context></context-group> <context-group purpose="location"><context context-type="linenumber">103</context></context-group> </trans-unit> - <trans-unit id="_msg785"> + <trans-unit id="_msg786"> <source xml:space="preserve">Signature</source> <context-group purpose="location"><context context-type="linenumber">110</context></context-group> </trans-unit> - <trans-unit id="_msg786"> + <trans-unit id="_msg787"> <source xml:space="preserve">Copy the current signature to the system clipboard</source> <context-group purpose="location"><context context-type="linenumber">140</context></context-group> </trans-unit> - <trans-unit id="_msg787"> + <trans-unit id="_msg788"> <source xml:space="preserve">Sign the message to prove you own this Bitcoin address</source> <context-group purpose="location"><context context-type="linenumber">161</context></context-group> </trans-unit> - <trans-unit id="_msg788"> + <trans-unit id="_msg789"> <source xml:space="preserve">Sign &Message</source> <context-group purpose="location"><context context-type="linenumber">164</context></context-group> </trans-unit> - <trans-unit id="_msg789"> + <trans-unit id="_msg790"> <source xml:space="preserve">Reset all sign message fields</source> <context-group purpose="location"><context context-type="linenumber">178</context></context-group> </trans-unit> - <trans-unit id="_msg790"> + <trans-unit id="_msg791"> <source xml:space="preserve">Clear &All</source> <context-group purpose="location"><context context-type="linenumber">181</context></context-group> <context-group purpose="location"><context context-type="linenumber">338</context></context-group> </trans-unit> - <trans-unit id="_msg791"> + <trans-unit id="_msg792"> <source xml:space="preserve">&Verify Message</source> <context-group purpose="location"><context context-type="linenumber">240</context></context-group> </trans-unit> - <trans-unit id="_msg792"> + <trans-unit id="_msg793"> <source xml:space="preserve">Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source> <context-group purpose="location"><context context-type="linenumber">246</context></context-group> </trans-unit> - <trans-unit id="_msg793"> + <trans-unit id="_msg794"> <source xml:space="preserve">The Bitcoin address the message was signed with</source> <context-group purpose="location"><context context-type="linenumber">267</context></context-group> </trans-unit> - <trans-unit id="_msg794"> + <trans-unit id="_msg795"> <source xml:space="preserve">The signed message to verify</source> <context-group purpose="location"><context context-type="linenumber">296</context></context-group> <context-group purpose="location"><context context-type="linenumber">299</context></context-group> </trans-unit> - <trans-unit id="_msg795"> + <trans-unit id="_msg796"> <source xml:space="preserve">The signature given when the message was signed</source> <context-group purpose="location"><context context-type="linenumber">306</context></context-group> <context-group purpose="location"><context context-type="linenumber">309</context></context-group> </trans-unit> - <trans-unit id="_msg796"> + <trans-unit id="_msg797"> <source xml:space="preserve">Verify the message to ensure it was signed with the specified Bitcoin address</source> <context-group purpose="location"><context context-type="linenumber">318</context></context-group> </trans-unit> - <trans-unit id="_msg797"> + <trans-unit id="_msg798"> <source xml:space="preserve">Verify &Message</source> <context-group purpose="location"><context context-type="linenumber">321</context></context-group> </trans-unit> - <trans-unit id="_msg798"> + <trans-unit id="_msg799"> <source xml:space="preserve">Reset all verify message fields</source> <context-group purpose="location"><context context-type="linenumber">335</context></context-group> </trans-unit> - <trans-unit id="_msg799"> + <trans-unit id="_msg800"> <source xml:space="preserve">Click "Sign Message" to generate signature</source> <context-group purpose="location"><context context-type="linenumber">125</context></context-group> </trans-unit> @@ -3667,61 +3671,61 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../signverifymessagedialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SignVerifyMessageDialog"> - <trans-unit id="_msg800"> + <trans-unit id="_msg801"> <source xml:space="preserve">The entered address is invalid.</source> <context-group purpose="location"><context context-type="linenumber">120</context></context-group> <context-group purpose="location"><context context-type="linenumber">219</context></context-group> </trans-unit> - <trans-unit id="_msg801"> + <trans-unit id="_msg802"> <source xml:space="preserve">Please check the address and try again.</source> <context-group purpose="location"><context context-type="linenumber">120</context></context-group> <context-group purpose="location"><context context-type="linenumber">127</context></context-group> <context-group purpose="location"><context context-type="linenumber">220</context></context-group> <context-group purpose="location"><context context-type="linenumber">227</context></context-group> </trans-unit> - <trans-unit id="_msg802"> + <trans-unit id="_msg803"> <source xml:space="preserve">The entered address does not refer to a key.</source> <context-group purpose="location"><context context-type="linenumber">127</context></context-group> <context-group purpose="location"><context context-type="linenumber">226</context></context-group> </trans-unit> - <trans-unit id="_msg803"> + <trans-unit id="_msg804"> <source xml:space="preserve">Wallet unlock was cancelled.</source> <context-group purpose="location"><context context-type="linenumber">135</context></context-group> </trans-unit> - <trans-unit id="_msg804"> + <trans-unit id="_msg805"> <source xml:space="preserve">No error</source> <context-group purpose="location"><context context-type="linenumber">146</context></context-group> </trans-unit> - <trans-unit id="_msg805"> + <trans-unit id="_msg806"> <source xml:space="preserve">Private key for the entered address is not available.</source> <context-group purpose="location"><context context-type="linenumber">149</context></context-group> </trans-unit> - <trans-unit id="_msg806"> + <trans-unit id="_msg807"> <source xml:space="preserve">Message signing failed.</source> <context-group purpose="location"><context context-type="linenumber">152</context></context-group> </trans-unit> - <trans-unit id="_msg807"> + <trans-unit id="_msg808"> <source xml:space="preserve">Message signed.</source> <context-group purpose="location"><context context-type="linenumber">164</context></context-group> </trans-unit> - <trans-unit id="_msg808"> + <trans-unit id="_msg809"> <source xml:space="preserve">The signature could not be decoded.</source> <context-group purpose="location"><context context-type="linenumber">233</context></context-group> </trans-unit> - <trans-unit id="_msg809"> + <trans-unit id="_msg810"> <source xml:space="preserve">Please check the signature and try again.</source> <context-group purpose="location"><context context-type="linenumber">234</context></context-group> <context-group purpose="location"><context context-type="linenumber">241</context></context-group> </trans-unit> - <trans-unit id="_msg810"> + <trans-unit id="_msg811"> <source xml:space="preserve">The signature did not match the message digest.</source> <context-group purpose="location"><context context-type="linenumber">240</context></context-group> </trans-unit> - <trans-unit id="_msg811"> + <trans-unit id="_msg812"> <source xml:space="preserve">Message verification failed.</source> <context-group purpose="location"><context context-type="linenumber">246</context></context-group> </trans-unit> - <trans-unit id="_msg812"> + <trans-unit id="_msg813"> <source xml:space="preserve">Message verified.</source> <context-group purpose="location"><context context-type="linenumber">214</context></context-group> </trans-unit> @@ -3729,11 +3733,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../splashscreen.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="SplashScreen"> - <trans-unit id="_msg813"> + <trans-unit id="_msg814"> <source xml:space="preserve">(press q to shutdown and continue later)</source> <context-group purpose="location"><context context-type="linenumber">187</context></context-group> </trans-unit> - <trans-unit id="_msg814"> + <trans-unit id="_msg815"> <source xml:space="preserve">press q to shutdown</source> <context-group purpose="location"><context context-type="linenumber">188</context></context-group> </trans-unit> @@ -3741,7 +3745,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../trafficgraphwidget.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="TrafficGraphWidget"> - <trans-unit id="_msg815"> + <trans-unit id="_msg816"> <source xml:space="preserve">kB/s</source> <context-group purpose="location"><context context-type="linenumber">79</context></context-group> </trans-unit> @@ -3749,82 +3753,82 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../transactiondesc.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="TransactionDesc"> - <trans-unit id="_msg816"> + <trans-unit id="_msg817"> <source xml:space="preserve">conflicted with a transaction with %1 confirmations</source> <context-group purpose="location"><context context-type="linenumber">43</context></context-group> <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</note> </trans-unit> - <trans-unit id="_msg817"> + <trans-unit id="_msg818"> <source xml:space="preserve">0/unconfirmed, in memory pool</source> <context-group purpose="location"><context context-type="linenumber">50</context></context-group> <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</note> </trans-unit> - <trans-unit id="_msg818"> + <trans-unit id="_msg819"> <source xml:space="preserve">0/unconfirmed, not in memory pool</source> <context-group purpose="location"><context context-type="linenumber">55</context></context-group> <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</note> </trans-unit> - <trans-unit id="_msg819"> + <trans-unit id="_msg820"> <source xml:space="preserve">abandoned</source> <context-group purpose="location"><context context-type="linenumber">61</context></context-group> <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</note> </trans-unit> - <trans-unit id="_msg820"> + <trans-unit id="_msg821"> <source xml:space="preserve">%1/unconfirmed</source> <context-group purpose="location"><context context-type="linenumber">69</context></context-group> <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</note> </trans-unit> - <trans-unit id="_msg821"> + <trans-unit id="_msg822"> <source xml:space="preserve">%1 confirmations</source> <context-group purpose="location"><context context-type="linenumber">74</context></context-group> <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</note> </trans-unit> - <trans-unit id="_msg822"> + <trans-unit id="_msg823"> <source xml:space="preserve">Status</source> <context-group purpose="location"><context context-type="linenumber">124</context></context-group> </trans-unit> - <trans-unit id="_msg823"> + <trans-unit id="_msg824"> <source xml:space="preserve">Date</source> <context-group purpose="location"><context context-type="linenumber">127</context></context-group> </trans-unit> - <trans-unit id="_msg824"> + <trans-unit id="_msg825"> <source xml:space="preserve">Source</source> <context-group purpose="location"><context context-type="linenumber">134</context></context-group> </trans-unit> - <trans-unit id="_msg825"> + <trans-unit id="_msg826"> <source xml:space="preserve">Generated</source> <context-group purpose="location"><context context-type="linenumber">134</context></context-group> </trans-unit> - <trans-unit id="_msg826"> + <trans-unit id="_msg827"> <source xml:space="preserve">From</source> <context-group purpose="location"><context context-type="linenumber">139</context></context-group> <context-group purpose="location"><context context-type="linenumber">153</context></context-group> <context-group purpose="location"><context context-type="linenumber">225</context></context-group> </trans-unit> - <trans-unit id="_msg827"> + <trans-unit id="_msg828"> <source xml:space="preserve">unknown</source> <context-group purpose="location"><context context-type="linenumber">153</context></context-group> </trans-unit> - <trans-unit id="_msg828"> + <trans-unit id="_msg829"> <source xml:space="preserve">To</source> <context-group purpose="location"><context context-type="linenumber">154</context></context-group> <context-group purpose="location"><context context-type="linenumber">174</context></context-group> <context-group purpose="location"><context context-type="linenumber">244</context></context-group> </trans-unit> - <trans-unit id="_msg829"> + <trans-unit id="_msg830"> <source xml:space="preserve">own address</source> <context-group purpose="location"><context context-type="linenumber">156</context></context-group> </trans-unit> - <trans-unit id="_msg830"> + <trans-unit id="_msg831"> <source xml:space="preserve">watch-only</source> <context-group purpose="location"><context context-type="linenumber">156</context></context-group> <context-group purpose="location"><context context-type="linenumber">225</context></context-group> </trans-unit> - <trans-unit id="_msg831"> + <trans-unit id="_msg832"> <source xml:space="preserve">label</source> <context-group purpose="location"><context context-type="linenumber">158</context></context-group> </trans-unit> - <trans-unit id="_msg832"> + <trans-unit id="_msg833"> <source xml:space="preserve">Credit</source> <context-group purpose="location"><context context-type="linenumber">194</context></context-group> <context-group purpose="location"><context context-type="linenumber">206</context></context-group> @@ -3834,98 +3838,98 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </trans-unit> <group restype="x-gettext-plurals"> <context-group purpose="location"><context context-type="linenumber">196</context></context-group> - <trans-unit id="_msg833[0]"> + <trans-unit id="_msg834[0]"> <source xml:space="preserve">matures in %n more block(s)</source> </trans-unit> - <trans-unit id="_msg833[1]"> + <trans-unit id="_msg834[1]"> <source xml:space="preserve">matures in %n more block(s)</source> </trans-unit> </group> - <trans-unit id="_msg834"> + <trans-unit id="_msg835"> <source xml:space="preserve">not accepted</source> <context-group purpose="location"><context context-type="linenumber">198</context></context-group> </trans-unit> - <trans-unit id="_msg835"> + <trans-unit id="_msg836"> <source xml:space="preserve">Debit</source> <context-group purpose="location"><context context-type="linenumber">258</context></context-group> <context-group purpose="location"><context context-type="linenumber">284</context></context-group> <context-group purpose="location"><context context-type="linenumber">347</context></context-group> </trans-unit> - <trans-unit id="_msg836"> + <trans-unit id="_msg837"> <source xml:space="preserve">Total debit</source> <context-group purpose="location"><context context-type="linenumber">268</context></context-group> </trans-unit> - <trans-unit id="_msg837"> + <trans-unit id="_msg838"> <source xml:space="preserve">Total credit</source> <context-group purpose="location"><context context-type="linenumber">269</context></context-group> </trans-unit> - <trans-unit id="_msg838"> + <trans-unit id="_msg839"> <source xml:space="preserve">Transaction fee</source> <context-group purpose="location"><context context-type="linenumber">274</context></context-group> </trans-unit> - <trans-unit id="_msg839"> + <trans-unit id="_msg840"> <source xml:space="preserve">Net amount</source> <context-group purpose="location"><context context-type="linenumber">296</context></context-group> </trans-unit> - <trans-unit id="_msg840"> + <trans-unit id="_msg841"> <source xml:space="preserve">Message</source> <context-group purpose="location"><context context-type="linenumber">302</context></context-group> <context-group purpose="location"><context context-type="linenumber">314</context></context-group> </trans-unit> - <trans-unit id="_msg841"> + <trans-unit id="_msg842"> <source xml:space="preserve">Comment</source> <context-group purpose="location"><context context-type="linenumber">304</context></context-group> </trans-unit> - <trans-unit id="_msg842"> + <trans-unit id="_msg843"> <source xml:space="preserve">Transaction ID</source> <context-group purpose="location"><context context-type="linenumber">306</context></context-group> </trans-unit> - <trans-unit id="_msg843"> + <trans-unit id="_msg844"> <source xml:space="preserve">Transaction total size</source> <context-group purpose="location"><context context-type="linenumber">307</context></context-group> </trans-unit> - <trans-unit id="_msg844"> + <trans-unit id="_msg845"> <source xml:space="preserve">Transaction virtual size</source> <context-group purpose="location"><context context-type="linenumber">308</context></context-group> </trans-unit> - <trans-unit id="_msg845"> + <trans-unit id="_msg846"> <source xml:space="preserve">Output index</source> <context-group purpose="location"><context context-type="linenumber">309</context></context-group> </trans-unit> - <trans-unit id="_msg846"> + <trans-unit id="_msg847"> <source xml:space="preserve"> (Certificate was not verified)</source> <context-group purpose="location"><context context-type="linenumber">325</context></context-group> </trans-unit> - <trans-unit id="_msg847"> + <trans-unit id="_msg848"> <source xml:space="preserve">Merchant</source> <context-group purpose="location"><context context-type="linenumber">328</context></context-group> </trans-unit> - <trans-unit id="_msg848"> + <trans-unit id="_msg849"> <source xml:space="preserve">Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> <context-group purpose="location"><context context-type="linenumber">336</context></context-group> </trans-unit> - <trans-unit id="_msg849"> + <trans-unit id="_msg850"> <source xml:space="preserve">Debug information</source> <context-group purpose="location"><context context-type="linenumber">344</context></context-group> </trans-unit> - <trans-unit id="_msg850"> + <trans-unit id="_msg851"> <source xml:space="preserve">Transaction</source> <context-group purpose="location"><context context-type="linenumber">352</context></context-group> </trans-unit> - <trans-unit id="_msg851"> + <trans-unit id="_msg852"> <source xml:space="preserve">Inputs</source> <context-group purpose="location"><context context-type="linenumber">355</context></context-group> </trans-unit> - <trans-unit id="_msg852"> + <trans-unit id="_msg853"> <source xml:space="preserve">Amount</source> <context-group purpose="location"><context context-type="linenumber">376</context></context-group> </trans-unit> - <trans-unit id="_msg853"> + <trans-unit id="_msg854"> <source xml:space="preserve">true</source> <context-group purpose="location"><context context-type="linenumber">377</context></context-group> <context-group purpose="location"><context context-type="linenumber">378</context></context-group> </trans-unit> - <trans-unit id="_msg854"> + <trans-unit id="_msg855"> <source xml:space="preserve">false</source> <context-group purpose="location"><context context-type="linenumber">377</context></context-group> <context-group purpose="location"><context context-type="linenumber">378</context></context-group> @@ -3934,7 +3938,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../forms/transactiondescdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="TransactionDescDialog"> - <trans-unit id="_msg855"> + <trans-unit id="_msg856"> <source xml:space="preserve">This pane shows a detailed description of the transaction</source> <context-group purpose="location"><context context-type="linenumber">20</context></context-group> </trans-unit> @@ -3942,7 +3946,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../transactiondescdialog.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="TransactionDescDialog"> - <trans-unit id="_msg856"> + <trans-unit id="_msg857"> <source xml:space="preserve">Details for %1</source> <context-group purpose="location"><context context-type="linenumber">18</context></context-group> </trans-unit> @@ -3950,99 +3954,99 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../transactiontablemodel.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="TransactionTableModel"> - <trans-unit id="_msg857"> + <trans-unit id="_msg858"> <source xml:space="preserve">Date</source> <context-group purpose="location"><context context-type="linenumber">261</context></context-group> </trans-unit> - <trans-unit id="_msg858"> + <trans-unit id="_msg859"> <source xml:space="preserve">Type</source> <context-group purpose="location"><context context-type="linenumber">261</context></context-group> </trans-unit> - <trans-unit id="_msg859"> + <trans-unit id="_msg860"> <source xml:space="preserve">Label</source> <context-group purpose="location"><context context-type="linenumber">261</context></context-group> </trans-unit> - <trans-unit id="_msg860"> + <trans-unit id="_msg861"> <source xml:space="preserve">Unconfirmed</source> <context-group purpose="location"><context context-type="linenumber">321</context></context-group> </trans-unit> - <trans-unit id="_msg861"> + <trans-unit id="_msg862"> <source xml:space="preserve">Abandoned</source> <context-group purpose="location"><context context-type="linenumber">324</context></context-group> </trans-unit> - <trans-unit id="_msg862"> + <trans-unit id="_msg863"> <source xml:space="preserve">Confirming (%1 of %2 recommended confirmations)</source> <context-group purpose="location"><context context-type="linenumber">327</context></context-group> </trans-unit> - <trans-unit id="_msg863"> + <trans-unit id="_msg864"> <source xml:space="preserve">Confirmed (%1 confirmations)</source> <context-group purpose="location"><context context-type="linenumber">330</context></context-group> </trans-unit> - <trans-unit id="_msg864"> + <trans-unit id="_msg865"> <source xml:space="preserve">Conflicted</source> <context-group purpose="location"><context context-type="linenumber">333</context></context-group> </trans-unit> - <trans-unit id="_msg865"> + <trans-unit id="_msg866"> <source xml:space="preserve">Immature (%1 confirmations, will be available after %2)</source> <context-group purpose="location"><context context-type="linenumber">336</context></context-group> </trans-unit> - <trans-unit id="_msg866"> + <trans-unit id="_msg867"> <source xml:space="preserve">Generated but not accepted</source> <context-group purpose="location"><context context-type="linenumber">339</context></context-group> </trans-unit> - <trans-unit id="_msg867"> + <trans-unit id="_msg868"> <source xml:space="preserve">Received with</source> <context-group purpose="location"><context context-type="linenumber">378</context></context-group> </trans-unit> - <trans-unit id="_msg868"> + <trans-unit id="_msg869"> <source xml:space="preserve">Received from</source> <context-group purpose="location"><context context-type="linenumber">380</context></context-group> </trans-unit> - <trans-unit id="_msg869"> + <trans-unit id="_msg870"> <source xml:space="preserve">Sent to</source> <context-group purpose="location"><context context-type="linenumber">383</context></context-group> </trans-unit> - <trans-unit id="_msg870"> + <trans-unit id="_msg871"> <source xml:space="preserve">Payment to yourself</source> <context-group purpose="location"><context context-type="linenumber">385</context></context-group> </trans-unit> - <trans-unit id="_msg871"> + <trans-unit id="_msg872"> <source xml:space="preserve">Mined</source> <context-group purpose="location"><context context-type="linenumber">387</context></context-group> </trans-unit> - <trans-unit id="_msg872"> + <trans-unit id="_msg873"> <source xml:space="preserve">watch-only</source> <context-group purpose="location"><context context-type="linenumber">415</context></context-group> </trans-unit> - <trans-unit id="_msg873"> + <trans-unit id="_msg874"> <source xml:space="preserve">(n/a)</source> <context-group purpose="location"><context context-type="linenumber">431</context></context-group> </trans-unit> - <trans-unit id="_msg874"> + <trans-unit id="_msg875"> <source xml:space="preserve">(no label)</source> <context-group purpose="location"><context context-type="linenumber">638</context></context-group> </trans-unit> - <trans-unit id="_msg875"> + <trans-unit id="_msg876"> <source xml:space="preserve">Transaction status. Hover over this field to show number of confirmations.</source> <context-group purpose="location"><context context-type="linenumber">677</context></context-group> </trans-unit> - <trans-unit id="_msg876"> + <trans-unit id="_msg877"> <source xml:space="preserve">Date and time that the transaction was received.</source> <context-group purpose="location"><context context-type="linenumber">679</context></context-group> </trans-unit> - <trans-unit id="_msg877"> + <trans-unit id="_msg878"> <source xml:space="preserve">Type of transaction.</source> <context-group purpose="location"><context context-type="linenumber">681</context></context-group> </trans-unit> - <trans-unit id="_msg878"> + <trans-unit id="_msg879"> <source xml:space="preserve">Whether or not a watch-only address is involved in this transaction.</source> <context-group purpose="location"><context context-type="linenumber">683</context></context-group> </trans-unit> - <trans-unit id="_msg879"> + <trans-unit id="_msg880"> <source xml:space="preserve">User-defined intent/purpose of the transaction.</source> <context-group purpose="location"><context context-type="linenumber">685</context></context-group> </trans-unit> - <trans-unit id="_msg880"> + <trans-unit id="_msg881"> <source xml:space="preserve">Amount removed from or added to balance.</source> <context-group purpose="location"><context context-type="linenumber">687</context></context-group> </trans-unit> @@ -4050,166 +4054,166 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../transactionview.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="TransactionView"> - <trans-unit id="_msg881"> + <trans-unit id="_msg882"> <source xml:space="preserve">All</source> <context-group purpose="location"><context context-type="linenumber">73</context></context-group> <context-group purpose="location"><context context-type="linenumber">89</context></context-group> </trans-unit> - <trans-unit id="_msg882"> + <trans-unit id="_msg883"> <source xml:space="preserve">Today</source> <context-group purpose="location"><context context-type="linenumber">74</context></context-group> </trans-unit> - <trans-unit id="_msg883"> + <trans-unit id="_msg884"> <source xml:space="preserve">This week</source> <context-group purpose="location"><context context-type="linenumber">75</context></context-group> </trans-unit> - <trans-unit id="_msg884"> + <trans-unit id="_msg885"> <source xml:space="preserve">This month</source> <context-group purpose="location"><context context-type="linenumber">76</context></context-group> </trans-unit> - <trans-unit id="_msg885"> + <trans-unit id="_msg886"> <source xml:space="preserve">Last month</source> <context-group purpose="location"><context context-type="linenumber">77</context></context-group> </trans-unit> - <trans-unit id="_msg886"> + <trans-unit id="_msg887"> <source xml:space="preserve">This year</source> <context-group purpose="location"><context context-type="linenumber">78</context></context-group> </trans-unit> - <trans-unit id="_msg887"> + <trans-unit id="_msg888"> <source xml:space="preserve">Received with</source> <context-group purpose="location"><context context-type="linenumber">90</context></context-group> </trans-unit> - <trans-unit id="_msg888"> + <trans-unit id="_msg889"> <source xml:space="preserve">Sent to</source> <context-group purpose="location"><context context-type="linenumber">92</context></context-group> </trans-unit> - <trans-unit id="_msg889"> + <trans-unit id="_msg890"> <source xml:space="preserve">To yourself</source> <context-group purpose="location"><context context-type="linenumber">94</context></context-group> </trans-unit> - <trans-unit id="_msg890"> + <trans-unit id="_msg891"> <source xml:space="preserve">Mined</source> <context-group purpose="location"><context context-type="linenumber">95</context></context-group> </trans-unit> - <trans-unit id="_msg891"> + <trans-unit id="_msg892"> <source xml:space="preserve">Other</source> <context-group purpose="location"><context context-type="linenumber">96</context></context-group> </trans-unit> - <trans-unit id="_msg892"> + <trans-unit id="_msg893"> <source xml:space="preserve">Enter address, transaction id, or label to search</source> <context-group purpose="location"><context context-type="linenumber">101</context></context-group> </trans-unit> - <trans-unit id="_msg893"> + <trans-unit id="_msg894"> <source xml:space="preserve">Min amount</source> <context-group purpose="location"><context context-type="linenumber">105</context></context-group> </trans-unit> - <trans-unit id="_msg894"> + <trans-unit id="_msg895"> <source xml:space="preserve">Range…</source> <context-group purpose="location"><context context-type="linenumber">79</context></context-group> </trans-unit> - <trans-unit id="_msg895"> + <trans-unit id="_msg896"> <source xml:space="preserve">&Copy address</source> <context-group purpose="location"><context context-type="linenumber">169</context></context-group> </trans-unit> - <trans-unit id="_msg896"> + <trans-unit id="_msg897"> <source xml:space="preserve">Copy &label</source> <context-group purpose="location"><context context-type="linenumber">170</context></context-group> </trans-unit> - <trans-unit id="_msg897"> + <trans-unit id="_msg898"> <source xml:space="preserve">Copy &amount</source> <context-group purpose="location"><context context-type="linenumber">171</context></context-group> </trans-unit> - <trans-unit id="_msg898"> + <trans-unit id="_msg899"> <source xml:space="preserve">Copy transaction &ID</source> <context-group purpose="location"><context context-type="linenumber">172</context></context-group> </trans-unit> - <trans-unit id="_msg899"> + <trans-unit id="_msg900"> <source xml:space="preserve">Copy &raw transaction</source> <context-group purpose="location"><context context-type="linenumber">173</context></context-group> </trans-unit> - <trans-unit id="_msg900"> + <trans-unit id="_msg901"> <source xml:space="preserve">Copy full transaction &details</source> <context-group purpose="location"><context context-type="linenumber">174</context></context-group> </trans-unit> - <trans-unit id="_msg901"> + <trans-unit id="_msg902"> <source xml:space="preserve">&Show transaction details</source> <context-group purpose="location"><context context-type="linenumber">175</context></context-group> </trans-unit> - <trans-unit id="_msg902"> + <trans-unit id="_msg903"> <source xml:space="preserve">Increase transaction &fee</source> <context-group purpose="location"><context context-type="linenumber">177</context></context-group> </trans-unit> - <trans-unit id="_msg903"> + <trans-unit id="_msg904"> <source xml:space="preserve">A&bandon transaction</source> <context-group purpose="location"><context context-type="linenumber">180</context></context-group> </trans-unit> - <trans-unit id="_msg904"> + <trans-unit id="_msg905"> <source xml:space="preserve">&Edit address label</source> <context-group purpose="location"><context context-type="linenumber">181</context></context-group> </trans-unit> - <trans-unit id="_msg905"> + <trans-unit id="_msg906"> <source xml:space="preserve">Show in %1</source> <context-group purpose="location"><context context-type="linenumber">240</context></context-group> <note annotates="source" from="developer">Transactions table context menu action to show the selected transaction in a third-party block explorer. %1 is a stand-in argument for the URL of the explorer.</note> </trans-unit> - <trans-unit id="_msg906"> + <trans-unit id="_msg907"> <source xml:space="preserve">Export Transaction History</source> <context-group purpose="location"><context context-type="linenumber">359</context></context-group> </trans-unit> - <trans-unit id="_msg907"> + <trans-unit id="_msg908"> <source xml:space="preserve">Comma separated file</source> <context-group purpose="location"><context context-type="linenumber">362</context></context-group> <note annotates="source" from="developer">Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</note> </trans-unit> - <trans-unit id="_msg908"> + <trans-unit id="_msg909"> <source xml:space="preserve">Confirmed</source> <context-group purpose="location"><context context-type="linenumber">371</context></context-group> </trans-unit> - <trans-unit id="_msg909"> + <trans-unit id="_msg910"> <source xml:space="preserve">Watch-only</source> <context-group purpose="location"><context context-type="linenumber">373</context></context-group> </trans-unit> - <trans-unit id="_msg910"> + <trans-unit id="_msg911"> <source xml:space="preserve">Date</source> <context-group purpose="location"><context context-type="linenumber">374</context></context-group> </trans-unit> - <trans-unit id="_msg911"> + <trans-unit id="_msg912"> <source xml:space="preserve">Type</source> <context-group purpose="location"><context context-type="linenumber">375</context></context-group> </trans-unit> - <trans-unit id="_msg912"> + <trans-unit id="_msg913"> <source xml:space="preserve">Label</source> <context-group purpose="location"><context context-type="linenumber">376</context></context-group> </trans-unit> - <trans-unit id="_msg913"> + <trans-unit id="_msg914"> <source xml:space="preserve">Address</source> <context-group purpose="location"><context context-type="linenumber">377</context></context-group> </trans-unit> - <trans-unit id="_msg914"> + <trans-unit id="_msg915"> <source xml:space="preserve">ID</source> <context-group purpose="location"><context context-type="linenumber">379</context></context-group> </trans-unit> - <trans-unit id="_msg915"> + <trans-unit id="_msg916"> <source xml:space="preserve">Exporting Failed</source> <context-group purpose="location"><context context-type="linenumber">382</context></context-group> </trans-unit> - <trans-unit id="_msg916"> + <trans-unit id="_msg917"> <source xml:space="preserve">There was an error trying to save the transaction history to %1.</source> <context-group purpose="location"><context context-type="linenumber">382</context></context-group> </trans-unit> - <trans-unit id="_msg917"> + <trans-unit id="_msg918"> <source xml:space="preserve">Exporting Successful</source> <context-group purpose="location"><context context-type="linenumber">386</context></context-group> </trans-unit> - <trans-unit id="_msg918"> + <trans-unit id="_msg919"> <source xml:space="preserve">The transaction history was successfully saved to %1.</source> <context-group purpose="location"><context context-type="linenumber">386</context></context-group> </trans-unit> - <trans-unit id="_msg919"> + <trans-unit id="_msg920"> <source xml:space="preserve">Range:</source> <context-group purpose="location"><context context-type="linenumber">558</context></context-group> </trans-unit> - <trans-unit id="_msg920"> + <trans-unit id="_msg921"> <source xml:space="preserve">to</source> <context-group purpose="location"><context context-type="linenumber">566</context></context-group> </trans-unit> @@ -4217,39 +4221,39 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 </body></file> <file original="../walletframe.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="WalletFrame"> - <trans-unit id="_msg921"> + <trans-unit id="_msg922"> <source xml:space="preserve">No wallet has been loaded. Go to File > Open Wallet to load a wallet. - OR -</source> <context-group purpose="location"><context context-type="linenumber">45</context></context-group> </trans-unit> - <trans-unit id="_msg922"> + <trans-unit id="_msg923"> <source xml:space="preserve">Create a new wallet</source> <context-group purpose="location"><context context-type="linenumber">50</context></context-group> </trans-unit> - <trans-unit id="_msg923"> + <trans-unit id="_msg924"> <source xml:space="preserve">Error</source> <context-group purpose="location"><context context-type="linenumber">201</context></context-group> <context-group purpose="location"><context context-type="linenumber">211</context></context-group> <context-group purpose="location"><context context-type="linenumber">229</context></context-group> </trans-unit> - <trans-unit id="_msg924"> + <trans-unit id="_msg925"> <source xml:space="preserve">Unable to decode PSBT from clipboard (invalid base64)</source> <context-group purpose="location"><context context-type="linenumber">201</context></context-group> </trans-unit> - <trans-unit id="_msg925"> + <trans-unit id="_msg926"> <source xml:space="preserve">Load Transaction Data</source> <context-group purpose="location"><context context-type="linenumber">207</context></context-group> </trans-unit> - <trans-unit id="_msg926"> + <trans-unit id="_msg927"> <source xml:space="preserve">Partially Signed Transaction (*.psbt)</source> <context-group purpose="location"><context context-type="linenumber">208</context></context-group> </trans-unit> - <trans-unit id="_msg927"> + <trans-unit id="_msg928"> <source xml:space="preserve">PSBT file must be smaller than 100 MiB</source> <context-group purpose="location"><context context-type="linenumber">211</context></context-group> </trans-unit> - <trans-unit id="_msg928"> + <trans-unit id="_msg929"> <source xml:space="preserve">Unable to decode PSBT</source> <context-group purpose="location"><context context-type="linenumber">229</context></context-group> </trans-unit> @@ -4257,67 +4261,67 @@ Go to File > Open Wallet to load a wallet. </body></file> <file original="../walletmodel.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="WalletModel"> - <trans-unit id="_msg929"> + <trans-unit id="_msg930"> <source xml:space="preserve">Send Coins</source> <context-group purpose="location"><context context-type="linenumber">221</context></context-group> </trans-unit> - <trans-unit id="_msg930"> + <trans-unit id="_msg931"> <source xml:space="preserve">Fee bump error</source> <context-group purpose="location"><context context-type="linenumber">484</context></context-group> <context-group purpose="location"><context context-type="linenumber">536</context></context-group> <context-group purpose="location"><context context-type="linenumber">551</context></context-group> <context-group purpose="location"><context context-type="linenumber">556</context></context-group> </trans-unit> - <trans-unit id="_msg931"> + <trans-unit id="_msg932"> <source xml:space="preserve">Increasing transaction fee failed</source> <context-group purpose="location"><context context-type="linenumber">484</context></context-group> </trans-unit> - <trans-unit id="_msg932"> + <trans-unit id="_msg933"> <source xml:space="preserve">Do you want to increase the fee?</source> <context-group purpose="location"><context context-type="linenumber">491</context></context-group> <note annotates="source" from="developer">Asks a user if they would like to manually increase the fee of a transaction that has already been created.</note> </trans-unit> - <trans-unit id="_msg933"> + <trans-unit id="_msg934"> <source xml:space="preserve">Current fee:</source> <context-group purpose="location"><context context-type="linenumber">495</context></context-group> </trans-unit> - <trans-unit id="_msg934"> + <trans-unit id="_msg935"> <source xml:space="preserve">Increase:</source> <context-group purpose="location"><context context-type="linenumber">499</context></context-group> </trans-unit> - <trans-unit id="_msg935"> + <trans-unit id="_msg936"> <source xml:space="preserve">New fee:</source> <context-group purpose="location"><context context-type="linenumber">503</context></context-group> </trans-unit> - <trans-unit id="_msg936"> + <trans-unit id="_msg937"> <source xml:space="preserve">Warning: This may pay the additional fee by reducing change outputs or adding inputs, when necessary. It may add a new change output if one does not already exist. These changes may potentially leak privacy.</source> <context-group purpose="location"><context context-type="linenumber">511</context></context-group> </trans-unit> - <trans-unit id="_msg937"> + <trans-unit id="_msg938"> <source xml:space="preserve">Confirm fee bump</source> <context-group purpose="location"><context context-type="linenumber">514</context></context-group> </trans-unit> - <trans-unit id="_msg938"> + <trans-unit id="_msg939"> <source xml:space="preserve">Can't draft transaction.</source> <context-group purpose="location"><context context-type="linenumber">536</context></context-group> </trans-unit> - <trans-unit id="_msg939"> + <trans-unit id="_msg940"> <source xml:space="preserve">PSBT copied</source> <context-group purpose="location"><context context-type="linenumber">543</context></context-group> </trans-unit> - <trans-unit id="_msg940"> + <trans-unit id="_msg941"> <source xml:space="preserve">Can't sign transaction.</source> <context-group purpose="location"><context context-type="linenumber">551</context></context-group> </trans-unit> - <trans-unit id="_msg941"> + <trans-unit id="_msg942"> <source xml:space="preserve">Could not commit transaction</source> <context-group purpose="location"><context context-type="linenumber">556</context></context-group> </trans-unit> - <trans-unit id="_msg942"> + <trans-unit id="_msg943"> <source xml:space="preserve">Can't display address</source> <context-group purpose="location"><context context-type="linenumber">570</context></context-group> </trans-unit> - <trans-unit id="_msg943"> + <trans-unit id="_msg944"> <source xml:space="preserve">default wallet</source> <context-group purpose="location"><context context-type="linenumber">588</context></context-group> </trans-unit> @@ -4325,40 +4329,40 @@ Go to File > Open Wallet to load a wallet. </body></file> <file original="../walletview.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="WalletView"> - <trans-unit id="_msg944"> + <trans-unit id="_msg945"> <source xml:space="preserve">&Export</source> <context-group purpose="location"><context context-type="linenumber">51</context></context-group> </trans-unit> - <trans-unit id="_msg945"> + <trans-unit id="_msg946"> <source xml:space="preserve">Export the data in the current tab to a file</source> <context-group purpose="location"><context context-type="linenumber">52</context></context-group> </trans-unit> - <trans-unit id="_msg946"> + <trans-unit id="_msg947"> <source xml:space="preserve">Backup Wallet</source> <context-group purpose="location"><context context-type="linenumber">214</context></context-group> </trans-unit> - <trans-unit id="_msg947"> + <trans-unit id="_msg948"> <source xml:space="preserve">Wallet Data</source> <context-group purpose="location"><context context-type="linenumber">216</context></context-group> <note annotates="source" from="developer">Name of the wallet data file format.</note> </trans-unit> - <trans-unit id="_msg948"> + <trans-unit id="_msg949"> <source xml:space="preserve">Backup Failed</source> <context-group purpose="location"><context context-type="linenumber">222</context></context-group> </trans-unit> - <trans-unit id="_msg949"> + <trans-unit id="_msg950"> <source xml:space="preserve">There was an error trying to save the wallet data to %1.</source> <context-group purpose="location"><context context-type="linenumber">222</context></context-group> </trans-unit> - <trans-unit id="_msg950"> + <trans-unit id="_msg951"> <source xml:space="preserve">Backup Successful</source> <context-group purpose="location"><context context-type="linenumber">226</context></context-group> </trans-unit> - <trans-unit id="_msg951"> + <trans-unit id="_msg952"> <source xml:space="preserve">The wallet data was successfully saved to %1.</source> <context-group purpose="location"><context context-type="linenumber">226</context></context-group> </trans-unit> - <trans-unit id="_msg952"> + <trans-unit id="_msg953"> <source xml:space="preserve">Cancel</source> <context-group purpose="location"><context context-type="linenumber">263</context></context-group> </trans-unit> @@ -4366,687 +4370,687 @@ Go to File > Open Wallet to load a wallet. </body></file> <file original="../bitcoinstrings.cpp" datatype="cpp" source-language="en"><body> <group restype="x-trolltech-linguist-context" resname="bitcoin-core"> - <trans-unit id="_msg953"> + <trans-unit id="_msg954"> <source xml:space="preserve">The %s developers</source> <context-group purpose="location"><context context-type="linenumber">12</context></context-group> </trans-unit> - <trans-unit id="_msg954"> + <trans-unit id="_msg955"> <source xml:space="preserve">%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source> <context-group purpose="location"><context context-type="linenumber">13</context></context-group> </trans-unit> - <trans-unit id="_msg955"> + <trans-unit id="_msg956"> <source xml:space="preserve">-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source> <context-group purpose="location"><context context-type="linenumber">20</context></context-group> </trans-unit> - <trans-unit id="_msg956"> + <trans-unit id="_msg957"> <source xml:space="preserve">Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source> <context-group purpose="location"><context context-type="linenumber">38</context></context-group> </trans-unit> - <trans-unit id="_msg957"> + <trans-unit id="_msg958"> <source xml:space="preserve">Cannot obtain a lock on data directory %s. %s is probably already running.</source> <context-group purpose="location"><context context-type="linenumber">41</context></context-group> </trans-unit> - <trans-unit id="_msg958"> + <trans-unit id="_msg959"> <source xml:space="preserve">Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified.</source> <context-group purpose="location"><context context-type="linenumber">46</context></context-group> </trans-unit> - <trans-unit id="_msg959"> + <trans-unit id="_msg960"> <source xml:space="preserve">Distributed under the MIT software license, see the accompanying file %s or %s</source> <context-group purpose="location"><context context-type="linenumber">50</context></context-group> </trans-unit> - <trans-unit id="_msg960"> + <trans-unit id="_msg961"> <source xml:space="preserve">Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source> <context-group purpose="location"><context context-type="linenumber">56</context></context-group> </trans-unit> - <trans-unit id="_msg961"> + <trans-unit id="_msg962"> <source xml:space="preserve">Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source> <context-group purpose="location"><context context-type="linenumber">59</context></context-group> </trans-unit> - <trans-unit id="_msg962"> + <trans-unit id="_msg963"> <source xml:space="preserve">Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source> <context-group purpose="location"><context context-type="linenumber">62</context></context-group> </trans-unit> - <trans-unit id="_msg963"> + <trans-unit id="_msg964"> <source xml:space="preserve">Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source> <context-group purpose="location"><context context-type="linenumber">64</context></context-group> </trans-unit> - <trans-unit id="_msg964"> + <trans-unit id="_msg965"> <source xml:space="preserve">Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source> <context-group purpose="location"><context context-type="linenumber">66</context></context-group> </trans-unit> - <trans-unit id="_msg965"> + <trans-unit id="_msg966"> <source xml:space="preserve">Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source> <context-group purpose="location"><context context-type="linenumber">69</context></context-group> </trans-unit> - <trans-unit id="_msg966"> + <trans-unit id="_msg967"> <source xml:space="preserve">Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source> <context-group purpose="location"><context context-type="linenumber">75</context></context-group> </trans-unit> - <trans-unit id="_msg967"> + <trans-unit id="_msg968"> <source xml:space="preserve">File %s already exists. If you are sure this is what you want, move it out of the way first.</source> <context-group purpose="location"><context context-type="linenumber">78</context></context-group> </trans-unit> - <trans-unit id="_msg968"> + <trans-unit id="_msg969"> <source xml:space="preserve">Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source> <context-group purpose="location"><context context-type="linenumber">81</context></context-group> </trans-unit> - <trans-unit id="_msg969"> + <trans-unit id="_msg970"> <source xml:space="preserve">Invalid or corrupt peers.dat (%s). If you believe this is a bug, please report it to %s. As a workaround, you can move the file (%s) out of the way (rename, move, or delete) to have a new one created on the next start.</source> <context-group purpose="location"><context context-type="linenumber">84</context></context-group> </trans-unit> - <trans-unit id="_msg970"> + <trans-unit id="_msg971"> <source xml:space="preserve">More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source> <context-group purpose="location"><context context-type="linenumber">88</context></context-group> </trans-unit> - <trans-unit id="_msg971"> + <trans-unit id="_msg972"> <source xml:space="preserve">No dump file provided. To use createfromdump, -dumpfile=<filename> must be provided.</source> <context-group purpose="location"><context context-type="linenumber">91</context></context-group> </trans-unit> - <trans-unit id="_msg972"> + <trans-unit id="_msg973"> <source xml:space="preserve">No dump file provided. To use dump, -dumpfile=<filename> must be provided.</source> <context-group purpose="location"><context context-type="linenumber">94</context></context-group> </trans-unit> - <trans-unit id="_msg973"> + <trans-unit id="_msg974"> <source xml:space="preserve">No wallet file format provided. To use createfromdump, -format=<format> must be provided.</source> <context-group purpose="location"><context context-type="linenumber">96</context></context-group> </trans-unit> - <trans-unit id="_msg974"> + <trans-unit id="_msg975"> <source xml:space="preserve">Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is not provided (no -proxy= and no -onion= given) or it is explicitly forbidden (-onion=0)</source> <context-group purpose="location"><context context-type="linenumber">99</context></context-group> </trans-unit> - <trans-unit id="_msg975"> + <trans-unit id="_msg976"> <source xml:space="preserve">Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source> <context-group purpose="location"><context context-type="linenumber">103</context></context-group> </trans-unit> - <trans-unit id="_msg976"> + <trans-unit id="_msg977"> <source xml:space="preserve">Please contribute if you find %s useful. Visit %s for further information about the software.</source> <context-group purpose="location"><context context-type="linenumber">106</context></context-group> </trans-unit> - <trans-unit id="_msg977"> + <trans-unit id="_msg978"> <source xml:space="preserve">Prune configured below the minimum of %d MiB. Please use a higher number.</source> <context-group purpose="location"><context context-type="linenumber">109</context></context-group> </trans-unit> - <trans-unit id="_msg978"> + <trans-unit id="_msg979"> <source xml:space="preserve">Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source> <context-group purpose="location"><context context-type="linenumber">111</context></context-group> </trans-unit> - <trans-unit id="_msg979"> + <trans-unit id="_msg980"> <source xml:space="preserve">Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source> <context-group purpose="location"><context context-type="linenumber">114</context></context-group> </trans-unit> - <trans-unit id="_msg980"> + <trans-unit id="_msg981"> <source xml:space="preserve">SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source> <context-group purpose="location"><context context-type="linenumber">117</context></context-group> </trans-unit> - <trans-unit id="_msg981"> + <trans-unit id="_msg982"> <source xml:space="preserve">The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source> <context-group purpose="location"><context context-type="linenumber">123</context></context-group> </trans-unit> - <trans-unit id="_msg982"> + <trans-unit id="_msg983"> <source xml:space="preserve">The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source> <context-group purpose="location"><context context-type="linenumber">128</context></context-group> </trans-unit> - <trans-unit id="_msg983"> + <trans-unit id="_msg984"> <source xml:space="preserve">The transaction amount is too small to send after the fee has been deducted</source> <context-group purpose="location"><context context-type="linenumber">132</context></context-group> </trans-unit> - <trans-unit id="_msg984"> + <trans-unit id="_msg985"> <source xml:space="preserve">This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</source> <context-group purpose="location"><context context-type="linenumber">134</context></context-group> </trans-unit> - <trans-unit id="_msg985"> + <trans-unit id="_msg986"> <source xml:space="preserve">This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source> <context-group purpose="location"><context context-type="linenumber">138</context></context-group> </trans-unit> - <trans-unit id="_msg986"> + <trans-unit id="_msg987"> <source xml:space="preserve">This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source> <context-group purpose="location"><context context-type="linenumber">141</context></context-group> </trans-unit> - <trans-unit id="_msg987"> + <trans-unit id="_msg988"> <source xml:space="preserve">This is the transaction fee you may discard if change is smaller than dust at this level</source> <context-group purpose="location"><context context-type="linenumber">144</context></context-group> </trans-unit> - <trans-unit id="_msg988"> + <trans-unit id="_msg989"> <source xml:space="preserve">This is the transaction fee you may pay when fee estimates are not available.</source> <context-group purpose="location"><context context-type="linenumber">147</context></context-group> </trans-unit> - <trans-unit id="_msg989"> + <trans-unit id="_msg990"> <source xml:space="preserve">Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source> <context-group purpose="location"><context context-type="linenumber">149</context></context-group> </trans-unit> - <trans-unit id="_msg990"> + <trans-unit id="_msg991"> <source xml:space="preserve">Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source> <context-group purpose="location"><context context-type="linenumber">152</context></context-group> </trans-unit> - <trans-unit id="_msg991"> + <trans-unit id="_msg992"> <source xml:space="preserve">Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source> <context-group purpose="location"><context context-type="linenumber">155</context></context-group> </trans-unit> - <trans-unit id="_msg992"> + <trans-unit id="_msg993"> <source xml:space="preserve">Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source> <context-group purpose="location"><context context-type="linenumber">158</context></context-group> </trans-unit> - <trans-unit id="_msg993"> + <trans-unit id="_msg994"> <source xml:space="preserve">Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source> <context-group purpose="location"><context context-type="linenumber">161</context></context-group> </trans-unit> - <trans-unit id="_msg994"> + <trans-unit id="_msg995"> <source xml:space="preserve">Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source> <context-group purpose="location"><context context-type="linenumber">165</context></context-group> </trans-unit> - <trans-unit id="_msg995"> + <trans-unit id="_msg996"> <source xml:space="preserve">Warning: Private keys detected in wallet {%s} with disabled private keys</source> <context-group purpose="location"><context context-type="linenumber">168</context></context-group> </trans-unit> - <trans-unit id="_msg996"> + <trans-unit id="_msg997"> <source xml:space="preserve">Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source> <context-group purpose="location"><context context-type="linenumber">170</context></context-group> </trans-unit> - <trans-unit id="_msg997"> + <trans-unit id="_msg998"> <source xml:space="preserve">Witness data for blocks after height %d requires validation. Please restart with -reindex.</source> <context-group purpose="location"><context context-type="linenumber">173</context></context-group> </trans-unit> - <trans-unit id="_msg998"> + <trans-unit id="_msg999"> <source xml:space="preserve">You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source> <context-group purpose="location"><context context-type="linenumber">176</context></context-group> </trans-unit> - <trans-unit id="_msg999"> + <trans-unit id="_msg1000"> <source xml:space="preserve">%s is set very high!</source> <context-group purpose="location"><context context-type="linenumber">179</context></context-group> </trans-unit> - <trans-unit id="_msg1000"> + <trans-unit id="_msg1001"> <source xml:space="preserve">-maxmempool must be at least %d MB</source> <context-group purpose="location"><context context-type="linenumber">180</context></context-group> </trans-unit> - <trans-unit id="_msg1001"> + <trans-unit id="_msg1002"> <source xml:space="preserve">A fatal internal error occurred, see debug.log for details</source> <context-group purpose="location"><context context-type="linenumber">181</context></context-group> </trans-unit> - <trans-unit id="_msg1002"> + <trans-unit id="_msg1003"> <source xml:space="preserve">Cannot resolve -%s address: '%s'</source> <context-group purpose="location"><context context-type="linenumber">182</context></context-group> </trans-unit> - <trans-unit id="_msg1003"> + <trans-unit id="_msg1004"> <source xml:space="preserve">Cannot set -forcednsseed to true when setting -dnsseed to false.</source> <context-group purpose="location"><context context-type="linenumber">183</context></context-group> </trans-unit> - <trans-unit id="_msg1004"> + <trans-unit id="_msg1005"> <source xml:space="preserve">Cannot set -peerblockfilters without -blockfilterindex.</source> <context-group purpose="location"><context context-type="linenumber">184</context></context-group> </trans-unit> - <trans-unit id="_msg1005"> + <trans-unit id="_msg1006"> <source xml:space="preserve">Cannot write to data directory '%s'; check permissions.</source> <context-group purpose="location"><context context-type="linenumber">185</context></context-group> </trans-unit> - <trans-unit id="_msg1006"> + <trans-unit id="_msg1007"> <source xml:space="preserve">The -txindex upgrade started by a previous version cannot be completed. Restart with the previous version or run a full -reindex.</source> <context-group purpose="location"><context context-type="linenumber">120</context></context-group> </trans-unit> - <trans-unit id="_msg1007"> + <trans-unit id="_msg1008"> <source xml:space="preserve">%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source> <context-group purpose="location"><context context-type="linenumber">16</context></context-group> </trans-unit> - <trans-unit id="_msg1008"> + <trans-unit id="_msg1009"> <source xml:space="preserve">-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source> <context-group purpose="location"><context context-type="linenumber">23</context></context-group> </trans-unit> - <trans-unit id="_msg1009"> + <trans-unit id="_msg1010"> <source xml:space="preserve">-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source> <context-group purpose="location"><context context-type="linenumber">27</context></context-group> </trans-unit> - <trans-unit id="_msg1010"> + <trans-unit id="_msg1011"> <source xml:space="preserve">-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source> <context-group purpose="location"><context context-type="linenumber">31</context></context-group> </trans-unit> - <trans-unit id="_msg1011"> + <trans-unit id="_msg1012"> <source xml:space="preserve">Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source> <context-group purpose="location"><context context-type="linenumber">35</context></context-group> </trans-unit> - <trans-unit id="_msg1012"> + <trans-unit id="_msg1013"> <source xml:space="preserve">Cannot provide specific connections and have addrman find outgoing connections at the same time.</source> <context-group purpose="location"><context context-type="linenumber">43</context></context-group> </trans-unit> - <trans-unit id="_msg1013"> + <trans-unit id="_msg1014"> <source xml:space="preserve">Error loading %s: External signer wallet being loaded without external signer support compiled</source> <context-group purpose="location"><context context-type="linenumber">53</context></context-group> </trans-unit> - <trans-unit id="_msg1014"> + <trans-unit id="_msg1015"> <source xml:space="preserve">Failed to rename invalid peers.dat file. Please move or delete it and try again.</source> <context-group purpose="location"><context context-type="linenumber">72</context></context-group> </trans-unit> - <trans-unit id="_msg1015"> + <trans-unit id="_msg1016"> <source xml:space="preserve">Config setting for %s only applied on %s network when in [%s] section.</source> <context-group purpose="location"><context context-type="linenumber">186</context></context-group> </trans-unit> - <trans-unit id="_msg1016"> + <trans-unit id="_msg1017"> <source xml:space="preserve">Copyright (C) %i-%i</source> <context-group purpose="location"><context context-type="linenumber">187</context></context-group> </trans-unit> - <trans-unit id="_msg1017"> + <trans-unit id="_msg1018"> <source xml:space="preserve">Corrupted block database detected</source> <context-group purpose="location"><context context-type="linenumber">188</context></context-group> </trans-unit> - <trans-unit id="_msg1018"> + <trans-unit id="_msg1019"> <source xml:space="preserve">Could not find asmap file %s</source> <context-group purpose="location"><context context-type="linenumber">189</context></context-group> </trans-unit> - <trans-unit id="_msg1019"> + <trans-unit id="_msg1020"> <source xml:space="preserve">Could not parse asmap file %s</source> <context-group purpose="location"><context context-type="linenumber">190</context></context-group> </trans-unit> - <trans-unit id="_msg1020"> + <trans-unit id="_msg1021"> <source xml:space="preserve">Disk space is too low!</source> <context-group purpose="location"><context context-type="linenumber">191</context></context-group> </trans-unit> - <trans-unit id="_msg1021"> + <trans-unit id="_msg1022"> <source xml:space="preserve">Do you want to rebuild the block database now?</source> <context-group purpose="location"><context context-type="linenumber">192</context></context-group> </trans-unit> - <trans-unit id="_msg1022"> + <trans-unit id="_msg1023"> <source xml:space="preserve">Done loading</source> <context-group purpose="location"><context context-type="linenumber">193</context></context-group> </trans-unit> - <trans-unit id="_msg1023"> + <trans-unit id="_msg1024"> <source xml:space="preserve">Dump file %s does not exist.</source> <context-group purpose="location"><context context-type="linenumber">194</context></context-group> </trans-unit> - <trans-unit id="_msg1024"> + <trans-unit id="_msg1025"> <source xml:space="preserve">Error creating %s</source> <context-group purpose="location"><context context-type="linenumber">195</context></context-group> </trans-unit> - <trans-unit id="_msg1025"> + <trans-unit id="_msg1026"> <source xml:space="preserve">Error initializing block database</source> <context-group purpose="location"><context context-type="linenumber">196</context></context-group> </trans-unit> - <trans-unit id="_msg1026"> + <trans-unit id="_msg1027"> <source xml:space="preserve">Error initializing wallet database environment %s!</source> <context-group purpose="location"><context context-type="linenumber">197</context></context-group> </trans-unit> - <trans-unit id="_msg1027"> + <trans-unit id="_msg1028"> <source xml:space="preserve">Error loading %s</source> <context-group purpose="location"><context context-type="linenumber">198</context></context-group> </trans-unit> - <trans-unit id="_msg1028"> + <trans-unit id="_msg1029"> <source xml:space="preserve">Error loading %s: Private keys can only be disabled during creation</source> <context-group purpose="location"><context context-type="linenumber">199</context></context-group> </trans-unit> - <trans-unit id="_msg1029"> + <trans-unit id="_msg1030"> <source xml:space="preserve">Error loading %s: Wallet corrupted</source> <context-group purpose="location"><context context-type="linenumber">200</context></context-group> </trans-unit> - <trans-unit id="_msg1030"> + <trans-unit id="_msg1031"> <source xml:space="preserve">Error loading %s: Wallet requires newer version of %s</source> <context-group purpose="location"><context context-type="linenumber">201</context></context-group> </trans-unit> - <trans-unit id="_msg1031"> + <trans-unit id="_msg1032"> <source xml:space="preserve">Error loading block database</source> <context-group purpose="location"><context context-type="linenumber">202</context></context-group> </trans-unit> - <trans-unit id="_msg1032"> + <trans-unit id="_msg1033"> <source xml:space="preserve">Error opening block database</source> <context-group purpose="location"><context context-type="linenumber">203</context></context-group> </trans-unit> - <trans-unit id="_msg1033"> + <trans-unit id="_msg1034"> <source xml:space="preserve">Error reading from database, shutting down.</source> <context-group purpose="location"><context context-type="linenumber">204</context></context-group> </trans-unit> - <trans-unit id="_msg1034"> + <trans-unit id="_msg1035"> <source xml:space="preserve">Error reading next record from wallet database</source> <context-group purpose="location"><context context-type="linenumber">205</context></context-group> </trans-unit> - <trans-unit id="_msg1035"> + <trans-unit id="_msg1036"> <source xml:space="preserve">Error: Couldn't create cursor into database</source> <context-group purpose="location"><context context-type="linenumber">206</context></context-group> </trans-unit> - <trans-unit id="_msg1036"> + <trans-unit id="_msg1037"> <source xml:space="preserve">Error: Disk space is low for %s</source> <context-group purpose="location"><context context-type="linenumber">207</context></context-group> </trans-unit> - <trans-unit id="_msg1037"> + <trans-unit id="_msg1038"> <source xml:space="preserve">Error: Dumpfile checksum does not match. Computed %s, expected %s</source> <context-group purpose="location"><context context-type="linenumber">208</context></context-group> </trans-unit> - <trans-unit id="_msg1038"> + <trans-unit id="_msg1039"> <source xml:space="preserve">Error: Got key that was not hex: %s</source> <context-group purpose="location"><context context-type="linenumber">209</context></context-group> </trans-unit> - <trans-unit id="_msg1039"> + <trans-unit id="_msg1040"> <source xml:space="preserve">Error: Got value that was not hex: %s</source> <context-group purpose="location"><context context-type="linenumber">210</context></context-group> </trans-unit> - <trans-unit id="_msg1040"> + <trans-unit id="_msg1041"> <source xml:space="preserve">Error: Keypool ran out, please call keypoolrefill first</source> <context-group purpose="location"><context context-type="linenumber">211</context></context-group> </trans-unit> - <trans-unit id="_msg1041"> + <trans-unit id="_msg1042"> <source xml:space="preserve">Error: Missing checksum</source> <context-group purpose="location"><context context-type="linenumber">212</context></context-group> </trans-unit> - <trans-unit id="_msg1042"> + <trans-unit id="_msg1043"> <source xml:space="preserve">Error: No %s addresses available.</source> <context-group purpose="location"><context context-type="linenumber">213</context></context-group> </trans-unit> - <trans-unit id="_msg1043"> + <trans-unit id="_msg1044"> <source xml:space="preserve">Error: Unable to parse version %u as a uint32_t</source> <context-group purpose="location"><context context-type="linenumber">214</context></context-group> </trans-unit> - <trans-unit id="_msg1044"> + <trans-unit id="_msg1045"> <source xml:space="preserve">Error: Unable to write record to new wallet</source> <context-group purpose="location"><context context-type="linenumber">215</context></context-group> </trans-unit> - <trans-unit id="_msg1045"> + <trans-unit id="_msg1046"> <source xml:space="preserve">Failed to listen on any port. Use -listen=0 if you want this.</source> <context-group purpose="location"><context context-type="linenumber">216</context></context-group> </trans-unit> - <trans-unit id="_msg1046"> + <trans-unit id="_msg1047"> <source xml:space="preserve">Failed to rescan the wallet during initialization</source> <context-group purpose="location"><context context-type="linenumber">217</context></context-group> </trans-unit> - <trans-unit id="_msg1047"> + <trans-unit id="_msg1048"> <source xml:space="preserve">Failed to verify database</source> <context-group purpose="location"><context context-type="linenumber">218</context></context-group> </trans-unit> - <trans-unit id="_msg1048"> + <trans-unit id="_msg1049"> <source xml:space="preserve">Fee rate (%s) is lower than the minimum fee rate setting (%s)</source> <context-group purpose="location"><context context-type="linenumber">219</context></context-group> </trans-unit> - <trans-unit id="_msg1049"> + <trans-unit id="_msg1050"> <source xml:space="preserve">Ignoring duplicate -wallet %s.</source> <context-group purpose="location"><context context-type="linenumber">220</context></context-group> </trans-unit> - <trans-unit id="_msg1050"> + <trans-unit id="_msg1051"> <source xml:space="preserve">Importing…</source> <context-group purpose="location"><context context-type="linenumber">221</context></context-group> </trans-unit> - <trans-unit id="_msg1051"> + <trans-unit id="_msg1052"> <source xml:space="preserve">Incorrect or no genesis block found. Wrong datadir for network?</source> <context-group purpose="location"><context context-type="linenumber">222</context></context-group> </trans-unit> - <trans-unit id="_msg1052"> + <trans-unit id="_msg1053"> <source xml:space="preserve">Initialization sanity check failed. %s is shutting down.</source> <context-group purpose="location"><context context-type="linenumber">223</context></context-group> </trans-unit> - <trans-unit id="_msg1053"> + <trans-unit id="_msg1054"> <source xml:space="preserve">Input not found or already spent</source> <context-group purpose="location"><context context-type="linenumber">224</context></context-group> </trans-unit> - <trans-unit id="_msg1054"> + <trans-unit id="_msg1055"> <source xml:space="preserve">Insufficient funds</source> <context-group purpose="location"><context context-type="linenumber">225</context></context-group> </trans-unit> - <trans-unit id="_msg1055"> + <trans-unit id="_msg1056"> <source xml:space="preserve">Invalid -i2psam address or hostname: '%s'</source> <context-group purpose="location"><context context-type="linenumber">226</context></context-group> </trans-unit> - <trans-unit id="_msg1056"> + <trans-unit id="_msg1057"> <source xml:space="preserve">Invalid -onion address or hostname: '%s'</source> <context-group purpose="location"><context context-type="linenumber">227</context></context-group> </trans-unit> - <trans-unit id="_msg1057"> + <trans-unit id="_msg1058"> <source xml:space="preserve">Invalid -proxy address or hostname: '%s'</source> <context-group purpose="location"><context context-type="linenumber">228</context></context-group> </trans-unit> - <trans-unit id="_msg1058"> + <trans-unit id="_msg1059"> <source xml:space="preserve">Invalid P2P permission: '%s'</source> <context-group purpose="location"><context context-type="linenumber">229</context></context-group> </trans-unit> - <trans-unit id="_msg1059"> + <trans-unit id="_msg1060"> <source xml:space="preserve">Invalid amount for -%s=<amount>: '%s'</source> <context-group purpose="location"><context context-type="linenumber">230</context></context-group> </trans-unit> - <trans-unit id="_msg1060"> + <trans-unit id="_msg1061"> <source xml:space="preserve">Invalid amount for -discardfee=<amount>: '%s'</source> <context-group purpose="location"><context context-type="linenumber">231</context></context-group> </trans-unit> - <trans-unit id="_msg1061"> + <trans-unit id="_msg1062"> <source xml:space="preserve">Invalid amount for -fallbackfee=<amount>: '%s'</source> <context-group purpose="location"><context context-type="linenumber">232</context></context-group> </trans-unit> - <trans-unit id="_msg1062"> + <trans-unit id="_msg1063"> <source xml:space="preserve">Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</source> <context-group purpose="location"><context context-type="linenumber">233</context></context-group> </trans-unit> - <trans-unit id="_msg1063"> + <trans-unit id="_msg1064"> <source xml:space="preserve">Invalid netmask specified in -whitelist: '%s'</source> <context-group purpose="location"><context context-type="linenumber">234</context></context-group> </trans-unit> - <trans-unit id="_msg1064"> + <trans-unit id="_msg1065"> <source xml:space="preserve">Listening for incoming connections failed (listen returned error %s)</source> <context-group purpose="location"><context context-type="linenumber">235</context></context-group> </trans-unit> - <trans-unit id="_msg1065"> + <trans-unit id="_msg1066"> <source xml:space="preserve">Loading P2P addresses…</source> <context-group purpose="location"><context context-type="linenumber">236</context></context-group> </trans-unit> - <trans-unit id="_msg1066"> + <trans-unit id="_msg1067"> <source xml:space="preserve">Loading banlist…</source> <context-group purpose="location"><context context-type="linenumber">237</context></context-group> </trans-unit> - <trans-unit id="_msg1067"> + <trans-unit id="_msg1068"> <source xml:space="preserve">Loading block index…</source> <context-group purpose="location"><context context-type="linenumber">238</context></context-group> </trans-unit> - <trans-unit id="_msg1068"> + <trans-unit id="_msg1069"> <source xml:space="preserve">Loading wallet…</source> <context-group purpose="location"><context context-type="linenumber">239</context></context-group> </trans-unit> - <trans-unit id="_msg1069"> + <trans-unit id="_msg1070"> <source xml:space="preserve">Missing amount</source> <context-group purpose="location"><context context-type="linenumber">240</context></context-group> </trans-unit> - <trans-unit id="_msg1070"> + <trans-unit id="_msg1071"> <source xml:space="preserve">Missing solving data for estimating transaction size</source> <context-group purpose="location"><context context-type="linenumber">241</context></context-group> </trans-unit> - <trans-unit id="_msg1071"> + <trans-unit id="_msg1072"> <source xml:space="preserve">Need to specify a port with -whitebind: '%s'</source> <context-group purpose="location"><context context-type="linenumber">242</context></context-group> </trans-unit> - <trans-unit id="_msg1072"> + <trans-unit id="_msg1073"> <source xml:space="preserve">No addresses available</source> <context-group purpose="location"><context context-type="linenumber">243</context></context-group> </trans-unit> - <trans-unit id="_msg1073"> + <trans-unit id="_msg1074"> <source xml:space="preserve">Not enough file descriptors available.</source> <context-group purpose="location"><context context-type="linenumber">244</context></context-group> </trans-unit> - <trans-unit id="_msg1074"> + <trans-unit id="_msg1075"> <source xml:space="preserve">Prune cannot be configured with a negative value.</source> <context-group purpose="location"><context context-type="linenumber">245</context></context-group> </trans-unit> - <trans-unit id="_msg1075"> + <trans-unit id="_msg1076"> <source xml:space="preserve">Prune mode is incompatible with -txindex.</source> <context-group purpose="location"><context context-type="linenumber">246</context></context-group> </trans-unit> - <trans-unit id="_msg1076"> + <trans-unit id="_msg1077"> <source xml:space="preserve">Pruning blockstore…</source> <context-group purpose="location"><context context-type="linenumber">247</context></context-group> </trans-unit> - <trans-unit id="_msg1077"> + <trans-unit id="_msg1078"> <source xml:space="preserve">Reducing -maxconnections from %d to %d, because of system limitations.</source> <context-group purpose="location"><context context-type="linenumber">248</context></context-group> </trans-unit> - <trans-unit id="_msg1078"> + <trans-unit id="_msg1079"> <source xml:space="preserve">Replaying blocks…</source> <context-group purpose="location"><context context-type="linenumber">249</context></context-group> </trans-unit> - <trans-unit id="_msg1079"> + <trans-unit id="_msg1080"> <source xml:space="preserve">Rescanning…</source> <context-group purpose="location"><context context-type="linenumber">250</context></context-group> </trans-unit> - <trans-unit id="_msg1080"> + <trans-unit id="_msg1081"> <source xml:space="preserve">SQLiteDatabase: Failed to execute statement to verify database: %s</source> <context-group purpose="location"><context context-type="linenumber">251</context></context-group> </trans-unit> - <trans-unit id="_msg1081"> + <trans-unit id="_msg1082"> <source xml:space="preserve">SQLiteDatabase: Failed to prepare statement to verify database: %s</source> <context-group purpose="location"><context context-type="linenumber">252</context></context-group> </trans-unit> - <trans-unit id="_msg1082"> + <trans-unit id="_msg1083"> <source xml:space="preserve">SQLiteDatabase: Failed to read database verification error: %s</source> <context-group purpose="location"><context context-type="linenumber">253</context></context-group> </trans-unit> - <trans-unit id="_msg1083"> + <trans-unit id="_msg1084"> <source xml:space="preserve">SQLiteDatabase: Unexpected application id. Expected %u, got %u</source> <context-group purpose="location"><context context-type="linenumber">254</context></context-group> </trans-unit> - <trans-unit id="_msg1084"> + <trans-unit id="_msg1085"> <source xml:space="preserve">Section [%s] is not recognized.</source> <context-group purpose="location"><context context-type="linenumber">255</context></context-group> </trans-unit> - <trans-unit id="_msg1085"> + <trans-unit id="_msg1086"> <source xml:space="preserve">Signing transaction failed</source> <context-group purpose="location"><context context-type="linenumber">256</context></context-group> </trans-unit> - <trans-unit id="_msg1086"> + <trans-unit id="_msg1087"> <source xml:space="preserve">Specified -walletdir "%s" does not exist</source> <context-group purpose="location"><context context-type="linenumber">257</context></context-group> </trans-unit> - <trans-unit id="_msg1087"> + <trans-unit id="_msg1088"> <source xml:space="preserve">Specified -walletdir "%s" is a relative path</source> <context-group purpose="location"><context context-type="linenumber">258</context></context-group> </trans-unit> - <trans-unit id="_msg1088"> + <trans-unit id="_msg1089"> <source xml:space="preserve">Specified -walletdir "%s" is not a directory</source> <context-group purpose="location"><context context-type="linenumber">259</context></context-group> </trans-unit> - <trans-unit id="_msg1089"> + <trans-unit id="_msg1090"> <source xml:space="preserve">Specified blocks directory "%s" does not exist.</source> <context-group purpose="location"><context context-type="linenumber">260</context></context-group> </trans-unit> - <trans-unit id="_msg1090"> + <trans-unit id="_msg1091"> <source xml:space="preserve">Starting network threads…</source> <context-group purpose="location"><context context-type="linenumber">261</context></context-group> </trans-unit> - <trans-unit id="_msg1091"> + <trans-unit id="_msg1092"> <source xml:space="preserve">The source code is available from %s.</source> <context-group purpose="location"><context context-type="linenumber">262</context></context-group> </trans-unit> - <trans-unit id="_msg1092"> + <trans-unit id="_msg1093"> <source xml:space="preserve">The specified config file %s does not exist</source> <context-group purpose="location"><context context-type="linenumber">263</context></context-group> </trans-unit> - <trans-unit id="_msg1093"> + <trans-unit id="_msg1094"> <source xml:space="preserve">The transaction amount is too small to pay the fee</source> <context-group purpose="location"><context context-type="linenumber">264</context></context-group> </trans-unit> - <trans-unit id="_msg1094"> + <trans-unit id="_msg1095"> <source xml:space="preserve">The wallet will avoid paying less than the minimum relay fee.</source> <context-group purpose="location"><context context-type="linenumber">265</context></context-group> </trans-unit> - <trans-unit id="_msg1095"> + <trans-unit id="_msg1096"> <source xml:space="preserve">This is experimental software.</source> <context-group purpose="location"><context context-type="linenumber">266</context></context-group> </trans-unit> - <trans-unit id="_msg1096"> + <trans-unit id="_msg1097"> <source xml:space="preserve">This is the minimum transaction fee you pay on every transaction.</source> <context-group purpose="location"><context context-type="linenumber">267</context></context-group> </trans-unit> - <trans-unit id="_msg1097"> + <trans-unit id="_msg1098"> <source xml:space="preserve">This is the transaction fee you will pay if you send a transaction.</source> <context-group purpose="location"><context context-type="linenumber">268</context></context-group> </trans-unit> - <trans-unit id="_msg1098"> + <trans-unit id="_msg1099"> <source xml:space="preserve">Transaction amount too small</source> <context-group purpose="location"><context context-type="linenumber">269</context></context-group> </trans-unit> - <trans-unit id="_msg1099"> + <trans-unit id="_msg1100"> <source xml:space="preserve">Transaction amounts must not be negative</source> <context-group purpose="location"><context context-type="linenumber">270</context></context-group> </trans-unit> - <trans-unit id="_msg1100"> + <trans-unit id="_msg1101"> <source xml:space="preserve">Transaction change output index out of range</source> <context-group purpose="location"><context context-type="linenumber">271</context></context-group> </trans-unit> - <trans-unit id="_msg1101"> + <trans-unit id="_msg1102"> <source xml:space="preserve">Transaction has too long of a mempool chain</source> <context-group purpose="location"><context context-type="linenumber">272</context></context-group> </trans-unit> - <trans-unit id="_msg1102"> + <trans-unit id="_msg1103"> <source xml:space="preserve">Transaction must have at least one recipient</source> <context-group purpose="location"><context context-type="linenumber">273</context></context-group> </trans-unit> - <trans-unit id="_msg1103"> + <trans-unit id="_msg1104"> <source xml:space="preserve">Transaction needs a change address, but we can't generate it.</source> <context-group purpose="location"><context context-type="linenumber">274</context></context-group> </trans-unit> - <trans-unit id="_msg1104"> + <trans-unit id="_msg1105"> <source xml:space="preserve">Transaction too large</source> <context-group purpose="location"><context context-type="linenumber">275</context></context-group> </trans-unit> - <trans-unit id="_msg1105"> + <trans-unit id="_msg1106"> <source xml:space="preserve">Unable to allocate memory for -maxsigcachesize: '%s' MiB</source> <context-group purpose="location"><context context-type="linenumber">276</context></context-group> </trans-unit> - <trans-unit id="_msg1106"> + <trans-unit id="_msg1107"> <source xml:space="preserve">Unable to bind to %s on this computer (bind returned error %s)</source> <context-group purpose="location"><context context-type="linenumber">277</context></context-group> </trans-unit> - <trans-unit id="_msg1107"> + <trans-unit id="_msg1108"> <source xml:space="preserve">Unable to bind to %s on this computer. %s is probably already running.</source> <context-group purpose="location"><context context-type="linenumber">278</context></context-group> </trans-unit> - <trans-unit id="_msg1108"> + <trans-unit id="_msg1109"> <source xml:space="preserve">Unable to create the PID file '%s': %s</source> <context-group purpose="location"><context context-type="linenumber">279</context></context-group> </trans-unit> - <trans-unit id="_msg1109"> + <trans-unit id="_msg1110"> <source xml:space="preserve">Unable to generate initial keys</source> <context-group purpose="location"><context context-type="linenumber">280</context></context-group> </trans-unit> - <trans-unit id="_msg1110"> + <trans-unit id="_msg1111"> <source xml:space="preserve">Unable to generate keys</source> <context-group purpose="location"><context context-type="linenumber">281</context></context-group> </trans-unit> - <trans-unit id="_msg1111"> + <trans-unit id="_msg1112"> <source xml:space="preserve">Unable to open %s for writing</source> <context-group purpose="location"><context context-type="linenumber">282</context></context-group> </trans-unit> - <trans-unit id="_msg1112"> + <trans-unit id="_msg1113"> <source xml:space="preserve">Unable to parse -maxuploadtarget: '%s'</source> <context-group purpose="location"><context context-type="linenumber">283</context></context-group> </trans-unit> - <trans-unit id="_msg1113"> + <trans-unit id="_msg1114"> <source xml:space="preserve">Unable to start HTTP server. See debug log for details.</source> <context-group purpose="location"><context context-type="linenumber">284</context></context-group> </trans-unit> - <trans-unit id="_msg1114"> + <trans-unit id="_msg1115"> <source xml:space="preserve">Unknown -blockfilterindex value %s.</source> <context-group purpose="location"><context context-type="linenumber">285</context></context-group> </trans-unit> - <trans-unit id="_msg1115"> + <trans-unit id="_msg1116"> <source xml:space="preserve">Unknown address type '%s'</source> <context-group purpose="location"><context context-type="linenumber">286</context></context-group> </trans-unit> - <trans-unit id="_msg1116"> + <trans-unit id="_msg1117"> <source xml:space="preserve">Unknown change type '%s'</source> <context-group purpose="location"><context context-type="linenumber">287</context></context-group> </trans-unit> - <trans-unit id="_msg1117"> + <trans-unit id="_msg1118"> <source xml:space="preserve">Unknown network specified in -onlynet: '%s'</source> <context-group purpose="location"><context context-type="linenumber">288</context></context-group> </trans-unit> - <trans-unit id="_msg1118"> + <trans-unit id="_msg1119"> <source xml:space="preserve">Unknown new rules activated (versionbit %i)</source> <context-group purpose="location"><context context-type="linenumber">289</context></context-group> </trans-unit> - <trans-unit id="_msg1119"> + <trans-unit id="_msg1120"> <source xml:space="preserve">Unsupported logging category %s=%s.</source> <context-group purpose="location"><context context-type="linenumber">290</context></context-group> </trans-unit> - <trans-unit id="_msg1120"> + <trans-unit id="_msg1121"> <source xml:space="preserve">User Agent comment (%s) contains unsafe characters.</source> <context-group purpose="location"><context context-type="linenumber">291</context></context-group> </trans-unit> - <trans-unit id="_msg1121"> + <trans-unit id="_msg1122"> <source xml:space="preserve">Verifying blocks…</source> <context-group purpose="location"><context context-type="linenumber">292</context></context-group> </trans-unit> - <trans-unit id="_msg1122"> + <trans-unit id="_msg1123"> <source xml:space="preserve">Verifying wallet(s)…</source> <context-group purpose="location"><context context-type="linenumber">293</context></context-group> </trans-unit> - <trans-unit id="_msg1123"> + <trans-unit id="_msg1124"> <source xml:space="preserve">Wallet needed to be rewritten: restart %s to complete</source> <context-group purpose="location"><context context-type="linenumber">294</context></context-group> </trans-unit> diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index a8133f481e..85a3c36f39 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -147,8 +147,6 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) { ui->setupUi(this); - m_balances.balance = -1; - // use a SingleColorIcon for the "out of sync warning" icon QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning")); ui->labelTransactionsStatus->setIcon(icon); @@ -177,8 +175,9 @@ void OverviewPage::handleTransactionClicked(const QModelIndex &index) void OverviewPage::setPrivacy(bool privacy) { m_privacy = privacy; - if (m_balances.balance != -1) { - setBalance(m_balances); + const auto& balances = walletModel->getCachedBalance(); + if (balances.balance != -1) { + setBalance(balances); } ui->listTransactions->setVisible(!m_privacy); @@ -197,7 +196,6 @@ OverviewPage::~OverviewPage() void OverviewPage::setBalance(const interfaces::WalletBalances& balances) { BitcoinUnit unit = walletModel->getOptionsModel()->getDisplayUnit(); - m_balances = balances; if (walletModel->wallet().isLegacy()) { if (walletModel->wallet().privateKeysDisabled()) { ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy)); @@ -276,14 +274,13 @@ void OverviewPage::setWalletModel(WalletModel *model) ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); // Keep up to date with wallet - interfaces::Wallet& wallet = model->wallet(); - interfaces::WalletBalances balances = wallet.getBalances(); - setBalance(balances); + setBalance(model->getCachedBalance()); connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance); connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit); - updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled()); + interfaces::Wallet& wallet = model->wallet(); + updateWatchOnlyLabels(wallet.haveWatchOnly() && !wallet.privateKeysDisabled()); connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) { updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled()); }); @@ -306,10 +303,10 @@ void OverviewPage::changeEvent(QEvent* e) void OverviewPage::updateDisplayUnit() { - if(walletModel && walletModel->getOptionsModel()) - { - if (m_balances.balance != -1) { - setBalance(m_balances); + if (walletModel && walletModel->getOptionsModel()) { + const auto& balances = walletModel->getCachedBalance(); + if (balances.balance != -1) { + setBalance(balances); } // Update txdelegate->unit with the current unit diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 058df1a8c5..56f45907db 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -52,7 +52,6 @@ private: Ui::OverviewPage *ui; ClientModel *clientModel; WalletModel *walletModel; - interfaces::WalletBalances m_balances; bool m_privacy{false}; const PlatformStyle* m_platform_style; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index bd44d12781..a75c1098a5 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -164,11 +164,9 @@ void SendCoinsDialog::setModel(WalletModel *_model) } } - interfaces::WalletBalances balances = _model->wallet().getBalances(); - setBalance(balances); connect(_model, &WalletModel::balanceChanged, this, &SendCoinsDialog::setBalance); - connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::updateDisplayUnit); - updateDisplayUnit(); + connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::refreshBalance); + refreshBalance(); // Coin Control connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::coinControlUpdateLabels); @@ -711,9 +709,9 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances) } } -void SendCoinsDialog::updateDisplayUnit() +void SendCoinsDialog::refreshBalance() { - setBalance(model->wallet().getBalances()); + setBalance(model->getCachedBalance()); ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); updateSmartFeeLabel(); } @@ -786,7 +784,7 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry) m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner(); // Calculate available amount to send. - CAmount amount = model->wallet().getAvailableBalance(*m_coin_control); + CAmount amount = model->getAvailableBalance(m_coin_control.get()); for (int i = 0; i < ui->entries->count(); ++i) { SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget()); if (e && !e->isHidden() && e != entry) { diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 400503d0c0..b58d4690a0 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -97,7 +97,7 @@ private Q_SLOTS: void on_buttonMinimizeFee_clicked(); void removeEntry(SendCoinsEntry* entry); void useAvailableBalance(SendCoinsEntry* entry); - void updateDisplayUnit(); + void refreshBalance(); void coinControlFeatureChanged(bool); void coinControlButtonClicked(); void coinControlChangeChecked(int); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index b8ae62ecab..b71dfb0e9f 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -129,6 +129,13 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st QVERIFY(text.indexOf(QString::fromStdString(expectError)) != -1); } +void CompareBalance(WalletModel& walletModel, CAmount expected_balance, QLabel* balance_label_to_check) +{ + BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit(); + QString balanceComparison = BitcoinUnits::formatWithUnit(unit, expected_balance, false, BitcoinUnits::SeparatorStyle::ALWAYS); + QCOMPARE(balance_label_to_check->text().trimmed(), balanceComparison); +} + //! Simple qt wallet tests. // // Test widgets can be debugged interactively calling show() on them and @@ -168,14 +175,14 @@ void TestGUI(interfaces::Node& node) if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false); CTxDestination dest = GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type); wallet->SetAddressBook(dest, "", "receive"); - wallet->SetLastBlockProcessed(105, node.context()->chainman->ActiveChain().Tip()->GetBlockHash()); + wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); } { WalletRescanReserver reserver(*wallet); reserver.reserve(); CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/false); QCOMPARE(result.status, CWallet::ScanResult::SUCCESS); - QCOMPARE(result.last_scanned_block, node.context()->chainman->ActiveChain().Tip()->GetBlockHash()); + QCOMPARE(result.last_scanned_block, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash())); QVERIFY(result.last_failed_block.IsNull()); } wallet->SetBroadcastTransactions(true); @@ -195,15 +202,10 @@ void TestGUI(interfaces::Node& node) sendCoinsDialog.setModel(&walletModel); transactionView.setModel(&walletModel); - { - // Check balance in send dialog - QLabel* balanceLabel = sendCoinsDialog.findChild<QLabel*>("labelBalance"); - QString balanceText = balanceLabel->text(); - BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit(); - CAmount balance = walletModel.wallet().getBalance(); - QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::SeparatorStyle::ALWAYS); - QCOMPARE(balanceText, balanceComparison); - } + // Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel. + walletModel.pollBalanceChanged(); + // Check balance in send dialog + CompareBalance(walletModel, walletModel.wallet().getBalance(), sendCoinsDialog.findChild<QLabel*>("labelBalance")); // Send two transactions, and verify they are added to transaction list. TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel(); @@ -223,12 +225,8 @@ void TestGUI(interfaces::Node& node) // Check current balance on OverviewPage OverviewPage overviewPage(platformStyle.get()); overviewPage.setWalletModel(&walletModel); - QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance"); - QString balanceText = balanceLabel->text().trimmed(); - BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit(); - CAmount balance = walletModel.wallet().getBalance(); - QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::SeparatorStyle::ALWAYS); - QCOMPARE(balanceText, balanceComparison); + walletModel.pollBalanceChanged(); // Manual balance polling update + CompareBalance(walletModel, walletModel.wallet().getBalance(), overviewPage.findChild<QLabel*>("labelBalance")); // Check Request Payment button ReceiveCoinsDialog receiveCoinsDialog(platformStyle.get()); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ac6c8bea46..c6f3f5b00c 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -67,6 +67,10 @@ WalletModel::~WalletModel() void WalletModel::startPollBalance() { + // Update the cached balance right away, so every view can make use of it, + // so them don't need to waste resources recalculating it. + pollBalanceChanged(); + // This timer will be fired repeatedly to update the balance // Since the QTimer::timeout is a private signal, it cannot be used // in the GUIUtil::ExceptionSafeConnect directly. @@ -120,12 +124,17 @@ void WalletModel::pollBalanceChanged() void WalletModel::checkBalanceChanged(const interfaces::WalletBalances& new_balances) { - if(new_balances.balanceChanged(m_cached_balances)) { + if (new_balances.balanceChanged(m_cached_balances)) { m_cached_balances = new_balances; Q_EMIT balanceChanged(new_balances); } } +interfaces::WalletBalances WalletModel::getCachedBalance() const +{ + return m_cached_balances; +} + void WalletModel::updateTransaction() { // Balance and number of transactions might have changed @@ -194,7 +203,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return DuplicateAddress; } - CAmount nBalance = m_wallet->getAvailableBalance(coinControl); + // If no coin was manually selected, use the cached balance + // Future: can merge this call with 'createTransaction'. + CAmount nBalance = getAvailableBalance(&coinControl); if(total > nBalance) { @@ -602,3 +613,8 @@ uint256 WalletModel::getLastBlockProcessed() const { return m_client_model ? m_client_model->getBestBlockHash() : uint256{}; } + +CAmount WalletModel::getAvailableBalance(const CCoinControl* control) +{ + return control && control->HasSelected() ? wallet().getAvailableBalance(*control) : getCachedBalance().balance; +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 0184fb8ec2..73dfe0386a 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -155,6 +155,13 @@ public: uint256 getLastBlockProcessed() const; + // Retrieve the cached wallet balance + interfaces::WalletBalances getCachedBalance() const; + + // If coin control has selected outputs, searches the total amount inside the wallet. + // Otherwise, uses the wallet's cached available balance. + CAmount getAvailableBalance(const wallet::CCoinControl* control); + private: std::unique_ptr<interfaces::Wallet> m_wallet; std::unique_ptr<interfaces::Handler> m_handler_unload; diff --git a/src/rest.cpp b/src/rest.cpp index 85815a9c8b..7f00db2222 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -784,14 +784,18 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std:: ChainstateManager* maybe_chainman = GetChainman(context, req); if (!maybe_chainman) return false; ChainstateManager& chainman = *maybe_chainman; + decltype(chainman.ActiveHeight()) active_height; + uint256 active_hash; { - auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool* mempool) { + auto process_utxos = [&vOutPoints, &outs, &hits, &active_height, &active_hash, &chainman](const CCoinsView& view, const CTxMemPool* mempool) EXCLUSIVE_LOCKS_REQUIRED(chainman.GetMutex()) { for (const COutPoint& vOutPoint : vOutPoints) { Coin coin; bool hit = (!mempool || !mempool->isSpent(vOutPoint)) && view.GetCoin(vOutPoint, coin); hits.push_back(hit); if (hit) outs.emplace_back(std::move(coin)); } + active_height = chainman.ActiveHeight(); + active_hash = chainman.ActiveTip()->GetBlockHash(); }; if (fCheckMemPool) { @@ -819,7 +823,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std:: // serialize data // use exact same output as mentioned in Bip64 CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); - ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs; + ssGetUTXOResponse << active_height << active_hash << bitmap << outs; std::string ssGetUTXOResponseString = ssGetUTXOResponse.str(); req->WriteHeader("Content-Type", "application/octet-stream"); @@ -829,7 +833,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std:: case RESTResponseFormat::HEX: { CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); - ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs; + ssGetUTXOResponse << active_height << active_hash << bitmap << outs; std::string strHex = HexStr(ssGetUTXOResponse) + "\n"; req->WriteHeader("Content-Type", "text/plain"); @@ -842,8 +846,8 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std:: // pack in some essentials // use more or less the same output as mentioned in Bip64 - objGetUTXOResponse.pushKV("chainHeight", chainman.ActiveChain().Height()); - objGetUTXOResponse.pushKV("chaintipHash", chainman.ActiveChain().Tip()->GetBlockHash().GetHex()); + objGetUTXOResponse.pushKV("chainHeight", active_height); + objGetUTXOResponse.pushKV("chaintipHash", active_hash.GetHex()); objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation); UniValue utxos(UniValue::VARR); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index ee287656b6..612dbbdacf 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -74,6 +74,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listsinceblock", 1, "target_confirmations" }, { "listsinceblock", 2, "include_watchonly" }, { "listsinceblock", 3, "include_removed" }, + { "listsinceblock", 4, "include_change" }, { "sendmany", 1, "amounts" }, { "sendmany", 2, "minconf" }, { "sendmany", 4, "subtractfeefrom" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 2902b35865..e9663d38b4 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -598,7 +598,6 @@ static RPCHelpMan getblocktemplate() std::string strMode = "template"; UniValue lpval = NullUniValue; std::set<std::string> setClientRules; - int64_t nMaxVersionPreVB = -1; CChainState& active_chainstate = chainman.ActiveChainstate(); CChain& active_chain = active_chainstate.m_chain; if (!request.params[0].isNull()) @@ -650,12 +649,6 @@ static RPCHelpMan getblocktemplate() const UniValue& v = aClientRules[i]; setClientRules.insert(v.get_str()); } - } else { - // NOTE: It is important that this NOT be read if versionbits is supported - const UniValue& uvMaxVersion = find_value(oparam, "maxversion"); - if (uvMaxVersion.isNum()) { - nMaxVersionPreVB = uvMaxVersion.getInt<int64_t>(); - } } } @@ -863,7 +856,6 @@ static RPCHelpMan getblocktemplate() if (setClientRules.find(vbinfo.name) == setClientRules.end()) { // Not supported by the client; make sure it's safe to proceed if (!vbinfo.gbt_force) { - // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name)); } } @@ -876,14 +868,6 @@ static RPCHelpMan getblocktemplate() result.pushKV("vbavailable", vbavailable); result.pushKV("vbrequired", int(0)); - if (nMaxVersionPreVB >= 2) { - // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here - // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks - // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated - // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated - aMutable.push_back("version/force"); - } - result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); result.pushKV("transactions", transactions); result.pushKV("coinbaseaux", aux); diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 9bcbe1ceef..434e106dad 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -644,7 +644,7 @@ public: assert(outscripts.size() == 1); subscripts.emplace_back(std::move(outscripts[0])); } - out = Merge(std::move(out), std::move(subprovider)); + out.Merge(std::move(subprovider)); std::vector<CPubKey> pubkeys; pubkeys.reserve(entries.size()); @@ -1472,6 +1472,10 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const } if (ctx == ParseScriptContext::TOP && Func("rawtr", expr)) { auto arg = Expr(expr); + if (expr.size()) { + error = strprintf("rawtr(): only one key expected."); + return nullptr; + } auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, error); if (!output_key) return nullptr; ++key_exp_index; diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp index c624a17628..a82a8b252a 100644 --- a/src/script/signingprovider.cpp +++ b/src/script/signingprovider.cpp @@ -77,20 +77,14 @@ bool FlatSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, Tapro return LookupHelper(tr_trees, output_key, builder); } -FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b) -{ - FlatSigningProvider ret; - ret.scripts = a.scripts; - ret.scripts.insert(b.scripts.begin(), b.scripts.end()); - ret.pubkeys = a.pubkeys; - ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end()); - ret.keys = a.keys; - ret.keys.insert(b.keys.begin(), b.keys.end()); - ret.origins = a.origins; - ret.origins.insert(b.origins.begin(), b.origins.end()); - ret.tr_trees = a.tr_trees; - ret.tr_trees.insert(b.tr_trees.begin(), b.tr_trees.end()); - return ret; +FlatSigningProvider& FlatSigningProvider::Merge(FlatSigningProvider&& b) +{ + scripts.merge(b.scripts); + pubkeys.merge(b.pubkeys); + keys.merge(b.keys); + origins.merge(b.origins); + tr_trees.merge(b.tr_trees); + return *this; } void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) diff --git a/src/script/signingprovider.h b/src/script/signingprovider.h index 792cc903f2..2d4234ea0b 100644 --- a/src/script/signingprovider.h +++ b/src/script/signingprovider.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_SCRIPT_SIGNINGPROVIDER_H #define BITCOIN_SCRIPT_SIGNINGPROVIDER_H +#include <attributes.h> #include <key.h> #include <pubkey.h> #include <script/keyorigin.h> @@ -85,9 +86,9 @@ struct FlatSigningProvider final : public SigningProvider bool GetKey(const CKeyID& keyid, CKey& key) const override; bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override; bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override; -}; -FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b); + FlatSigningProvider& Merge(FlatSigningProvider&& b) LIFETIMEBOUND; +}; /** Fillable signing provider that keeps keys in an address->secret map */ class FillableSigningProvider : public SigningProvider diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index 1eb4b373b4..d0ad037228 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -312,7 +312,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string& txdata.Init(spend, std::move(utxos), /*force=*/true); MutableTransactionSignatureCreator creator{spend, 0, CAmount{0}, &txdata, SIGHASH_DEFAULT}; SignatureData sigdata; - BOOST_CHECK_MESSAGE(ProduceSignature(Merge(keys_priv, script_provider), creator, spks[n], sigdata), prv); + BOOST_CHECK_MESSAGE(ProduceSignature(FlatSigningProvider{keys_priv}.Merge(FlatSigningProvider{script_provider}), creator, spks[n], sigdata), prv); } /* Infer a descriptor from the generated script, and verify its solvability and that it roundtrips. */ @@ -464,6 +464,31 @@ Check("sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGN CheckUnparsable("", "raw(asdf)", "Raw script is not hex"); // Invalid script CheckUnparsable("", "raw(Ü)#00000000", "Invalid characters in payload"); // Invalid chars + Check( + "rawtr(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/86'/1'/0'/1/*)#a5gn3t7k", + "rawtr(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/86'/1'/0'/1/*)#4ur3xhft", + "", + "rawtr([5a61ff8e/86'/1'/0']xpub6DtZpc9PRL2B6pwoNGysmHAaBofDmWv5S6KQEKKGPKhf5fV62ywDtSziSApYVK3JnYY5KUSgiCwiXW5wtd8z7LNBxT9Mu5sEro8itdGfTeA/1/*)#llheyd9x", + RANGE | HARDENED | XONLY_KEYS, + {{"51205172af752f057d543ce8e4a6f8dcf15548ec6be44041bfa93b72e191cfc8c1ee"}, {"51201b66f20b86f700c945ecb9ad9b0ad1662b73084e2bfea48bee02126350b8a5b1"}, {"512063e70f66d815218abcc2306aa930aaca07c5cde73b75127eb27b5e8c16b58a25"}}, + OutputType::BECH32M, + {{0x80000056, 0x80000001, 0x80000000, 1, 0}, {0x80000056, 0x80000001, 0x80000000, 1, 1}, {0x80000056, 0x80000001, 0x80000000, 1, 2}}); + + + Check( + "rawtr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", + "rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", + "rawtr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", + "rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", + SIGNABLE | XONLY_KEYS, + {{"5120a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd"}}, + OutputType::BECH32M); + + CheckUnparsable( + "", + "rawtr(xpub68FQ9imX6mCWacw6eNRjaa8q8ynnHmUd5i7MVR51ZMPP5JycyfVHSLQVFPHMYiTybWJnSBL2tCBpy6aJTR2DYrshWYfwAxs8SosGXd66d8/*, xpub69Mvq3QMipdvnd9hAyeTnT5jrkcBuLErV212nsGf3qr7JPWysc9HnNhCsazdzj1etSx28hPSE8D7DnceFbNdw4Kg8SyRfjE2HFLv1P8TSGc/*)", + "rawtr(): only one key expected."); + // A 2of4 but using a direct push rather than OP_2 CScript nonminimalmultisig; CKey keys[4]; diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp index 49b7d2003b..cb901b2259 100644 --- a/src/test/interfaces_tests.cpp +++ b/src/test/interfaces_tests.cpp @@ -17,6 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup) BOOST_AUTO_TEST_CASE(findBlock) { + LOCK(Assert(m_node.chainman)->GetMutex()); auto& chain = m_node.chain; const CChain& active = Assert(m_node.chainman)->ActiveChain(); @@ -61,6 +62,7 @@ BOOST_AUTO_TEST_CASE(findBlock) BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight) { + LOCK(Assert(m_node.chainman)->GetMutex()); auto& chain = m_node.chain; const CChain& active = Assert(m_node.chainman)->ActiveChain(); uint256 hash; @@ -73,6 +75,7 @@ BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight) BOOST_AUTO_TEST_CASE(findAncestorByHeight) { + LOCK(Assert(m_node.chainman)->GetMutex()); auto& chain = m_node.chain; const CChain& active = Assert(m_node.chainman)->ActiveChain(); uint256 hash; @@ -83,6 +86,7 @@ BOOST_AUTO_TEST_CASE(findAncestorByHeight) BOOST_AUTO_TEST_CASE(findAncestorByHash) { + LOCK(Assert(m_node.chainman)->GetMutex()); auto& chain = m_node.chain; const CChain& active = Assert(m_node.chainman)->ActiveChain(); int height = -1; @@ -94,7 +98,7 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash) BOOST_AUTO_TEST_CASE(findCommonAncestor) { auto& chain = m_node.chain; - const CChain& active = Assert(m_node.chainman)->ActiveChain(); + const CChain& active = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return Assert(m_node.chainman)->ActiveChain()); auto* orig_tip = active.Tip(); for (int i = 0; i < 10; ++i) { BlockValidationState state; diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index fda56ccff7..70e2f89e0b 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -249,6 +249,22 @@ BOOST_AUTO_TEST_CASE(util_Join) BOOST_CHECK_EQUAL(Join<std::string>({"foo", "bar"}, ", ", op_upper), "FOO, BAR"); } +BOOST_AUTO_TEST_CASE(util_ReplaceAll) +{ + const std::string original("A test \"%s\" string '%s'."); + auto test_replaceall = [&original](const std::string& search, const std::string& substitute, const std::string& expected) { + auto test = original; + ReplaceAll(test, search, substitute); + BOOST_CHECK_EQUAL(test, expected); + }; + + test_replaceall("", "foo", original); + test_replaceall(original, "foo", "foo"); + test_replaceall("%s", "foo", "A test \"foo\" string 'foo'."); + test_replaceall("\"", "foo", "A test foo%sfoo string '%s'."); + test_replaceall("'", "foo", "A test \"%s\" string foo%sfoo."); +} + BOOST_AUTO_TEST_CASE(util_TrimString) { BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar"); diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 7ade4d8195..7a82e1a736 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -234,7 +234,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) // Run the test multiple times for (int test_runs = 3; test_runs > 0; --test_runs) { - BOOST_CHECK_EQUAL(last_mined->GetHash(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); + BOOST_CHECK_EQUAL(last_mined->GetHash(), WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockHash())); // Later on split from here const uint256 split_hash{last_mined->hashPrevBlock}; @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) ProcessBlock(b); } // Check that the reorg was eventually successful - BOOST_CHECK_EQUAL(last_mined->GetHash(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); + BOOST_CHECK_EQUAL(last_mined->GetHash(), WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockHash())); // We can join the other thread, which returns when the reorg was successful rpc_thread.join(); @@ -325,6 +325,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) BOOST_AUTO_TEST_CASE(witness_commitment_index) { + LOCK(Assert(m_node.chainman)->GetMutex()); CScript pubKey; pubKey << 1 << OP_TRUE; auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get()}.CreateNewBlock(pubKey); diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 14de96ff41..7b7bd05b5c 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -49,12 +49,12 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) auto all = manager.GetAll(); BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end()); - auto& active_chain = manager.ActiveChain(); + auto& active_chain = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain()); BOOST_CHECK_EQUAL(&active_chain, &c1.m_chain); - BOOST_CHECK_EQUAL(manager.ActiveHeight(), -1); + BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), -1); - auto active_tip = manager.ActiveTip(); + auto active_tip = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip()); auto exp_tip = c1.m_chain.Tip(); BOOST_CHECK_EQUAL(active_tip, exp_tip); @@ -84,12 +84,12 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) auto all2 = manager.GetAll(); BOOST_CHECK_EQUAL_COLLECTIONS(all2.begin(), all2.end(), chainstates.begin(), chainstates.end()); - auto& active_chain2 = manager.ActiveChain(); + auto& active_chain2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain()); BOOST_CHECK_EQUAL(&active_chain2, &c2.m_chain); - BOOST_CHECK_EQUAL(manager.ActiveHeight(), 0); + BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 0); - auto active_tip2 = manager.ActiveTip(); + auto active_tip2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip()); auto exp_tip2 = c2.m_chain.Tip(); BOOST_CHECK_EQUAL(active_tip2, exp_tip2); @@ -236,7 +236,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup) BOOST_CHECK(WITH_LOCK(::cs_main, return !chainman.ActiveChain().Genesis()->IsAssumedValid())); const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params()); - const CBlockIndex* tip = chainman.ActiveTip(); + const CBlockIndex* tip = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip()); BOOST_CHECK_EQUAL(tip->nChainTx, au_data.nChainTx); @@ -335,7 +335,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup) const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid; CBlockIndex* validated_tip{nullptr}; - CBlockIndex* assumed_tip{chainman.ActiveChain().Tip()}; + CBlockIndex* assumed_tip{WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip())}; auto reload_all_block_indexes = [&]() { for (CChainState* cs : chainman.GetAll()) { diff --git a/src/util/string.cpp b/src/util/string.cpp index dff782c330..db6dbe4135 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -4,11 +4,12 @@ #include <util/string.h> -#include <boost/algorithm/string/replace.hpp> - +#include <regex> #include <string> +#include <utility> -void ReplaceAll(std::string& in_out, std::string_view search, std::string_view substitute) +void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute) { - boost::replace_all(in_out, search, substitute); + if (search.empty()) return; + in_out = std::regex_replace(in_out, std::regex(std::move(search)), substitute); } diff --git a/src/util/string.h b/src/util/string.h index df20e34ae9..dd4de888bb 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -17,7 +17,7 @@ #include <string_view> #include <vector> -void ReplaceAll(std::string& in_out, std::string_view search, std::string_view substitute); +void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute); [[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, char sep) { diff --git a/src/validation.h b/src/validation.h index 17286c7910..324074aee9 100644 --- a/src/validation.h +++ b/src/validation.h @@ -868,6 +868,19 @@ public: const CChainParams& GetParams() const { return m_chainparams; } const Consensus::Params& GetConsensus() const { return m_chainparams.GetConsensus(); } + /** + * Alias for ::cs_main. + * Should be used in new code to make it easier to make ::cs_main a member + * of this class. + * Generally, methods of this class should be annotated to require this + * mutex. This will make calling code more verbose, but also help to: + * - Clarify that the method will acquire a mutex that heavily affects + * overall performance. + * - Force call sites to think how long they need to acquire the mutex to + * get consistent results. + */ + RecursiveMutex& GetMutex() const LOCK_RETURNED(::cs_main) { return ::cs_main; } + std::thread m_load_block; //! A single BlockManager instance is shared across each constructed //! chainstate to avoid duplicating block metadata. @@ -938,9 +951,9 @@ public: //! The most-work chain. CChainState& ActiveChainstate() const; - CChain& ActiveChain() const { return ActiveChainstate().m_chain; } - int ActiveHeight() const { return ActiveChain().Height(); } - CBlockIndex* ActiveTip() const { return ActiveChain().Tip(); } + CChain& ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChainstate().m_chain; } + int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChain().Height(); } + CBlockIndex* ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChain().Tip(); } node::BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { diff --git a/src/wallet/receive.cpp b/src/wallet/receive.cpp index 944925d600..db169aad12 100644 --- a/src/wallet/receive.cpp +++ b/src/wallet/receive.cpp @@ -193,7 +193,8 @@ CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx, std::list<COutputEntry>& listReceived, - std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) + std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter, + bool include_change) { nFee = 0; listReceived.clear(); @@ -218,8 +219,7 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx, // 2) the output is to us (received) if (nDebit > 0) { - // Don't report 'change' txouts - if (OutputIsChange(wallet, txout)) + if (!include_change && OutputIsChange(wallet, txout)) continue; } else if (!(fIsMine & filter)) diff --git a/src/wallet/receive.h b/src/wallet/receive.h index 41a70b089a..9125b1e9aa 100644 --- a/src/wallet/receive.h +++ b/src/wallet/receive.h @@ -42,7 +42,8 @@ struct COutputEntry void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx, std::list<COutputEntry>& listReceived, std::list<COutputEntry>& listSent, - CAmount& nFee, const isminefilter& filter); + CAmount& nFee, const isminefilter& filter, + bool include_change); bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter); bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx); diff --git a/src/wallet/rpc/coins.cpp b/src/wallet/rpc/coins.cpp index d40d800f28..50766f20eb 100644 --- a/src/wallet/rpc/coins.cpp +++ b/src/wallet/rpc/coins.cpp @@ -543,6 +543,9 @@ RPCHelpMan listunspent() {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"}, {RPCResult::Type::BOOL, "reused", /*optional=*/true, "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"}, {RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"}, + {RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the scriptPubKey of this coin.", { + {RPCResult::Type::STR, "desc", "The descriptor string."}, + }}, {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n" "from outside keys and unconfirmed replacement transactions are considered unsafe\n" "and are not eligible for spending by fundrawtransaction and sendtoaddress."}, @@ -638,7 +641,7 @@ RPCHelpMan listunspent() cctl.m_max_depth = nMaxDepth; cctl.m_include_unsafe_inputs = include_unsafe; LOCK(pwallet->cs_wallet); - vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount).all(); + vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount).All(); } LOCK(pwallet->cs_wallet); @@ -722,6 +725,7 @@ RPCHelpMan listunspent() entry.pushKV("desc", descriptor->ToString()); } } + PushParentDescriptors(*pwallet, scriptPubKey, entry); if (avoid_reuse) entry.pushKV("reused", reused); entry.pushKV("safe", out.safe); results.push_back(entry); diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index 628bf3cc99..8bbb862a7b 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -226,8 +226,8 @@ RPCHelpMan sendtoaddress() "The recipient will receive less bitcoins than you enter in the amount field."}, {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"}, - {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n" - " \"" + FeeModes("\"\n\"") + "\""}, + {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" + "\"" + FeeModes("\"\n\"") + "\""}, {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true}, "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n" "dirty if they have previously been used in a transaction. If true, this also activates avoidpartialspends, grouping outputs by their addresses."}, {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, @@ -335,8 +335,8 @@ RPCHelpMan sendmany() }, {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"}, {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"}, - {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n" - " \"" + FeeModes("\"\n\"") + "\""}, + {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" + "\"" + FeeModes("\"\n\"") + "\""}, {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra infomration about the transaction."}, }, @@ -451,8 +451,8 @@ static std::vector<RPCArg> FundTxDoc(bool solving_data = true) { std::vector<RPCArg> args = { {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"}, - {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n" - " \"" + FeeModes("\"\n\"") + "\""}, + {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" + "\"" + FeeModes("\"\n\"") + "\""}, { "replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Marks this transaction as BIP125-replaceable.\n" "Allows this transaction to be replaced by a transaction with higher fees" @@ -644,7 +644,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out, throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to parse descriptor '%s': %s", desc_str, error)); } desc->Expand(0, desc_out, scripts_temp, desc_out); - coinControl.m_external_provider = Merge(coinControl.m_external_provider, desc_out); + coinControl.m_external_provider.Merge(std::move(desc_out)); } } } @@ -967,7 +967,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) "still be replaceable in practice, for example if it has unconfirmed ancestors which\n" "are replaceable).\n"}, {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" - "\"" + FeeModes("\"\n\"") + "\""}, + "\"" + FeeModes("\"\n\"") + "\""}, }, "options"}, }, @@ -1131,8 +1131,8 @@ RPCHelpMan send() }, }, {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"}, - {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n" - " \"" + FeeModes("\"\n\"") + "\""}, + {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" + "\"" + FeeModes("\"\n\"") + "\""}, {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "", Cat<std::vector<RPCArg>>( @@ -1252,8 +1252,8 @@ RPCHelpMan sendall() }, }, {"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"}, - {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n" - " \"" + FeeModes("\"\n\"") + "\""}, + {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" + "\"" + FeeModes("\"\n\"") + "\""}, {"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."}, { "options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "", @@ -1382,7 +1382,7 @@ RPCHelpMan sendall() total_input_value += tx->tx->vout[input.prevout.n].nValue; } } else { - for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, /*nMinimumAmount=*/0).all()) { + for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, /*nMinimumAmount=*/0).All()) { CHECK_NONFATAL(output.input_bytes > 0); if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) { continue; diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp index 9c8003d6d7..a0769d3ecb 100644 --- a/src/wallet/rpc/transactions.cpp +++ b/src/wallet/rpc/transactions.cpp @@ -315,13 +315,16 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest) * @param filter_label Optional label string to filter incoming transactions. */ template <class Vec> -static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) +static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, + Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label, + bool include_change = false) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { CAmount nFee; std::list<COutputEntry> listReceived; std::list<COutputEntry> listSent; - CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine); + CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine, include_change); bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY); @@ -367,6 +370,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM entry.pushKV("involvesWatchonly", true); } MaybePushAddress(entry, r.destination); + PushParentDescriptors(wallet, wtx.tx->vout.at(r.vout).scriptPubKey, entry); if (wtx.IsCoinBase()) { if (wallet.GetTxDepthInMainChain(wtx) < 1) @@ -418,7 +422,11 @@ static const std::vector<RPCResult> TransactionDescriptionString() {RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."}, {RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction, only present if not empty."}, {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" - "may be unknown for unconfirmed transactions not in the mempool."}}; + "may be unknown for unconfirmed transactions not in the mempool."}, + {RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin.", { + {RPCResult::Type::STR, "desc", "The descriptor string."}, + }}, + }; } RPCHelpMan listtransactions() @@ -543,6 +551,7 @@ RPCHelpMan listsinceblock() {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Include transactions to watch-only addresses (see 'importaddress')"}, {"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n" "(not guaranteed to work on pruned nodes)"}, + {"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"}, }, RPCResult{ RPCResult::Type::OBJ, "", "", @@ -623,6 +632,7 @@ RPCHelpMan listsinceblock() } bool include_removed = (request.params[3].isNull() || request.params[3].get_bool()); + bool include_change = (!request.params[4].isNull() && request.params[4].get_bool()); int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1; @@ -632,7 +642,7 @@ RPCHelpMan listsinceblock() const CWalletTx& tx = pairWtx.second; if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) { - ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */); + ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */, /*include_change=*/include_change); } } @@ -649,7 +659,7 @@ RPCHelpMan listsinceblock() if (it != wallet.mapWallet.end()) { // We want all transactions regardless of confirmation count to appear here, // even negative confirmation ones, hence the big negative. - ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */); + ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */, /*include_change=*/include_change); } } blockId = block.hashPrevBlock; @@ -709,6 +719,9 @@ RPCHelpMan gettransaction() "'send' category of transactions."}, {RPCResult::Type::BOOL, "abandoned", /*optional=*/true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" "'send' category of transactions."}, + {RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin.", { + {RPCResult::Type::STR, "desc", "The descriptor string."}, + }}, }}, }}, {RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"}, diff --git a/src/wallet/rpc/util.cpp b/src/wallet/rpc/util.cpp index 4fcb393226..3c1634324e 100644 --- a/src/wallet/rpc/util.cpp +++ b/src/wallet/rpc/util.cpp @@ -64,12 +64,11 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques return pwallet; } - std::vector<std::shared_ptr<CWallet>> wallets = GetWallets(context); - if (wallets.size() == 1) { - return wallets[0]; - } + size_t count{0}; + auto wallet = GetDefaultWallet(context, count); + if (wallet) return wallet; - if (wallets.empty()) { + if (count == 0) { throw JSONRPCError( RPC_WALLET_NOT_FOUND, "No wallet is loaded. Load a wallet using loadwallet or create a new one with createwallet. (Note: A default wallet is no longer automatically created)"); } @@ -123,6 +122,15 @@ std::string LabelFromValue(const UniValue& value) return label; } +void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry) +{ + UniValue parent_descs(UniValue::VARR); + for (const auto& desc: wallet.GetWalletDescriptors(script_pubkey)) { + parent_descs.push_back(desc.descriptor->ToString()); + } + entry.pushKV("parent_descs", parent_descs); +} + void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error) { if (!wallet) { diff --git a/src/wallet/rpc/util.h b/src/wallet/rpc/util.h index 7b810eb06e..2ca28914e7 100644 --- a/src/wallet/rpc/util.h +++ b/src/wallet/rpc/util.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_WALLET_RPC_UTIL_H #define BITCOIN_WALLET_RPC_UTIL_H +#include <script/script.h> + #include <any> #include <memory> #include <string> @@ -39,6 +41,8 @@ const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wal bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param); bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet); std::string LabelFromValue(const UniValue& value); +//! Fetch parent descriptors of this scriptPubKey. +void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry); void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error); } // namespace wallet diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index 7ff017775e..8d40846332 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -1965,6 +1965,11 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_ desc_prefix = "tr(" + xpub + "/86'"; break; } + case OutputType::UNKNOWN: { + // We should never have a DescriptorScriptPubKeyMan for an UNKNOWN OutputType, + // so if we get to this point something is wrong + assert(false); + } } // no default case, so the compiler can warn about missing cases assert(!desc_prefix.empty()); @@ -2080,7 +2085,7 @@ std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvid // Fetch SigningProvider from cache to avoid re-deriving auto it = m_map_signing_providers.find(index); if (it != m_map_signing_providers.end()) { - *out_keys = Merge(*out_keys, it->second); + out_keys->Merge(FlatSigningProvider{it->second}); } else { // Get the scripts, keys, and key origins for this script std::vector<CScript> scripts_temp; @@ -2117,7 +2122,7 @@ bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const s if (!coin_keys) { continue; } - *keys = Merge(*keys, *coin_keys); + keys->Merge(std::move(*coin_keys)); } return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors); @@ -2178,7 +2183,7 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>(); std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, sign); if (script_keys) { - *keys = Merge(*keys, *script_keys); + keys->Merge(std::move(*script_keys)); } else { // Maybe there are pubkeys listed that we can sign for script_keys = std::make_unique<FlatSigningProvider>(); @@ -2186,7 +2191,7 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& const CPubKey& pubkey = pk_pair.first; std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey); if (pk_keys) { - *keys = Merge(*keys, *pk_keys); + keys->Merge(std::move(*pk_keys)); } } for (const auto& pk_pair : input.m_tap_bip32_paths) { @@ -2198,7 +2203,7 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& fullpubkey.Set(b, b + 33); std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(fullpubkey); if (pk_keys) { - *keys = Merge(*keys, *pk_keys); + keys->Merge(std::move(*pk_keys)); } } } diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 61d86844df..001acd04e2 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -79,30 +79,68 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle return CalculateMaximumSignedTxSize(tx, wallet, txouts, coin_control); } -uint64_t CoinsResult::size() const +size_t CoinsResult::Size() const { - return bech32m.size() + bech32.size() + P2SH_segwit.size() + legacy.size() + other.size(); + size_t size{0}; + for (const auto& it : coins) { + size += it.second.size(); + } + return size; } -std::vector<COutput> CoinsResult::all() const +std::vector<COutput> CoinsResult::All() const { std::vector<COutput> all; - all.reserve(this->size()); - all.insert(all.end(), bech32m.begin(), bech32m.end()); - all.insert(all.end(), bech32.begin(), bech32.end()); - all.insert(all.end(), P2SH_segwit.begin(), P2SH_segwit.end()); - all.insert(all.end(), legacy.begin(), legacy.end()); - all.insert(all.end(), other.begin(), other.end()); + all.reserve(coins.size()); + for (const auto& it : coins) { + all.insert(all.end(), it.second.begin(), it.second.end()); + } return all; } -void CoinsResult::clear() +void CoinsResult::Clear() { + coins.clear(); +} + +void CoinsResult::Erase(std::set<COutPoint>& preset_coins) { - bech32m.clear(); - bech32.clear(); - P2SH_segwit.clear(); - legacy.clear(); - other.clear(); + 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; + } + } +} + +void CoinsResult::Shuffle(FastRandomContext& rng_fast) +{ + for (auto& it : coins) { + ::Shuffle(it.second.begin(), it.second.end(), rng_fast); + } +} + +void CoinsResult::Add(OutputType type, const COutput& out) +{ + coins[type].emplace_back(out); +} + +static OutputType GetOutputType(TxoutType type, bool is_from_p2sh) +{ + switch (type) { + case TxoutType::WITNESS_V1_TAPROOT: + return OutputType::BECH32M; + case TxoutType::WITNESS_V0_KEYHASH: + case TxoutType::WITNESS_V0_SCRIPTHASH: + if (is_from_p2sh) return OutputType::P2SH_SEGWIT; + else return OutputType::BECH32; + case TxoutType::SCRIPTHASH: + case TxoutType::PUBKEYHASH: + return OutputType::LEGACY; + default: + return OutputType::UNKNOWN; + } } CoinsResult AvailableCoins(const CWallet& wallet, @@ -222,51 +260,32 @@ CoinsResult AvailableCoins(const CWallet& wallet, // Filter by spendable outputs only if (!spendable && only_spendable) continue; - // When parsing a scriptPubKey, Solver returns the parsed pubkeys or hashes (depending on the script) - // We don't need those here, so we are leaving them in return_values_unused - std::vector<std::vector<uint8_t>> return_values_unused; - TxoutType type; - bool is_from_p2sh{false}; - // If the Output is P2SH and spendable, we want to know if it is // a P2SH (legacy) or one of P2SH-P2WPKH, P2SH-P2WSH (P2SH-Segwit). We can determine // this from the redeemScript. If the Output is not spendable, it will be classified // as a P2SH (legacy), since we have no way of knowing otherwise without the redeemScript + CScript script; + bool is_from_p2sh{false}; if (output.scriptPubKey.IsPayToScriptHash() && solvable) { - CScript redeemScript; CTxDestination destination; if (!ExtractDestination(output.scriptPubKey, destination)) continue; const CScriptID& hash = CScriptID(std::get<ScriptHash>(destination)); - if (!provider->GetCScript(hash, redeemScript)) + if (!provider->GetCScript(hash, script)) continue; - type = Solver(redeemScript, return_values_unused); is_from_p2sh = true; } else { - type = Solver(output.scriptPubKey, return_values_unused); + script = output.scriptPubKey; } COutput coin(outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate); - switch (type) { - case TxoutType::WITNESS_UNKNOWN: - case TxoutType::WITNESS_V1_TAPROOT: - result.bech32m.push_back(coin); - break; - case TxoutType::WITNESS_V0_KEYHASH: - case TxoutType::WITNESS_V0_SCRIPTHASH: - if (is_from_p2sh) { - result.P2SH_segwit.push_back(coin); - break; - } - result.bech32.push_back(coin); - break; - case TxoutType::SCRIPTHASH: - case TxoutType::PUBKEYHASH: - result.legacy.push_back(coin); - break; - default: - result.other.push_back(coin); - }; + + // When parsing a scriptPubKey, Solver returns the parsed pubkeys or hashes (depending on the script) + // We don't need those here, so we are leaving them in return_values_unused + std::vector<std::vector<uint8_t>> return_values_unused; + TxoutType type; + type = Solver(script, return_values_unused); + result.Add(GetOutputType(type, is_from_p2sh), coin); // Cache total amount as we go result.total_amount += output.nValue; @@ -278,7 +297,7 @@ CoinsResult AvailableCoins(const CWallet& wallet, } // Checks the maximum number of UTXO's. - if (nMaximumCount > 0 && result.size() >= nMaximumCount) { + if (nMaximumCount > 0 && result.Size() >= nMaximumCount) { return result; } } @@ -334,7 +353,7 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet) std::map<CTxDestination, std::vector<COutput>> result; - for (const COutput& coin : AvailableCoinsListUnspent(wallet).all()) { + for (const COutput& coin : AvailableCoinsListUnspent(wallet).All()) { CTxDestination address; if ((coin.spendable || (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.solvable)) && ExtractDestination(FindNonChangeParentOutput(wallet, coin.outpoint).scriptPubKey, address)) { @@ -457,31 +476,25 @@ std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAm { // Run coin selection on each OutputType and compute the Waste Metric std::vector<SelectionResult> results; - if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.legacy, coin_selection_params)}) { - results.push_back(*result); - } - if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.P2SH_segwit, coin_selection_params)}) { - results.push_back(*result); - } - if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.bech32, coin_selection_params)}) { - results.push_back(*result); - } - if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.bech32m, coin_selection_params)}) { - results.push_back(*result); + for (const auto& it : available_coins.coins) { + if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, it.second, coin_selection_params)}) { + results.push_back(*result); + } } - - // If we can't fund the transaction from any individual OutputType, run coin selection - // over all available coins, else pick the best solution from the results - if (results.size() == 0) { - if (allow_mixed_output_types) { - if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.all(), coin_selection_params)}) { - return result; - } + // If we have at least one solution for funding the transaction without mixing, choose the minimum one according to waste metric + // and return the result + if (results.size() > 0) return *std::min_element(results.begin(), results.end()); + + // If we can't fund the transaction from any individual OutputType, run coin selection one last time + // over all available coins, which would allow mixing + if (allow_mixed_output_types) { + if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.All(), coin_selection_params)}) { + return result; } - return std::optional<SelectionResult>(); - }; - std::optional<SelectionResult> result{*std::min_element(results.begin(), results.end())}; - return result; + } + // Either mixing is not allowed and we couldn't find a solution from any single OutputType, or mixing was allowed and we still couldn't + // find a solution using all available coins + return std::nullopt; }; std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins, const CoinSelectionParams& coin_selection_params) @@ -556,8 +569,12 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a if (!coin_control.GetExternalOutput(outpoint, txout)) { return std::nullopt; } + } + + if (input_bytes == -1) { input_bytes = CalculateMaximumSignedInputSize(txout, outpoint, &coin_control.m_external_provider, &coin_control); } + // If available, override calculated size with coin control specified size if (coin_control.HasInputWeight(outpoint)) { input_bytes = GetVirtualTransactionSize(coin_control.GetInputWeight(outpoint), 0, 0); @@ -592,11 +609,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a // remove preset inputs from coins so that Coin Selection doesn't pick them. if (coin_control.HasSelected()) { - available_coins.legacy.erase(remove_if(available_coins.legacy.begin(), available_coins.legacy.end(), [&](const COutput& c) { return preset_coins.count(c.outpoint); }), available_coins.legacy.end()); - available_coins.P2SH_segwit.erase(remove_if(available_coins.P2SH_segwit.begin(), available_coins.P2SH_segwit.end(), [&](const COutput& c) { return preset_coins.count(c.outpoint); }), available_coins.P2SH_segwit.end()); - available_coins.bech32.erase(remove_if(available_coins.bech32.begin(), available_coins.bech32.end(), [&](const COutput& c) { return preset_coins.count(c.outpoint); }), available_coins.bech32.end()); - available_coins.bech32m.erase(remove_if(available_coins.bech32m.begin(), available_coins.bech32m.end(), [&](const COutput& c) { return preset_coins.count(c.outpoint); }), available_coins.bech32m.end()); - available_coins.other.erase(remove_if(available_coins.other.begin(), available_coins.other.end(), [&](const COutput& c) { return preset_coins.count(c.outpoint); }), available_coins.other.end()); + available_coins.Erase(preset_coins); } unsigned int limit_ancestor_count = 0; @@ -608,15 +621,11 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a // form groups from remaining coins; note that preset coins will not // automatically have their associated (same address) coins included - if (coin_control.m_avoid_partial_spends && available_coins.size() > OUTPUT_GROUP_MAX_ENTRIES) { + if (coin_control.m_avoid_partial_spends && available_coins.Size() > OUTPUT_GROUP_MAX_ENTRIES) { // Cases where we have 101+ outputs all pointing to the same destination may result in // privacy leaks as they will potentially be deterministically sorted. We solve that by // explicitly shuffling the outputs before processing - Shuffle(available_coins.legacy.begin(), available_coins.legacy.end(), coin_selection_params.rng_fast); - Shuffle(available_coins.P2SH_segwit.begin(), available_coins.P2SH_segwit.end(), coin_selection_params.rng_fast); - Shuffle(available_coins.bech32.begin(), available_coins.bech32.end(), coin_selection_params.rng_fast); - Shuffle(available_coins.bech32m.begin(), available_coins.bech32m.end(), coin_selection_params.rng_fast); - Shuffle(available_coins.other.begin(), available_coins.other.end(), coin_selection_params.rng_fast); + available_coins.Shuffle(coin_selection_params.rng_fast); } // Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the @@ -1122,12 +1131,16 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet, wallet.chain().findCoins(coins); for (const CTxIn& txin : tx.vin) { - // if it's not in the wallet and corresponding UTXO is found than select as external output const auto& outPoint = txin.prevout; - if (wallet.mapWallet.find(outPoint.hash) == wallet.mapWallet.end() && !coins[outPoint].out.IsNull()) { - coinControl.SelectExternal(outPoint, coins[outPoint].out); - } else { + if (wallet.IsMine(outPoint)) { + // The input was found in the wallet, so select as internal coinControl.Select(outPoint); + } else if (coins[outPoint].out.IsNull()) { + error = _("Unable to find UTXO for external input"); + return false; + } else { + // The input was not in the wallet, but is in the UTXO set, so select as external + coinControl.SelectExternal(outPoint, coins[outPoint].out); } } diff --git a/src/wallet/spend.h b/src/wallet/spend.h index fdb5113ba4..c29e5be5c7 100644 --- a/src/wallet/spend.h +++ b/src/wallet/spend.h @@ -34,26 +34,22 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* walle * This struct is really just a wrapper around OutputType vectors with a convenient * method for concatenating and returning all COutputs as one vector. * - * clear(), size() methods are implemented so that one can interact with - * the CoinsResult struct as if it was a vector + * Size(), Clear(), Erase(), Shuffle(), and Add() methods are implemented to + * allow easy interaction with the struct. */ struct CoinsResult { - /** Vectors for each OutputType */ - std::vector<COutput> legacy; - std::vector<COutput> P2SH_segwit; - std::vector<COutput> bech32; - std::vector<COutput> bech32m; - - /** Other is a catch-all for anything that doesn't match the known OutputTypes */ - std::vector<COutput> other; + std::map<OutputType, std::vector<COutput>> coins; /** Concatenate and return all COutputs as one vector */ - std::vector<COutput> all() const; + std::vector<COutput> All() const; /** The following methods are provided so that CoinsResult can mimic a vector, * i.e., methods can work with individual OutputType vectors or on the entire object */ - uint64_t size() const; - void clear(); + size_t Size() const; + void Clear(); + void Erase(std::set<COutPoint>& preset_coins); + void Shuffle(FastRandomContext& rng_fast); + void Add(OutputType type, const COutput& out); /** Sum of all available coins */ CAmount total_amount{0}; diff --git a/src/wallet/test/availablecoins_tests.cpp b/src/wallet/test/availablecoins_tests.cpp index 3356128112..2427a343d5 100644 --- a/src/wallet/test/availablecoins_tests.cpp +++ b/src/wallet/test/availablecoins_tests.cpp @@ -44,6 +44,7 @@ public: CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); LOCK(wallet->cs_wallet); + LOCK(m_node.chainman->GetMutex()); wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash()); auto it = wallet->mapWallet.find(tx->GetHash()); BOOST_CHECK(it != wallet->mapWallet.end()); @@ -63,8 +64,8 @@ BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, AvailableCoinsTestingSetup) // Verify our wallet has one usable coinbase UTXO before starting // This UTXO is a P2PK, so it should show up in the Other bucket available_coins = AvailableCoins(*wallet); - BOOST_CHECK_EQUAL(available_coins.size(), 1U); - BOOST_CHECK_EQUAL(available_coins.other.size(), 1U); + BOOST_CHECK_EQUAL(available_coins.Size(), 1U); + BOOST_CHECK_EQUAL(available_coins.coins[OutputType::UNKNOWN].size(), 1U); // We will create a self transfer for each of the OutputTypes and // verify it is put in the correct bucket after running GetAvailablecoins @@ -78,27 +79,28 @@ BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, AvailableCoinsTestingSetup) BOOST_ASSERT(dest); AddTx(CRecipient{{GetScriptForDestination(*dest)}, 1 * COIN, /*fSubtractFeeFromAmount=*/true}); available_coins = AvailableCoins(*wallet); - BOOST_CHECK_EQUAL(available_coins.bech32m.size(), 2U); + BOOST_CHECK_EQUAL(available_coins.coins[OutputType::BECH32M].size(), 2U); // Bech32 dest = wallet->GetNewDestination(OutputType::BECH32, ""); BOOST_ASSERT(dest); AddTx(CRecipient{{GetScriptForDestination(*dest)}, 2 * COIN, /*fSubtractFeeFromAmount=*/true}); available_coins = AvailableCoins(*wallet); - BOOST_CHECK_EQUAL(available_coins.bech32.size(), 2U); + BOOST_CHECK_EQUAL(available_coins.coins[OutputType::BECH32].size(), 2U); // P2SH-SEGWIT dest = wallet->GetNewDestination(OutputType::P2SH_SEGWIT, ""); + BOOST_ASSERT(dest); AddTx(CRecipient{{GetScriptForDestination(*dest)}, 3 * COIN, /*fSubtractFeeFromAmount=*/true}); available_coins = AvailableCoins(*wallet); - BOOST_CHECK_EQUAL(available_coins.P2SH_segwit.size(), 2U); + BOOST_CHECK_EQUAL(available_coins.coins[OutputType::P2SH_SEGWIT].size(), 2U); // Legacy (P2PKH) dest = wallet->GetNewDestination(OutputType::LEGACY, ""); BOOST_ASSERT(dest); AddTx(CRecipient{{GetScriptForDestination(*dest)}, 4 * COIN, /*fSubtractFeeFromAmount=*/true}); available_coins = AvailableCoins(*wallet); - BOOST_CHECK_EQUAL(available_coins.legacy.size(), 2U); + BOOST_CHECK_EQUAL(available_coins.coins[OutputType::LEGACY].size(), 2U); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp index a4a7216436..4dfdc87a38 100644 --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -83,7 +83,7 @@ static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmoun assert(ret.second); CWalletTx& wtx = (*ret.first).second; const auto& txout = wtx.tx->vout.at(nInput); - available_coins.bech32.emplace_back(COutPoint(wtx.GetHash(), nInput), txout, nAge, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, wtx.GetTxTime(), fIsFromMe, feerate); + available_coins.coins[OutputType::BECH32].emplace_back(COutPoint(wtx.GetHash(), nInput), txout, nAge, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, wtx.GetTxTime(), fIsFromMe, feerate); } /** Check if SelectionResult a is equivalent to SelectionResult b. @@ -308,15 +308,15 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) CoinsResult available_coins; add_coin(available_coins, *wallet, 1, coin_selection_params_bnb.m_effective_feerate); - available_coins.all().at(0).input_bytes = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail - BOOST_CHECK(!SelectCoinsBnB(GroupCoins(available_coins.all()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change)); + available_coins.All().at(0).input_bytes = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail + BOOST_CHECK(!SelectCoinsBnB(GroupCoins(available_coins.All()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change)); // Test fees subtracted from output: - available_coins.clear(); + available_coins.Clear(); add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate); - available_coins.all().at(0).input_bytes = 40; + available_coins.All().at(0).input_bytes = 40; coin_selection_params_bnb.m_subtract_fee_outputs = true; - const auto result9 = SelectCoinsBnB(GroupCoins(available_coins.all()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change); + const auto result9 = SelectCoinsBnB(GroupCoins(available_coins.All()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change); BOOST_CHECK(result9); BOOST_CHECK_EQUAL(result9->GetSelectedValue(), 1 * CENT); } @@ -335,7 +335,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) add_coin(available_coins, *wallet, 2 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true); CCoinControl coin_control; coin_control.m_allow_other_inputs = true; - coin_control.Select(available_coins.all().at(0).outpoint); + coin_control.Select(available_coins.All().at(0).outpoint); coin_selection_params_bnb.m_effective_feerate = CFeeRate(0); const auto result10 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb); BOOST_CHECK(result10); @@ -362,7 +362,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) CCoinControl coin_control; const auto result11 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb); BOOST_CHECK(EquivalentResult(expected_result, *result11)); - available_coins.clear(); + available_coins.Clear(); // more coins should be selected when effective fee < long term fee coin_selection_params_bnb.m_effective_feerate = CFeeRate(3000); @@ -377,7 +377,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) add_coin(1 * CENT, 2, expected_result); const auto result12 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb); BOOST_CHECK(EquivalentResult(expected_result, *result12)); - available_coins.clear(); + available_coins.Clear(); // pre selected coin should be selected even if disadvantageous coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000); @@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) add_coin(9 * CENT, 2, expected_result); add_coin(1 * CENT, 2, expected_result); coin_control.m_allow_other_inputs = true; - coin_control.Select(available_coins.all().at(1).outpoint); // pre select 9 coin + coin_control.Select(available_coins.All().at(1).outpoint); // pre select 9 coin const auto result13 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb); BOOST_CHECK(EquivalentResult(expected_result, *result13)); } @@ -413,28 +413,28 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // test multiple times to allow for differences in the shuffle order for (int i = 0; i < RUN_TESTS; i++) { - available_coins.clear(); + available_coins.Clear(); // with an empty wallet we can't even pay one cent - BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 1 * CENT, CENT)); + BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 1 * CENT, CENT)); add_coin(available_coins, *wallet, 1*CENT, CFeeRate(0), 4); // add a new 1 cent coin // with a new 1 cent coin, we still can't find a mature 1 cent - BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 1 * CENT, CENT)); + BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 1 * CENT, CENT)); // but we can find a new 1 cent - const auto result1 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 1 * CENT, CENT); + const auto result1 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT); BOOST_CHECK(result1); BOOST_CHECK_EQUAL(result1->GetSelectedValue(), 1 * CENT); add_coin(available_coins, *wallet, 2*CENT); // add a mature 2 cent coin // we can't make 3 cents of mature coins - BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 3 * CENT, CENT)); + BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 3 * CENT, CENT)); // we can make 3 cents of new coins - const auto result2 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 3 * CENT, CENT); + const auto result2 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 3 * CENT, CENT); BOOST_CHECK(result2); BOOST_CHECK_EQUAL(result2->GetSelectedValue(), 3 * CENT); @@ -445,44 +445,44 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38 // we can't make 38 cents only if we disallow new coins: - BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 38 * CENT, CENT)); + BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 38 * CENT, CENT)); // we can't even make 37 cents if we don't allow new coins even if they're from us - BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard_extra), 38 * CENT, CENT)); + BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard_extra), 38 * CENT, CENT)); // but we can make 37 cents if we accept new coins from ourself - const auto result3 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 37 * CENT, CENT); + const auto result3 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 37 * CENT, CENT); BOOST_CHECK(result3); BOOST_CHECK_EQUAL(result3->GetSelectedValue(), 37 * CENT); // and we can make 38 cents if we accept all new coins - const auto result4 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 38 * CENT, CENT); + const auto result4 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 38 * CENT, CENT); BOOST_CHECK(result4); BOOST_CHECK_EQUAL(result4->GetSelectedValue(), 38 * CENT); // try making 34 cents from 1,2,5,10,20 - we can't do it exactly - const auto result5 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 34 * CENT, CENT); + const auto result5 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 34 * CENT, CENT); BOOST_CHECK(result5); BOOST_CHECK_EQUAL(result5->GetSelectedValue(), 35 * CENT); // but 35 cents is closest BOOST_CHECK_EQUAL(result5->GetInputSet().size(), 3U); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible) // when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5 - const auto result6 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 7 * CENT, CENT); + const auto result6 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 7 * CENT, CENT); BOOST_CHECK(result6); BOOST_CHECK_EQUAL(result6->GetSelectedValue(), 7 * CENT); BOOST_CHECK_EQUAL(result6->GetInputSet().size(), 2U); // when we try making 8 cents, the smaller coins (1,2,5) are exactly enough. - const auto result7 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 8 * CENT, CENT); + const auto result7 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 8 * CENT, CENT); BOOST_CHECK(result7); BOOST_CHECK(result7->GetSelectedValue() == 8 * CENT); BOOST_CHECK_EQUAL(result7->GetInputSet().size(), 3U); // when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10) - const auto result8 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 9 * CENT, CENT); + const auto result8 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 9 * CENT, CENT); BOOST_CHECK(result8); BOOST_CHECK_EQUAL(result8->GetSelectedValue(), 10 * CENT); BOOST_CHECK_EQUAL(result8->GetInputSet().size(), 1U); // now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin - available_coins.clear(); + available_coins.Clear(); add_coin(available_coins, *wallet, 6*CENT); add_coin(available_coins, *wallet, 7*CENT); @@ -491,12 +491,12 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) add_coin(available_coins, *wallet, 30*CENT); // now we have 6+7+8+20+30 = 71 cents total // check that we have 71 and not 72 - const auto result9 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 71 * CENT, CENT); + const auto result9 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 71 * CENT, CENT); BOOST_CHECK(result9); - BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 72 * CENT, CENT)); + BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 72 * CENT, CENT)); // now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20 - const auto result10 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 16 * CENT, CENT); + const auto result10 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 16 * CENT, CENT); BOOST_CHECK(result10); BOOST_CHECK_EQUAL(result10->GetSelectedValue(), 20 * CENT); // we should get 20 in one coin BOOST_CHECK_EQUAL(result10->GetInputSet().size(), 1U); @@ -504,7 +504,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) add_coin(available_coins, *wallet, 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total // now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20 - const auto result11 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 16 * CENT, CENT); + const auto result11 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 16 * CENT, CENT); BOOST_CHECK(result11); BOOST_CHECK_EQUAL(result11->GetSelectedValue(), 18 * CENT); // we should get 18 in 3 coins BOOST_CHECK_EQUAL(result11->GetInputSet().size(), 3U); @@ -512,13 +512,13 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) add_coin(available_coins, *wallet, 18*CENT); // now we have 5+6+7+8+18+20+30 // and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18 - const auto result12 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 16 * CENT, CENT); + const auto result12 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 16 * CENT, CENT); BOOST_CHECK(result12); BOOST_CHECK_EQUAL(result12->GetSelectedValue(), 18 * CENT); // we should get 18 in 1 coin BOOST_CHECK_EQUAL(result12->GetInputSet().size(), 1U); // because in the event of a tie, the biggest coin wins // now try making 11 cents. we should get 5+6 - const auto result13 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 11 * CENT, CENT); + const auto result13 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 11 * CENT, CENT); BOOST_CHECK(result13); BOOST_CHECK_EQUAL(result13->GetSelectedValue(), 11 * CENT); BOOST_CHECK_EQUAL(result13->GetInputSet().size(), 2U); @@ -528,19 +528,19 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) add_coin(available_coins, *wallet, 2*COIN); add_coin(available_coins, *wallet, 3*COIN); add_coin(available_coins, *wallet, 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents - const auto result14 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 95 * CENT, CENT); + const auto result14 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 95 * CENT, CENT); BOOST_CHECK(result14); BOOST_CHECK_EQUAL(result14->GetSelectedValue(), 1 * COIN); // we should get 1 BTC in 1 coin BOOST_CHECK_EQUAL(result14->GetInputSet().size(), 1U); - const auto result15 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 195 * CENT, CENT); + const auto result15 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 195 * CENT, CENT); BOOST_CHECK(result15); BOOST_CHECK_EQUAL(result15->GetSelectedValue(), 2 * COIN); // we should get 2 BTC in 1 coin BOOST_CHECK_EQUAL(result15->GetInputSet().size(), 1U); // empty the wallet and start again, now with fractions of a cent, to test small change avoidance - available_coins.clear(); + available_coins.Clear(); add_coin(available_coins, *wallet, CENT * 1 / 10); add_coin(available_coins, *wallet, CENT * 2 / 10); add_coin(available_coins, *wallet, CENT * 3 / 10); @@ -549,7 +549,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // try making 1 * CENT from the 1.5 * CENT // we'll get change smaller than CENT whatever happens, so can expect CENT exactly - const auto result16 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), CENT, CENT); + const auto result16 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT, CENT); BOOST_CHECK(result16); BOOST_CHECK_EQUAL(result16->GetSelectedValue(), CENT); @@ -557,7 +557,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) add_coin(available_coins, *wallet, 1111*CENT); // try making 1 from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 - const auto result17 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 1 * CENT, CENT); + const auto result17 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT); BOOST_CHECK(result17); BOOST_CHECK_EQUAL(result17->GetSelectedValue(), 1 * CENT); // we should get the exact amount @@ -566,17 +566,17 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) add_coin(available_coins, *wallet, CENT * 7 / 10); // and try again to make 1.0 * CENT - const auto result18 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 1 * CENT, CENT); + const auto result18 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT); BOOST_CHECK(result18); BOOST_CHECK_EQUAL(result18->GetSelectedValue(), 1 * CENT); // we should get the exact amount // run the 'mtgox' test (see https://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf) // they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change - available_coins.clear(); + available_coins.Clear(); for (int j = 0; j < 20; j++) add_coin(available_coins, *wallet, 50000 * COIN); - const auto result19 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 500000 * COIN, CENT); + const auto result19 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 500000 * COIN, CENT); BOOST_CHECK(result19); BOOST_CHECK_EQUAL(result19->GetSelectedValue(), 500000 * COIN); // we should get the exact amount BOOST_CHECK_EQUAL(result19->GetInputSet().size(), 10U); // in ten coins @@ -585,41 +585,41 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // we need to try finding an exact subset anyway // sometimes it will fail, and so we use the next biggest coin: - available_coins.clear(); + available_coins.Clear(); add_coin(available_coins, *wallet, CENT * 5 / 10); add_coin(available_coins, *wallet, CENT * 6 / 10); add_coin(available_coins, *wallet, CENT * 7 / 10); add_coin(available_coins, *wallet, 1111 * CENT); - const auto result20 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 1 * CENT, CENT); + const auto result20 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT); BOOST_CHECK(result20); BOOST_CHECK_EQUAL(result20->GetSelectedValue(), 1111 * CENT); // we get the bigger coin BOOST_CHECK_EQUAL(result20->GetInputSet().size(), 1U); // but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0) - available_coins.clear(); + available_coins.Clear(); add_coin(available_coins, *wallet, CENT * 4 / 10); add_coin(available_coins, *wallet, CENT * 6 / 10); add_coin(available_coins, *wallet, CENT * 8 / 10); add_coin(available_coins, *wallet, 1111 * CENT); - const auto result21 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), CENT, CENT); + const auto result21 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT, CENT); BOOST_CHECK(result21); BOOST_CHECK_EQUAL(result21->GetSelectedValue(), CENT); // we should get the exact amount BOOST_CHECK_EQUAL(result21->GetInputSet().size(), 2U); // in two coins 0.4+0.6 // test avoiding small change - available_coins.clear(); + available_coins.Clear(); add_coin(available_coins, *wallet, CENT * 5 / 100); add_coin(available_coins, *wallet, CENT * 1); add_coin(available_coins, *wallet, CENT * 100); // trying to make 100.01 from these three coins - const auto result22 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), CENT * 10001 / 100, CENT); + const auto result22 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT * 10001 / 100, CENT); BOOST_CHECK(result22); BOOST_CHECK_EQUAL(result22->GetSelectedValue(), CENT * 10105 / 100); // we should get all coins BOOST_CHECK_EQUAL(result22->GetInputSet().size(), 3U); // but if we try to make 99.9, we should take the bigger of the two small coins to avoid small change - const auto result23 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), CENT * 9990 / 100, CENT); + const auto result23 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT * 9990 / 100, CENT); BOOST_CHECK(result23); BOOST_CHECK_EQUAL(result23->GetSelectedValue(), 101 * CENT); BOOST_CHECK_EQUAL(result23->GetInputSet().size(), 2U); @@ -627,14 +627,14 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // test with many inputs for (CAmount amt=1500; amt < COIN; amt*=10) { - available_coins.clear(); + available_coins.Clear(); // Create 676 inputs (= (old MAX_STANDARD_TX_SIZE == 100000) / 148 bytes per input) for (uint16_t j = 0; j < 676; j++) add_coin(available_coins, *wallet, amt); // We only create the wallet once to save time, but we still run the coin selection RUN_TESTS times. for (int i = 0; i < RUN_TESTS; i++) { - const auto result24 = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_confirmed), 2000, CENT); + const auto result24 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 2000, CENT); BOOST_CHECK(result24); if (amt - 2000 < CENT) { @@ -653,7 +653,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // test randomness { - available_coins.clear(); + available_coins.Clear(); for (int i2 = 0; i2 < 100; i2++) add_coin(available_coins, *wallet, COIN); @@ -661,9 +661,9 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) for (int i = 0; i < RUN_TESTS; i++) { // picking 50 from 100 coins doesn't depend on the shuffle, // but does depend on randomness in the stochastic approximation code - const auto result25 = KnapsackSolver(GroupCoins(available_coins.all()), 50 * COIN, CENT); + const auto result25 = KnapsackSolver(GroupCoins(available_coins.All()), 50 * COIN, CENT); BOOST_CHECK(result25); - const auto result26 = KnapsackSolver(GroupCoins(available_coins.all()), 50 * COIN, CENT); + const auto result26 = KnapsackSolver(GroupCoins(available_coins.All()), 50 * COIN, CENT); BOOST_CHECK(result26); BOOST_CHECK(!EqualResult(*result25, *result26)); @@ -674,9 +674,9 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) // When choosing 1 from 100 identical coins, 1% of the time, this test will choose the same coin twice // which will cause it to fail. // To avoid that issue, run the test RANDOM_REPEATS times and only complain if all of them fail - const auto result27 = KnapsackSolver(GroupCoins(available_coins.all()), COIN, CENT); + const auto result27 = KnapsackSolver(GroupCoins(available_coins.All()), COIN, CENT); BOOST_CHECK(result27); - const auto result28 = KnapsackSolver(GroupCoins(available_coins.all()), COIN, CENT); + const auto result28 = KnapsackSolver(GroupCoins(available_coins.All()), COIN, CENT); BOOST_CHECK(result28); if (EqualResult(*result27, *result28)) fails++; @@ -697,9 +697,9 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) int fails = 0; for (int j = 0; j < RANDOM_REPEATS; j++) { - const auto result29 = KnapsackSolver(GroupCoins(available_coins.all()), 90 * CENT, CENT); + const auto result29 = KnapsackSolver(GroupCoins(available_coins.All()), 90 * CENT, CENT); BOOST_CHECK(result29); - const auto result30 = KnapsackSolver(GroupCoins(available_coins.all()), 90 * CENT, CENT); + const auto result30 = KnapsackSolver(GroupCoins(available_coins.All()), 90 * CENT, CENT); BOOST_CHECK(result30); if (EqualResult(*result29, *result30)) fails++; @@ -725,7 +725,7 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset) add_coin(available_coins, *wallet, 1000 * COIN); add_coin(available_coins, *wallet, 3 * COIN); - const auto result = KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 1003 * COIN, CENT, rand); + const auto result = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 1003 * COIN, CENT, rand); BOOST_CHECK(result); BOOST_CHECK_EQUAL(result->GetSelectedValue(), 1003 * COIN); BOOST_CHECK_EQUAL(result->GetInputSet().size(), 2U); diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp index dc935a1a04..a75b014870 100644 --- a/src/wallet/test/spend_tests.cpp +++ b/src/wallet/test/spend_tests.cpp @@ -18,7 +18,7 @@ BOOST_FIXTURE_TEST_SUITE(spend_tests, WalletTestingSetup) BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup) { CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); - auto wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey); + auto wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), m_args, coinbaseKey); // Check that a subtract-from-recipient transaction slightly less than the // coinbase input amount does not create a change output (because it would diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 093f510945..60fdbde71b 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -91,16 +91,17 @@ static void AddKey(CWallet& wallet, const CKey& key) BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) { // Cap last block file size, and mine new block in a new block file. - CBlockIndex* oldTip = m_node.chainman->ActiveChain().Tip(); + CBlockIndex* oldTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()); WITH_LOCK(::cs_main, m_node.chainman->m_blockman.GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE); CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); - CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip(); + CBlockIndex* newTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()); // Verify ScanForWalletTransactions fails to read an unknown start block. { CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase()); { LOCK(wallet.cs_wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } @@ -121,6 +122,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) CWallet wallet(m_node.chain.get(), "", m_args, CreateMockWalletDatabase()); { LOCK(wallet.cs_wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } @@ -165,6 +167,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase()); { LOCK(wallet.cs_wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } @@ -192,6 +195,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase()); { LOCK(wallet.cs_wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } @@ -210,10 +214,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup) { // Cap last block file size, and mine new block in a new block file. - CBlockIndex* oldTip = m_node.chainman->ActiveChain().Tip(); + CBlockIndex* oldTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()); WITH_LOCK(::cs_main, m_node.chainman->m_blockman.GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE); CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); - CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip(); + CBlockIndex* newTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()); // Prune the older block file. int file_number; @@ -277,7 +281,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { // Create two blocks with same timestamp to verify that importwallet rescan // will pick up both blocks, not just the first. - const int64_t BLOCK_TIME = m_node.chainman->ActiveChain().Tip()->GetBlockTimeMax() + 5; + const int64_t BLOCK_TIME = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockTimeMax() + 5); SetMockTime(BLOCK_TIME); m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); @@ -302,6 +306,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); AddWallet(context, wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } JSONRPCRequest request; @@ -327,6 +332,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) request.params.setArray(); request.params.push_back(backup_file); AddWallet(context, wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); wallet::importwallet().HandleRequest(request); RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt); @@ -350,9 +356,10 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup) { CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase()); - CWalletTx wtx{m_coinbase_txns.back(), TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/0}}; LOCK(wallet.cs_wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); + CWalletTx wtx{m_coinbase_txns.back(), TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/0}}; wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); wallet.SetupDescriptorScriptPubKeyMans(); @@ -520,7 +527,7 @@ public: ListCoinsTestingSetup() { CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); - wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey); + wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), m_args, coinbaseKey); } ~ListCoinsTestingSetup() @@ -547,6 +554,7 @@ public: CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); LOCK(wallet->cs_wallet); + LOCK(Assert(m_node.chainman)->GetMutex()); wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash()); auto it = wallet->mapWallet.find(tx->GetHash()); BOOST_CHECK(it != wallet->mapWallet.end()); @@ -591,7 +599,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup) // Lock both coins. Confirm number of available coins drops to 0. { LOCK(wallet->cs_wallet); - BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).size(), 2U); + BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).Size(), 2U); } for (const auto& group : list) { for (const auto& coin : group.second) { @@ -601,7 +609,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup) } { LOCK(wallet->cs_wallet); - BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).size(), 0U); + BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).Size(), 0U); } // Confirm ListCoins still returns same result as before, despite coins // being locked. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index de1078e646..45d2c3692d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -149,6 +149,13 @@ std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context) return context.wallets; } +std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count) +{ + LOCK(context.wallets_mutex); + count = context.wallets.size(); + return count == 1 ? context.wallets[0] : nullptr; +} + std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name) { LOCK(context.wallets_mutex); @@ -1421,6 +1428,19 @@ bool CWallet::IsMine(const CTransaction& tx) const return false; } +isminetype CWallet::IsMine(const COutPoint& outpoint) const +{ + AssertLockHeld(cs_wallet); + auto wtx = GetWalletTx(outpoint.hash); + if (!wtx) { + return ISMINE_NO; + } + if (outpoint.n >= wtx->tx->vout.size()) { + return ISMINE_NO; + } + return IsMine(wtx->tx->vout[outpoint.n]); +} + bool CWallet::IsFromMe(const CTransaction& tx) const { return (GetDebit(tx, ISMINE_ALL) > 0); @@ -3336,6 +3356,18 @@ std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& scri return nullptr; } +std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& script) const +{ + std::vector<WalletDescriptor> descs; + for (const auto spk_man: GetScriptPubKeyMans(script)) { + if (const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) { + LOCK(desc_spk_man->cs_desc_man); + descs.push_back(desc_spk_man->GetWalletDescriptor()); + } + } + return descs; +} + LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const { if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { @@ -3414,6 +3446,7 @@ void CWallet::SetupDescriptorScriptPubKeyMans() for (bool internal : {false, true}) { for (OutputType t : OUTPUT_TYPES) { + if (t == OutputType::UNKNOWN) continue; auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this)); if (IsCrypted()) { if (IsLocked()) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index cf33ea21f2..3a46d0a987 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -64,6 +64,7 @@ bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet); bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings); bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start); std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context); +std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count); std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name); std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings); std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings); @@ -684,6 +685,7 @@ public: CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const; isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + isminetype IsMine(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); /** should probably be renamed to IsRelevantToMe */ bool IsFromMe(const CTransaction& tx) const; CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; @@ -845,6 +847,9 @@ public: std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const; std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script, SignatureData& sigdata) const; + //! Get the wallet descriptors for a script. + std::vector<WalletDescriptor> GetWalletDescriptors(const CScript& script) const; + //! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external. LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const; LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan(); diff --git a/test/functional/p2p_initial_headers_sync.py b/test/functional/p2p_initial_headers_sync.py new file mode 100755 index 0000000000..e67c384da7 --- /dev/null +++ b/test/functional/p2p_initial_headers_sync.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# Copyright (c) 2022 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test initial headers download + +Test that we only try to initially sync headers from one peer (until our chain +is close to caught up), and that each block announcement results in only one +additional peer receiving a getheaders message. +""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.messages import ( + CInv, + MSG_BLOCK, + msg_headers, + msg_inv, +) +from test_framework.p2p import ( + p2p_lock, + P2PInterface, +) +from test_framework.util import ( + assert_equal, +) +import random + +class HeadersSyncTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 1 + + def announce_random_block(self, peers): + new_block_announcement = msg_inv(inv=[CInv(MSG_BLOCK, random.randrange(1<<256))]) + for p in peers: + p.send_and_ping(new_block_announcement) + + def run_test(self): + self.log.info("Adding a peer to node0") + peer1 = self.nodes[0].add_p2p_connection(P2PInterface()) + + # Wait for peer1 to receive a getheaders + peer1.wait_for_getheaders() + # An empty reply will clear the outstanding getheaders request, + # allowing additional getheaders requests to be sent to this peer in + # the future. + peer1.send_message(msg_headers()) + + self.log.info("Connecting two more peers to node0") + # Connect 2 more peers; they should not receive a getheaders yet + peer2 = self.nodes[0].add_p2p_connection(P2PInterface()) + peer3 = self.nodes[0].add_p2p_connection(P2PInterface()) + + all_peers = [peer1, peer2, peer3] + + self.log.info("Verify that peer2 and peer3 don't receive a getheaders after connecting") + for p in all_peers: + p.sync_with_ping() + with p2p_lock: + assert "getheaders" not in peer2.last_message + assert "getheaders" not in peer3.last_message + + with p2p_lock: + peer1.last_message.pop("getheaders", None) + + self.log.info("Have all peers announce a new block") + self.announce_random_block(all_peers) + + self.log.info("Check that peer1 receives a getheaders in response") + peer1.wait_for_getheaders() + peer1.send_message(msg_headers()) # Send empty response, see above + with p2p_lock: + peer1.last_message.pop("getheaders", None) + + self.log.info("Check that exactly 1 of {peer2, peer3} received a getheaders in response") + count = 0 + peer_receiving_getheaders = None + for p in [peer2, peer3]: + with p2p_lock: + if "getheaders" in p.last_message: + count += 1 + peer_receiving_getheaders = p + p.last_message.pop("getheaders", None) + p.send_message(msg_headers()) # Send empty response, see above + + assert_equal(count, 1) + + self.log.info("Announce another new block, from all peers") + self.announce_random_block(all_peers) + + self.log.info("Check that peer1 receives a getheaders in response") + peer1.wait_for_getheaders() + + self.log.info("Check that the remaining peer received a getheaders as well") + expected_peer = peer2 + if peer2 == peer_receiving_getheaders: + expected_peer = peer3 + + expected_peer.wait_for_getheaders() + + self.log.info("Success!") + +if __name__ == '__main__': + HeadersSyncTest().main() + diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index cf9ad3f458..5a870de6c7 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -408,7 +408,7 @@ class RawTransactionsTest(BitcoinTestFramework): inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin! outputs = { self.nodes[0].getnewaddress() : 1.0} rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx) + assert_raises_rpc_error(-4, "Unable to find UTXO for external input", self.nodes[2].fundrawtransaction, rawtx) def test_fee_p2pkh(self): """Compare fee of a standard pubkeyhash transaction.""" @@ -1079,17 +1079,28 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[2].createwallet("test_weight_calculation") wallet = self.nodes[2].get_wallet_rpc("test_weight_calculation") - addr = wallet.getnewaddress() - txid = self.nodes[0].sendtoaddress(addr, 5) + addr = wallet.getnewaddress(address_type="bech32") + ext_addr = self.nodes[0].getnewaddress(address_type="bech32") + txid = self.nodes[0].send([{addr: 5}, {ext_addr: 5}])["txid"] vout = find_vout_for_address(self.nodes[0], txid, addr) + ext_vout = find_vout_for_address(self.nodes[0], txid, ext_addr) - self.nodes[0].sendtoaddress(wallet.getnewaddress(), 5) + self.nodes[0].sendtoaddress(wallet.getnewaddress(address_type="bech32"), 5) self.generate(self.nodes[0], 1) - rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(): 9.999}]) - fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10}) + rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(address_type="bech32"): 8}]) + fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10, "change_type": "bech32"}) # with 71-byte signatures we should expect following tx size - tx_size = 10 + 41*2 + 31*2 + (2 + 107*2)/4 + # tx overhead (10) + 2 inputs (41 each) + 2 p2wpkh (31 each) + (segwit marker and flag (2) + 2 p2wpkh 71 byte sig witnesses (107 each)) / witness scaling factor (4) + tx_size = ceil(10 + 41*2 + 31*2 + (2 + 107*2)/4) + assert_equal(fundedtx['fee'] * COIN, tx_size * 10) + + # Using the other output should have 72 byte sigs + rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': ext_vout}], [{self.nodes[0].getnewaddress(): 13}]) + ext_desc = self.nodes[0].getaddressinfo(ext_addr)["desc"] + fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10, "change_type": "bech32", "solving_data": {"descriptors": [ext_desc]}}) + # tx overhead (10) + 3 inputs (41 each) + 2 p2wpkh(31 each) + (segwit marker and flag (2) + 2 p2wpkh 71 bytes sig witnesses (107 each) + p2wpkh 72 byte sig witness (108)) / witness scaling factor (4) + tx_size = ceil(10 + 41*3 + 31*2 + (2 + 107*2 + 108)/4) assert_equal(fundedtx['fee'] * COIN, tx_size * 10) self.nodes[2].unloadwallet("test_weight_calculation") diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 3676b698f0..37d0c4f87e 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -247,6 +247,7 @@ BASE_SCRIPTS = [ 'rpc_generate.py', 'wallet_balance.py --legacy-wallet', 'wallet_balance.py --descriptors', + 'p2p_initial_headers_sync.py', 'feature_nulldummy.py', 'mempool_accept.py', 'mempool_expiry.py', diff --git a/test/functional/wallet_avoid_mixing_output_types.py b/test/functional/wallet_avoid_mixing_output_types.py index 46f41d9c22..cad9d02808 100755 --- a/test/functional/wallet_avoid_mixing_output_types.py +++ b/test/functional/wallet_avoid_mixing_output_types.py @@ -124,6 +124,7 @@ class AddressInputTypeGrouping(BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_wallet() + self.skip_if_no_sqlite() def make_payment(self, A, B, v, addr_type): fee_rate = random.randint(1, 20) diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 9cf1b3d2c4..adeb551895 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -7,6 +7,7 @@ from decimal import Decimal from itertools import product from test_framework.blocktools import COINBASE_MATURITY +from test_framework.descriptors import descsum_create from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_array_result, @@ -700,6 +701,38 @@ class WalletTest(BitcoinTestFramework): txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False) assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four) + self.log.info("Testing 'listunspent' outputs the parent descriptor(s) of coins") + # Create two multisig descriptors, and send a UTxO each. + multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))") + multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))") + addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0] + addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0] + txid_a = self.nodes[0].sendtoaddress(addr_a, 0.01) + txid_b = self.nodes[0].sendtoaddress(addr_b, 0.01) + self.generate(self.nodes[0], 1, sync_fun=self.no_op) + # Now import the descriptors, make sure we can identify on which descriptor each coin was received. + self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True) + wo_wallet = self.nodes[0].get_wallet_rpc("wo") + wo_wallet.importdescriptors([ + { + "desc": multi_a, + "active": False, + "timestamp": "now", + }, + { + "desc": multi_b, + "active": False, + "timestamp": "now", + }, + ]) + coins = wo_wallet.listunspent(minconf=0) + assert_equal(len(coins), 2) + coin_a = next(c for c in coins if c["txid"] == txid_a) + assert_equal(coin_a["parent_descs"][0], multi_a) + coin_b = next(c for c in coins if c["txid"] == txid_b) + assert_equal(coin_b["parent_descs"][0], multi_b) + self.nodes[0].unloadwallet("wo") + if __name__ == '__main__': WalletTest().main() diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 1f3a276d9c..36dbec467b 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -6,6 +6,7 @@ from test_framework.address import key_to_p2wpkh from test_framework.blocktools import COINBASE_MATURITY +from test_framework.descriptors import descsum_create from test_framework.key import ECKey from test_framework.test_framework import BitcoinTestFramework from test_framework.messages import MAX_BIP125_RBF_SEQUENCE @@ -39,6 +40,8 @@ class ListSinceBlockTest(BitcoinTestFramework): self.test_double_send() self.double_spends_filtered() self.test_targetconfirmations() + self.test_desc() + self.test_send_to_self() def test_no_blockhash(self): self.log.info("Test no blockhash") @@ -383,5 +386,65 @@ class ListSinceBlockTest(BitcoinTestFramework): assert_equal(original_found, False) assert_equal(double_found, False) + def test_desc(self): + """Make sure we can track coins by descriptor.""" + self.log.info("Test descriptor lookup by scriptPubKey.") + + # Create a watchonly wallet tracking two multisig descriptors. + multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))") + multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))") + self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True) + wo_wallet = self.nodes[0].get_wallet_rpc("wo") + wo_wallet.importdescriptors([ + { + "desc": multi_a, + "active": False, + "timestamp": "now", + }, + { + "desc": multi_b, + "active": False, + "timestamp": "now", + }, + ]) + + # Send a coin to each descriptor. + assert_equal(len(wo_wallet.listsinceblock()["transactions"]), 0) + addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0] + addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0] + self.nodes[2].sendtoaddress(addr_a, 1) + self.nodes[2].sendtoaddress(addr_b, 2) + self.generate(self.nodes[2], 1) + + # We can identify on which descriptor each coin was received. + coins = wo_wallet.listsinceblock()["transactions"] + assert_equal(len(coins), 2) + coin_a = next(c for c in coins if c["amount"] == 1) + assert_equal(coin_a["parent_descs"][0], multi_a) + coin_b = next(c for c in coins if c["amount"] == 2) + assert_equal(coin_b["parent_descs"][0], multi_b) + + def test_send_to_self(self): + """We can make listsinceblock output our change outputs.""" + self.log.info("Test the inclusion of change outputs in the output.") + + # Create a UTxO paying to one of our change addresses. + block_hash = self.nodes[2].getbestblockhash() + addr = self.nodes[2].getrawchangeaddress() + self.nodes[2].sendtoaddress(addr, 1) + + # If we don't list change, we won't have an entry for it. + coins = self.nodes[2].listsinceblock(blockhash=block_hash)["transactions"] + assert not any(c["address"] == addr for c in coins) + + # Now if we list change, we'll get both the send (to a change address) and + # the actual change. + res = self.nodes[2].listsinceblock(blockhash=block_hash, include_change=True) + coins = [entry for entry in res["transactions"] if entry["category"] == "receive"] + assert_equal(len(coins), 2) + assert any(c["address"] == addr for c in coins) + assert all(self.nodes[2].getaddressinfo(c["address"])["ischange"] for c in coins) + + if __name__ == '__main__': ListSinceBlockTest().main() diff --git a/test/lint/lint-includes.py b/test/lint/lint-includes.py index afdca0d418..b3fa4b9303 100755 --- a/test/lint/lint-includes.py +++ b/test/lint/lint-includes.py @@ -21,8 +21,7 @@ EXCLUDED_DIRS = ["src/leveldb/", "src/minisketch/", ] -EXPECTED_BOOST_INCLUDES = ["boost/algorithm/string/replace.hpp", - "boost/date_time/posix_time/posix_time.hpp", +EXPECTED_BOOST_INCLUDES = ["boost/date_time/posix_time/posix_time.hpp", "boost/multi_index/hashed_index.hpp", "boost/multi_index/ordered_index.hpp", "boost/multi_index/sequenced_index.hpp", |