aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.clang-tidy2
-rw-r--r--src/Makefile.am28
-rw-r--r--src/Makefile.bench.include10
-rw-r--r--src/Makefile.test.include14
-rw-r--r--src/addrman.cpp151
-rw-r--r--src/addrman.h26
-rw-r--r--src/addrman_impl.h42
-rw-r--r--src/bench/addrman.cpp2
-rw-r--r--src/bench/coin_selection.cpp6
-rw-r--r--src/bench/descriptors.cpp30
-rw-r--r--src/bench/wallet_loading.cpp5
-rw-r--r--src/bitcoin-chainstate.cpp6
-rw-r--r--src/bitcoin-cli.cpp2
-rw-r--r--src/blockfilter.cpp2
-rw-r--r--src/chain.cpp8
-rw-r--r--src/chain.h2
-rw-r--r--src/coins.cpp6
-rw-r--r--src/crc32c/CMakeLists.txt7
-rw-r--r--src/cuckoocache.h23
-rw-r--r--src/external_signer.cpp2
-rw-r--r--src/init.cpp62
-rw-r--r--src/init/common.cpp2
-rw-r--r--src/interfaces/wallet.h44
-rw-r--r--src/kernel/mempool_options.h19
-rw-r--r--src/kernel/validation_cache_sizes.h20
-rw-r--r--src/key.cpp1
-rw-r--r--src/key.h4
-rw-r--r--src/leveldb/util/env_posix.cc2
-rw-r--r--src/mempool_args.cpp39
-rw-r--r--src/net.cpp24
-rw-r--r--src/net_processing.cpp26
-rw-r--r--src/node/blockstorage.cpp6
-rw-r--r--src/node/interfaces.cpp76
-rw-r--r--src/node/mempool_args.cpp99
-rw-r--r--src/node/mempool_args.h (renamed from src/mempool_args.h)13
-rw-r--r--src/node/psbt.cpp2
-rw-r--r--src/node/validation_cache_args.cpp34
-rw-r--r--src/node/validation_cache_args.h17
-rw-r--r--src/outputtype.cpp2
-rw-r--r--src/policy/policy.cpp13
-rw-r--r--src/policy/policy.h8
-rw-r--r--src/policy/settings.cpp5
-rw-r--r--src/policy/settings.h29
-rw-r--r--src/protocol.h11
-rw-r--r--src/psbt.h3
-rw-r--r--src/pubkey.cpp1
-rw-r--r--src/pubkey.h4
-rw-r--r--src/qt/addresstablemodel.cpp2
-rw-r--r--src/qt/bitcoinstrings.cpp42
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/locale/bitcoin_en.ts548
-rw-r--r--src/qt/locale/bitcoin_en.xlf3494
-rw-r--r--src/qt/overviewpage.cpp23
-rw-r--r--src/qt/overviewpage.h1
-rw-r--r--src/qt/sendcoinsdialog.cpp12
-rw-r--r--src/qt/sendcoinsdialog.h2
-rw-r--r--src/qt/test/wallettests.cpp28
-rw-r--r--src/qt/walletcontroller.cpp27
-rw-r--r--src/qt/walletmodel.cpp24
-rw-r--r--src/qt/walletmodel.h7
-rw-r--r--src/rest.cpp41
-rw-r--r--src/rpc/client.cpp2
-rw-r--r--src/rpc/fees.cpp3
-rw-r--r--src/rpc/mempool.cpp6
-rw-r--r--src/rpc/net.cpp12
-rw-r--r--src/rpc/rawtransaction.cpp6
-rw-r--r--src/rpc/rawtransaction_util.cpp7
-rw-r--r--src/rpc/rawtransaction_util.h3
-rw-r--r--src/rpc/request.cpp6
-rw-r--r--src/script/descriptor.cpp46
-rw-r--r--src/script/script.h2
-rw-r--r--src/script/sigcache.cpp18
-rw-r--r--src/script/sigcache.h11
-rw-r--r--src/script/sign.cpp24
-rw-r--r--src/script/sign.h6
-rw-r--r--src/script/standard.cpp3
-rw-r--r--src/script/standard.h11
-rw-r--r--src/serialize.h23
-rw-r--r--src/test/addrman_tests.cpp26
-rw-r--r--src/test/bip32_tests.cpp18
-rw-r--r--src/test/descriptor_tests.cpp7
-rw-r--r--src/test/fuzz/addrman.cpp18
-rw-r--r--src/test/fuzz/integer.cpp3
-rw-r--r--src/test/fuzz/key.cpp6
-rw-r--r--src/test/fuzz/load_external_block_file.cpp11
-rw-r--r--src/test/fuzz/rbf.cpp2
-rw-r--r--src/test/fuzz/script.cpp3
-rw-r--r--src/test/fuzz/script_sigcache.cpp11
-rw-r--r--src/test/fuzz/transaction.cpp5
-rw-r--r--src/test/fuzz/tx_pool.cpp11
-rw-r--r--src/test/fuzz/txorphan.cpp4
-rw-r--r--src/test/fuzz/util.cpp5
-rw-r--r--src/test/fuzz/util.h5
-rw-r--r--src/test/fuzz/validation_load_mempool.cpp2
-rw-r--r--src/test/miner_tests.cpp16
-rw-r--r--src/test/multisig_tests.cpp22
-rw-r--r--src/test/netbase_tests.cpp18
-rw-r--r--src/test/rbf_tests.cpp230
-rw-r--r--src/test/result_tests.cpp96
-rw-r--r--src/test/rpc_tests.cpp4
-rw-r--r--src/test/script_p2sh_tests.cpp14
-rw-r--r--src/test/skiplist_tests.cpp6
-rw-r--r--src/test/system_tests.cpp5
-rw-r--r--src/test/transaction_tests.cpp22
-rw-r--r--src/test/txvalidationcache_tests.cpp5
-rw-r--r--src/test/util/setup_common.cpp18
-rw-r--r--src/test/util/wallet.cpp6
-rw-r--r--src/test/validation_chainstate_tests.cpp11
-rw-r--r--src/test/validation_flush_tests.cpp11
-rw-r--r--src/timedata.h7
-rw-r--r--src/txmempool.cpp14
-rw-r--r--src/txmempool.h16
-rw-r--r--src/txorphanage.cpp4
-rw-r--r--src/txorphanage.h2
-rw-r--r--src/univalue/include/univalue.h20
-rw-r--r--src/univalue/lib/univalue.cpp33
-rw-r--r--src/univalue/test/object.cpp45
-rw-r--r--src/util/result.h87
-rw-r--r--src/util/system.cpp18
-rw-r--r--src/util/system.h2
-rw-r--r--src/util/time.h1
-rw-r--r--src/validation.cpp78
-rw-r--r--src/validation.h39
-rw-r--r--src/wallet/coinselection.h2
-rw-r--r--src/wallet/external_signer_scriptpubkeyman.cpp3
-rw-r--r--src/wallet/feebumper.cpp6
-rw-r--r--src/wallet/fees.cpp2
-rw-r--r--src/wallet/interfaces.cpp39
-rw-r--r--src/wallet/rpc/addresses.cpp10
-rw-r--r--src/wallet/rpc/backup.cpp2
-rw-r--r--src/wallet/rpc/coins.cpp2
-rw-r--r--src/wallet/rpc/spend.cpp30
-rw-r--r--src/wallet/rpc/wallet.cpp114
-rw-r--r--src/wallet/scriptpubkeyman.cpp72
-rw-r--r--src/wallet/scriptpubkeyman.h14
-rw-r--r--src/wallet/spend.cpp232
-rw-r--r--src/wallet/spend.h71
-rw-r--r--src/wallet/test/availablecoins_tests.cpp105
-rw-r--r--src/wallet/test/coinselector_tests.cpp268
-rw-r--r--src/wallet/test/fuzz/notifications.cpp5
-rw-r--r--src/wallet/test/spend_tests.cpp2
-rw-r--r--src/wallet/test/wallet_tests.cpp117
-rw-r--r--src/wallet/wallet.cpp91
-rw-r--r--src/wallet/wallet.h20
144 files changed, 4505 insertions, 3071 deletions
diff --git a/src/.clang-tidy b/src/.clang-tidy
index df2a080075..b9371b147b 100644
--- a/src/.clang-tidy
+++ b/src/.clang-tidy
@@ -5,6 +5,7 @@ misc-unused-using-decls,
modernize-use-default-member-init,
modernize-use-nullptr,
readability-redundant-declaration,
+readability-redundant-string-init,
'
WarningsAsErrors: '
bugprone-argument-comment,
@@ -12,4 +13,5 @@ misc-unused-using-decls,
modernize-use-default-member-init,
modernize-use-nullptr,
readability-redundant-declaration,
+readability-redundant-string-init,
'
diff --git a/src/Makefile.am b/src/Makefile.am
index 23bc180095..18c6c25b96 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -139,7 +139,6 @@ BITCOIN_CORE_H = \
compat/cpuid.h \
compat/endian.h \
compressor.h \
- node/connection_types.h \
consensus/consensus.h \
consensus/tx_check.h \
consensus/tx_verify.h \
@@ -149,7 +148,6 @@ BITCOIN_CORE_H = \
dbwrapper.h \
deploymentinfo.h \
deploymentstatus.h \
- node/eviction.h \
external_signer.h \
flatfile.h \
fs.h \
@@ -179,12 +177,12 @@ BITCOIN_CORE_H = \
kernel/mempool_limits.h \
kernel/mempool_options.h \
kernel/mempool_persist.h \
+ kernel/validation_cache_sizes.h \
key.h \
key_io.h \
logging.h \
logging/timer.h \
mapport.h \
- mempool_args.h \
memusage.h \
merkleblock.h \
net.h \
@@ -199,14 +197,18 @@ BITCOIN_CORE_H = \
node/caches.h \
node/chainstate.h \
node/coin.h \
+ node/connection_types.h \
node/context.h \
+ node/eviction.h \
+ node/interface_ui.h \
+ node/mempool_args.h \
node/mempool_persist_args.h \
node/miner.h \
node/minisketchwrapper.h \
node/psbt.h \
node/transaction.h \
- node/interface_ui.h \
node/utxo_snapshot.h \
+ node/validation_cache_args.h \
noui.h \
outputtype.h \
policy/feerate.h \
@@ -372,10 +374,9 @@ libbitcoin_node_a_SOURCES = \
kernel/context.cpp \
kernel/mempool_persist.cpp \
mapport.cpp \
- mempool_args.cpp \
net.cpp \
- netgroup.cpp \
net_processing.cpp \
+ netgroup.cpp \
node/blockstorage.cpp \
node/caches.cpp \
node/chainstate.cpp \
@@ -383,13 +384,15 @@ libbitcoin_node_a_SOURCES = \
node/connection_types.cpp \
node/context.cpp \
node/eviction.cpp \
+ node/interface_ui.cpp \
node/interfaces.cpp \
+ node/mempool_args.cpp \
node/mempool_persist_args.cpp \
node/miner.cpp \
node/minisketchwrapper.cpp \
node/psbt.cpp \
node/transaction.cpp \
- node/interface_ui.cpp \
+ node/validation_cache_args.cpp \
noui.cpp \
policy/fees.cpp \
policy/fees_args.cpp \
@@ -402,8 +405,8 @@ libbitcoin_node_a_SOURCES = \
rpc/fees.cpp \
rpc/mempool.cpp \
rpc/mining.cpp \
- rpc/node.cpp \
rpc/net.cpp \
+ rpc/node.cpp \
rpc/output_script.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
@@ -1062,6 +1065,15 @@ nodist_libbitcoin_ipc_a_SOURCES = $(libbitcoin_ipc_mpgen_output)
CLEANFILES += $(libbitcoin_ipc_mpgen_output)
endif
+%.raw.h: %.raw
+ @$(MKDIR_P) $(@D)
+ @{ \
+ echo "static unsigned const char $(*F)_raw[] = {" && \
+ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
+ echo "};"; \
+ } > "$@.new" && mv -f "$@.new" "$@"
+ @echo "Generated $@"
+
include Makefile.minisketch.include
include Makefile.crc32c.include
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 532f668668..a23d872250 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -27,6 +27,7 @@ bench_bench_bitcoin_SOURCES = \
bench/crypto_hash.cpp \
bench/data.cpp \
bench/data.h \
+ bench/descriptors.cpp \
bench/duplicate_inputs.cpp \
bench/examples.cpp \
bench/gcs_filter.cpp \
@@ -93,12 +94,3 @@ bench: $(BENCH_BINARY) FORCE
bitcoin_bench_clean : FORCE
rm -f $(CLEAN_BITCOIN_BENCH) $(bench_bench_bitcoin_OBJECTS) $(BENCH_BINARY)
-
-%.raw.h: %.raw
- @$(MKDIR_P) $(@D)
- @{ \
- echo "static unsigned const char $(*F)_raw[] = {" && \
- $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
- echo "};"; \
- } > "$@.new" && mv -f "$@.new" "$@"
- @echo "Generated $@"
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index d9195ad32e..75a404c50a 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -117,7 +117,9 @@ BITCOIN_TESTS =\
test/prevector_tests.cpp \
test/raii_event_tests.cpp \
test/random_tests.cpp \
+ test/rbf_tests.cpp \
test/rest_tests.cpp \
+ test/result_tests.cpp \
test/reverselock_tests.cpp \
test/rpc_tests.cpp \
test/sanity_tests.cpp \
@@ -167,6 +169,7 @@ BITCOIN_TESTS += \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/wallet_transaction_tests.cpp \
wallet/test/coinselector_tests.cpp \
+ wallet/test/availablecoins_tests.cpp \
wallet/test/init_tests.cpp \
wallet/test/ismine_tests.cpp \
wallet/test/scriptpubkeyman_tests.cpp
@@ -336,7 +339,7 @@ nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
-CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno test/fuzz/*.gcda test/fuzz/*.gcno test/util/*.gcda test/util/*.gcno $(GENERATED_TEST_FILES) $(BITCOIN_TESTS:=.log)
+CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno test/fuzz/*.gcda test/fuzz/*.gcno test/util/*.gcda test/util/*.gcno $(GENERATED_TEST_FILES) $(addsuffix .log,$(basename $(BITCOIN_TESTS)))
CLEANFILES += $(CLEAN_BITCOIN_TEST)
@@ -412,12 +415,3 @@ endif
echo "};};"; \
} > "$@.new" && mv -f "$@.new" "$@"
@echo "Generated $@"
-
-%.raw.h: %.raw
- @$(MKDIR_P) $(@D)
- @{ \
- echo "static unsigned const char $(*F)_raw[] = {" && \
- $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
- echo "};"; \
- } > "$@.new" && mv -f "$@.new" "$@"
- @echo "Generated $@"
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 204bb544c5..f16ff2230b 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -14,10 +14,10 @@
#include <random.h>
#include <serialize.h>
#include <streams.h>
-#include <timedata.h>
#include <tinyformat.h>
#include <uint256.h>
#include <util/check.h>
+#include <util/time.h>
#include <cmath>
#include <optional>
@@ -29,19 +29,19 @@ static constexpr uint32_t ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP{64};
/** Maximum number of times an address can occur in the new table */
static constexpr int32_t ADDRMAN_NEW_BUCKETS_PER_ADDRESS{8};
/** How old addresses can maximally be */
-static constexpr int64_t ADDRMAN_HORIZON_DAYS{30};
+static constexpr auto ADDRMAN_HORIZON{30 * 24h};
/** After how many failed attempts we give up on a new node */
static constexpr int32_t ADDRMAN_RETRIES{3};
/** How many successive failures are allowed ... */
static constexpr int32_t ADDRMAN_MAX_FAILURES{10};
-/** ... in at least this many days */
-static constexpr int64_t ADDRMAN_MIN_FAIL_DAYS{7};
+/** ... in at least this duration */
+static constexpr auto ADDRMAN_MIN_FAIL{7 * 24h};
/** How recent a successful connection should be before we allow an address to be evicted from tried */
-static constexpr int64_t ADDRMAN_REPLACEMENT_HOURS{4};
+static constexpr auto ADDRMAN_REPLACEMENT{4h};
/** The maximum number of tried addr collisions to store */
static constexpr size_t ADDRMAN_SET_TRIED_COLLISION_SIZE{10};
-/** The maximum time we'll spend trying to resolve a tried table collision, in seconds */
-static constexpr int64_t ADDRMAN_TEST_WINDOW{40*60}; // 40 minutes
+/** The maximum time we'll spend trying to resolve a tried table collision */
+static constexpr auto ADDRMAN_TEST_WINDOW{40min};
int AddrInfo::GetTriedBucket(const uint256& nKey, const NetGroupManager& netgroupman) const
{
@@ -64,36 +64,39 @@ int AddrInfo::GetBucketPosition(const uint256& nKey, bool fNew, int nBucket) con
return hash1 % ADDRMAN_BUCKET_SIZE;
}
-bool AddrInfo::IsTerrible(int64_t nNow) const
+bool AddrInfo::IsTerrible(NodeSeconds now) const
{
- if (nNow - nLastTry <= 60) { // never remove things tried in the last minute
+ if (now - m_last_try <= 1min) { // never remove things tried in the last minute
return false;
}
- if (nTime > nNow + 10 * 60) // came in a flying DeLorean
+ if (nTime > now + 10min) { // came in a flying DeLorean
return true;
+ }
- if (nNow - nTime > ADDRMAN_HORIZON_DAYS * 24 * 60 * 60) { // not seen in recent history
+ if (now - nTime > ADDRMAN_HORIZON) { // not seen in recent history
return true;
}
- if (nLastSuccess == 0 && nAttempts >= ADDRMAN_RETRIES) // tried N times and never a success
+ if (TicksSinceEpoch<std::chrono::seconds>(m_last_success) == 0 && nAttempts >= ADDRMAN_RETRIES) { // tried N times and never a success
return true;
+ }
- if (nNow - nLastSuccess > ADDRMAN_MIN_FAIL_DAYS * 24 * 60 * 60 && nAttempts >= ADDRMAN_MAX_FAILURES) // N successive failures in the last week
+ if (now - m_last_success > ADDRMAN_MIN_FAIL && nAttempts >= ADDRMAN_MAX_FAILURES) { // N successive failures in the last week
return true;
+ }
return false;
}
-double AddrInfo::GetChance(int64_t nNow) const
+double AddrInfo::GetChance(NodeSeconds now) const
{
double fChance = 1.0;
- int64_t nSinceLastTry = std::max<int64_t>(nNow - nLastTry, 0);
// deprioritize very recent attempts away
- if (nSinceLastTry < 60 * 10)
+ if (now - m_last_try < 10min) {
fChance *= 0.01;
+ }
// deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages.
fChance *= pow(0.66, std::min(nAttempts, 8));
@@ -540,7 +543,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
info.fInTried = true;
}
-bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
AssertLockHeld(cs);
@@ -552,15 +555,15 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
// Do not set a penalty for a source's self-announcement
if (addr == source) {
- nTimePenalty = 0;
+ time_penalty = 0s;
}
if (pinfo) {
// periodically update nTime
- bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
- int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
- if (pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty) {
- pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty);
+ const bool currently_online{NodeClock::now() - addr.nTime < 24h};
+ const auto update_interval{currently_online ? 1h : 24h};
+ if (pinfo->nTime < addr.nTime - update_interval - time_penalty) {
+ pinfo->nTime = std::max(NodeSeconds{0s}, addr.nTime - time_penalty);
}
// add services
@@ -587,7 +590,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
return false;
} else {
pinfo = Create(addr, source, &nId);
- pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
+ pinfo->nTime = std::max(NodeSeconds{0s}, pinfo->nTime - time_penalty);
nNew++;
}
@@ -617,13 +620,13 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
return fInsert;
}
-bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
+bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, NodeSeconds time)
{
AssertLockHeld(cs);
int nId;
- nLastGood = nTime;
+ m_last_good = time;
AddrInfo* pinfo = Find(addr, &nId);
@@ -633,8 +636,8 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
AddrInfo& info = *pinfo;
// update info
- info.nLastSuccess = nTime;
- info.nLastTry = nTime;
+ info.m_last_success = time;
+ info.m_last_try = time;
info.nAttempts = 0;
// nTime is not updated here, to avoid leaking information about
// currently-connected peers.
@@ -671,11 +674,11 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
}
}
-bool AddrManImpl::Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrManImpl::Add_(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
int added{0};
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) {
- added += AddSingle(*it, source, nTimePenalty) ? 1 : 0;
+ added += AddSingle(*it, source, time_penalty) ? 1 : 0;
}
if (added > 0) {
LogPrint(BCLog::ADDRMAN, "Added %i addresses (of %i) from %s: %i tried, %i new\n", added, vAddr.size(), source.ToString(), nTried, nNew);
@@ -683,7 +686,7 @@ bool AddrManImpl::Add_(const std::vector<CAddress> &vAddr, const CNetAddr& sourc
return added > 0;
}
-void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
+void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, NodeSeconds time)
{
AssertLockHeld(cs);
@@ -696,14 +699,14 @@ void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTi
AddrInfo& info = *pinfo;
// update info
- info.nLastTry = nTime;
- if (fCountFailure && info.nLastCountAttempt < nLastGood) {
- info.nLastCountAttempt = nTime;
+ info.m_last_try = time;
+ if (fCountFailure && info.m_last_count_attempt < m_last_good) {
+ info.m_last_count_attempt = time;
info.nAttempts++;
}
}
-std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
+std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool newOnly) const
{
AssertLockHeld(cs);
@@ -736,7 +739,7 @@ std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
// With probability GetChance() * fChanceFactor, return the entry.
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from tried\n", info.ToString());
- return {info, info.nLastTry};
+ return {info, info.m_last_try};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
fChanceFactor *= 1.2;
@@ -764,7 +767,7 @@ std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
// With probability GetChance() * fChanceFactor, return the entry.
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from new\n", info.ToString());
- return {info, info.nLastTry};
+ return {info, info.m_last_try};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
fChanceFactor *= 1.2;
@@ -785,7 +788,7 @@ std::vector<CAddress> AddrManImpl::GetAddr_(size_t max_addresses, size_t max_pct
}
// gather a list of random nodes, skipping those of low quality
- const int64_t now{GetAdjustedTime()};
+ const auto now{Now<NodeSeconds>()};
std::vector<CAddress> addresses;
for (unsigned int n = 0; n < vRandom.size(); n++) {
if (addresses.size() >= nNodes)
@@ -810,7 +813,7 @@ std::vector<CAddress> AddrManImpl::GetAddr_(size_t max_addresses, size_t max_pct
return addresses;
}
-void AddrManImpl::Connected_(const CService& addr, int64_t nTime)
+void AddrManImpl::Connected_(const CService& addr, NodeSeconds time)
{
AssertLockHeld(cs);
@@ -823,9 +826,10 @@ void AddrManImpl::Connected_(const CService& addr, int64_t nTime)
AddrInfo& info = *pinfo;
// update info
- int64_t nUpdateInterval = 20 * 60;
- if (nTime - info.nTime > nUpdateInterval)
- info.nTime = nTime;
+ const auto update_interval{20min};
+ if (time - info.nTime > update_interval) {
+ info.nTime = time;
+ }
}
void AddrManImpl::SetServices_(const CService& addr, ServiceFlags nServices)
@@ -870,22 +874,22 @@ void AddrManImpl::ResolveCollisions_()
int id_old = vvTried[tried_bucket][tried_bucket_pos];
AddrInfo& info_old = mapInfo[id_old];
- const auto current_time{GetAdjustedTime()};
+ const auto current_time{Now<NodeSeconds>()};
// Has successfully connected in last X hours
- if (current_time - info_old.nLastSuccess < ADDRMAN_REPLACEMENT_HOURS*(60*60)) {
+ if (current_time - info_old.m_last_success < ADDRMAN_REPLACEMENT) {
erase_collision = true;
- } else if (current_time - info_old.nLastTry < ADDRMAN_REPLACEMENT_HOURS*(60*60)) { // attempted to connect and failed in last X hours
+ } else if (current_time - info_old.m_last_try < ADDRMAN_REPLACEMENT) { // attempted to connect and failed in last X hours
// Give address at least 60 seconds to successfully connect
- if (current_time - info_old.nLastTry > 60) {
+ if (current_time - info_old.m_last_try > 60s) {
LogPrint(BCLog::ADDRMAN, "Replacing %s with %s in tried table\n", info_old.ToString(), info_new.ToString());
// Replaces an existing address already in the tried table with the new address
Good_(info_new, false, current_time);
erase_collision = true;
}
- } else if (current_time - info_new.nLastSuccess > ADDRMAN_TEST_WINDOW) {
+ } else if (current_time - info_new.m_last_success > ADDRMAN_TEST_WINDOW) {
// If the collision hasn't resolved in some reasonable amount of time,
// just evict the old entry -- we must not be able to
// connect to it for some reason.
@@ -894,7 +898,7 @@ void AddrManImpl::ResolveCollisions_()
erase_collision = true;
}
} else { // Collision is not actually a collision anymore
- Good_(info_new, false, GetAdjustedTime());
+ Good_(info_new, false, Now<NodeSeconds>());
erase_collision = true;
}
}
@@ -907,7 +911,7 @@ void AddrManImpl::ResolveCollisions_()
}
}
-std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()
+std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision_()
{
AssertLockHeld(cs);
@@ -932,7 +936,7 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()
int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
const AddrInfo& info_old = mapInfo[vvTried[tried_bucket][tried_bucket_pos]];
- return {info_old, info_old.nLastTry};
+ return {info_old, info_old.m_last_try};
}
std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& addr)
@@ -990,8 +994,9 @@ int AddrManImpl::CheckAddrman() const
int n = entry.first;
const AddrInfo& info = entry.second;
if (info.fInTried) {
- if (!info.nLastSuccess)
+ if (!TicksSinceEpoch<std::chrono::seconds>(info.m_last_success)) {
return -1;
+ }
if (info.nRefCount)
return -2;
setTried.insert(n);
@@ -1008,10 +1013,12 @@ int AddrManImpl::CheckAddrman() const
}
if (info.nRandomPos < 0 || (size_t)info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n)
return -14;
- if (info.nLastTry < 0)
+ if (info.m_last_try < NodeSeconds{0s}) {
return -6;
- if (info.nLastSuccess < 0)
+ }
+ if (info.m_last_success < NodeSeconds{0s}) {
return -8;
+ }
}
if (setTried.size() != (size_t)nTried)
@@ -1067,29 +1074,29 @@ size_t AddrManImpl::size() const
return vRandom.size();
}
-bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
LOCK(cs);
Check();
- auto ret = Add_(vAddr, source, nTimePenalty);
+ auto ret = Add_(vAddr, source, time_penalty);
Check();
return ret;
}
-bool AddrManImpl::Good(const CService& addr, int64_t nTime)
+bool AddrManImpl::Good(const CService& addr, NodeSeconds time)
{
LOCK(cs);
Check();
- auto ret = Good_(addr, /*test_before_evict=*/true, nTime);
+ auto ret = Good_(addr, /*test_before_evict=*/true, time);
Check();
return ret;
}
-void AddrManImpl::Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
+void AddrManImpl::Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
{
LOCK(cs);
Check();
- Attempt_(addr, fCountFailure, nTime);
+ Attempt_(addr, fCountFailure, time);
Check();
}
@@ -1101,7 +1108,7 @@ void AddrManImpl::ResolveCollisions()
Check();
}
-std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision()
+std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision()
{
LOCK(cs);
Check();
@@ -1110,7 +1117,7 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision()
return ret;
}
-std::pair<CAddress, int64_t> AddrManImpl::Select(bool newOnly) const
+std::pair<CAddress, NodeSeconds> AddrManImpl::Select(bool newOnly) const
{
LOCK(cs);
Check();
@@ -1128,11 +1135,11 @@ std::vector<CAddress> AddrManImpl::GetAddr(size_t max_addresses, size_t max_pct,
return addresses;
}
-void AddrManImpl::Connected(const CService& addr, int64_t nTime)
+void AddrManImpl::Connected(const CService& addr, NodeSeconds time)
{
LOCK(cs);
Check();
- Connected_(addr, nTime);
+ Connected_(addr, time);
Check();
}
@@ -1184,19 +1191,19 @@ size_t AddrMan::size() const
return m_impl->size();
}
-bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
- return m_impl->Add(vAddr, source, nTimePenalty);
+ return m_impl->Add(vAddr, source, time_penalty);
}
-bool AddrMan::Good(const CService& addr, int64_t nTime)
+bool AddrMan::Good(const CService& addr, NodeSeconds time)
{
- return m_impl->Good(addr, nTime);
+ return m_impl->Good(addr, time);
}
-void AddrMan::Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
+void AddrMan::Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
{
- m_impl->Attempt(addr, fCountFailure, nTime);
+ m_impl->Attempt(addr, fCountFailure, time);
}
void AddrMan::ResolveCollisions()
@@ -1204,12 +1211,12 @@ void AddrMan::ResolveCollisions()
m_impl->ResolveCollisions();
}
-std::pair<CAddress, int64_t> AddrMan::SelectTriedCollision()
+std::pair<CAddress, NodeSeconds> AddrMan::SelectTriedCollision()
{
return m_impl->SelectTriedCollision();
}
-std::pair<CAddress, int64_t> AddrMan::Select(bool newOnly) const
+std::pair<CAddress, NodeSeconds> AddrMan::Select(bool newOnly) const
{
return m_impl->Select(newOnly);
}
@@ -1219,9 +1226,9 @@ std::vector<CAddress> AddrMan::GetAddr(size_t max_addresses, size_t max_pct, std
return m_impl->GetAddr(max_addresses, max_pct, network);
}
-void AddrMan::Connected(const CService& addr, int64_t nTime)
+void AddrMan::Connected(const CService& addr, NodeSeconds time)
{
- m_impl->Connected(addr, nTime);
+ m_impl->Connected(addr, time);
}
void AddrMan::SetServices(const CService& addr, ServiceFlags nServices)
diff --git a/src/addrman.h b/src/addrman.h
index a0063e8a9c..5099c8c7a3 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -10,7 +10,7 @@
#include <netgroup.h>
#include <protocol.h>
#include <streams.h>
-#include <timedata.h>
+#include <util/time.h>
#include <cstdint>
#include <memory>
@@ -107,23 +107,23 @@ public:
*
* @param[in] vAddr Address records to attempt to add.
* @param[in] source The address of the node that sent us these addr records.
- * @param[in] nTimePenalty A "time penalty" to apply to the address record's nTime. If a peer
+ * @param[in] time_penalty A "time penalty" to apply to the address record's nTime. If a peer
* sends us an address record with nTime=n, then we'll add it to our
- * addrman with nTime=(n - nTimePenalty).
+ * addrman with nTime=(n - time_penalty).
* @return true if at least one address is successfully added. */
- bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty = 0);
+ bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty = 0s);
/**
* Mark an address record as accessible and attempt to move it to addrman's tried table.
*
* @param[in] addr Address record to attempt to move to tried table.
- * @param[in] nTime The time that we were last connected to this peer.
+ * @param[in] time The time that we were last connected to this peer.
* @return true if the address is successfully moved from the new table to the tried table.
*/
- bool Good(const CService& addr, int64_t nTime = GetAdjustedTime());
+ bool Good(const CService& addr, NodeSeconds time = Now<NodeSeconds>());
//! Mark an entry as connection attempted to.
- void Attempt(const CService& addr, bool fCountFailure, int64_t nTime = GetAdjustedTime());
+ void Attempt(const CService& addr, bool fCountFailure, NodeSeconds time = Now<NodeSeconds>());
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
void ResolveCollisions();
@@ -133,18 +133,18 @@ public:
* attempting to evict.
*
* @return CAddress The record for the selected tried peer.
- * int64_t The last time we attempted to connect to that peer.
+ * seconds The last time we attempted to connect to that peer.
*/
- std::pair<CAddress, int64_t> SelectTriedCollision();
+ std::pair<CAddress, NodeSeconds> SelectTriedCollision();
/**
* Choose an address to connect to.
*
* @param[in] newOnly Whether to only select addresses from the new table.
* @return CAddress The record for the selected peer.
- * int64_t The last time we attempted to connect to that peer.
+ * seconds The last time we attempted to connect to that peer.
*/
- std::pair<CAddress, int64_t> Select(bool newOnly = false) const;
+ std::pair<CAddress, NodeSeconds> Select(bool newOnly = false) const;
/**
* Return all or many randomly selected addresses, optionally by network.
@@ -166,9 +166,9 @@ public:
* not leak information about currently connected peers.
*
* @param[in] addr The address of the peer we were connected to
- * @param[in] nTime The time that we were last connected to this peer
+ * @param[in] time The time that we were last connected to this peer
*/
- void Connected(const CService& addr, int64_t nTime = GetAdjustedTime());
+ void Connected(const CService& addr, NodeSeconds time = Now<NodeSeconds>());
//! Update an entry's service bits.
void SetServices(const CService& addr, ServiceFlags nServices);
diff --git a/src/addrman_impl.h b/src/addrman_impl.h
index 9d98cdde54..376e79f49f 100644
--- a/src/addrman_impl.h
+++ b/src/addrman_impl.h
@@ -11,7 +11,9 @@
#include <protocol.h>
#include <serialize.h>
#include <sync.h>
+#include <timedata.h>
#include <uint256.h>
+#include <util/time.h>
#include <cstdint>
#include <optional>
@@ -38,16 +40,16 @@ class AddrInfo : public CAddress
{
public:
//! last try whatsoever by us (memory only)
- int64_t nLastTry{0};
+ NodeSeconds m_last_try{0s};
//! last counted attempt (memory only)
- int64_t nLastCountAttempt{0};
+ NodeSeconds m_last_count_attempt{0s};
//! where knowledge about this address first came from
CNetAddr source;
//! last successful connection by us
- int64_t nLastSuccess{0};
+ NodeSeconds m_last_success{0s};
//! connection attempts since last successful attempt
int nAttempts{0};
@@ -64,7 +66,7 @@ public:
SERIALIZE_METHODS(AddrInfo, obj)
{
READWRITEAS(CAddress, obj);
- READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
+ READWRITE(obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
}
AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
@@ -91,10 +93,10 @@ public:
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
//! Determine whether the statistics about this entry are bad enough so that it can just be deleted
- bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
+ bool IsTerrible(NodeSeconds now = Now<NodeSeconds>()) const;
//! Calculate the relative chance this entry should be given when selecting nodes to connect to
- double GetChance(int64_t nNow = GetAdjustedTime()) const;
+ double GetChance(NodeSeconds now = Now<NodeSeconds>()) const;
};
class AddrManImpl
@@ -112,26 +114,26 @@ public:
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
- bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
+ bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
- bool Good(const CService& addr, int64_t nTime)
+ bool Good(const CService& addr, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
- void Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
+ void Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs);
- std::pair<CAddress, int64_t> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
+ std::pair<CAddress, NodeSeconds> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
- std::pair<CAddress, int64_t> Select(bool newOnly) const
+ std::pair<CAddress, NodeSeconds> Select(bool newOnly) const
EXCLUSIVE_LOCKS_REQUIRED(!cs);
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
EXCLUSIVE_LOCKS_REQUIRED(!cs);
- void Connected(const CService& addr, int64_t nTime)
+ void Connected(const CService& addr, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
void SetServices(const CService& addr, ServiceFlags nServices)
@@ -202,7 +204,7 @@ private:
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
//! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
- int64_t nLastGood GUARDED_BY(cs){1};
+ NodeSeconds m_last_good GUARDED_BY(cs){1s};
//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
std::set<int> m_tried_collisions;
@@ -233,25 +235,25 @@ private:
/** Attempt to add a single address to addrman's new table.
* @see AddrMan::Add() for parameters. */
- bool AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool AddSingle(const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
- bool Good_(const CService& addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool Good_(const CService& addr, bool test_before_evict, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
- bool Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool Add_(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
- void Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void Attempt_(const CService& addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
- std::pair<CAddress, int64_t> Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ std::pair<CAddress, NodeSeconds> Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
std::vector<CAddress> GetAddr_(size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
- void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void Connected_(const CService& addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
void SetServices_(const CService& addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
- std::pair<CAddress, int64_t> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
+ std::pair<CAddress, NodeSeconds> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);
diff --git a/src/bench/addrman.cpp b/src/bench/addrman.cpp
index 76300f4db8..f14d1f89b6 100644
--- a/src/bench/addrman.cpp
+++ b/src/bench/addrman.cpp
@@ -43,7 +43,7 @@ static void CreateAddresses()
CAddress ret(CService(addr, port), NODE_NETWORK);
- ret.nTime = GetAdjustedTime();
+ ret.nTime = Now<NodeSeconds>();
return ret;
};
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index eaefb9b63a..a80ec3703c 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -56,10 +56,10 @@ static void CoinSelection(benchmark::Bench& bench)
addCoin(3 * COIN, wallet, wtxs);
// Create coins
- std::vector<COutput> coins;
+ wallet::CoinsResult available_coins;
for (const auto& wtx : wtxs) {
const auto txout = wtx->tx->vout.at(0);
- coins.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.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);
@@ -76,7 +76,7 @@ static void CoinSelection(benchmark::Bench& bench)
/*avoid_partial=*/ false,
};
bench.run([&] {
- auto result = AttemptSelection(wallet, 1003 * COIN, filter_standard, coins, coin_selection_params);
+ auto result = AttemptSelection(wallet, 1003 * COIN, filter_standard, available_coins, coin_selection_params, /*allow_mixed_output_types=*/true);
assert(result);
assert(result->GetSelectedValue() == 1003 * COIN);
assert(result->GetInputSet().size() == 2);
diff --git a/src/bench/descriptors.cpp b/src/bench/descriptors.cpp
new file mode 100644
index 0000000000..5c868a8573
--- /dev/null
+++ b/src/bench/descriptors.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <key.h>
+#include <script/descriptor.h>
+#include <script/standard.h>
+
+#include <string>
+#include <utility>
+
+static void ExpandDescriptor(benchmark::Bench& bench)
+{
+ const auto desc_str = "sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))";
+ const std::pair<int64_t, int64_t> range = {0, 1000};
+ FlatSigningProvider provider;
+ std::string error;
+ auto desc = Parse(desc_str, provider, error);
+
+ bench.run([&] {
+ for (int i = range.first; i <= range.second; ++i) {
+ std::vector<CScript> scripts;
+ bool success = desc->Expand(i, provider, scripts, provider);
+ assert(success);
+ }
+ });
+}
+
+BENCHMARK(ExpandDescriptor);
diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
index a10f7ff7d1..27e4dd015d 100644
--- a/src/bench/wallet_loading.cpp
+++ b/src/bench/wallet_loading.cpp
@@ -45,11 +45,8 @@ static void BenchUnloadWallet(std::shared_ptr<CWallet>&& wallet)
static void AddTx(CWallet& wallet)
{
- const auto& dest = wallet.GetNewDestination(OutputType::BECH32, "");
- assert(dest.HasRes());
-
CMutableTransaction mtx;
- mtx.vout.push_back({COIN, GetScriptForDestination(dest.GetObj())});
+ mtx.vout.push_back({COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, "")))});
mtx.vin.push_back(CTxIn());
wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{});
diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp
index 4656cb23e7..fc3f91d492 100644
--- a/src/bitcoin-chainstate.cpp
+++ b/src/bitcoin-chainstate.cpp
@@ -13,6 +13,7 @@
#include <kernel/checks.h>
#include <kernel/context.h>
+#include <kernel/validation_cache_sizes.h>
#include <chainparams.h>
#include <consensus/validation.h>
@@ -62,8 +63,9 @@ int main(int argc, char* argv[])
// Necessary for CheckInputScripts (eventually called by ProcessNewBlock),
// which will try the script cache first and fall back to actually
// performing the check with the signature cache.
- InitSignatureCache();
- InitScriptExecutionCache();
+ kernel::ValidationCacheSizes validation_cache_sizes{};
+ Assert(InitSignatureCache(validation_cache_sizes.signature_cache_bytes));
+ Assert(InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes));
// SETUP: Scheduling and Background Signals
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 7cc956ebda..6ce4e05e4d 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -807,7 +807,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
if (failedToGetAuthCookie) {
throw std::runtime_error(strprintf(
"Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
- fs::PathToString(GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)))));
+ fs::PathToString(GetConfigFile(gArgs.GetPathArg("-conf", BITCOIN_CONF_FILENAME)))));
} else {
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
}
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index 1ad6872143..0ff79bb3ca 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -148,7 +148,7 @@ bool GCSFilter::MatchAny(const ElementSet& elements) const
const std::string& BlockFilterTypeName(BlockFilterType filter_type)
{
- static std::string unknown_retval = "";
+ static std::string unknown_retval;
auto it = g_filter_types.find(filter_type);
return it != g_filter_types.end() ? it->second : unknown_retval;
}
diff --git a/src/chain.cpp b/src/chain.cpp
index 0f898bafd5..446bb216c2 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -18,11 +18,9 @@ std::string CBlockIndex::ToString() const
pprev, nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString());
}
-void CChain::SetTip(CBlockIndex *pindex) {
- if (pindex == nullptr) {
- vChain.clear();
- return;
- }
+void CChain::SetTip(CBlockIndex& block)
+{
+ CBlockIndex* pindex = &block;
vChain.resize(pindex->nHeight + 1);
while (pindex && vChain[pindex->nHeight] != pindex) {
vChain[pindex->nHeight] = pindex;
diff --git a/src/chain.h b/src/chain.h
index 627a3dfab2..1c5cd3f1f6 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -465,7 +465,7 @@ public:
}
/** Set/initialize a chain with a given tip. */
- void SetTip(CBlockIndex* pindex);
+ void SetTip(CBlockIndex& block);
/** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const;
diff --git a/src/coins.cpp b/src/coins.cpp
index 1abdcb54d2..1753d33b71 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -99,9 +99,9 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
TRACE5(utxocache, add,
outpoint.hash.data(),
(uint32_t)outpoint.n,
- (uint32_t)coin.nHeight,
- (int64_t)coin.out.nValue,
- (bool)coin.IsCoinBase());
+ (uint32_t)it->second.coin.nHeight,
+ (int64_t)it->second.coin.out.nValue,
+ (bool)it->second.coin.IsCoinBase());
}
void CCoinsViewCache::EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coin) {
diff --git a/src/crc32c/CMakeLists.txt b/src/crc32c/CMakeLists.txt
index 71692d5796..2f52db104c 100644
--- a/src/crc32c/CMakeLists.txt
+++ b/src/crc32c/CMakeLists.txt
@@ -296,9 +296,10 @@ target_include_directories(crc32c
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
-target_compile_definitions(crc32c
-PRIVATE
- CRC32C_HAVE_CONFIG_H=1
+set_property(
+ TARGET crc32c_arm64 crc32c_sse42 crc32c
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS CRC32C_HAVE_CONFIG_H
)
set_target_properties(crc32c
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index d0dc61c7e6..61f553806e 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -12,7 +12,9 @@
#include <atomic>
#include <cmath>
#include <cstring>
+#include <limits>
#include <memory>
+#include <optional>
#include <utility>
#include <vector>
@@ -326,7 +328,7 @@ public:
}
/** setup initializes the container to store no more than new_size
- * elements.
+ * elements and no less than 2 elements.
*
* setup should only be called once.
*
@@ -336,8 +338,8 @@ public:
uint32_t setup(uint32_t new_size)
{
// depth_limit must be at least one otherwise errors can occur.
- depth_limit = static_cast<uint8_t>(std::log2(static_cast<float>(std::max((uint32_t)2, new_size))));
size = std::max<uint32_t>(2, new_size);
+ depth_limit = static_cast<uint8_t>(std::log2(static_cast<float>(size)));
table.resize(size);
collection_flags.setup(size);
epoch_flags.resize(size);
@@ -357,12 +359,21 @@ public:
*
* @param bytes the approximate number of bytes to use for this data
* structure
- * @returns the maximum number of elements storable (see setup()
- * documentation for more detail)
+ * @returns A pair of the maximum number of elements storable (see setup()
+ * documentation for more detail) and the approxmiate total size of these
+ * elements in bytes or std::nullopt if the size requested is too large.
*/
- uint32_t setup_bytes(size_t bytes)
+ std::optional<std::pair<uint32_t, size_t>> setup_bytes(size_t bytes)
{
- return setup(bytes/sizeof(Element));
+ size_t requested_num_elems = bytes / sizeof(Element);
+ if (std::numeric_limits<uint32_t>::max() < requested_num_elems) {
+ return std::nullopt;
+ }
+
+ auto num_elems = setup(bytes/sizeof(Element));
+
+ size_t approx_size_bytes = num_elems * sizeof(Element);
+ return std::make_pair(num_elems, approx_size_bytes);
}
/** insert loops at most depth_limit times trying to insert a hash
diff --git a/src/external_signer.cpp b/src/external_signer.cpp
index d125fe479b..6bab0a856c 100644
--- a/src/external_signer.cpp
+++ b/src/external_signer.cpp
@@ -49,7 +49,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
if (signer.m_fingerprint.compare(fingerprintStr) == 0) duplicate = true;
}
if (duplicate) break;
- std::string name = "";
+ std::string name;
const UniValue& model_field = find_value(signer, "model");
if (model_field.isStr() && model_field.getValStr() != "") {
name += model_field.getValStr();
diff --git a/src/init.cpp b/src/init.cpp
index a94bbe6460..4606b77e9f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -11,6 +11,7 @@
#include <kernel/checks.h>
#include <kernel/mempool_persist.h>
+#include <kernel/validation_cache_sizes.h>
#include <addrman.h>
#include <banman.h>
@@ -31,7 +32,6 @@
#include <interfaces/init.h>
#include <interfaces/node.h>
#include <mapport.h>
-#include <mempool_args.h>
#include <net.h>
#include <net_permissions.h>
#include <net_processing.h>
@@ -42,8 +42,10 @@
#include <node/chainstate.h>
#include <node/context.h>
#include <node/interface_ui.h>
+#include <node/mempool_args.h>
#include <node/mempool_persist_args.h>
#include <node/miner.h>
+#include <node/validation_cache_args.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/fees_args.h>
@@ -105,7 +107,9 @@
#endif
using kernel::DumpMempool;
+using kernel::ValidationCacheSizes;
+using node::ApplyArgsManOptions;
using node::CacheSizes;
using node::CalculateCacheSizes;
using node::DEFAULT_PERSIST_MEMPOOL;
@@ -548,7 +552,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-addrmantest", "Allows to test address relay on localhost", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-capturemessages", "Capture all P2P messages to disk", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-printpriority", strprintf("Log transaction fee rate in " + CURRENCY_UNIT + "/kvB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
@@ -935,16 +939,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
}
- // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
- // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
- if (args.IsArgSet("-incrementalrelayfee")) {
- if (std::optional<CAmount> inc_relay_fee = ParseMoney(args.GetArg("-incrementalrelayfee", ""))) {
- ::incrementalRelayFee = CFeeRate{inc_relay_fee.value()};
- } else {
- return InitError(AmountErrMsg("incrementalrelayfee", args.GetArg("-incrementalrelayfee", "")));
- }
- }
-
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
int64_t nPruneArg = args.GetIntArg("-prune", 0);
if (nPruneArg < 0) {
@@ -973,19 +967,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
return InitError(Untranslated("peertimeout must be a positive integer."));
}
- if (args.IsArgSet("-minrelaytxfee")) {
- if (std::optional<CAmount> min_relay_fee = ParseMoney(args.GetArg("-minrelaytxfee", ""))) {
- // High fee check is done afterward in CWallet::Create()
- ::minRelayTxFee = CFeeRate{min_relay_fee.value()};
- } else {
- return InitError(AmountErrMsg("minrelaytxfee", args.GetArg("-minrelaytxfee", "")));
- }
- } else if (incrementalRelayFee > ::minRelayTxFee) {
- // Allow only setting incrementalRelayFee to control both
- ::minRelayTxFee = incrementalRelayFee;
- LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n",::minRelayTxFee.ToString());
- }
-
// Sanity check argument for min fee for including tx in block
// TODO: Harmonize which arguments need sanity checking and where that happens
if (args.IsArgSet("-blockmintxfee")) {
@@ -994,28 +975,10 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
}
}
- // Feerate used to define dust. Shouldn't be changed lightly as old
- // implementations may inadvertently create non-standard transactions
- if (args.IsArgSet("-dustrelayfee")) {
- if (std::optional<CAmount> parsed = ParseMoney(args.GetArg("-dustrelayfee", ""))) {
- dustRelayFee = CFeeRate{parsed.value()};
- } else {
- return InitError(AmountErrMsg("dustrelayfee", args.GetArg("-dustrelayfee", "")));
- }
- }
-
- fRequireStandard = !args.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
- if (!chainparams.IsTestChain() && !fRequireStandard) {
- return InitError(strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString()));
- }
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
if (!g_wallet_init_interface.ParameterInteraction()) return false;
- fIsBareMultisigStd = args.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
- fAcceptDatacarrier = args.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
- nMaxDatacarrierBytes = args.GetIntArg("-datacarriersize", nMaxDatacarrierBytes);
-
// Option to startup with mocktime set (used for regression testing):
SetMockTime(args.GetIntArg("-mocktime", 0)); // SetMockTime(0) is a no-op
@@ -1156,8 +1119,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));
}
- InitSignatureCache();
- InitScriptExecutionCache();
+ ValidationCacheSizes validation_cache_sizes{};
+ ApplyArgsManOptions(args, validation_cache_sizes);
+ if (!InitSignatureCache(validation_cache_sizes.signature_cache_bytes)
+ || !InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes))
+ {
+ return InitError(strprintf(_("Unable to allocate memory for -maxsigcachesize: '%s' MiB"), args.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_BYTES >> 20)));
+ }
int script_threads = args.GetIntArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (script_threads <= 0) {
@@ -1418,7 +1386,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
.estimator = node.fee_estimator.get(),
.check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
};
- ApplyArgsManOptions(args, mempool_opts);
+ if (const auto err{ApplyArgsManOptions(args, chainparams, mempool_opts)}) {
+ return InitError(*err);
+ }
mempool_opts.check_ratio = std::clamp<int>(mempool_opts.check_ratio, 0, 1'000'000);
int64_t descendant_limit_bytes = mempool_opts.limits.descendant_size_vbytes * 40;
diff --git a/src/init/common.cpp b/src/init/common.cpp
index a0cdf44f47..bdd7f16307 100644
--- a/src/init/common.cpp
+++ b/src/init/common.cpp
@@ -99,7 +99,7 @@ bool StartLogging(const ArgsManager& args)
LogPrintf("Using data directory %s\n", fs::PathToString(gArgs.GetDataDirNet()));
// Only log conf file usage message if conf file actually exists.
- fs::path config_file_path = GetConfigFile(args.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ fs::path config_file_path = GetConfigFile(args.GetPathArg("-conf", BITCOIN_CONF_FILENAME));
if (fs::exists(config_file_path)) {
LogPrintf("Config file: %s\n", fs::PathToString(config_file_path));
} else if (args.IsArgSet("-conf")) {
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index e29fefae56..1148dc7e4c 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -88,7 +88,7 @@ public:
virtual std::string getWalletName() = 0;
// Get a new address.
- virtual BResult<CTxDestination> getNewDestination(const OutputType type, const std::string label) = 0;
+ virtual util::Result<CTxDestination> getNewDestination(const OutputType type, const std::string& label) = 0;
//! Get public key.
virtual bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) = 0;
@@ -139,7 +139,7 @@ public:
virtual void listLockedCoins(std::vector<COutPoint>& outputs) = 0;
//! Create transaction.
- virtual BResult<CTransactionRef> createTransaction(const std::vector<wallet::CRecipient>& recipients,
+ virtual util::Result<CTransactionRef> createTransaction(const std::vector<wallet::CRecipient>& recipients,
const wallet::CCoinControl& coin_control,
bool sign,
int& change_pos,
@@ -183,7 +183,7 @@ public:
virtual WalletTx getWalletTx(const uint256& txid) = 0;
//! Get list of all wallet transactions.
- virtual std::vector<WalletTx> getWalletTxs() = 0;
+ virtual std::set<WalletTx> getWalletTxs() = 0;
//! Try to get updated status for a particular transaction, if possible without blocking.
virtual bool tryGetTxStatus(const uint256& txid,
@@ -320,31 +320,31 @@ class WalletLoader : public ChainClient
{
public:
//! Create new wallet.
- virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
+ virtual util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) = 0;
- //! Load existing wallet.
- virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
+ //! Load existing wallet.
+ virtual util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) = 0;
- //! Return default wallet directory.
- virtual std::string getWalletDir() = 0;
+ //! Return default wallet directory.
+ virtual std::string getWalletDir() = 0;
- //! Restore backup wallet
- virtual BResult<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) = 0;
+ //! Restore backup wallet
+ virtual util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) = 0;
- //! Return available wallets in wallet directory.
- virtual std::vector<std::string> listWalletDir() = 0;
+ //! Return available wallets in wallet directory.
+ virtual std::vector<std::string> listWalletDir() = 0;
- //! Return interfaces for accessing wallets (if any).
- virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
+ //! Return interfaces for accessing wallets (if any).
+ virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
- //! Register handler for load wallet messages. This callback is triggered by
- //! createWallet and loadWallet above, and also triggered when wallets are
- //! loaded at startup or by RPC.
- using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
- virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
+ //! Register handler for load wallet messages. This callback is triggered by
+ //! createWallet and loadWallet above, and also triggered when wallets are
+ //! loaded at startup or by RPC.
+ using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
+ virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
- //! Return pointer to internal context, useful for testing.
- virtual wallet::WalletContext* context() { return nullptr; }
+ //! Return pointer to internal context, useful for testing.
+ virtual wallet::WalletContext* context() { return nullptr; }
};
//! Information about one wallet address.
@@ -395,6 +395,8 @@ struct WalletTx
int64_t time;
std::map<std::string, std::string> value_map;
bool is_coinbase;
+
+ bool operator<(const WalletTx& a) const { return tx->GetHash() < a.tx->GetHash(); }
};
//! Updated transaction status.
diff --git a/src/kernel/mempool_options.h b/src/kernel/mempool_options.h
index 07953b443b..dad6f14c39 100644
--- a/src/kernel/mempool_options.h
+++ b/src/kernel/mempool_options.h
@@ -6,8 +6,13 @@
#include <kernel/mempool_limits.h>
+#include <policy/feerate.h>
+#include <policy/policy.h>
+#include <script/standard.h>
+
#include <chrono>
#include <cstdint>
+#include <optional>
class CBlockPolicyEstimator;
@@ -33,6 +38,20 @@ struct MemPoolOptions {
int check_ratio{0};
int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000};
std::chrono::seconds expiry{std::chrono::hours{DEFAULT_MEMPOOL_EXPIRY_HOURS}};
+ CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ /** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
+ CFeeRate min_relay_feerate{DEFAULT_MIN_RELAY_TX_FEE};
+ CFeeRate dust_relay_feerate{DUST_RELAY_TX_FEE};
+ /**
+ * A data carrying output is an unspendable output containing data. The script
+ * type is designated as TxoutType::NULL_DATA.
+ *
+ * Maximum size of TxoutType::NULL_DATA scripts that this node considers standard.
+ * If nullopt, any size is nonstandard.
+ */
+ std::optional<unsigned> max_datacarrier_bytes{DEFAULT_ACCEPT_DATACARRIER ? std::optional{MAX_OP_RETURN_RELAY} : std::nullopt};
+ bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG};
+ bool require_standard{true};
bool full_rbf{DEFAULT_MEMPOOL_FULL_RBF};
MemPoolLimits limits{};
};
diff --git a/src/kernel/validation_cache_sizes.h b/src/kernel/validation_cache_sizes.h
new file mode 100644
index 0000000000..72e4d1a52c
--- /dev/null
+++ b/src/kernel/validation_cache_sizes.h
@@ -0,0 +1,20 @@
+// 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.
+
+#ifndef BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
+#define BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
+
+#include <script/sigcache.h>
+
+#include <cstddef>
+#include <limits>
+
+namespace kernel {
+struct ValidationCacheSizes {
+ size_t signature_cache_bytes{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
+ size_t script_execution_cache_bytes{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
+};
+}
+
+#endif // BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
diff --git a/src/key.cpp b/src/key.cpp
index 9b0971a2dd..199808505d 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -333,6 +333,7 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
}
bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
+ if (nDepth == std::numeric_limits<unsigned char>::max()) return false;
out.nDepth = nDepth + 1;
CKeyID id = key.GetPubKey().GetID();
memcpy(out.vchFingerprint, &id, 4);
diff --git a/src/key.h b/src/key.h
index 12d03778a0..e9b78ebd44 100644
--- a/src/key.h
+++ b/src/key.h
@@ -146,7 +146,7 @@ public:
bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const;
//! Derive BIP32 child key.
- bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
+ [[nodiscard]] bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
/**
* Verify thoroughly whether a private key and a public key match.
@@ -176,7 +176,7 @@ struct CExtKey {
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
- bool Derive(CExtKey& out, unsigned int nChild) const;
+ [[nodiscard]] bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const;
void SetSeed(Span<const std::byte> seed);
};
diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
index 18626b327c..fac41be6ce 100644
--- a/src/leveldb/util/env_posix.cc
+++ b/src/leveldb/util/env_posix.cc
@@ -49,7 +49,7 @@ constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 4096 : 0;
int g_mmap_limit = kDefaultMmapLimit;
// Common flags defined for all posix open operations
-#if defined(HAVE_O_CLOEXEC)
+#if HAVE_O_CLOEXEC
constexpr const int kOpenBaseFlags = O_CLOEXEC;
#else
constexpr const int kOpenBaseFlags = 0;
diff --git a/src/mempool_args.cpp b/src/mempool_args.cpp
deleted file mode 100644
index 77caa127e9..0000000000
--- a/src/mempool_args.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.
-
-#include <mempool_args.h>
-
-#include <kernel/mempool_limits.h>
-#include <kernel/mempool_options.h>
-
-#include <util/system.h>
-
-using kernel::MemPoolLimits;
-using kernel::MemPoolOptions;
-
-namespace {
-void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolLimits& mempool_limits)
-{
- mempool_limits.ancestor_count = argsman.GetIntArg("-limitancestorcount", mempool_limits.ancestor_count);
-
- if (auto vkb = argsman.GetIntArg("-limitancestorsize")) mempool_limits.ancestor_size_vbytes = *vkb * 1'000;
-
- mempool_limits.descendant_count = argsman.GetIntArg("-limitdescendantcount", mempool_limits.descendant_count);
-
- if (auto vkb = argsman.GetIntArg("-limitdescendantsize")) mempool_limits.descendant_size_vbytes = *vkb * 1'000;
-}
-}
-
-void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolOptions& mempool_opts)
-{
- mempool_opts.check_ratio = argsman.GetIntArg("-checkmempool", mempool_opts.check_ratio);
-
- if (auto mb = argsman.GetIntArg("-maxmempool")) mempool_opts.max_size_bytes = *mb * 1'000'000;
-
- if (auto hours = argsman.GetIntArg("-mempoolexpiry")) mempool_opts.expiry = std::chrono::hours{*hours};
-
- mempool_opts.full_rbf = argsman.GetBoolArg("-mempoolfullrbf", mempool_opts.full_rbf);
-
- ApplyArgsManOptions(argsman, mempool_opts.limits);
-}
diff --git a/src/net.cpp b/src/net.cpp
index 83e6ff2745..865ce2ea97 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -187,7 +187,7 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
// it'll get a pile of addresses with newer timestamps.
// Seed nodes are given a random 'last seen time' of between one and two
// weeks ago.
- const int64_t nOneWeek = 7*24*60*60;
+ const auto one_week{7 * 24h};
std::vector<CAddress> vSeedsOut;
FastRandomContext rng;
CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
@@ -195,7 +195,7 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
CService endpoint;
s >> endpoint;
CAddress addr{endpoint, GetDesirableServiceFlags(NODE_NONE)};
- addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
+ addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - one_week, -one_week);
LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToString());
vSeedsOut.push_back(addr);
}
@@ -208,12 +208,11 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
// one by discovery.
CService GetLocalAddress(const CNetAddr& addrPeer)
{
- CService ret{CNetAddr(), GetListenPort()};
CService addr;
if (GetLocal(addr, &addrPeer)) {
- ret = CService{addr};
+ return addr;
}
- return ret;
+ return CService{CNetAddr(), GetListenPort()};
}
static int GetnScore(const CService& addr)
@@ -452,10 +451,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
}
}
- /// debug print
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "trying connection %s lastseen=%.1fhrs\n",
- pszDest ? pszDest : addrConnect.ToString(),
- pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0);
+ pszDest ? pszDest : addrConnect.ToString(),
+ Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.nTime));
// Resolve
const uint16_t default_port{pszDest != nullptr ? Params().GetDefaultPort(pszDest) :
@@ -1469,9 +1467,8 @@ void CConnman::ThreadDNSAddressSeed()
unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed
if (LookupHost(host, vIPs, nMaxIPs, true)) {
for (const CNetAddr& ip : vIPs) {
- int nOneDay = 24*3600;
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
- addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old
+ addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
}
@@ -1737,7 +1734,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
addrman.ResolveCollisions();
- int64_t nANow = GetAdjustedTime();
+ const auto current_time{NodeClock::now()};
int nTries = 0;
while (!interruptNet)
{
@@ -1760,7 +1757,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
break;
CAddress addr;
- int64_t addr_last_try{0};
+ NodeSeconds addr_last_try{0s};
if (fFeeler) {
// First, try to get a tried table collision address. This returns
@@ -1800,8 +1797,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
continue;
// only consider very recently tried nodes after 30 failed attempts
- if (nANow - addr_last_try < 600 && nTries < 30)
+ if (current_time - addr_last_try < 10min && nTries < 30) {
continue;
+ }
// for non-feelers, require all the services we'll want,
// for feelers, only require they be a full node (only because most
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 1a81c500c8..ed78ae5a81 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -29,6 +29,7 @@
#include <scheduler.h>
#include <streams.h>
#include <sync.h>
+#include <timedata.h>
#include <tinyformat.h>
#include <txmempool.h>
#include <txorphanage.h>
@@ -2935,7 +2936,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// indicate to the peer that we will participate in addr relay.
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
{
- CAddress addr{GetLocalAddress(pfrom.addr), peer->m_our_services, (uint32_t)GetAdjustedTime()};
+ CAddress addr{GetLocalAddress(pfrom.addr), peer->m_our_services, Now<NodeSeconds>()};
FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
@@ -3140,8 +3141,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// Store the new addresses
std::vector<CAddress> vAddrOk;
- int64_t nNow = GetAdjustedTime();
- int64_t nSince = nNow - 10 * 60;
+ const auto current_a_time{Now<NodeSeconds>()};
// Update/increment addr rate limiting bucket.
const auto current_time{GetTime<std::chrono::microseconds>()};
@@ -3177,8 +3177,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (!MayHaveUsefulAddressDB(addr.nServices) && !HasAllDesirableServiceFlags(addr.nServices))
continue;
- if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
- addr.nTime = nNow - 5 * 24 * 60 * 60;
+ if (addr.nTime <= NodeSeconds{100000000s} || addr.nTime > current_a_time + 10min) {
+ addr.nTime = current_a_time - 5 * 24h;
+ }
AddAddressKnown(*peer, addr);
if (m_banman && (m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr))) {
// Do not process banned/discouraged addresses beyond remembering we received them
@@ -3186,7 +3187,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
++num_proc;
bool fReachable = IsReachable(addr);
- if (addr.nTime > nSince && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
+ if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
// Relay to a limited number of other nodes
RelayAddress(pfrom.GetId(), addr, fReachable);
}
@@ -3199,7 +3200,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
vAddr.size(), num_proc, num_rate_limit, pfrom.GetId());
- m_addrman.Add(vAddrOk, pfrom.addr, 2 * 60 * 60);
+ m_addrman.Add(vAddrOk, pfrom.addr, 2h);
if (vAddr.size() < 1000) peer->m_getaddr_sent = false;
// AddrFetch: Require multiple addresses to avoid disconnecting on self-announcements
@@ -3657,10 +3658,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// DoS prevention: do not allow m_orphanage to grow unbounded (see CVE-2012-3789)
unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, gArgs.GetIntArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
- unsigned int nEvicted = m_orphanage.LimitOrphans(nMaxOrphanTx);
- if (nEvicted > 0) {
- LogPrint(BCLog::MEMPOOL, "orphanage overflow, removed %u tx\n", nEvicted);
- }
+ m_orphanage.LimitOrphans(nMaxOrphanTx);
} else {
LogPrint(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
// We will continue to reject this tx since it has rejected
@@ -4712,7 +4710,7 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
peer.m_addr_known->reset();
}
if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
- CAddress local_addr{*local_service, peer.m_our_services, (uint32_t)GetAdjustedTime()};
+ CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
FastRandomContext insecure_rand;
PushAddress(peer, local_addr, insecure_rand);
}
@@ -4788,8 +4786,8 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
}
if (current_time > peer.m_next_send_feefilter) {
CAmount filterToSend = g_filter_rounder.round(currentFilter);
- // We always have a fee filter of at least minRelayTxFee
- filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
+ // We always have a fee filter of at least the min relay fee
+ filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
if (filterToSend != peer.m_fee_filter_sent) {
m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend));
peer.m_fee_filter_sent = filterToSend;
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index bac05f6be2..601d0bdf58 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -21,6 +21,7 @@
#include <util/system.h>
#include <validation.h>
+#include <map>
#include <unordered_map>
namespace node {
@@ -834,6 +835,9 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
// -reindex
if (fReindex) {
int nFile = 0;
+ // Map of disk positions for blocks with unknown parent (only used for reindex);
+ // parent hash -> child disk position, multiple children can have the same parent.
+ std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
while (true) {
FlatFilePos pos(nFile, 0);
if (!fs::exists(GetBlockPosFilename(pos))) {
@@ -844,7 +848,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
break; // This error is logged in OpenBlockFile
}
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
- chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos);
+ chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index be7e3992f0..2c845d0127 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -36,7 +36,6 @@
#include <shutdown.h>
#include <support/allocators/secure.h>
#include <sync.h>
-#include <timedata.h>
#include <txmempool.h>
#include <uint256.h>
#include <univalue.h>
@@ -67,6 +66,8 @@ using interfaces::Node;
using interfaces::WalletLoader;
namespace node {
+// All members of the classes in this namespace are intentionally public, as the
+// classes themselves are private.
namespace {
#ifdef ENABLE_EXTERNAL_SIGNER
class ExternalSignerImpl : public interfaces::ExternalSigner
@@ -74,15 +75,12 @@ class ExternalSignerImpl : public interfaces::ExternalSigner
public:
ExternalSignerImpl(::ExternalSigner signer) : m_signer(std::move(signer)) {}
std::string getName() override { return m_signer.m_name; }
-private:
::ExternalSigner m_signer;
};
#endif
class NodeImpl : public Node
{
-private:
- ChainstateManager& chainman() { return *Assert(m_context->chainman); }
public:
explicit NodeImpl(NodeContext& context) { setContext(&context); }
void initLogging() override { InitLogging(*Assert(m_context->args)); }
@@ -289,12 +287,7 @@ public:
}
double getVerificationProgress() override
{
- const CBlockIndex* tip;
- {
- LOCK(::cs_main);
- tip = chainman().ActiveChain().Tip();
- }
- return GuessVerificationProgress(chainman().GetParams().TxData(), tip);
+ return GuessVerificationProgress(chainman().GetParams().TxData(), WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()));
}
bool isInitialBlockDownload() override {
return chainman().ActiveChainstate().IsInitialBlockDownload();
@@ -308,7 +301,11 @@ public:
}
}
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
- CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
+ CFeeRate getDustRelayFee() override
+ {
+ if (!m_context->mempool) return CFeeRate{DUST_RELAY_TX_FEE};
+ return m_context->mempool->m_dust_relay_feerate;
+ }
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
{
JSONRPCRequest req;
@@ -390,6 +387,7 @@ public:
{
m_context = context;
}
+ ChainstateManager& chainman() { return *Assert(m_context->chainman); }
NodeContext* m_context{nullptr};
};
@@ -502,40 +500,28 @@ public:
class ChainImpl : public Chain
{
-private:
- ChainstateManager& chainman() { return *Assert(m_node.chainman); }
public:
explicit ChainImpl(NodeContext& node) : m_node(node) {}
std::optional<int> getHeight() override
{
- LOCK(::cs_main);
- const CChain& active = chainman().ActiveChain();
- int height = active.Height();
- if (height >= 0) {
- return height;
- }
- return std::nullopt;
+ const int height{WITH_LOCK(::cs_main, return chainman().ActiveChain().Height())};
+ return height >= 0 ? std::optional{height} : std::nullopt;
}
uint256 getBlockHash(int height) override
{
LOCK(::cs_main);
- const CChain& active = chainman().ActiveChain();
- CBlockIndex* block = active[height];
- assert(block);
- return block->GetBlockHash();
+ return Assert(chainman().ActiveChain()[height])->GetBlockHash();
}
bool haveBlockOnDisk(int height) override
{
LOCK(::cs_main);
- const CChain& active = chainman().ActiveChain();
- CBlockIndex* block = active[height];
+ const CBlockIndex* block{chainman().ActiveChain()[height]};
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
CBlockLocator getTipLocator() override
{
LOCK(::cs_main);
- const CChain& active = chainman().ActiveChain();
- return active.GetLocator();
+ return chainman().ActiveChain().GetLocator();
}
CBlockLocator getActiveChainLocator(const uint256& block_hash) override
{
@@ -547,8 +533,7 @@ public:
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LOCK(::cs_main);
- const CChainState& active = chainman().ActiveChainstate();
- if (const CBlockIndex* fork = active.FindForkInGlobalIndex(locator)) {
+ if (const CBlockIndex* fork = chainman().ActiveChainstate().FindForkInGlobalIndex(locator)) {
return fork->nHeight;
}
return std::nullopt;
@@ -556,8 +541,7 @@ public:
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = chainman().ActiveChain();
- return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, active);
+ return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain());
}
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
{
@@ -579,11 +563,10 @@ public:
bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = chainman().ActiveChain();
const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash);
const CBlockIndex* ancestor = chainman().m_blockman.LookupBlockIndex(ancestor_hash);
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
- return FillBlock(ancestor, ancestor_out, lock, active);
+ return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain());
}
bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
{
@@ -697,9 +680,21 @@ public:
if (!m_node.mempool) return {};
return m_node.mempool->GetMinFee();
}
- CFeeRate relayMinFee() override { return ::minRelayTxFee; }
- CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
- CFeeRate relayDustFee() override { return ::dustRelayFee; }
+ CFeeRate relayMinFee() override
+ {
+ if (!m_node.mempool) return CFeeRate{DEFAULT_MIN_RELAY_TX_FEE};
+ return m_node.mempool->m_min_relay_feerate;
+ }
+ CFeeRate relayIncrementalFee() override
+ {
+ if (!m_node.mempool) return CFeeRate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ return m_node.mempool->m_incremental_relay_feerate;
+ }
+ CFeeRate relayDustFee() override
+ {
+ if (!m_node.mempool) return CFeeRate{DUST_RELAY_TX_FEE};
+ return m_node.mempool->m_dust_relay_feerate;
+ }
bool havePruned() override
{
LOCK(::cs_main);
@@ -723,11 +718,7 @@ public:
}
void waitForNotificationsIfTipChanged(const uint256& old_tip) override
{
- if (!old_tip.IsNull()) {
- LOCK(::cs_main);
- const CChain& active = chainman().ActiveChain();
- if (old_tip == active.Tip()->GetBlockHash()) return;
- }
+ if (!old_tip.IsNull() && old_tip == WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()->GetBlockHash())) return;
SyncWithValidationInterfaceQueue();
}
std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
@@ -783,6 +774,7 @@ public:
}
NodeContext* context() override { return &m_node; }
+ ChainstateManager& chainman() { return *Assert(m_node.chainman); }
NodeContext& m_node;
};
} // namespace
diff --git a/src/node/mempool_args.cpp b/src/node/mempool_args.cpp
new file mode 100644
index 0000000000..60993f1d8d
--- /dev/null
+++ b/src/node/mempool_args.cpp
@@ -0,0 +1,99 @@
+// 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.
+
+#include <node/mempool_args.h>
+
+#include <kernel/mempool_limits.h>
+#include <kernel/mempool_options.h>
+
+#include <chainparams.h>
+#include <consensus/amount.h>
+#include <logging.h>
+#include <policy/feerate.h>
+#include <policy/policy.h>
+#include <tinyformat.h>
+#include <util/error.h>
+#include <util/moneystr.h>
+#include <util/system.h>
+#include <util/translation.h>
+
+#include <chrono>
+#include <memory>
+
+using kernel::MemPoolLimits;
+using kernel::MemPoolOptions;
+
+namespace {
+void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolLimits& mempool_limits)
+{
+ mempool_limits.ancestor_count = argsman.GetIntArg("-limitancestorcount", mempool_limits.ancestor_count);
+
+ if (auto vkb = argsman.GetIntArg("-limitancestorsize")) mempool_limits.ancestor_size_vbytes = *vkb * 1'000;
+
+ mempool_limits.descendant_count = argsman.GetIntArg("-limitdescendantcount", mempool_limits.descendant_count);
+
+ if (auto vkb = argsman.GetIntArg("-limitdescendantsize")) mempool_limits.descendant_size_vbytes = *vkb * 1'000;
+}
+}
+
+std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, MemPoolOptions& mempool_opts)
+{
+ mempool_opts.check_ratio = argsman.GetIntArg("-checkmempool", mempool_opts.check_ratio);
+
+ if (auto mb = argsman.GetIntArg("-maxmempool")) mempool_opts.max_size_bytes = *mb * 1'000'000;
+
+ if (auto hours = argsman.GetIntArg("-mempoolexpiry")) mempool_opts.expiry = std::chrono::hours{*hours};
+
+ // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
+ // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
+ if (argsman.IsArgSet("-incrementalrelayfee")) {
+ if (std::optional<CAmount> inc_relay_fee = ParseMoney(argsman.GetArg("-incrementalrelayfee", ""))) {
+ mempool_opts.incremental_relay_feerate = CFeeRate{inc_relay_fee.value()};
+ } else {
+ return AmountErrMsg("incrementalrelayfee", argsman.GetArg("-incrementalrelayfee", ""));
+ }
+ }
+
+ if (argsman.IsArgSet("-minrelaytxfee")) {
+ if (std::optional<CAmount> min_relay_feerate = ParseMoney(argsman.GetArg("-minrelaytxfee", ""))) {
+ // High fee check is done afterward in CWallet::Create()
+ mempool_opts.min_relay_feerate = CFeeRate{min_relay_feerate.value()};
+ } else {
+ return AmountErrMsg("minrelaytxfee", argsman.GetArg("-minrelaytxfee", ""));
+ }
+ } else if (mempool_opts.incremental_relay_feerate > mempool_opts.min_relay_feerate) {
+ // Allow only setting incremental fee to control both
+ mempool_opts.min_relay_feerate = mempool_opts.incremental_relay_feerate;
+ LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n", mempool_opts.min_relay_feerate.ToString());
+ }
+
+ // Feerate used to define dust. Shouldn't be changed lightly as old
+ // implementations may inadvertently create non-standard transactions
+ if (argsman.IsArgSet("-dustrelayfee")) {
+ if (std::optional<CAmount> parsed = ParseMoney(argsman.GetArg("-dustrelayfee", ""))) {
+ mempool_opts.dust_relay_feerate = CFeeRate{parsed.value()};
+ } else {
+ return AmountErrMsg("dustrelayfee", argsman.GetArg("-dustrelayfee", ""));
+ }
+ }
+
+ mempool_opts.permit_bare_multisig = argsman.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
+
+ if (argsman.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER)) {
+ mempool_opts.max_datacarrier_bytes = argsman.GetIntArg("-datacarriersize", MAX_OP_RETURN_RELAY);
+ } else {
+ mempool_opts.max_datacarrier_bytes = std::nullopt;
+ }
+
+ mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
+ if (!chainparams.IsTestChain() && !mempool_opts.require_standard) {
+ return strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString());
+ }
+
+ mempool_opts.full_rbf = argsman.GetBoolArg("-mempoolfullrbf", mempool_opts.full_rbf);
+
+ ApplyArgsManOptions(argsman, mempool_opts.limits);
+
+ return std::nullopt;
+}
diff --git a/src/mempool_args.h b/src/node/mempool_args.h
index 9a4abe6618..52d8b4f265 100644
--- a/src/mempool_args.h
+++ b/src/node/mempool_args.h
@@ -2,21 +2,26 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_MEMPOOL_ARGS_H
-#define BITCOIN_MEMPOOL_ARGS_H
+#ifndef BITCOIN_NODE_MEMPOOL_ARGS_H
+#define BITCOIN_NODE_MEMPOOL_ARGS_H
+
+#include <optional>
class ArgsManager;
+class CChainParams;
+struct bilingual_str;
namespace kernel {
struct MemPoolOptions;
};
/**
* Overlay the options set in \p argsman on top of corresponding members in \p mempool_opts.
+ * Returns an error if one was encountered.
*
* @param[in] argsman The ArgsManager in which to check set options.
* @param[in,out] mempool_opts The MemPoolOptions to modify according to \p argsman.
*/
-void ApplyArgsManOptions(const ArgsManager& argsman, kernel::MemPoolOptions& mempool_opts);
+[[nodiscard]] std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, kernel::MemPoolOptions& mempool_opts);
-#endif // BITCOIN_MEMPOOL_ARGS_H
+#endif // BITCOIN_NODE_MEMPOOL_ARGS_H
diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp
index 5a932f435d..57162cd679 100644
--- a/src/node/psbt.cpp
+++ b/src/node/psbt.cpp
@@ -137,7 +137,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
if (success) {
CTransaction ctx = CTransaction(mtx);
- size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
+ size_t size(GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS), ::nBytesPerSigOp));
result.estimated_vsize = size;
// Estimate fee rate
CFeeRate feerate(fee, size);
diff --git a/src/node/validation_cache_args.cpp b/src/node/validation_cache_args.cpp
new file mode 100644
index 0000000000..5ea0a8ca0a
--- /dev/null
+++ b/src/node/validation_cache_args.cpp
@@ -0,0 +1,34 @@
+// 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.
+
+#include <node/validation_cache_args.h>
+
+#include <kernel/validation_cache_sizes.h>
+
+#include <util/system.h>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+
+using kernel::ValidationCacheSizes;
+
+namespace node {
+void ApplyArgsManOptions(const ArgsManager& argsman, ValidationCacheSizes& cache_sizes)
+{
+ if (auto max_size = argsman.GetIntArg("-maxsigcachesize")) {
+ // 1. When supplied with a max_size of 0, both InitSignatureCache and
+ // InitScriptExecutionCache create the minimum possible cache (2
+ // elements). Therefore, we can use 0 as a floor here.
+ // 2. Multiply first, divide after to avoid integer truncation.
+ size_t clamped_size_each = std::max<int64_t>(*max_size, 0) * (1 << 20) / 2;
+ cache_sizes = {
+ .signature_cache_bytes = clamped_size_each,
+ .script_execution_cache_bytes = clamped_size_each,
+ };
+ }
+}
+} // namespace node
diff --git a/src/node/validation_cache_args.h b/src/node/validation_cache_args.h
new file mode 100644
index 0000000000..f447c13b49
--- /dev/null
+++ b/src/node/validation_cache_args.h
@@ -0,0 +1,17 @@
+// 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.
+
+#ifndef BITCOIN_NODE_VALIDATION_CACHE_ARGS_H
+#define BITCOIN_NODE_VALIDATION_CACHE_ARGS_H
+
+class ArgsManager;
+namespace kernel {
+struct ValidationCacheSizes;
+};
+
+namespace node {
+void ApplyArgsManOptions(const ArgsManager& argsman, kernel::ValidationCacheSizes& cache_sizes);
+} // namespace node
+
+#endif // BITCOIN_NODE_VALIDATION_CACHE_ARGS_H
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index 19366295e6..5be9942d7d 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -91,8 +91,6 @@ CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore,
case OutputType::BECH32: {
CTxDestination witdest = WitnessV0ScriptHash(script);
CScript witprog = GetScriptForDestination(witdest);
- // Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
- if (!IsSolvable(keystore, witprog)) return ScriptHash(script);
// Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
keystore.AddCScript(witprog);
if (type == OutputType::BECH32) {
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index f6452266b7..5086542865 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -67,7 +67,7 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}
-bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
+bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType)
{
std::vector<std::vector<unsigned char> > vSolutions;
whichType = Solver(scriptPubKey, vSolutions);
@@ -82,15 +82,16 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
return false;
if (m < 1 || m > n)
return false;
- } else if (whichType == TxoutType::NULL_DATA &&
- (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
- return false;
+ } else if (whichType == TxoutType::NULL_DATA) {
+ if (!max_datacarrier_bytes || scriptPubKey.size() > *max_datacarrier_bytes) {
+ return false;
+ }
}
return true;
}
-bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
+bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
{
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
@@ -130,7 +131,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
unsigned int nDataOut = 0;
TxoutType whichType;
for (const CTxOut& txout : tx.vout) {
- if (!::IsStandard(txout.scriptPubKey, whichType)) {
+ if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
reason = "scriptpubkey";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index cd98a601a3..3d2660b081 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -47,8 +47,8 @@ static constexpr unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE{80};
static constexpr unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE{3600};
/** The maximum size of a standard ScriptSig */
static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650};
-/** Min feerate for defining dust. Historically this has been based on the
- * minRelayTxFee, however changing the dust limit changes which transactions are
+/** Min feerate for defining dust.
+ * Changing the dust limit changes which transactions are
* standard and should be done with care and ideally rarely. It makes sense to
* only increase the dust limit after prior releases were already not creating
* outputs below the new threshold */
@@ -105,7 +105,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
-bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
+bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType);
// Changing the default transaction version requires a two step process: first
@@ -117,7 +117,7 @@ static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
* Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
-bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
+bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
diff --git a/src/policy/settings.cpp b/src/policy/settings.cpp
index 0b67d274ce..39e00f1111 100644
--- a/src/policy/settings.cpp
+++ b/src/policy/settings.cpp
@@ -5,11 +5,6 @@
#include <policy/settings.h>
-#include <policy/feerate.h>
#include <policy/policy.h>
-bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
-CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
-CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
-CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
diff --git a/src/policy/settings.h b/src/policy/settings.h
index 2311d01fe8..f0d6f779ae 100644
--- a/src/policy/settings.h
+++ b/src/policy/settings.h
@@ -6,35 +6,6 @@
#ifndef BITCOIN_POLICY_SETTINGS_H
#define BITCOIN_POLICY_SETTINGS_H
-#include <policy/feerate.h>
-#include <policy/policy.h>
-
-#include <cstdint>
-#include <string>
-
-class CTransaction;
-
-// Policy settings which are configurable at runtime.
-extern CFeeRate incrementalRelayFee;
-extern CFeeRate dustRelayFee;
-/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
-extern CFeeRate minRelayTxFee;
extern unsigned int nBytesPerSigOp;
-extern bool fIsBareMultisigStd;
-
-static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
-{
- return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
-}
-
-static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
-{
- return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
-}
-
-static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
-{
- return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
-}
#endif // BITCOIN_POLICY_SETTINGS_H
diff --git a/src/protocol.h b/src/protocol.h
index da2d24aff3..b85dc0d820 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -11,6 +11,7 @@
#include <serialize.h>
#include <streams.h>
#include <uint256.h>
+#include <util/time.h>
#include <cstdint>
#include <limits>
@@ -352,7 +353,7 @@ static inline bool MayHaveUsefulAddressDB(ServiceFlags services)
/** A CService with information about it as peer */
class CAddress : public CService
{
- static constexpr uint32_t TIME_INIT{100000000};
+ static constexpr std::chrono::seconds TIME_INIT{100000000};
/** Historically, CAddress disk serialization stored the CLIENT_VERSION, optionally OR'ed with
* the ADDRV2_FORMAT flag to indicate V2 serialization. The first field has since been
@@ -382,7 +383,7 @@ class CAddress : public CService
public:
CAddress() : CService{} {};
CAddress(CService ipIn, ServiceFlags nServicesIn) : CService{ipIn}, nServices{nServicesIn} {};
- CAddress(CService ipIn, ServiceFlags nServicesIn, uint32_t nTimeIn) : CService{ipIn}, nTime{nTimeIn}, nServices{nServicesIn} {};
+ CAddress(CService ipIn, ServiceFlags nServicesIn, NodeSeconds time) : CService{ipIn}, nTime{time}, nServices{nServicesIn} {};
SERIALIZE_METHODS(CAddress, obj)
{
@@ -415,7 +416,7 @@ public:
use_v2 = s.GetVersion() & ADDRV2_FORMAT;
}
- READWRITE(obj.nTime);
+ READWRITE(Using<LossyChronoFormatter<uint32_t>>(obj.nTime));
// nServices is serialized as CompactSize in V2; as uint64_t in V1.
if (use_v2) {
uint64_t services_tmp;
@@ -430,8 +431,8 @@ public:
SerReadWriteMany(os, ser_action, ReadWriteAsHelper<CService>(obj));
}
- //! Always included in serialization.
- uint32_t nTime{TIME_INIT};
+ //! Always included in serialization. The behavior is unspecified if the value is not representable as uint32_t.
+ NodeSeconds nTime{TIME_INIT};
//! Serialized as uint64_t in V1, and as CompactSize in V2.
ServiceFlags nServices{NODE_NONE};
diff --git a/src/psbt.h b/src/psbt.h
index eef7d7dd3b..d5c67802c7 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -641,6 +641,9 @@ struct PSBTInput
s >> leaf_hashes;
size_t after_hashes = s.size();
size_t hashes_len = before_hashes - after_hashes;
+ if (hashes_len > value_len) {
+ throw std::ios_base::failure("Input Taproot BIP32 keypath has an invalid length");
+ }
size_t origin_len = value_len - hashes_len;
m_tap_bip32_paths.emplace(xonly, std::make_pair(leaf_hashes, DeserializeKeyOrigin(s, origin_len)));
break;
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index a4a1be6388..2e37e16690 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -365,6 +365,7 @@ void CExtPubKey::DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VE
}
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
+ if (nDepth == std::numeric_limits<unsigned char>::max()) return false;
out.nDepth = nDepth + 1;
CKeyID id = pubkey.GetID();
memcpy(out.vchFingerprint, &id, 4);
diff --git a/src/pubkey.h b/src/pubkey.h
index 463efe1b00..0485a38f72 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -218,7 +218,7 @@ public:
bool Decompress();
//! Derive BIP32 child pubkey.
- bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
+ [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
};
class XOnlyPubKey
@@ -327,7 +327,7 @@ struct CExtPubKey {
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
- bool Derive(CExtPubKey& out, unsigned int nChild) const;
+ [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
};
/** Users of this module must hold an ECCVerifyHandle. The constructor and
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index bb50b5384a..8b5da7f9f0 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -384,7 +384,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
return QString();
}
}
- strAddress = EncodeDestination(op_dest.GetObj());
+ strAddress = EncodeDestination(*op_dest);
}
else
{
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index ba804d6955..13694c638d 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -14,9 +14,28 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring "
"a backup."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"%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."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"-maxtxfee is set very high! Fees this large could be paid on a single "
"transaction."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-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."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-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."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-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."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Assumed-valid: last wallet synchronisation goes beyond available block data. "
+"You need to wait for the background validation chain to download more blocks."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Cannot downgrade wallet from version %i to version %i. Wallet version "
"unchanged."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -51,7 +70,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and "
"\"bech32\" address types"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Error: Listening for incoming connections failed (listen returned error %s)"),
+"Failed to rename invalid peers.dat file. Please move or delete it and try "
+"again."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -"
"fallbackfee."),
@@ -77,6 +97,10 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"No wallet file format provided. To use createfromdump, -format=<format> must "
"be provided."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"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)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Please check that your computer's date and time are correct! If your clock "
"is wrong, %s will not work properly."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -85,6 +109,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Prune configured below the minimum of %d MiB. Please use a higher number."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Prune mode is incompatible with -reindex-chainstate. Use full -reindex "
+"instead."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Prune: last wallet synchronisation goes beyond pruned data. You need to -"
"reindex (download the whole blockchain again in case of pruned node)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -129,6 +156,13 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Unknown wallet file format \"%s\" provided. Please provide one of \"bdb\" or "
"\"sqlite\"."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Unsupported chainstate database format found. Please restart with -reindex-"
+"chainstate. This will rebuild the chainstate database."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Wallet created successfully. The legacy wallet type is being deprecated and "
+"support for creating and opening legacy wallets will be removed in the "
+"future."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: Dumpfile wallet format \"%s\" does not match command line specified "
"format \"%s\"."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -169,7 +203,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error reading from database, shutting down."),
QT_TRANSLATE_NOOP("bitcoin-core", "Error reading next record from wallet database"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error upgrading chainstate database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Couldn't create cursor into database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low for %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Dumpfile checksum does not match. Computed %s, expected %s"),
@@ -199,6 +232,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -discardfee=<amount>: '%s'
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -fallbackfee=<amount>: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid netmask specified in -whitelist: '%s'"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Listening for incoming connections failed (listen returned error %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading P2P addresses…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading banlist…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index…"),
@@ -207,10 +241,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Missing amount"),
QT_TRANSLATE_NOOP("bitcoin-core", "Missing solving data for estimating transaction size"),
QT_TRANSLATE_NOOP("bitcoin-core", "Need to specify a port with -whitebind: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "No addresses available"),
-QT_TRANSLATE_NOOP("bitcoin-core", "No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>."),
QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."),
QT_TRANSLATE_NOOP("bitcoin-core", "Prune cannot be configured with a negative value."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Prune mode is incompatible with -coinstatsindex."),
QT_TRANSLATE_NOOP("bitcoin-core", "Prune mode is incompatible with -txindex."),
QT_TRANSLATE_NOOP("bitcoin-core", "Pruning blockstore…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Reducing -maxconnections from %d to %d, because of system limitations."),
@@ -241,6 +273,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Transaction has too long of a mempool chain")
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction must have at least one recipient"),
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction needs a change address, but we can't generate it."),
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unable to allocate memory for -maxsigcachesize: '%s' MiB"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer. %s is probably already running."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to create the PID file '%s': %s"),
@@ -255,7 +288,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Unknown change type '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown new rules activated (versionbit %i)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported logging category %s=%s."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Upgrading UTXO database"),
QT_TRANSLATE_NOOP("bitcoin-core", "User Agent comment (%s) contains unsafe characters."),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet(s)…"),
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 2551be0af3..5cc21dd40b 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -428,7 +428,7 @@ void openDebugLogfile()
bool openBitcoinConf()
{
- fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ fs::path pathConfig = GetConfigFile(gArgs.GetPathArg("-conf", BITCOIN_CONF_FILENAME));
/* Create the file */
std::ofstream configFile{pathConfig, std::ios_base::app};
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 35d8201877..0fe69051a4 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -55,7 +55,7 @@
</message>
<message>
<location line="-30"/>
- <location filename="../addressbookpage.cpp" line="+122"/>
+ <location filename="../addressbookpage.cpp" line="+128"/>
<source>&amp;Delete</source>
<translation>&amp;Delete</translation>
</message>
@@ -313,7 +313,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>BitcoinApplication</name>
<message>
- <location filename="../bitcoin.cpp" line="+433"/>
+ <location filename="../bitcoin.cpp" line="+286"/>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+178"/>
<source>Runaway exception</source>
<translation type="unfinished"></translation>
</message>
@@ -336,7 +341,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+250"/>
+ <location filename="../bitcoingui.cpp" line="+253"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -396,7 +401,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+127"/>
+ <location line="+160"/>
<source>&amp;Minimize</source>
<translation type="unfinished"></translation>
</message>
@@ -406,18 +411,18 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+392"/>
+ <location line="+393"/>
<source>Network activity disabled.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+422"/>
+ <location line="+429"/>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1109"/>
+ <location line="-1150"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -507,17 +512,17 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+10"/>
<source>Close All Wallets…</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+94"/>
+ <location line="+119"/>
<source>&amp;File</source>
<translation>&amp;File</translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+20"/>
<source>&amp;Settings</source>
<translation>&amp;Settings</translation>
</message>
@@ -532,12 +537,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="+456"/>
+ <location line="+457"/>
<source>Syncing Headers (%1%)…</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+47"/>
+ <location line="+48"/>
<source>Synchronizing with network…</source>
<translation type="unfinished"></translation>
</message>
@@ -562,7 +567,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-788"/>
+ <location line="-823"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
@@ -577,12 +582,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+26"/>
<source>&amp;Command-line options</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="+710"/>
+ <location line="+739"/>
<source>Processed %n block(s) of transaction history.</source>
<translation>
<numerusform>Processed %n block of transaction history.</numerusform>
@@ -630,7 +635,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Up to date</translation>
</message>
<message>
- <location line="-747"/>
+ <location line="-808"/>
+ <source>Ctrl+Q</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+26"/>
<source>Load Partially Signed Bitcoin Transaction</source>
<translation type="unfinished"></translation>
</message>
@@ -686,6 +696,18 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
<message>
<location line="+7"/>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Close all wallets</source>
<translation type="unfinished"></translation>
</message>
@@ -715,12 +737,41 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+63"/>
+ <location line="+6"/>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to + restore a wallet.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+71"/>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Window</translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+3"/>
+ <source>Ctrl+M</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
<source>Zoom</source>
<translation type="unfinished"></translation>
</message>
@@ -730,7 +781,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+257"/>
+ <location line="+258"/>
<source>%1 client</source>
<translation type="unfinished"></translation>
</message>
@@ -778,7 +829,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+158"/>
+ <location line="+159"/>
<source>Error: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -849,7 +900,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+23"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</translation>
</message>
@@ -1022,7 +1073,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+155"/>
+ <location line="+154"/>
<source>yes</source>
<translation type="unfinished"></translation>
</message>
@@ -1061,7 +1112,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>CreateWalletActivity</name>
<message>
- <location filename="../walletcontroller.cpp" line="+243"/>
+ <location filename="../walletcontroller.cpp" line="+244"/>
<source>Create Wallet</source>
<extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
<translation type="unfinished"></translation>
@@ -1073,7 +1124,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+29"/>
+ <location line="+33"/>
<source>Create wallet failed</source>
<translation type="unfinished"></translation>
</message>
@@ -1087,6 +1138,11 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<source>Can&apos;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>
@@ -1276,7 +1332,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>HelpMessageDialog</name>
<message>
- <location filename="../utilitydialog.cpp" line="+37"/>
+ <location filename="../utilitydialog.cpp" line="+38"/>
<source>version</source>
<translation type="unfinished">version</translation>
</message>
@@ -1286,7 +1342,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+18"/>
<source>Command-line options</source>
<translation type="unfinished"></translation>
</message>
@@ -1353,20 +1409,29 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<source>Bitcoin</source>
<translation type="unfinished">Bitcoin</translation>
</message>
- <message>
+ <message numerus="yes">
<location line="+162"/>
- <source>%1 GB of space available</source>
- <translation type="unfinished"></translation>
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
- <message>
+ <message numerus="yes">
<location line="+2"/>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished"></translation>
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
- <message>
+ <message numerus="yes">
<location line="+3"/>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished"></translation>
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
<message>
<location line="+72"/>
@@ -1411,7 +1476,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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>
@@ -1521,7 +1586,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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>
@@ -1604,7 +1669,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+272"/>
+ <location line="+227"/>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+45"/>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished"></translation>
</message>
@@ -1916,12 +1986,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+65"/>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+141"/>
+ <location line="+206"/>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1931,7 +1996,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>&amp;Cancel</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+99"/>
+ <location filename="../optionsdialog.cpp" line="+96"/>
<source>Compiled without external signing support (required for external signing)</source>
<extracomment>&quot;External signing&quot; means using devices such as hardware wallets.</extracomment>
<translation type="unfinished"></translation>
@@ -1942,28 +2007,37 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>default</translation>
</message>
<message>
- <location line="+81"/>
+ <location line="+86"/>
<source>none</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+97"/>
+ <location line="+107"/>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation>Confirm options reset</translation>
</message>
<message>
- <location line="+1"/>
- <location line="+70"/>
+ <location line="-9"/>
+ <location line="+79"/>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-75"/>
+ <source>Current settings will be backed up at &quot;%1&quot;.</source>
+ <extracomment>Text explaining to the user that the client&apos;s current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location&apos;s path.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-70"/>
+ <location line="+3"/>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+20"/>
<source>Configuration options</source>
<extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
<translation type="unfinished"></translation>
@@ -2006,6 +2080,14 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <location filename="../optionsmodel.cpp" line="+204"/>
+ <source>Could not read setting &quot;%1&quot;, %2.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<location filename="../forms/overviewpage.ui" line="+14"/>
@@ -2099,7 +2181,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../overviewpage.cpp" line="+187"/>
+ <location filename="../overviewpage.cpp" line="+186"/>
<source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
<translation type="unfinished"></translation>
</message>
@@ -2271,7 +2353,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+173"/>
+ <location filename="../paymentserver.cpp" line="+152"/>
<source>Payment request error</source>
<translation type="unfinished"></translation>
</message>
@@ -2281,7 +2363,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+50"/>
+ <location line="+48"/>
<location line="+16"/>
<location line="+6"/>
<location line="+7"/>
@@ -2315,7 +2397,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<context>
<name>PeerTableModel</name>
<message>
- <location filename="../peertablemodel.h" line="+108"/>
+ <location filename="../peertablemodel.h" line="+112"/>
<source>User Agent</source>
<extracomment>Title of Peers Table column which contains the peer&apos;s User Agent string.</extracomment>
<translation type="unfinished"></translation>
@@ -2327,12 +2409,18 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-15"/>
+ <location line="-18"/>
<source>Peer</source>
<extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+3"/>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+6"/>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
@@ -2369,7 +2457,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">Network</translation>
</message>
<message>
- <location filename="../peertablemodel.cpp" line="+79"/>
+ <location filename="../peertablemodel.cpp" line="+78"/>
<source>Inbound</source>
<extracomment>An Inbound Connection from a Peer.</extracomment>
<translation type="unfinished"></translation>
@@ -2384,17 +2472,22 @@ If you are receiving this error you should request the merchant provide a BIP21
<context>
<name>QObject</name>
<message>
- <location filename="../bitcoinunits.cpp" line="+215"/>
+ <location filename="../bitcoinunits.cpp" line="+197"/>
<source>Amount</source>
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+127"/>
+ <location filename="../guiutil.cpp" line="+129"/>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+546"/>
+ <location line="+288"/>
+ <source>Ctrl+W</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+256"/>
<source>Unroutable</source>
<translation type="unfinished"></translation>
</message>
@@ -2446,23 +2539,27 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+15"/>
+ <location line="+13"/>
+ <location line="+12"/>
<source>%1 d</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="-11"/>
+ <location line="+12"/>
<source>%1 h</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="-11"/>
+ <location line="+12"/>
<source>%1 m</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <location line="+28"/>
+ <location line="-10"/>
+ <location line="+11"/>
+ <location line="+26"/>
<source>%1 s</source>
<translation type="unfinished"></translation>
</message>
@@ -2556,7 +2653,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="-276"/>
+ <location filename="../bitcoin.cpp" line="-294"/>
<source>Do you want to reset settings to default values, or to abort without making changes?</source>
<extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
<translation type="unfinished"></translation>
@@ -2568,7 +2665,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+373"/>
+ <location line="+393"/>
<source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
<translation type="unfinished"></translation>
</message>
@@ -2583,7 +2680,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+74"/>
<source>%1 didn&apos;t yet exit safely…</source>
<translation type="unfinished"></translation>
</message>
@@ -2672,7 +2769,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<location line="+26"/>
<location line="+26"/>
<location line="+26"/>
- <location filename="../rpcconsole.h" line="+139"/>
+ <location filename="../rpcconsole.h" line="+143"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -2791,7 +2888,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<location line="+68"/>
- <location filename="../rpcconsole.cpp" line="+1160"/>
+ <location filename="../rpcconsole.cpp" line="+1155"/>
<source>Select a peer to view detailed information.</source>
<translation type="unfinished"></translation>
</message>
@@ -2833,34 +2930,37 @@ If you are receiving this error you should request the merchant provide a BIP21
<message>
<location line="+23"/>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+23"/>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>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).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Addresses Processed</source>
+ <location line="+26"/>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+23"/>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
+ <location line="-23"/>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+26"/>
<source>Addresses Rate-Limited</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@@ -3021,7 +3121,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-201"/>
+ <location filename="../rpcconsole.cpp" line="-202"/>
<source>In:</source>
<translation type="unfinished"></translation>
</message>
@@ -3066,12 +3166,12 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+41"/>
+ <location line="+42"/>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-457"/>
+ <location filename="../rpcconsole.cpp" line="-458"/>
<source>Inbound: initiated by peer</source>
<extracomment>Explanatory text for an inbound peer connection.</extracomment>
<translation type="unfinished"></translation>
@@ -3177,7 +3277,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+26"/>
<source>&amp;Copy IP/Netmask</source>
<extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer&apos;s IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
<translation type="unfinished"></translation>
@@ -3193,17 +3293,37 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+77"/>
+ <location line="+78"/>
<source>Executing command without any wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-2"/>
+ <location line="+316"/>
+ <source>Ctrl+I</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Ctrl+T</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Ctrl+N</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Ctrl+P</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-321"/>
<source>Executing command using &quot;%1&quot; wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-145"/>
+ <location line="-146"/>
<source>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.
@@ -3215,7 +3335,7 @@ For more information on using this console, type %6.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+155"/>
+ <location line="+156"/>
<source>Executing…</source>
<extracomment>A console message indicating an entered command is currently being executed.</extracomment>
<translation type="unfinished"></translation>
@@ -3231,7 +3351,7 @@ For more information on using this console, type %6.
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.h" line="-41"/>
+ <location filename="../rpcconsole.h" line="-42"/>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
@@ -3446,7 +3566,7 @@ For more information on using this console, type %6.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+41"/>
+ <location line="+38"/>
<source>(no label)</source>
<translation type="unfinished"></translation>
</message>
@@ -3467,10 +3587,43 @@ For more information on using this console, type %6.
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <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>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <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>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+752"/>
+ <location filename="../sendcoinsdialog.cpp" line="+759"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -3657,7 +3810,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-653"/>
+ <location filename="../sendcoinsdialog.cpp" line="-660"/>
<source>Copy quantity</source>
<translation type="unfinished"></translation>
</message>
@@ -3739,29 +3892,29 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+67"/>
+ <location line="+66"/>
<source>To review recipient list click &quot;Show Details…&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+44"/>
+ <location line="+60"/>
<source>Sign failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>External signer not found</source>
<extracomment>&quot;External signer&quot; means using devices such as hardware wallets.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>External signer failure</source>
<extracomment>&quot;External signer&quot; means using devices such as hardware wallets.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+58"/>
+ <location line="-34"/>
<source>Save Transaction Data</source>
<translation type="unfinished"></translation>
</message>
@@ -3777,17 +3930,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+176"/>
+ <location line="+266"/>
<source>External balance:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-303"/>
+ <location line="-315"/>
<source>or</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-19"/>
+ <location line="-18"/>
<source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
<translation type="unfinished"></translation>
</message>
@@ -3826,17 +3979,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+14"/>
+ <location line="+13"/>
<source>Total Amount</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+99"/>
<source>Confirm send coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+284"/>
+ <location line="+222"/>
<source>Watch-only balance:</source>
<translation type="unfinished"></translation>
</message>
@@ -3875,13 +4028,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="+3"/>
- <source>Payment request expired.</source>
- <translation type="unfinished"></translation>
- </message>
<message numerus="yes">
- <location line="+124"/>
+ <location line="+123"/>
<source>Estimated to begin confirmation within %n block(s).</source>
<translation>
<numerusform>Estimated to begin confirmation within %n block.</numerusform>
@@ -3917,14 +4065,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>SendCoinsEntry</name>
<message>
- <location filename="../forms/sendcoinsentry.ui" line="+155"/>
- <location line="+550"/>
- <location line="+533"/>
+ <location filename="../forms/sendcoinsentry.ui" line="+151"/>
<source>A&amp;mount:</source>
<translation>A&amp;mount:</translation>
</message>
<message>
- <location line="-1199"/>
+ <location line="-116"/>
<source>Pay &amp;To:</source>
<translation>Pay &amp;To:</translation>
</message>
@@ -3960,13 +4106,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</message>
<message>
<location line="+7"/>
- <location line="+562"/>
- <location line="+533"/>
<source>Remove this entry</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1035"/>
+ <location line="+60"/>
<source>The amount to send in the selected unit</source>
<translation type="unfinished"></translation>
</message>
@@ -3991,17 +4135,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+443"/>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+529"/>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-1023"/>
+ <location line="-51"/>
<location line="+3"/>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished"></translation>
@@ -4011,23 +4145,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<source>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>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="+448"/>
- <location line="+529"/>
- <source>Pay To:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-495"/>
- <location line="+533"/>
- <source>Memo:</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
<message>
- <location filename="../sendcoinsdialog.h" line="+131"/>
+ <location filename="../sendcoinsdialog.h" line="+144"/>
<source>Send</source>
<translation type="unfinished"></translation>
</message>
@@ -4274,42 +4396,43 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="+40"/>
+ <location filename="../transactiondesc.cpp" line="+43"/>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+0"/>
- <source>in memory pool</source>
+ <location line="+7"/>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+0"/>
- <source>not in memory pool</source>
+ <location line="+5"/>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1"/>
+ <location line="+6"/>
<source>abandoned</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+8"/>
<source>%1/unconfirmed</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+5"/>
<source>%1 confirmations</source>
+ <extracomment>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.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+51"/>
+ <location line="+50"/>
<source>Status</source>
<translation type="unfinished"></translation>
</message>
@@ -4507,7 +4630,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+260"/>
+ <location filename="../transactiontablemodel.cpp" line="+261"/>
<source>Date</source>
<translation type="unfinished">Date</translation>
</message>
@@ -4844,7 +4967,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>WalletController</name>
<message>
- <location filename="../walletcontroller.cpp" line="-259"/>
+ <location filename="../walletcontroller.cpp" line="-344"/>
<source>Close wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4884,19 +5007,19 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+154"/>
- <location line="+9"/>
+ <location line="+151"/>
<location line="+10"/>
+ <location line="+18"/>
<source>Error</source>
<translation type="unfinished">Error</translation>
</message>
<message>
- <location line="-19"/>
+ <location line="-28"/>
<source>Unable to decode PSBT from clipboard (invalid base64)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Load Transaction Data</source>
<translation type="unfinished"></translation>
</message>
@@ -4911,7 +5034,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+18"/>
<source>Unable to decode PSBT</source>
<translation type="unfinished"></translation>
</message>
@@ -4924,7 +5047,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished">Send Coins</translation>
</message>
<message>
- <location line="+260"/>
+ <location line="+263"/>
<location line="+52"/>
<location line="+15"/>
<location line="+5"/>
@@ -5001,7 +5124,7 @@ Go to File &gt; Open Wallet to load a wallet.
<context>
<name>WalletView</name>
<message>
- <location filename="../walletview.cpp" line="+52"/>
+ <location filename="../walletview.cpp" line="+51"/>
<source>&amp;Export</source>
<translation type="unfinished">&amp;Export</translation>
</message>
@@ -5011,7 +5134,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished">Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+164"/>
+ <location line="+162"/>
<source>Backup Wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -5060,12 +5183,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+7"/>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+18"/>
<source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
<translation type="unfinished"></translation>
</message>
@@ -5115,12 +5238,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
+ <location line="+6"/>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished"></translation>
</message>
@@ -5161,6 +5279,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+3"/>
+ <source>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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Please check that your computer&apos;s date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished"></translation>
</message>
@@ -5176,6 +5299,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+2"/>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished"></translation>
</message>
@@ -5241,6 +5369,16 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+3"/>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Warning: Dumpfile wallet format &quot;%s&quot; does not match command line specified format &quot;%s&quot;.</source>
<translation type="unfinished"></translation>
</message>
@@ -5300,12 +5438,37 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-58"/>
+ <location line="-65"/>
<source>The -txindex upgrade started by a previous version cannot be completed. Restart with the previous version or run a full -reindex.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-69"/>
+ <location line="-104"/>
+ <source>%s request to listen on port %u. This port is considered &quot;bad&quot; 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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>-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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>-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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>-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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
<translation type="unfinished"></translation>
</message>
@@ -5315,7 +5478,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+118"/>
+ <location line="+19"/>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+114"/>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished"></translation>
</message>
@@ -5416,11 +5584,6 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Error: Couldn&apos;t create cursor into database</source>
<translation type="unfinished"></translation>
</message>
@@ -5566,6 +5729,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Loading P2P addresses…</source>
<translation type="unfinished"></translation>
</message>
@@ -5606,11 +5774,6 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Not enough file descriptors available.</source>
<translation type="unfinished"></translation>
</message>
@@ -5621,11 +5784,6 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished"></translation>
</message>
@@ -5776,6 +5934,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Unable to allocate memory for -maxsigcachesize: &apos;%s&apos; MiB</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished"></translation>
</message>
@@ -5846,11 +6009,6 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished"></translation>
</message>
@@ -5870,7 +6028,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="-496"/>
+ <location filename="../bitcoin.cpp" line="-519"/>
<source>Settings file could not be read</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/qt/locale/bitcoin_en.xlf b/src/qt/locale/bitcoin_en.xlf
index 30ee5e4de6..c5f0c933f4 100644
--- a/src/qt/locale/bitcoin_en.xlf
+++ b/src/qt/locale/bitcoin_en.xlf
@@ -45,7 +45,7 @@
<trans-unit id="_msg11">
<source xml:space="preserve">&amp;Delete</source>
<context-group purpose="location"><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../addressbookpage.cpp</context><context context-type="linenumber">122</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../addressbookpage.cpp</context><context context-type="linenumber">128</context></context-group>
</trans-unit>
</group>
</body></file>
@@ -53,62 +53,62 @@
<group restype="x-trolltech-linguist-context" resname="AddressBookPage">
<trans-unit id="_msg12">
<source xml:space="preserve">Choose the address to send coins to</source>
- <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
<trans-unit id="_msg13">
<source xml:space="preserve">Choose the address to receive coins with</source>
- <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">91</context></context-group>
</trans-unit>
<trans-unit id="_msg14">
<source xml:space="preserve">C&amp;hoose</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
<trans-unit id="_msg15">
<source xml:space="preserve">Sending addresses</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">102</context></context-group>
</trans-unit>
<trans-unit id="_msg16">
<source xml:space="preserve">Receiving addresses</source>
- <context-group purpose="location"><context context-type="linenumber">97</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
</trans-unit>
<trans-unit id="_msg17">
<source xml:space="preserve">These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <context-group purpose="location"><context context-type="linenumber">104</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">110</context></context-group>
</trans-unit>
<trans-unit id="_msg18">
<source xml:space="preserve">These are your Bitcoin addresses for receiving payments. Use the &apos;Create new receiving address&apos; button in the receive tab to create new addresses.
Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
- <context-group purpose="location"><context context-type="linenumber">109</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">115</context></context-group>
</trans-unit>
<trans-unit id="_msg19">
<source xml:space="preserve">&amp;Copy Address</source>
- <context-group purpose="location"><context context-type="linenumber">117</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
<trans-unit id="_msg20">
<source xml:space="preserve">Copy &amp;Label</source>
- <context-group purpose="location"><context context-type="linenumber">118</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
<trans-unit id="_msg21">
<source xml:space="preserve">&amp;Edit</source>
- <context-group purpose="location"><context context-type="linenumber">119</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
<trans-unit id="_msg22">
<source xml:space="preserve">Export Address List</source>
- <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
</trans-unit>
<trans-unit id="_msg23">
<source xml:space="preserve">Comma separated file</source>
- <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</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="_msg24">
<source xml:space="preserve">There was an error trying to save the address list to %1. Please try again.</source>
- <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
<note annotates="source" from="developer">An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</note>
</trans-unit>
<trans-unit id="_msg25">
<source xml:space="preserve">Exporting Failed</source>
- <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
</group>
</body></file>
@@ -267,568 +267,610 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<file original="../bitcoin.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="BitcoinApplication">
<trans-unit id="_msg58">
- <source xml:space="preserve">Runaway exception</source>
- <context-group purpose="location"><context context-type="linenumber">433</context></context-group>
+ <source xml:space="preserve">Settings file %1 might be corrupt or invalid.</source>
+ <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
</trans-unit>
<trans-unit id="_msg59">
- <source xml:space="preserve">A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <context-group purpose="location"><context context-type="linenumber">434</context></context-group>
+ <source xml:space="preserve">Runaway exception</source>
+ <context-group purpose="location"><context context-type="linenumber">464</context></context-group>
</trans-unit>
<trans-unit id="_msg60">
- <source xml:space="preserve">Internal error</source>
- <context-group purpose="location"><context context-type="linenumber">443</context></context-group>
+ <source xml:space="preserve">A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <context-group purpose="location"><context context-type="linenumber">465</context></context-group>
</trans-unit>
<trans-unit id="_msg61">
+ <source xml:space="preserve">Internal error</source>
+ <context-group purpose="location"><context context-type="linenumber">474</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg62">
<source xml:space="preserve">An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <context-group purpose="location"><context context-type="linenumber">444</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">475</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg62">
+ <trans-unit id="_msg63">
<source xml:space="preserve">Do you want to reset settings to default values, or to abort without making changes?</source>
- <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
<note annotates="source" from="developer">Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</note>
</trans-unit>
- <trans-unit id="_msg63">
+ <trans-unit id="_msg64">
<source xml:space="preserve">A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">205</context></context-group>
<note annotates="source" from="developer">Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</note>
</trans-unit>
- <trans-unit id="_msg64">
+ <trans-unit id="_msg65">
<source xml:space="preserve">Error: Specified data directory &quot;%1&quot; does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">565</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">598</context></context-group>
</trans-unit>
- <trans-unit id="_msg65">
+ <trans-unit id="_msg66">
<source xml:space="preserve">Error: Cannot parse configuration file: %1.</source>
- <context-group purpose="location"><context context-type="linenumber">571</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">604</context></context-group>
</trans-unit>
- <trans-unit id="_msg66">
+ <trans-unit id="_msg67">
<source xml:space="preserve">Error: %1</source>
- <context-group purpose="location"><context context-type="linenumber">586</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">619</context></context-group>
</trans-unit>
- <trans-unit id="_msg67">
+ <trans-unit id="_msg68">
<source xml:space="preserve">%1 didn&apos;t yet exit safely…</source>
- <context-group purpose="location"><context context-type="linenumber">657</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">693</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="bitcoin-core">
- <trans-unit id="_msg68">
+ <trans-unit id="_msg69">
<source xml:space="preserve">Settings file could not be read</source>
- <context-group purpose="location"><context context-type="linenumber">161</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
</trans-unit>
- <trans-unit id="_msg69">
+ <trans-unit id="_msg70">
<source xml:space="preserve">Settings file could not be written</source>
- <context-group purpose="location"><context context-type="linenumber">184</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../bitcoingui.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="BitcoinGUI">
- <trans-unit id="_msg70">
- <source xml:space="preserve">&amp;Overview</source>
- <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
- </trans-unit>
<trans-unit id="_msg71">
- <source xml:space="preserve">Show general overview of wallet</source>
- <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
+ <source xml:space="preserve">&amp;Overview</source>
+ <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
</trans-unit>
<trans-unit id="_msg72">
- <source xml:space="preserve">&amp;Transactions</source>
- <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
+ <source xml:space="preserve">Show general overview of wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
</trans-unit>
<trans-unit id="_msg73">
- <source xml:space="preserve">Browse transaction history</source>
- <context-group purpose="location"><context context-type="linenumber">272</context></context-group>
+ <source xml:space="preserve">&amp;Transactions</source>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
<trans-unit id="_msg74">
- <source xml:space="preserve">E&amp;xit</source>
- <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
+ <source xml:space="preserve">Browse transaction history</source>
+ <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
<trans-unit id="_msg75">
- <source xml:space="preserve">Quit application</source>
- <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
+ <source xml:space="preserve">E&amp;xit</source>
+ <context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
<trans-unit id="_msg76">
- <source xml:space="preserve">&amp;About %1</source>
+ <source xml:space="preserve">Quit application</source>
<context-group purpose="location"><context context-type="linenumber">295</context></context-group>
</trans-unit>
<trans-unit id="_msg77">
- <source xml:space="preserve">Show information about %1</source>
- <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
+ <source xml:space="preserve">&amp;About %1</source>
+ <context-group purpose="location"><context context-type="linenumber">298</context></context-group>
</trans-unit>
<trans-unit id="_msg78">
- <source xml:space="preserve">About &amp;Qt</source>
+ <source xml:space="preserve">Show information about %1</source>
<context-group purpose="location"><context context-type="linenumber">299</context></context-group>
</trans-unit>
<trans-unit id="_msg79">
- <source xml:space="preserve">Show information about Qt</source>
- <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
+ <source xml:space="preserve">About &amp;Qt</source>
+ <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
</trans-unit>
<trans-unit id="_msg80">
- <source xml:space="preserve">Modify configuration options for %1</source>
+ <source xml:space="preserve">Show information about Qt</source>
<context-group purpose="location"><context context-type="linenumber">303</context></context-group>
</trans-unit>
<trans-unit id="_msg81">
- <source xml:space="preserve">Create a new wallet</source>
- <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
+ <source xml:space="preserve">Modify configuration options for %1</source>
+ <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
<trans-unit id="_msg82">
- <source xml:space="preserve">&amp;Minimize</source>
- <context-group purpose="location"><context context-type="linenumber">474</context></context-group>
+ <source xml:space="preserve">Create a new wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
</trans-unit>
<trans-unit id="_msg83">
- <source xml:space="preserve">Wallet:</source>
- <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
+ <source xml:space="preserve">&amp;Minimize</source>
+ <context-group purpose="location"><context context-type="linenumber">510</context></context-group>
</trans-unit>
<trans-unit id="_msg84">
- <source xml:space="preserve">Network activity disabled.</source>
- <context-group purpose="location"><context context-type="linenumber">945</context></context-group>
- <note annotates="source" from="developer">A substring of the tooltip.</note>
+ <source xml:space="preserve">Wallet:</source>
+ <context-group purpose="location"><context context-type="linenumber">589</context></context-group>
</trans-unit>
<trans-unit id="_msg85">
- <source xml:space="preserve">Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1367</context></context-group>
+ <source xml:space="preserve">Network activity disabled.</source>
+ <context-group purpose="location"><context context-type="linenumber">982</context></context-group>
+ <note annotates="source" from="developer">A substring of the tooltip.</note>
</trans-unit>
<trans-unit id="_msg86">
- <source xml:space="preserve">Send coins to a Bitcoin address</source>
- <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
+ <source xml:space="preserve">Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <context-group purpose="location"><context context-type="linenumber">1411</context></context-group>
</trans-unit>
<trans-unit id="_msg87">
- <source xml:space="preserve">Backup wallet to another location</source>
- <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
+ <source xml:space="preserve">Send coins to a Bitcoin address</source>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
<trans-unit id="_msg88">
- <source xml:space="preserve">Change the passphrase used for wallet encryption</source>
- <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
+ <source xml:space="preserve">Backup wallet to another location</source>
+ <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
</trans-unit>
<trans-unit id="_msg89">
- <source xml:space="preserve">&amp;Send</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <source xml:space="preserve">Change the passphrase used for wallet encryption</source>
+ <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
</trans-unit>
<trans-unit id="_msg90">
- <source xml:space="preserve">&amp;Receive</source>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
+ <source xml:space="preserve">&amp;Send</source>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
<trans-unit id="_msg91">
- <source xml:space="preserve">&amp;Options…</source>
- <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <source xml:space="preserve">&amp;Receive</source>
+ <context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
<trans-unit id="_msg92">
- <source xml:space="preserve">&amp;Encrypt Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
+ <source xml:space="preserve">&amp;Options…</source>
+ <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
<trans-unit id="_msg93">
- <source xml:space="preserve">Encrypt the private keys that belong to your wallet</source>
- <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
+ <source xml:space="preserve">&amp;Encrypt Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
</trans-unit>
<trans-unit id="_msg94">
- <source xml:space="preserve">&amp;Backup Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
+ <source xml:space="preserve">Encrypt the private keys that belong to your wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
</trans-unit>
<trans-unit id="_msg95">
- <source xml:space="preserve">&amp;Change Passphrase…</source>
- <context-group purpose="location"><context context-type="linenumber">312</context></context-group>
+ <source xml:space="preserve">&amp;Backup Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
</trans-unit>
<trans-unit id="_msg96">
- <source xml:space="preserve">Sign &amp;message…</source>
- <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
+ <source xml:space="preserve">&amp;Change Passphrase…</source>
+ <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
<trans-unit id="_msg97">
- <source xml:space="preserve">Sign messages with your Bitcoin addresses to prove you own them</source>
- <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
+ <source xml:space="preserve">Sign &amp;message…</source>
+ <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
</trans-unit>
<trans-unit id="_msg98">
- <source xml:space="preserve">&amp;Verify message…</source>
- <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
+ <source xml:space="preserve">Sign messages with your Bitcoin addresses to prove you own them</source>
+ <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
</trans-unit>
<trans-unit id="_msg99">
- <source xml:space="preserve">Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
+ <source xml:space="preserve">&amp;Verify message…</source>
+ <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
</trans-unit>
<trans-unit id="_msg100">
- <source xml:space="preserve">&amp;Load PSBT from file…</source>
- <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
+ <source xml:space="preserve">Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
</trans-unit>
<trans-unit id="_msg101">
- <source xml:space="preserve">Open &amp;URI…</source>
- <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
+ <source xml:space="preserve">&amp;Load PSBT from file…</source>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
<trans-unit id="_msg102">
- <source xml:space="preserve">Close Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
+ <source xml:space="preserve">Open &amp;URI…</source>
+ <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
</trans-unit>
<trans-unit id="_msg103">
- <source xml:space="preserve">Create Wallet…</source>
+ <source xml:space="preserve">Close Wallet…</source>
<context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
<trans-unit id="_msg104">
- <source xml:space="preserve">Close All Wallets…</source>
- <context-group purpose="location"><context context-type="linenumber">349</context></context-group>
+ <source xml:space="preserve">Create Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">348</context></context-group>
</trans-unit>
<trans-unit id="_msg105">
- <source xml:space="preserve">&amp;File</source>
- <context-group purpose="location"><context context-type="linenumber">443</context></context-group>
+ <source xml:space="preserve">Close All Wallets…</source>
+ <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
</trans-unit>
<trans-unit id="_msg106">
- <source xml:space="preserve">&amp;Settings</source>
- <context-group purpose="location"><context context-type="linenumber">461</context></context-group>
+ <source xml:space="preserve">&amp;File</source>
+ <context-group purpose="location"><context context-type="linenumber">477</context></context-group>
</trans-unit>
<trans-unit id="_msg107">
- <source xml:space="preserve">&amp;Help</source>
- <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
+ <source xml:space="preserve">&amp;Settings</source>
+ <context-group purpose="location"><context context-type="linenumber">497</context></context-group>
</trans-unit>
<trans-unit id="_msg108">
- <source xml:space="preserve">Tabs toolbar</source>
- <context-group purpose="location"><context context-type="linenumber">533</context></context-group>
+ <source xml:space="preserve">&amp;Help</source>
+ <context-group purpose="location"><context context-type="linenumber">558</context></context-group>
</trans-unit>
<trans-unit id="_msg109">
- <source xml:space="preserve">Syncing Headers (%1%)…</source>
- <context-group purpose="location"><context context-type="linenumber">989</context></context-group>
+ <source xml:space="preserve">Tabs toolbar</source>
+ <context-group purpose="location"><context context-type="linenumber">569</context></context-group>
</trans-unit>
<trans-unit id="_msg110">
- <source xml:space="preserve">Synchronizing with network…</source>
- <context-group purpose="location"><context context-type="linenumber">1036</context></context-group>
+ <source xml:space="preserve">Syncing Headers (%1%)…</source>
+ <context-group purpose="location"><context context-type="linenumber">1026</context></context-group>
</trans-unit>
<trans-unit id="_msg111">
- <source xml:space="preserve">Indexing blocks on disk…</source>
- <context-group purpose="location"><context context-type="linenumber">1041</context></context-group>
+ <source xml:space="preserve">Synchronizing with network…</source>
+ <context-group purpose="location"><context context-type="linenumber">1074</context></context-group>
</trans-unit>
<trans-unit id="_msg112">
- <source xml:space="preserve">Processing blocks on disk…</source>
- <context-group purpose="location"><context context-type="linenumber">1043</context></context-group>
+ <source xml:space="preserve">Indexing blocks on disk…</source>
+ <context-group purpose="location"><context context-type="linenumber">1079</context></context-group>
</trans-unit>
<trans-unit id="_msg113">
- <source xml:space="preserve">Reindexing blocks on disk…</source>
- <context-group purpose="location"><context context-type="linenumber">1047</context></context-group>
+ <source xml:space="preserve">Processing blocks on disk…</source>
+ <context-group purpose="location"><context context-type="linenumber">1081</context></context-group>
</trans-unit>
<trans-unit id="_msg114">
- <source xml:space="preserve">Connecting to peers…</source>
- <context-group purpose="location"><context context-type="linenumber">1053</context></context-group>
+ <source xml:space="preserve">Reindexing blocks on disk…</source>
+ <context-group purpose="location"><context context-type="linenumber">1085</context></context-group>
</trans-unit>
<trans-unit id="_msg115">
- <source xml:space="preserve">Request payments (generates QR codes and bitcoin: URIs)</source>
- <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
+ <source xml:space="preserve">Connecting to peers…</source>
+ <context-group purpose="location"><context context-type="linenumber">1091</context></context-group>
</trans-unit>
<trans-unit id="_msg116">
- <source xml:space="preserve">Show the list of used sending addresses and labels</source>
- <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
+ <source xml:space="preserve">Request payments (generates QR codes and bitcoin: URIs)</source>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
<trans-unit id="_msg117">
- <source xml:space="preserve">Show the list of used receiving addresses and labels</source>
- <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
+ <source xml:space="preserve">Show the list of used sending addresses and labels</source>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
<trans-unit id="_msg118">
+ <source xml:space="preserve">Show the list of used receiving addresses and labels</source>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg119">
<source xml:space="preserve">&amp;Command-line options</source>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">361</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">1062</context></context-group>
- <trans-unit id="_msg119[0]">
+ <context-group purpose="location"><context context-type="linenumber">1100</context></context-group>
+ <trans-unit id="_msg120[0]">
<source xml:space="preserve">Processed %n block(s) of transaction history.</source>
</trans-unit>
- <trans-unit id="_msg119[1]">
+ <trans-unit id="_msg120[1]">
<source xml:space="preserve">Processed %n block(s) of transaction history.</source>
</trans-unit>
</group>
- <trans-unit id="_msg120">
- <source xml:space="preserve">%1 behind</source>
- <context-group purpose="location"><context context-type="linenumber">1085</context></context-group>
- </trans-unit>
<trans-unit id="_msg121">
- <source xml:space="preserve">Catching up…</source>
- <context-group purpose="location"><context context-type="linenumber">1090</context></context-group>
+ <source xml:space="preserve">%1 behind</source>
+ <context-group purpose="location"><context context-type="linenumber">1123</context></context-group>
</trans-unit>
<trans-unit id="_msg122">
- <source xml:space="preserve">Last received block was generated %1 ago.</source>
- <context-group purpose="location"><context context-type="linenumber">1109</context></context-group>
+ <source xml:space="preserve">Catching up…</source>
+ <context-group purpose="location"><context context-type="linenumber">1128</context></context-group>
</trans-unit>
<trans-unit id="_msg123">
- <source xml:space="preserve">Transactions after this will not yet be visible.</source>
- <context-group purpose="location"><context context-type="linenumber">1111</context></context-group>
+ <source xml:space="preserve">Last received block was generated %1 ago.</source>
+ <context-group purpose="location"><context context-type="linenumber">1147</context></context-group>
</trans-unit>
<trans-unit id="_msg124">
- <source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">1136</context></context-group>
+ <source xml:space="preserve">Transactions after this will not yet be visible.</source>
+ <context-group purpose="location"><context context-type="linenumber">1149</context></context-group>
</trans-unit>
<trans-unit id="_msg125">
- <source xml:space="preserve">Warning</source>
- <context-group purpose="location"><context context-type="linenumber">1140</context></context-group>
+ <source xml:space="preserve">Error</source>
+ <context-group purpose="location"><context context-type="linenumber">1174</context></context-group>
</trans-unit>
<trans-unit id="_msg126">
- <source xml:space="preserve">Information</source>
- <context-group purpose="location"><context context-type="linenumber">1144</context></context-group>
+ <source xml:space="preserve">Warning</source>
+ <context-group purpose="location"><context context-type="linenumber">1178</context></context-group>
</trans-unit>
<trans-unit id="_msg127">
- <source xml:space="preserve">Up to date</source>
- <context-group purpose="location"><context context-type="linenumber">1066</context></context-group>
+ <source xml:space="preserve">Information</source>
+ <context-group purpose="location"><context context-type="linenumber">1182</context></context-group>
</trans-unit>
<trans-unit id="_msg128">
- <source xml:space="preserve">Load Partially Signed Bitcoin Transaction</source>
- <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
+ <source xml:space="preserve">Up to date</source>
+ <context-group purpose="location"><context context-type="linenumber">1104</context></context-group>
</trans-unit>
<trans-unit id="_msg129">
- <source xml:space="preserve">Load PSBT from &amp;clipboard…</source>
- <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
+ <source xml:space="preserve">Ctrl+Q</source>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
<trans-unit id="_msg130">
- <source xml:space="preserve">Load Partially Signed Bitcoin Transaction from clipboard</source>
- <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
+ <source xml:space="preserve">Load Partially Signed Bitcoin Transaction</source>
+ <context-group purpose="location"><context context-type="linenumber">322</context></context-group>
</trans-unit>
<trans-unit id="_msg131">
- <source xml:space="preserve">Node window</source>
+ <source xml:space="preserve">Load PSBT from &amp;clipboard…</source>
<context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
<trans-unit id="_msg132">
- <source xml:space="preserve">Open node debugging and diagnostic console</source>
+ <source xml:space="preserve">Load Partially Signed Bitcoin Transaction from clipboard</source>
<context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
<trans-unit id="_msg133">
- <source xml:space="preserve">&amp;Sending addresses</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <source xml:space="preserve">Node window</source>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
<trans-unit id="_msg134">
- <source xml:space="preserve">&amp;Receiving addresses</source>
- <context-group purpose="location"><context context-type="linenumber">331</context></context-group>
+ <source xml:space="preserve">Open node debugging and diagnostic console</source>
+ <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
</trans-unit>
<trans-unit id="_msg135">
- <source xml:space="preserve">Open a bitcoin: URI</source>
- <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ <source xml:space="preserve">&amp;Sending addresses</source>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
<trans-unit id="_msg136">
- <source xml:space="preserve">Open Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
+ <source xml:space="preserve">&amp;Receiving addresses</source>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
<trans-unit id="_msg137">
- <source xml:space="preserve">Open a wallet</source>
- <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
+ <source xml:space="preserve">Open a bitcoin: URI</source>
+ <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
</trans-unit>
<trans-unit id="_msg138">
- <source xml:space="preserve">Close wallet</source>
- <context-group purpose="location"><context context-type="linenumber">343</context></context-group>
+ <source xml:space="preserve">Open Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">340</context></context-group>
</trans-unit>
<trans-unit id="_msg139">
- <source xml:space="preserve">Close all wallets</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <source xml:space="preserve">Open a wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
</trans-unit>
<trans-unit id="_msg140">
- <source xml:space="preserve">Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <context-group purpose="location"><context context-type="linenumber">354</context></context-group>
+ <source xml:space="preserve">Close wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">346</context></context-group>
</trans-unit>
<trans-unit id="_msg141">
- <source xml:space="preserve">&amp;Mask values</source>
- <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
+ <source xml:space="preserve">Restore Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">353</context></context-group>
+ <note annotates="source" from="developer">Name of the menu item that restores wallet from a backup file.</note>
</trans-unit>
<trans-unit id="_msg142">
- <source xml:space="preserve">Mask the values in the Overview tab</source>
- <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
+ <source xml:space="preserve">Restore a wallet from a backup file</source>
+ <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
+ <note annotates="source" from="developer">Status tip for Restore Wallet menu item</note>
</trans-unit>
<trans-unit id="_msg143">
- <source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">389</context></context-group>
+ <source xml:space="preserve">Close all wallets</source>
+ <context-group purpose="location"><context context-type="linenumber">359</context></context-group>
</trans-unit>
<trans-unit id="_msg144">
- <source xml:space="preserve">No wallets available</source>
- <context-group purpose="location"><context context-type="linenumber">409</context></context-group>
+ <source xml:space="preserve">Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <context-group purpose="location"><context context-type="linenumber">363</context></context-group>
</trans-unit>
<trans-unit id="_msg145">
- <source xml:space="preserve">&amp;Window</source>
- <context-group purpose="location"><context context-type="linenumber">472</context></context-group>
+ <source xml:space="preserve">&amp;Mask values</source>
+ <context-group purpose="location"><context context-type="linenumber">365</context></context-group>
</trans-unit>
<trans-unit id="_msg146">
- <source xml:space="preserve">Zoom</source>
- <context-group purpose="location"><context context-type="linenumber">484</context></context-group>
+ <source xml:space="preserve">Mask the values in the Overview tab</source>
+ <context-group purpose="location"><context context-type="linenumber">367</context></context-group>
</trans-unit>
<trans-unit id="_msg147">
- <source xml:space="preserve">Main Window</source>
- <context-group purpose="location"><context context-type="linenumber">502</context></context-group>
+ <source xml:space="preserve">default wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">398</context></context-group>
</trans-unit>
<trans-unit id="_msg148">
- <source xml:space="preserve">%1 client</source>
- <context-group purpose="location"><context context-type="linenumber">759</context></context-group>
+ <source xml:space="preserve">No wallets available</source>
+ <context-group purpose="location"><context context-type="linenumber">418</context></context-group>
</trans-unit>
<trans-unit id="_msg149">
- <source xml:space="preserve">&amp;Hide</source>
- <context-group purpose="location"><context context-type="linenumber">824</context></context-group>
+ <source xml:space="preserve">Wallet Data</source>
+ <context-group purpose="location"><context context-type="linenumber">424</context></context-group>
+ <note annotates="source" from="developer">Name of the wallet data file format.</note>
</trans-unit>
<trans-unit id="_msg150">
+ <source xml:space="preserve">Load Wallet Backup</source>
+ <context-group purpose="location"><context context-type="linenumber">427</context></context-group>
+ <note annotates="source" from="developer">The title for Restore Wallet File Windows</note>
+ </trans-unit>
+ <trans-unit id="_msg151">
+ <source xml:space="preserve">Restore Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">435</context></context-group>
+ <note annotates="source" from="developer">Title of pop-up window shown when the user is attempting to + restore a wallet.</note>
+ </trans-unit>
+ <trans-unit id="_msg152">
+ <source xml:space="preserve">Wallet Name</source>
+ <context-group purpose="location"><context context-type="linenumber">437</context></context-group>
+ <note annotates="source" from="developer">Label of the input field where the name of the wallet is entered.</note>
+ </trans-unit>
+ <trans-unit id="_msg153">
+ <source xml:space="preserve">&amp;Window</source>
+ <context-group purpose="location"><context context-type="linenumber">508</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg154">
+ <source xml:space="preserve">Ctrl+M</source>
+ <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg155">
+ <source xml:space="preserve">Zoom</source>
+ <context-group purpose="location"><context context-type="linenumber">520</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg156">
+ <source xml:space="preserve">Main Window</source>
+ <context-group purpose="location"><context context-type="linenumber">538</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg157">
+ <source xml:space="preserve">%1 client</source>
+ <context-group purpose="location"><context context-type="linenumber">796</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg158">
+ <source xml:space="preserve">&amp;Hide</source>
+ <context-group purpose="location"><context context-type="linenumber">861</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg159">
<source xml:space="preserve">S&amp;how</source>
- <context-group purpose="location"><context context-type="linenumber">825</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">862</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">942</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">979</context></context-group>
<note annotates="source" from="developer">A substring of the tooltip.</note>
- <trans-unit id="_msg151[0]">
+ <trans-unit id="_msg160[0]">
<source xml:space="preserve">%n active connection(s) to Bitcoin network.</source>
</trans-unit>
- <trans-unit id="_msg151[1]">
+ <trans-unit id="_msg160[1]">
<source xml:space="preserve">%n active connection(s) to Bitcoin network.</source>
</trans-unit>
</group>
- <trans-unit id="_msg152">
+ <trans-unit id="_msg161">
<source xml:space="preserve">Click for more actions.</source>
- <context-group purpose="location"><context context-type="linenumber">952</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">989</context></context-group>
<note annotates="source" from="developer">A substring of the tooltip. &quot;More actions&quot; are available via the context menu.</note>
</trans-unit>
- <trans-unit id="_msg153">
+ <trans-unit id="_msg162">
<source xml:space="preserve">Show Peers tab</source>
- <context-group purpose="location"><context context-type="linenumber">969</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1006</context></context-group>
<note annotates="source" from="developer">A context menu item. The &quot;Peers tab&quot; is an element of the &quot;Node window&quot;.</note>
</trans-unit>
- <trans-unit id="_msg154">
+ <trans-unit id="_msg163">
<source xml:space="preserve">Disable network activity</source>
- <context-group purpose="location"><context context-type="linenumber">977</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1014</context></context-group>
<note annotates="source" from="developer">A context menu item.</note>
</trans-unit>
- <trans-unit id="_msg155">
+ <trans-unit id="_msg164">
<source xml:space="preserve">Enable network activity</source>
- <context-group purpose="location"><context context-type="linenumber">979</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1016</context></context-group>
<note annotates="source" from="developer">A context menu item. The network activity was disabled previously.</note>
</trans-unit>
- <trans-unit id="_msg156">
+ <trans-unit id="_msg165">
<source xml:space="preserve">Error: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1137</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1175</context></context-group>
</trans-unit>
- <trans-unit id="_msg157">
+ <trans-unit id="_msg166">
<source xml:space="preserve">Warning: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1141</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1179</context></context-group>
</trans-unit>
- <trans-unit id="_msg158">
+ <trans-unit id="_msg167">
<source xml:space="preserve">Date: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1249</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1287</context></context-group>
</trans-unit>
- <trans-unit id="_msg159">
+ <trans-unit id="_msg168">
<source xml:space="preserve">Amount: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1250</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1288</context></context-group>
</trans-unit>
- <trans-unit id="_msg160">
+ <trans-unit id="_msg169">
<source xml:space="preserve">Wallet: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1252</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1290</context></context-group>
</trans-unit>
- <trans-unit id="_msg161">
+ <trans-unit id="_msg170">
<source xml:space="preserve">Type: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1292</context></context-group>
</trans-unit>
- <trans-unit id="_msg162">
+ <trans-unit id="_msg171">
<source xml:space="preserve">Label: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1256</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1294</context></context-group>
</trans-unit>
- <trans-unit id="_msg163">
+ <trans-unit id="_msg172">
<source xml:space="preserve">Address: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1258</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1296</context></context-group>
</trans-unit>
- <trans-unit id="_msg164">
+ <trans-unit id="_msg173">
<source xml:space="preserve">Sent transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1297</context></context-group>
</trans-unit>
- <trans-unit id="_msg165">
+ <trans-unit id="_msg174">
<source xml:space="preserve">Incoming transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1297</context></context-group>
</trans-unit>
- <trans-unit id="_msg166">
+ <trans-unit id="_msg175">
<source xml:space="preserve">HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1349</context></context-group>
</trans-unit>
- <trans-unit id="_msg167">
+ <trans-unit id="_msg176">
<source xml:space="preserve">HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1349</context></context-group>
</trans-unit>
- <trans-unit id="_msg168">
+ <trans-unit id="_msg177">
<source xml:space="preserve">Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1349</context></context-group>
</trans-unit>
- <trans-unit id="_msg169">
+ <trans-unit id="_msg178">
<source xml:space="preserve">Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1328</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1372</context></context-group>
</trans-unit>
- <trans-unit id="_msg170">
+ <trans-unit id="_msg179">
<source xml:space="preserve">Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1336</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1380</context></context-group>
</trans-unit>
- <trans-unit id="_msg171">
+ <trans-unit id="_msg180">
<source xml:space="preserve">Original message:</source>
- <context-group purpose="location"><context context-type="linenumber">1455</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1499</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="UnitDisplayStatusBarControl">
- <trans-unit id="_msg172">
+ <trans-unit id="_msg181">
<source xml:space="preserve">Unit to show amounts in. Click to select another unit.</source>
- <context-group purpose="location"><context context-type="linenumber">1496</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1540</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/coincontroldialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CoinControlDialog">
- <trans-unit id="_msg173">
+ <trans-unit id="_msg182">
<source xml:space="preserve">Coin Selection</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg174">
+ <trans-unit id="_msg183">
<source xml:space="preserve">Quantity:</source>
<context-group purpose="location"><context context-type="linenumber">48</context></context-group>
</trans-unit>
- <trans-unit id="_msg175">
+ <trans-unit id="_msg184">
<source xml:space="preserve">Bytes:</source>
<context-group purpose="location"><context context-type="linenumber">77</context></context-group>
</trans-unit>
- <trans-unit id="_msg176">
+ <trans-unit id="_msg185">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">122</context></context-group>
</trans-unit>
- <trans-unit id="_msg177">
+ <trans-unit id="_msg186">
<source xml:space="preserve">Fee:</source>
<context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
- <trans-unit id="_msg178">
+ <trans-unit id="_msg187">
<source xml:space="preserve">Dust:</source>
<context-group purpose="location"><context context-type="linenumber">154</context></context-group>
</trans-unit>
- <trans-unit id="_msg179">
+ <trans-unit id="_msg188">
<source xml:space="preserve">After Fee:</source>
<context-group purpose="location"><context context-type="linenumber">247</context></context-group>
</trans-unit>
- <trans-unit id="_msg180">
+ <trans-unit id="_msg189">
<source xml:space="preserve">Change:</source>
<context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg181">
+ <trans-unit id="_msg190">
<source xml:space="preserve">(un)select all</source>
<context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg182">
+ <trans-unit id="_msg191">
<source xml:space="preserve">Tree mode</source>
<context-group purpose="location"><context context-type="linenumber">351</context></context-group>
</trans-unit>
- <trans-unit id="_msg183">
+ <trans-unit id="_msg192">
<source xml:space="preserve">List mode</source>
<context-group purpose="location"><context context-type="linenumber">364</context></context-group>
</trans-unit>
- <trans-unit id="_msg184">
+ <trans-unit id="_msg193">
<source xml:space="preserve">Amount</source>
<context-group purpose="location"><context context-type="linenumber">420</context></context-group>
</trans-unit>
- <trans-unit id="_msg185">
+ <trans-unit id="_msg194">
<source xml:space="preserve">Received with label</source>
<context-group purpose="location"><context context-type="linenumber">425</context></context-group>
</trans-unit>
- <trans-unit id="_msg186">
+ <trans-unit id="_msg195">
<source xml:space="preserve">Received with address</source>
<context-group purpose="location"><context context-type="linenumber">430</context></context-group>
</trans-unit>
- <trans-unit id="_msg187">
+ <trans-unit id="_msg196">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">435</context></context-group>
</trans-unit>
- <trans-unit id="_msg188">
+ <trans-unit id="_msg197">
<source xml:space="preserve">Confirmations</source>
<context-group purpose="location"><context context-type="linenumber">440</context></context-group>
</trans-unit>
- <trans-unit id="_msg189">
+ <trans-unit id="_msg198">
<source xml:space="preserve">Confirmed</source>
<context-group purpose="location"><context context-type="linenumber">443</context></context-group>
</trans-unit>
@@ -836,232 +878,263 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../coincontroldialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CoinControlDialog">
- <trans-unit id="_msg190">
+ <trans-unit id="_msg199">
<source xml:space="preserve">Copy amount</source>
<context-group purpose="location"><context context-type="linenumber">69</context></context-group>
</trans-unit>
- <trans-unit id="_msg191">
+ <trans-unit id="_msg200">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
</trans-unit>
- <trans-unit id="_msg192">
+ <trans-unit id="_msg201">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">59</context></context-group>
</trans-unit>
- <trans-unit id="_msg193">
+ <trans-unit id="_msg202">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg194">
+ <trans-unit id="_msg203">
<source xml:space="preserve">Copy transaction &amp;ID and output index</source>
<context-group purpose="location"><context context-type="linenumber">61</context></context-group>
</trans-unit>
- <trans-unit id="_msg195">
+ <trans-unit id="_msg204">
<source xml:space="preserve">L&amp;ock unspent</source>
<context-group purpose="location"><context context-type="linenumber">63</context></context-group>
</trans-unit>
- <trans-unit id="_msg196">
+ <trans-unit id="_msg205">
<source xml:space="preserve">&amp;Unlock unspent</source>
<context-group purpose="location"><context context-type="linenumber">64</context></context-group>
</trans-unit>
- <trans-unit id="_msg197">
+ <trans-unit id="_msg206">
<source xml:space="preserve">Copy quantity</source>
<context-group purpose="location"><context context-type="linenumber">68</context></context-group>
</trans-unit>
- <trans-unit id="_msg198">
+ <trans-unit id="_msg207">
<source xml:space="preserve">Copy fee</source>
<context-group purpose="location"><context context-type="linenumber">70</context></context-group>
</trans-unit>
- <trans-unit id="_msg199">
+ <trans-unit id="_msg208">
<source xml:space="preserve">Copy after fee</source>
<context-group purpose="location"><context context-type="linenumber">71</context></context-group>
</trans-unit>
- <trans-unit id="_msg200">
+ <trans-unit id="_msg209">
<source xml:space="preserve">Copy bytes</source>
<context-group purpose="location"><context context-type="linenumber">72</context></context-group>
</trans-unit>
- <trans-unit id="_msg201">
+ <trans-unit id="_msg210">
<source xml:space="preserve">Copy dust</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
- <trans-unit id="_msg202">
+ <trans-unit id="_msg211">
<source xml:space="preserve">Copy change</source>
<context-group purpose="location"><context context-type="linenumber">74</context></context-group>
</trans-unit>
- <trans-unit id="_msg203">
+ <trans-unit id="_msg212">
<source xml:space="preserve">(%1 locked)</source>
<context-group purpose="location"><context context-type="linenumber">380</context></context-group>
</trans-unit>
- <trans-unit id="_msg204">
+ <trans-unit id="_msg213">
<source xml:space="preserve">yes</source>
- <context-group purpose="location"><context context-type="linenumber">535</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">534</context></context-group>
</trans-unit>
- <trans-unit id="_msg205">
+ <trans-unit id="_msg214">
<source xml:space="preserve">no</source>
- <context-group purpose="location"><context context-type="linenumber">535</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">534</context></context-group>
</trans-unit>
- <trans-unit id="_msg206">
+ <trans-unit id="_msg215">
<source xml:space="preserve">This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <context-group purpose="location"><context context-type="linenumber">549</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">548</context></context-group>
</trans-unit>
- <trans-unit id="_msg207">
+ <trans-unit id="_msg216">
<source xml:space="preserve">Can vary +/- %1 satoshi(s) per input.</source>
- <context-group purpose="location"><context context-type="linenumber">554</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
</trans-unit>
- <trans-unit id="_msg208">
+ <trans-unit id="_msg217">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">601</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">655</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">600</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">654</context></context-group>
</trans-unit>
- <trans-unit id="_msg209">
+ <trans-unit id="_msg218">
<source xml:space="preserve">change from %1 (%2)</source>
- <context-group purpose="location"><context context-type="linenumber">648</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">647</context></context-group>
</trans-unit>
- <trans-unit id="_msg210">
+ <trans-unit id="_msg219">
<source xml:space="preserve">(change)</source>
- <context-group purpose="location"><context context-type="linenumber">649</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">648</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletcontroller.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletActivity">
- <trans-unit id="_msg211">
+ <trans-unit id="_msg220">
<source xml:space="preserve">Create Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
<note annotates="source" from="developer">Title of window indicating the progress of creation of a new wallet.</note>
</trans-unit>
- <trans-unit id="_msg212">
+ <trans-unit id="_msg221">
<source xml:space="preserve">Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
<note annotates="source" from="developer">Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</note>
</trans-unit>
- <trans-unit id="_msg213">
+ <trans-unit id="_msg222">
<source xml:space="preserve">Create wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
- <trans-unit id="_msg214">
+ <trans-unit id="_msg223">
<source xml:space="preserve">Create wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">277</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
</trans-unit>
- <trans-unit id="_msg215">
+ <trans-unit id="_msg224">
<source xml:space="preserve">Can&apos;t list signers</source>
- <context-group purpose="location"><context context-type="linenumber">293</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="_msg216">
+ <trans-unit id="_msg226">
<source xml:space="preserve">Load Wallets</source>
- <context-group purpose="location"><context context-type="linenumber">362</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="_msg217">
+ <trans-unit id="_msg227">
<source xml:space="preserve">Loading wallets…</source>
- <context-group purpose="location"><context context-type="linenumber">365</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="_msg218">
+ <trans-unit id="_msg228">
<source xml:space="preserve">Open wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
- <trans-unit id="_msg219">
+ <trans-unit id="_msg229">
<source xml:space="preserve">Open wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
- <trans-unit id="_msg220">
+ <trans-unit id="_msg230">
<source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg221">
+ <trans-unit id="_msg231">
<source xml:space="preserve">Open Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">339</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="_msg222">
+ <trans-unit id="_msg232">
<source xml:space="preserve">Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <context-group purpose="location"><context context-type="linenumber">342</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="_msg233">
+ <source xml:space="preserve">Restore Wallet</source>
+ <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="_msg234">
+ <source xml:space="preserve">Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <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="_msg235">
+ <source xml:space="preserve">Restore wallet failed</source>
+ <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="_msg236">
+ <source xml:space="preserve">Restore wallet warning</source>
+ <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="_msg237">
+ <source xml:space="preserve">Restore wallet message</source>
+ <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="_msg223">
+ <trans-unit id="_msg238">
<source xml:space="preserve">Close wallet</source>
- <context-group purpose="location"><context context-type="linenumber">83</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
</trans-unit>
- <trans-unit id="_msg224">
+ <trans-unit id="_msg239">
<source xml:space="preserve">Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
</trans-unit>
- <trans-unit id="_msg225">
+ <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">85</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg226">
+ <trans-unit id="_msg241">
<source xml:space="preserve">Close all wallets</source>
- <context-group purpose="location"><context context-type="linenumber">98</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg227">
+ <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">99</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
</group>
</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="_msg228">
+ <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="_msg229">
+ <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="_msg230">
+ <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="_msg231">
+ <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="_msg232">
+ <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="_msg233">
+ <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="_msg234">
+ <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="_msg235">
+ <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="_msg236">
+ <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="_msg237">
+ <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="_msg238">
+ <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="_msg239">
+ <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="_msg240">
+ <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="_msg241">
+ <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>
@@ -1069,15 +1142,15 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../createwalletdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletDialog">
- <trans-unit id="_msg242">
+ <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="_msg243">
+ <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="_msg244">
+ <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">&quot;External signing&quot; means using devices such as hardware wallets.</note>
@@ -1086,23 +1159,23 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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="_msg245">
+ <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="_msg246">
+ <trans-unit id="_msg261">
<source xml:space="preserve">&amp;Label</source>
<context-group purpose="location"><context context-type="linenumber">25</context></context-group>
</trans-unit>
- <trans-unit id="_msg247">
+ <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="_msg248">
+ <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="_msg249">
+ <trans-unit id="_msg264">
<source xml:space="preserve">&amp;Address</source>
<context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
@@ -1110,35 +1183,35 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../editaddressdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="EditAddressDialog">
- <trans-unit id="_msg250">
+ <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="_msg251">
+ <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="_msg252">
+ <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="_msg253">
+ <trans-unit id="_msg268">
<source xml:space="preserve">The entered address &quot;%1&quot; is not a valid Bitcoin address.</source>
<context-group purpose="location"><context context-type="linenumber">113</context></context-group>
</trans-unit>
- <trans-unit id="_msg254">
+ <trans-unit id="_msg269">
<source xml:space="preserve">Address &quot;%1&quot; already exists as a receiving address with label &quot;%2&quot; 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="_msg255">
+ <trans-unit id="_msg270">
<source xml:space="preserve">The entered address &quot;%1&quot; is already in the address book with label &quot;%2&quot;.</source>
<context-group purpose="location"><context context-type="linenumber">151</context></context-group>
</trans-unit>
- <trans-unit id="_msg256">
+ <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="_msg257">
+ <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>
@@ -1146,75 +1219,90 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../intro.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="FreespaceChecker">
- <trans-unit id="_msg258">
+ <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="_msg259">
+ <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="_msg260">
+ <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="_msg261">
+ <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="_msg262">
+ <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="_msg263">
+ <trans-unit id="_msg278">
<source xml:space="preserve">Bitcoin</source>
<context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
- <trans-unit id="_msg264">
- <source xml:space="preserve">%1 GB of space available</source>
+ <group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">301</context></context-group>
- </trans-unit>
- <trans-unit id="_msg265">
- <source xml:space="preserve">(of %1 GB needed)</source>
+ <trans-unit id="_msg279[0]">
+ <source xml:space="preserve">%n GB of space available</source>
+ </trans-unit>
+ <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>
- <trans-unit id="_msg266">
- <source xml:space="preserve">(%1 GB needed for full chain)</source>
+ <trans-unit id="_msg280[0]">
+ <source xml:space="preserve">(of %n GB needed)</source>
+ </trans-unit>
+ <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>
- <trans-unit id="_msg267">
+ <trans-unit id="_msg281[0]">
+ <source xml:space="preserve">(%n GB needed for full chain)</source>
+ </trans-unit>
+ <trans-unit id="_msg281[1]">
+ <source xml:space="preserve">(%n GB needed for full chain)</source>
+ </trans-unit>
+ </group>
+ <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="_msg268">
+ <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="_msg269[0]">
+ <trans-unit id="_msg284[0]">
<source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source>
</trans-unit>
- <trans-unit id="_msg269[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="_msg270">
+ <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="_msg271">
+ <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="_msg272">
+ <trans-unit id="_msg287">
<source xml:space="preserve">Error: Specified data directory &quot;%1&quot; cannot be created.</source>
<context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg273">
+ <trans-unit id="_msg288">
<source xml:space="preserve">Error</source>
<context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
@@ -1222,25 +1310,25 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../utilitydialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="HelpMessageDialog">
- <trans-unit id="_msg274">
+ <trans-unit id="_msg289">
<source xml:space="preserve">version</source>
- <context-group purpose="location"><context context-type="linenumber">37</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">38</context></context-group>
</trans-unit>
- <trans-unit id="_msg275">
+ <trans-unit id="_msg290">
<source xml:space="preserve">About %1</source>
- <context-group purpose="location"><context context-type="linenumber">41</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
- <trans-unit id="_msg276">
+ <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="_msg277">
+ <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="_msg278">
+ <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>
@@ -1248,47 +1336,47 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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="_msg279">
+ <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="_msg280">
+ <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="_msg281">
+ <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="_msg282">
+ <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="_msg283">
+ <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="_msg284">
+ <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="_msg285">
+ <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="_msg286">
+ <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="_msg287">
+ <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="_msg288">
+ <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="_msg289">
+ <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>
@@ -1296,54 +1384,54 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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="_msg290">
+ <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="_msg291">
+ <trans-unit id="_msg306">
<source xml:space="preserve">Recent transactions may not yet be visible, and therefore your wallet&apos;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="_msg292">
+ <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="_msg293">
+ <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="_msg294">
+ <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="_msg295">
+ <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="_msg296">
+ <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="_msg297">
+ <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="_msg298">
+ <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="_msg299">
+ <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="_msg300">
+ <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="_msg301">
+ <trans-unit id="_msg316">
<source xml:space="preserve">Esc</source>
<context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
@@ -1351,17 +1439,17 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../modaloverlay.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ModalOverlay">
- <trans-unit id="_msg302">
+ <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="_msg303">
+ <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="_msg304">
+ <trans-unit id="_msg319">
<source xml:space="preserve">unknown</source>
<context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
@@ -1369,15 +1457,15 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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="_msg305">
+ <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="_msg306">
+ <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="_msg307">
+ <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>
@@ -1386,310 +1474,310 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</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="_msg308">
+ <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="_msg309">
+ <trans-unit id="_msg324">
<source xml:space="preserve">&amp;Main</source>
<context-group purpose="location"><context context-type="linenumber">27</context></context-group>
</trans-unit>
- <trans-unit id="_msg310">
+ <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="_msg311">
+ <trans-unit id="_msg326">
<source xml:space="preserve">&amp;Start %1 on system login</source>
<context-group purpose="location"><context context-type="linenumber">36</context></context-group>
</trans-unit>
- <trans-unit id="_msg312">
+ <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="_msg313">
+ <trans-unit id="_msg328">
<source xml:space="preserve">Size of &amp;database cache</source>
<context-group purpose="location"><context context-type="linenumber">111</context></context-group>
</trans-unit>
- <trans-unit id="_msg314">
+ <trans-unit id="_msg329">
<source xml:space="preserve">Number of script &amp;verification threads</source>
<context-group purpose="location"><context context-type="linenumber">157</context></context-group>
</trans-unit>
- <trans-unit id="_msg315">
+ <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="_msg316">
+ <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="_msg317">
+ <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="_msg318">
+ <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="_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="_msg319">
+ <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="_msg320">
+ <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="_msg321">
+ <trans-unit id="_msg337">
<source xml:space="preserve">&amp;Reset Options</source>
<context-group purpose="location"><context context-type="linenumber">960</context></context-group>
</trans-unit>
- <trans-unit id="_msg322">
+ <trans-unit id="_msg338">
<source xml:space="preserve">&amp;Network</source>
<context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
- <trans-unit id="_msg323">
+ <trans-unit id="_msg339">
<source xml:space="preserve">Prune &amp;block storage to</source>
<context-group purpose="location"><context context-type="linenumber">61</context></context-group>
</trans-unit>
- <trans-unit id="_msg324">
+ <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="_msg325">
+ <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="_msg326">
+ <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="_msg327">
+ <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="_msg328">
+ <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="_msg329">
+ <trans-unit id="_msg345">
<source xml:space="preserve">(0 = auto, &lt;0 = leave that many cores free)</source>
<context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg330">
+ <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="_msg331">
+ <trans-unit id="_msg347">
<source xml:space="preserve">Enable R&amp;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="_msg332">
+ <trans-unit id="_msg348">
<source xml:space="preserve">W&amp;allet</source>
<context-group purpose="location"><context context-type="linenumber">216</context></context-group>
</trans-unit>
- <trans-unit id="_msg333">
+ <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="_msg334">
+ <trans-unit id="_msg350">
<source xml:space="preserve">Subtract &amp;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="_msg335">
+ <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="_msg336">
+ <trans-unit id="_msg352">
<source xml:space="preserve">Enable coin &amp;control features</source>
<context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg337">
+ <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="_msg338">
+ <trans-unit id="_msg354">
<source xml:space="preserve">&amp;Spend unconfirmed change</source>
<context-group purpose="location"><context context-type="linenumber">251</context></context-group>
</trans-unit>
- <trans-unit id="_msg339">
+ <trans-unit id="_msg355">
<source xml:space="preserve">Enable &amp;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="_msg340">
+ <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="_msg341">
+ <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="_msg342">
+ <trans-unit id="_msg358">
<source xml:space="preserve">&amp;External signer script path</source>
<context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg343">
+ <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="_msg344">
+ <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="_msg345">
+ <trans-unit id="_msg361">
<source xml:space="preserve">Map port using &amp;UPnP</source>
<context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
- <trans-unit id="_msg346">
+ <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="_msg347">
+ <trans-unit id="_msg363">
<source xml:space="preserve">Map port using NA&amp;T-PMP</source>
<context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
- <trans-unit id="_msg348">
+ <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="_msg349">
+ <trans-unit id="_msg365">
<source xml:space="preserve">Allow incomin&amp;g connections</source>
<context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg350">
+ <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="_msg351">
+ <trans-unit id="_msg367">
<source xml:space="preserve">&amp;Connect through SOCKS5 proxy (default proxy):</source>
<context-group purpose="location"><context context-type="linenumber">354</context></context-group>
</trans-unit>
- <trans-unit id="_msg352">
+ <trans-unit id="_msg368">
<source xml:space="preserve">Proxy &amp;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="_msg353">
+ <trans-unit id="_msg369">
<source xml:space="preserve">&amp;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="_msg354">
+ <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="_msg355">
+ <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="_msg356">
+ <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="_msg357">
+ <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="_msg358">
+ <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="_msg359">
+ <trans-unit id="_msg375">
<source xml:space="preserve">&amp;Window</source>
<context-group purpose="location"><context context-type="linenumber">643</context></context-group>
</trans-unit>
- <trans-unit id="_msg360">
+ <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="_msg361">
+ <trans-unit id="_msg377">
<source xml:space="preserve">&amp;Show tray icon</source>
<context-group purpose="location"><context context-type="linenumber">652</context></context-group>
</trans-unit>
- <trans-unit id="_msg362">
+ <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="_msg363">
+ <trans-unit id="_msg379">
<source xml:space="preserve">&amp;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="_msg364">
+ <trans-unit id="_msg380">
<source xml:space="preserve">M&amp;inimize on close</source>
<context-group purpose="location"><context context-type="linenumber">675</context></context-group>
</trans-unit>
- <trans-unit id="_msg365">
+ <trans-unit id="_msg381">
<source xml:space="preserve">&amp;Display</source>
<context-group purpose="location"><context context-type="linenumber">696</context></context-group>
</trans-unit>
- <trans-unit id="_msg366">
+ <trans-unit id="_msg382">
<source xml:space="preserve">User Interface &amp;language:</source>
<context-group purpose="location"><context context-type="linenumber">704</context></context-group>
</trans-unit>
- <trans-unit id="_msg367">
+ <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="_msg368">
+ <trans-unit id="_msg384">
<source xml:space="preserve">&amp;Unit to show amounts in:</source>
<context-group purpose="location"><context context-type="linenumber">728</context></context-group>
</trans-unit>
- <trans-unit id="_msg369">
+ <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="_msg370">
+ <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="_msg371">
+ <trans-unit id="_msg387">
<source xml:space="preserve">&amp;Third-party transaction URLs</source>
<context-group purpose="location"><context context-type="linenumber">755</context></context-group>
</trans-unit>
- <trans-unit id="_msg372">
+ <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="_msg373">
+ <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="_msg374">
+ <trans-unit id="_msg390">
<source xml:space="preserve">Use separate SOCKS&amp;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="_msg375">
+ <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="_msg376">
+ <trans-unit id="_msg392">
<source xml:space="preserve">embedded &quot;%1&quot;</source>
<context-group purpose="location"><context context-type="linenumber">785</context></context-group>
</trans-unit>
- <trans-unit id="_msg377">
+ <trans-unit id="_msg393">
<source xml:space="preserve">closest matching &quot;%1&quot;</source>
<context-group purpose="location"><context context-type="linenumber">834</context></context-group>
</trans-unit>
- <trans-unit id="_msg378">
- <source xml:space="preserve">Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <context-group purpose="location"><context context-type="linenumber">899</context></context-group>
- </trans-unit>
- <trans-unit id="_msg379">
+ <trans-unit id="_msg394">
<source xml:space="preserve">&amp;OK</source>
<context-group purpose="location"><context context-type="linenumber">1040</context></context-group>
</trans-unit>
- <trans-unit id="_msg380">
+ <trans-unit id="_msg395">
<source xml:space="preserve">&amp;Cancel</source>
<context-group purpose="location"><context context-type="linenumber">1053</context></context-group>
</trans-unit>
@@ -1697,140 +1785,156 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../optionsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OptionsDialog">
- <trans-unit id="_msg381">
+ <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">99</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
<note annotates="source" from="developer">&quot;External signing&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg382">
+ <trans-unit id="_msg397">
<source xml:space="preserve">default</source>
- <context-group purpose="location"><context context-type="linenumber">111</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
</trans-unit>
- <trans-unit id="_msg383">
+ <trans-unit id="_msg398">
<source xml:space="preserve">none</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg384">
+ <trans-unit id="_msg399">
<source xml:space="preserve">Confirm options reset</source>
- <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
+ <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="_msg385">
+ <trans-unit id="_msg400">
<source xml:space="preserve">Client restart required to activate changes.</source>
- <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">360</context></context-group>
+ <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="_msg386">
+ <trans-unit id="_msg401">
+ <source xml:space="preserve">Current settings will be backed up at &quot;%1&quot;.</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&apos;s current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location&apos;s path.</note>
+ </trans-unit>
+ <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">290</context></context-group>
+ <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="_msg387">
+ <trans-unit id="_msg403">
<source xml:space="preserve">Configuration options</source>
- <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
+ <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="_msg388">
+ <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">311</context></context-group>
+ <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="_msg389">
+ <trans-unit id="_msg405">
<source xml:space="preserve">Continue</source>
- <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg390">
+ <trans-unit id="_msg406">
<source xml:space="preserve">Cancel</source>
- <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg391">
+ <trans-unit id="_msg407">
<source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg392">
+ <trans-unit id="_msg408">
<source xml:space="preserve">The configuration file could not be opened.</source>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg393">
+ <trans-unit id="_msg409">
<source xml:space="preserve">This change would require a client restart.</source>
- <context-group purpose="location"><context context-type="linenumber">364</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg394">
+ <trans-unit id="_msg410">
<source xml:space="preserve">The supplied proxy address is invalid.</source>
- <context-group purpose="location"><context context-type="linenumber">392</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">403</context></context-group>
+ </trans-unit>
+ </group>
+ </body></file>
+ <file original="../optionsmodel.cpp" datatype="cpp" source-language="en"><body>
+ <group restype="x-trolltech-linguist-context" resname="OptionsModel">
+ <trans-unit id="_msg411">
+ <source xml:space="preserve">Could not read setting &quot;%1&quot;, %2.</source>
+ <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
</trans-unit>
</group>
</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="_msg395">
+ <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="_msg396">
+ <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="_msg397">
+ <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="_msg398">
+ <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="_msg399">
+ <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="_msg400">
+ <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="_msg401">
+ <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="_msg402">
+ <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="_msg403">
+ <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="_msg404">
+ <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="_msg405">
+ <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="_msg406">
+ <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="_msg407">
+ <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="_msg408">
+ <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="_msg409">
+ <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="_msg410">
+ <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="_msg411">
+ <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="_msg412">
+ <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>
@@ -1838,35 +1942,35 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../overviewpage.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OverviewPage">
- <trans-unit id="_msg413">
+ <trans-unit id="_msg430">
<source xml:space="preserve">Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
- <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">186</context></context-group>
</trans-unit>
</group>
</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="_msg414">
+ <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="_msg415">
+ <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="_msg416">
+ <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="_msg417">
+ <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="_msg418">
+ <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="_msg419">
+ <trans-unit id="_msg436">
<source xml:space="preserve">Close</source>
<context-group purpose="location"><context context-type="linenumber">136</context></context-group>
</trans-unit>
@@ -1874,108 +1978,108 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../psbtoperationsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PSBTOperationsDialog">
- <trans-unit id="_msg420">
+ <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="_msg421">
+ <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="_msg422">
+ <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="_msg423">
+ <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="_msg424">
+ <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="_msg425">
+ <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="_msg426">
+ <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="_msg427">
+ <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="_msg428">
+ <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="_msg429">
+ <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="_msg430">
+ <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="_msg431">
+ <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="_msg432">
+ <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="_msg433">
+ <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="_msg434">
+ <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="_msg435">
+ <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="_msg436">
+ <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="_msg437">
+ <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="_msg438">
+ <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="_msg439">
+ <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="_msg440">
+ <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="_msg441">
+ <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="_msg442">
+ <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="_msg443">
+ <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="_msg444">
+ <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="_msg445">
+ <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>
@@ -1983,295 +2087,308 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../paymentserver.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PaymentServer">
- <trans-unit id="_msg446">
+ <trans-unit id="_msg463">
<source xml:space="preserve">Payment request error</source>
- <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg447">
+ <trans-unit id="_msg464">
<source xml:space="preserve">Cannot start bitcoin: click-to-pay handler</source>
- <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg448">
+ <trans-unit id="_msg465">
<source xml:space="preserve">URI handling</source>
- <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
+ <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="_msg449">
+ <trans-unit id="_msg466">
<source xml:space="preserve">&apos;bitcoin://&apos; is not a valid URI. Use &apos;bitcoin:&apos; instead.</source>
- <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg450">
+ <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&apos;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>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
</trans-unit>
- <trans-unit id="_msg451">
+ <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">254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">231</context></context-group>
</trans-unit>
- <trans-unit id="_msg452">
+ <trans-unit id="_msg469">
<source xml:space="preserve">Payment request file handling</source>
- <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../peertablemodel.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PeerTableModel">
- <trans-unit id="_msg453">
+ <trans-unit id="_msg470">
<source xml:space="preserve">User Agent</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <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&apos;s User Agent string.</note>
</trans-unit>
- <trans-unit id="_msg454">
+ <trans-unit id="_msg471">
<source xml:space="preserve">Ping</source>
- <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
+ <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="_msg455">
+ <trans-unit id="_msg472">
<source xml:space="preserve">Peer</source>
- <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
+ <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="_msg456">
+ <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="_msg474">
<source xml:space="preserve">Direction</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <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="_msg457">
+ <trans-unit id="_msg475">
<source xml:space="preserve">Sent</source>
- <context-group purpose="location"><context context-type="linenumber">102</context></context-group>
+ <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="_msg458">
+ <trans-unit id="_msg476">
<source xml:space="preserve">Received</source>
- <context-group purpose="location"><context context-type="linenumber">105</context></context-group>
+ <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="_msg459">
+ <trans-unit id="_msg477">
<source xml:space="preserve">Address</source>
- <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
+ <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="_msg460">
+ <trans-unit id="_msg478">
<source xml:space="preserve">Type</source>
- <context-group purpose="location"><context context-type="linenumber">93</context></context-group>
+ <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 &quot;type&quot; describes why the connection exists.</note>
</trans-unit>
- <trans-unit id="_msg461">
+ <trans-unit id="_msg479">
<source xml:space="preserve">Network</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <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>
</trans-unit>
</group>
</body></file>
<file original="../peertablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PeerTableModel">
- <trans-unit id="_msg462">
+ <trans-unit id="_msg480">
<source xml:space="preserve">Inbound</source>
- <context-group purpose="location"><context context-type="linenumber">79</context></context-group>
+ <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="_msg463">
+ <trans-unit id="_msg481">
<source xml:space="preserve">Outbound</source>
- <context-group purpose="location"><context context-type="linenumber">81</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">80</context></context-group>
<note annotates="source" from="developer">An Outbound Connection to a Peer.</note>
</trans-unit>
</group>
</body></file>
<file original="../bitcoinunits.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg464">
+ <trans-unit id="_msg482">
<source xml:space="preserve">Amount</source>
- <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../guiutil.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg465">
+ <trans-unit id="_msg483">
<source xml:space="preserve">Enter a Bitcoin address (e.g. %1)</source>
- <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">129</context></context-group>
</trans-unit>
- <trans-unit id="_msg466">
+ <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="_msg485">
<source xml:space="preserve">Unroutable</source>
<context-group purpose="location"><context context-type="linenumber">673</context></context-group>
</trans-unit>
- <trans-unit id="_msg467">
+ <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="_msg468">
+ <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="_msg469">
+ <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="_msg470">
+ <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="_msg471">
+ <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="_msg472">
+ <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="_msg473">
+ <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="_msg474">
+ <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="_msg475">
+ <trans-unit id="_msg494">
<source xml:space="preserve">%1 d</source>
- <context-group purpose="location"><context context-type="linenumber">724</context></context-group>
+ <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="_msg476">
+ <trans-unit id="_msg495">
<source xml:space="preserve">%1 h</source>
- <context-group purpose="location"><context context-type="linenumber">726</context></context-group>
+ <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="_msg477">
+ <trans-unit id="_msg496">
<source xml:space="preserve">%1 m</source>
- <context-group purpose="location"><context context-type="linenumber">728</context></context-group>
+ <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="_msg478">
+ <trans-unit id="_msg497">
<source xml:space="preserve">%1 s</source>
- <context-group purpose="location"><context context-type="linenumber">730</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">758</context></context-group>
+ <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="_msg479">
+ <trans-unit id="_msg498">
<source xml:space="preserve">None</source>
- <context-group purpose="location"><context context-type="linenumber">746</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">751</context></context-group>
</trans-unit>
- <trans-unit id="_msg480">
+ <trans-unit id="_msg499">
<source xml:space="preserve">N/A</source>
- <context-group purpose="location"><context context-type="linenumber">752</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">757</context></context-group>
</trans-unit>
- <trans-unit id="_msg481">
+ <trans-unit id="_msg500">
<source xml:space="preserve">%1 ms</source>
- <context-group purpose="location"><context context-type="linenumber">753</context></context-group>
+ <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">771</context></context-group>
- <trans-unit id="_msg482[0]">
+ <context-group purpose="location"><context context-type="linenumber">776</context></context-group>
+ <trans-unit id="_msg501[0]">
<source xml:space="preserve">%n second(s)</source>
</trans-unit>
- <trans-unit id="_msg482[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">775</context></context-group>
- <trans-unit id="_msg483[0]">
+ <context-group purpose="location"><context context-type="linenumber">780</context></context-group>
+ <trans-unit id="_msg502[0]">
<source xml:space="preserve">%n minute(s)</source>
</trans-unit>
- <trans-unit id="_msg483[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">779</context></context-group>
- <trans-unit id="_msg484[0]">
+ <context-group purpose="location"><context context-type="linenumber">784</context></context-group>
+ <trans-unit id="_msg503[0]">
<source xml:space="preserve">%n hour(s)</source>
</trans-unit>
- <trans-unit id="_msg484[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">783</context></context-group>
- <trans-unit id="_msg485[0]">
+ <context-group purpose="location"><context context-type="linenumber">788</context></context-group>
+ <trans-unit id="_msg504[0]">
<source xml:space="preserve">%n day(s)</source>
</trans-unit>
- <trans-unit id="_msg485[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">787</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">793</context></context-group>
- <trans-unit id="_msg486[0]">
+ <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="_msg505[0]">
<source xml:space="preserve">%n week(s)</source>
</trans-unit>
- <trans-unit id="_msg486[1]">
+ <trans-unit id="_msg505[1]">
<source xml:space="preserve">%n week(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg487">
+ <trans-unit id="_msg506">
<source xml:space="preserve">%1 and %2</source>
- <context-group purpose="location"><context context-type="linenumber">793</context></context-group>
+ <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">793</context></context-group>
- <trans-unit id="_msg488[0]">
+ <context-group purpose="location"><context context-type="linenumber">798</context></context-group>
+ <trans-unit id="_msg507[0]">
<source xml:space="preserve">%n year(s)</source>
</trans-unit>
- <trans-unit id="_msg488[1]">
+ <trans-unit id="_msg507[1]">
<source xml:space="preserve">%n year(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg489">
+ <trans-unit id="_msg508">
<source xml:space="preserve">%1 B</source>
- <context-group purpose="location"><context context-type="linenumber">801</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">806</context></context-group>
</trans-unit>
- <trans-unit id="_msg490">
+ <trans-unit id="_msg509">
<source xml:space="preserve">%1 kB</source>
- <context-group purpose="location"><context context-type="linenumber">803</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">808</context></context-group>
</trans-unit>
- <trans-unit id="_msg491">
+ <trans-unit id="_msg510">
<source xml:space="preserve">%1 MB</source>
- <context-group purpose="location"><context context-type="linenumber">805</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">810</context></context-group>
</trans-unit>
- <trans-unit id="_msg492">
+ <trans-unit id="_msg511">
<source xml:space="preserve">%1 GB</source>
- <context-group purpose="location"><context context-type="linenumber">807</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">812</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../qrimagewidget.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QRImageWidget">
- <trans-unit id="_msg493">
+ <trans-unit id="_msg512">
<source xml:space="preserve">&amp;Save Image…</source>
<context-group purpose="location"><context context-type="linenumber">30</context></context-group>
</trans-unit>
- <trans-unit id="_msg494">
+ <trans-unit id="_msg513">
<source xml:space="preserve">&amp;Copy Image</source>
<context-group purpose="location"><context context-type="linenumber">31</context></context-group>
</trans-unit>
- <trans-unit id="_msg495">
+ <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="_msg496">
+ <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="_msg497">
+ <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="_msg498">
+ <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="_msg499">
+ <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>
@@ -2280,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="_msg500">
+ <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>
@@ -2319,290 +2436,293 @@ If you are receiving this error you should request the merchant provide a BIP21
<context-group purpose="location"><context context-type="linenumber">1610</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1636</context></context-group>
<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">139</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="_msg501">
+ <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="_msg502">
+ <trans-unit id="_msg521">
<source xml:space="preserve">&amp;Information</source>
<context-group purpose="location"><context context-type="linenumber">43</context></context-group>
</trans-unit>
- <trans-unit id="_msg503">
+ <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="_msg504">
+ <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="_msg505">
+ <trans-unit id="_msg524">
<source xml:space="preserve">To specify a non-default location of the data directory use the &apos;%1&apos; option.</source>
<context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
- <trans-unit id="_msg506">
+ <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="_msg507">
+ <trans-unit id="_msg526">
<source xml:space="preserve">To specify a non-default location of the blocks directory use the &apos;%1&apos; option.</source>
<context-group purpose="location"><context context-type="linenumber">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg508">
+ <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="_msg509">
+ <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="_msg510">
+ <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="_msg511">
+ <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="_msg512">
+ <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="_msg513">
+ <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="_msg514">
+ <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="_msg515">
+ <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="_msg516">
+ <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="_msg517">
+ <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="_msg518">
+ <trans-unit id="_msg537">
<source xml:space="preserve">&amp;Reset</source>
<context-group purpose="location"><context context-type="linenumber">665</context></context-group>
</trans-unit>
- <trans-unit id="_msg519">
+ <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="_msg520">
+ <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="_msg521">
+ <trans-unit id="_msg540">
<source xml:space="preserve">&amp;Peers</source>
<context-group purpose="location"><context context-type="linenumber">866</context></context-group>
</trans-unit>
- <trans-unit id="_msg522">
+ <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="_msg523">
+ <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">1160</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="_msg524">
+ <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="_msg525">
+ <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="_msg526">
+ <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="_msg527">
+ <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="_msg528">
+ <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="_msg529">
+ <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="_msg530">
+ <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="_msg531">
+ <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.</note>
+ <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="_msg532">
+ <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="_msg533">
- <source xml:space="preserve">Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
+ <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.</note>
+ <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="_msg534">
+ <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="_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="_msg535">
- <source xml:space="preserve">Total number of addresses dropped 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.</note>
- </trans-unit>
- <trans-unit id="_msg536">
+ <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="_msg537">
+ <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="_msg538">
+ <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="_msg539">
+ <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="_msg540">
+ <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="_msg541">
+ <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="_msg542">
+ <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="_msg543">
+ <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="_msg544">
+ <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="_msg545">
+ <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="_msg546">
+ <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="_msg547">
+ <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="_msg548">
+ <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="_msg549">
+ <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="_msg550">
+ <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="_msg551">
+ <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="_msg552">
+ <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="_msg553">
+ <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="_msg554">
+ <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="_msg555">
+ <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="_msg556">
+ <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="_msg557">
+ <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="_msg558">
+ <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="_msg559">
+ <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="_msg560">
+ <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="_msg561">
+ <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="_msg562">
+ <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="_msg563">
+ <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="_msg564">
+ <trans-unit id="_msg583">
<source xml:space="preserve">&amp;Open</source>
<context-group purpose="location"><context context-type="linenumber">400</context></context-group>
</trans-unit>
- <trans-unit id="_msg565">
+ <trans-unit id="_msg584">
<source xml:space="preserve">&amp;Console</source>
<context-group purpose="location"><context context-type="linenumber">426</context></context-group>
</trans-unit>
- <trans-unit id="_msg566">
+ <trans-unit id="_msg585">
<source xml:space="preserve">&amp;Network Traffic</source>
<context-group purpose="location"><context context-type="linenumber">613</context></context-group>
</trans-unit>
- <trans-unit id="_msg567">
+ <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="_msg568">
+ <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="_msg569">
+ <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>
@@ -2610,123 +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="_msg570">
+ <trans-unit id="_msg589">
<source xml:space="preserve">In:</source>
- <context-group purpose="location"><context context-type="linenumber">959</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">953</context></context-group>
</trans-unit>
- <trans-unit id="_msg571">
+ <trans-unit id="_msg590">
<source xml:space="preserve">Out:</source>
- <context-group purpose="location"><context context-type="linenumber">960</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">954</context></context-group>
</trans-unit>
- <trans-unit id="_msg572">
+ <trans-unit id="_msg591">
<source xml:space="preserve">Inbound: initiated by peer</source>
- <context-group purpose="location"><context context-type="linenumber">503</context></context-group>
+ <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="_msg573">
+ <trans-unit id="_msg592">
<source xml:space="preserve">Outbound Full Relay: default</source>
- <context-group purpose="location"><context context-type="linenumber">507</context></context-group>
+ <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="_msg574">
+ <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">510</context></context-group>
+ <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="_msg575">
+ <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">515</context></context-group>
+ <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="_msg576">
+ <trans-unit id="_msg595">
<source xml:space="preserve">Outbound Feeler: short-lived, for testing addresses</source>
- <context-group purpose="location"><context context-type="linenumber">521</context></context-group>
+ <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="_msg577">
+ <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">524</context></context-group>
+ <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="_msg578">
+ <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">528</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">521</context></context-group>
</trans-unit>
- <trans-unit id="_msg579">
+ <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">529</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
</trans-unit>
- <trans-unit id="_msg580">
+ <trans-unit id="_msg599">
<source xml:space="preserve">no high bandwidth relay selected</source>
- <context-group purpose="location"><context context-type="linenumber">530</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">523</context></context-group>
</trans-unit>
- <trans-unit id="_msg581">
+ <trans-unit id="_msg600">
<source xml:space="preserve">Ctrl++</source>
- <context-group purpose="location"><context context-type="linenumber">543</context></context-group>
+ <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="_msg582">
+ <trans-unit id="_msg601">
<source xml:space="preserve">Ctrl+=</source>
- <context-group purpose="location"><context context-type="linenumber">545</context></context-group>
+ <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="_msg583">
+ <trans-unit id="_msg602">
<source xml:space="preserve">Ctrl+-</source>
- <context-group purpose="location"><context context-type="linenumber">549</context></context-group>
+ <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="_msg584">
+ <trans-unit id="_msg603">
<source xml:space="preserve">Ctrl+_</source>
- <context-group purpose="location"><context context-type="linenumber">551</context></context-group>
+ <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="_msg585">
+ <trans-unit id="_msg604">
<source xml:space="preserve">&amp;Copy address</source>
- <context-group purpose="location"><context context-type="linenumber">702</context></context-group>
+ <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="_msg586">
+ <trans-unit id="_msg605">
<source xml:space="preserve">&amp;Disconnect</source>
- <context-group purpose="location"><context context-type="linenumber">706</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">699</context></context-group>
</trans-unit>
- <trans-unit id="_msg587">
+ <trans-unit id="_msg606">
<source xml:space="preserve">1 &amp;hour</source>
- <context-group purpose="location"><context context-type="linenumber">707</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">700</context></context-group>
</trans-unit>
- <trans-unit id="_msg588">
+ <trans-unit id="_msg607">
<source xml:space="preserve">1 d&amp;ay</source>
- <context-group purpose="location"><context context-type="linenumber">708</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">701</context></context-group>
</trans-unit>
- <trans-unit id="_msg589">
+ <trans-unit id="_msg608">
<source xml:space="preserve">1 &amp;week</source>
- <context-group purpose="location"><context context-type="linenumber">709</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">702</context></context-group>
</trans-unit>
- <trans-unit id="_msg590">
+ <trans-unit id="_msg609">
<source xml:space="preserve">1 &amp;year</source>
- <context-group purpose="location"><context context-type="linenumber">710</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">703</context></context-group>
</trans-unit>
- <trans-unit id="_msg591">
+ <trans-unit id="_msg610">
<source xml:space="preserve">&amp;Copy IP/Netmask</source>
- <context-group purpose="location"><context context-type="linenumber">735</context></context-group>
+ <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&apos;s IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</note>
</trans-unit>
- <trans-unit id="_msg592">
+ <trans-unit id="_msg611">
<source xml:space="preserve">&amp;Unban</source>
- <context-group purpose="location"><context context-type="linenumber">739</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">733</context></context-group>
</trans-unit>
- <trans-unit id="_msg593">
+ <trans-unit id="_msg612">
<source xml:space="preserve">Network activity disabled</source>
- <context-group purpose="location"><context context-type="linenumber">963</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">957</context></context-group>
</trans-unit>
- <trans-unit id="_msg594">
+ <trans-unit id="_msg613">
<source xml:space="preserve">Executing command without any wallet</source>
- <context-group purpose="location"><context context-type="linenumber">1040</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1035</context></context-group>
</trans-unit>
- <trans-unit id="_msg595">
+ <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="_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="_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="_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="_msg618">
<source xml:space="preserve">Executing command using &quot;%1&quot; wallet</source>
- <context-group purpose="location"><context context-type="linenumber">1038</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1033</context></context-group>
</trans-unit>
- <trans-unit id="_msg596">
+ <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.
@@ -2734,124 +2870,124 @@ Type %5 for an overview of available commands.
For more information on using this console, type %6.
%7WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.%8</source>
- <context-group purpose="location"><context context-type="linenumber">893</context></context-group>
+ <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="_msg597">
+ <trans-unit id="_msg620">
<source xml:space="preserve">Executing…</source>
- <context-group purpose="location"><context context-type="linenumber">1048</context></context-group>
+ <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="_msg598">
+ <trans-unit id="_msg621">
<source xml:space="preserve">(peer: %1)</source>
- <context-group purpose="location"><context context-type="linenumber">1166</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1161</context></context-group>
</trans-unit>
- <trans-unit id="_msg599">
+ <trans-unit id="_msg622">
<source xml:space="preserve">via %1</source>
- <context-group purpose="location"><context context-type="linenumber">1168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1163</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../rpcconsole.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="RPCConsole">
- <trans-unit id="_msg600">
+ <trans-unit id="_msg623">
<source xml:space="preserve">Yes</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg601">
+ <trans-unit id="_msg624">
<source xml:space="preserve">No</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg602">
+ <trans-unit id="_msg625">
<source xml:space="preserve">To</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg603">
+ <trans-unit id="_msg626">
<source xml:space="preserve">From</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg604">
+ <trans-unit id="_msg627">
<source xml:space="preserve">Ban for</source>
- <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
- <trans-unit id="_msg605">
+ <trans-unit id="_msg628">
<source xml:space="preserve">Never</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
</trans-unit>
- <trans-unit id="_msg606">
+ <trans-unit id="_msg629">
<source xml:space="preserve">Unknown</source>
- <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
</group>
</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="_msg607">
+ <trans-unit id="_msg630">
<source xml:space="preserve">&amp;Amount:</source>
<context-group purpose="location"><context context-type="linenumber">37</context></context-group>
</trans-unit>
- <trans-unit id="_msg608">
+ <trans-unit id="_msg631">
<source xml:space="preserve">&amp;Label:</source>
<context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg609">
+ <trans-unit id="_msg632">
<source xml:space="preserve">&amp;Message:</source>
<context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg610">
+ <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="_msg611">
+ <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="_msg612">
+ <trans-unit id="_msg635">
<source xml:space="preserve">Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
- <trans-unit id="_msg613">
+ <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="_msg614">
+ <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="_msg615">
+ <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="_msg616">
+ <trans-unit id="_msg639">
<source xml:space="preserve">&amp;Create new receiving address</source>
<context-group purpose="location"><context context-type="linenumber">111</context></context-group>
</trans-unit>
- <trans-unit id="_msg617">
+ <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="_msg618">
+ <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="_msg619">
+ <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="_msg620">
+ <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="_msg621">
+ <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="_msg622">
+ <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="_msg623">
+ <trans-unit id="_msg646">
<source xml:space="preserve">Remove</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
@@ -2859,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="_msg624">
+ <trans-unit id="_msg647">
<source xml:space="preserve">Copy &amp;URI</source>
<context-group purpose="location"><context context-type="linenumber">47</context></context-group>
</trans-unit>
- <trans-unit id="_msg625">
+ <trans-unit id="_msg648">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">48</context></context-group>
</trans-unit>
- <trans-unit id="_msg626">
+ <trans-unit id="_msg649">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">49</context></context-group>
</trans-unit>
- <trans-unit id="_msg627">
+ <trans-unit id="_msg650">
<source xml:space="preserve">Copy &amp;message</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg628">
+ <trans-unit id="_msg651">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg629">
+ <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="_msg630">
+ <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>
@@ -2891,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="_msg631">
+ <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="_msg632">
+ <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="_msg633">
+ <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="_msg634">
+ <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="_msg635">
+ <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="_msg636">
+ <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="_msg637">
+ <trans-unit id="_msg660">
<source xml:space="preserve">Copy &amp;URI</source>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg638">
+ <trans-unit id="_msg661">
<source xml:space="preserve">Copy &amp;Address</source>
<context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg639">
+ <trans-unit id="_msg662">
<source xml:space="preserve">&amp;Verify</source>
<context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg640">
+ <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="_msg641">
+ <trans-unit id="_msg664">
<source xml:space="preserve">&amp;Save Image…</source>
<context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg642">
+ <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>
@@ -2943,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="_msg643">
+ <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>
@@ -2951,186 +3087,186 @@ 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="_msg644">
+ <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="_msg645">
+ <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="_msg646">
+ <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="_msg647">
+ <trans-unit id="_msg670">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">73</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">70</context></context-group>
</trans-unit>
- <trans-unit id="_msg648">
+ <trans-unit id="_msg671">
<source xml:space="preserve">(no message)</source>
- <context-group purpose="location"><context context-type="linenumber">82</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">79</context></context-group>
</trans-unit>
- <trans-unit id="_msg649">
+ <trans-unit id="_msg672">
<source xml:space="preserve">(no amount requested)</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
</trans-unit>
- <trans-unit id="_msg650">
+ <trans-unit id="_msg673">
<source xml:space="preserve">Requested</source>
- <context-group purpose="location"><context context-type="linenumber">133</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">130</context></context-group>
</trans-unit>
</group>
</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="_msg651">
+ <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">752</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="_msg652">
+ <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="_msg653">
+ <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="_msg654">
+ <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="_msg655">
+ <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="_msg656">
+ <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="_msg657">
+ <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="_msg658">
+ <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="_msg659">
+ <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="_msg660">
+ <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="_msg661">
+ <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="_msg662">
+ <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="_msg663">
+ <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="_msg664">
+ <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="_msg665">
+ <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="_msg666">
+ <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="_msg667">
+ <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="_msg668">
+ <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="_msg669">
+ <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="_msg670">
+ <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="_msg671">
+ <trans-unit id="_msg694">
<source xml:space="preserve">Add &amp;Recipient</source>
<context-group purpose="location"><context context-type="linenumber">1163</context></context-group>
</trans-unit>
- <trans-unit id="_msg672">
+ <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="_msg673">
+ <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="_msg674">
+ <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="_msg675">
+ <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="_msg676">
+ <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="_msg677">
+ <trans-unit id="_msg700">
<source xml:space="preserve">Specify a custom fee per kB (1,000 bytes) of the transaction&apos;s virtual size.
Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100 satoshis per kvB&quot; 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="_msg678">
+ <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="_msg679">
+ <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="_msg680">
+ <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="_msg681">
+ <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="_msg682">
+ <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="_msg683">
+ <trans-unit id="_msg706">
<source xml:space="preserve">With Replace-By-Fee (BIP-125) you can increase a transaction&apos;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="_msg684">
+ <trans-unit id="_msg707">
<source xml:space="preserve">Clear &amp;All</source>
<context-group purpose="location"><context context-type="linenumber">1146</context></context-group>
</trans-unit>
- <trans-unit id="_msg685">
+ <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="_msg686">
+ <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="_msg687">
+ <trans-unit id="_msg710">
<source xml:space="preserve">S&amp;end</source>
<context-group purpose="location"><context context-type="linenumber">1120</context></context-group>
</trans-unit>
@@ -3138,422 +3274,396 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../sendcoinsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendCoinsDialog">
- <trans-unit id="_msg688">
+ <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="_msg689">
+ <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="_msg690">
+ <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="_msg691">
+ <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="_msg692">
+ <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="_msg693">
+ <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="_msg694">
+ <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="_msg695">
+ <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="_msg696">
+ <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">&quot;device&quot; usually means a hardware wallet.</note>
</trans-unit>
- <trans-unit id="_msg697">
+ <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="_msg698">
+ <trans-unit id="_msg721">
<source xml:space="preserve">Set external signer script path in Options -&gt; Wallet</source>
<context-group purpose="location"><context context-type="linenumber">218</context></context-group>
<note annotates="source" from="developer">&quot;External signer&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg699">
+ <trans-unit id="_msg722">
<source xml:space="preserve">Cr&amp;eate Unsigned</source>
<context-group purpose="location"><context context-type="linenumber">221</context></context-group>
</trans-unit>
- <trans-unit id="_msg700">
+ <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="_msg701">
+ <trans-unit id="_msg724">
<source xml:space="preserve"> from wallet &apos;%1&apos;</source>
<context-group purpose="location"><context context-type="linenumber">312</context></context-group>
</trans-unit>
- <trans-unit id="_msg702">
+ <trans-unit id="_msg725">
<source xml:space="preserve">%1 to &apos;%2&apos;</source>
<context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
- <trans-unit id="_msg703">
+ <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="_msg704">
+ <trans-unit id="_msg727">
<source xml:space="preserve">To review recipient list click &quot;Show Details…&quot;</source>
- <context-group purpose="location"><context context-type="linenumber">395</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">394</context></context-group>
</trans-unit>
- <trans-unit id="_msg705">
+ <trans-unit id="_msg728">
<source xml:space="preserve">Sign failed</source>
- <context-group purpose="location"><context context-type="linenumber">439</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">454</context></context-group>
</trans-unit>
- <trans-unit id="_msg706">
+ <trans-unit id="_msg729">
<source xml:space="preserve">External signer not found</source>
- <context-group purpose="location"><context context-type="linenumber">445</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">459</context></context-group>
<note annotates="source" from="developer">&quot;External signer&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg707">
+ <trans-unit id="_msg730">
<source xml:space="preserve">External signer failure</source>
- <context-group purpose="location"><context context-type="linenumber">451</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">464</context></context-group>
<note annotates="source" from="developer">&quot;External signer&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg708">
+ <trans-unit id="_msg731">
<source xml:space="preserve">Save Transaction Data</source>
- <context-group purpose="location"><context context-type="linenumber">509</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">430</context></context-group>
</trans-unit>
- <trans-unit id="_msg709">
+ <trans-unit id="_msg732">
<source xml:space="preserve">Partially Signed Transaction (Binary)</source>
- <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
+ <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="_msg710">
+ <trans-unit id="_msg733">
<source xml:space="preserve">PSBT saved</source>
- <context-group purpose="location"><context context-type="linenumber">518</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">439</context></context-group>
</trans-unit>
- <trans-unit id="_msg711">
+ <trans-unit id="_msg734">
<source xml:space="preserve">External balance:</source>
- <context-group purpose="location"><context context-type="linenumber">694</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">705</context></context-group>
</trans-unit>
- <trans-unit id="_msg712">
+ <trans-unit id="_msg735">
<source xml:space="preserve">or</source>
- <context-group purpose="location"><context context-type="linenumber">391</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">390</context></context-group>
</trans-unit>
- <trans-unit id="_msg713">
+ <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="_msg714">
+ <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="_msg715">
+ <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="_msg716">
+ <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="_msg717">
+ <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="_msg718">
+ <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="_msg719">
+ <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="_msg720">
+ <trans-unit id="_msg743">
<source xml:space="preserve">Total Amount</source>
- <context-group purpose="location"><context context-type="linenumber">388</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">387</context></context-group>
</trans-unit>
- <trans-unit id="_msg721">
+ <trans-unit id="_msg744">
<source xml:space="preserve">Confirm send coins</source>
- <context-group purpose="location"><context context-type="linenumber">413</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">486</context></context-group>
</trans-unit>
- <trans-unit id="_msg722">
+ <trans-unit id="_msg745">
<source xml:space="preserve">Watch-only balance:</source>
- <context-group purpose="location"><context context-type="linenumber">697</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">708</context></context-group>
</trans-unit>
- <trans-unit id="_msg723">
+ <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">721</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">732</context></context-group>
</trans-unit>
- <trans-unit id="_msg724">
+ <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">724</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">735</context></context-group>
</trans-unit>
- <trans-unit id="_msg725">
+ <trans-unit id="_msg748">
<source xml:space="preserve">The amount exceeds your balance.</source>
- <context-group purpose="location"><context context-type="linenumber">727</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">738</context></context-group>
</trans-unit>
- <trans-unit id="_msg726">
+ <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">730</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">741</context></context-group>
</trans-unit>
- <trans-unit id="_msg727">
+ <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">733</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">744</context></context-group>
</trans-unit>
- <trans-unit id="_msg728">
+ <trans-unit id="_msg751">
<source xml:space="preserve">Transaction creation failed!</source>
- <context-group purpose="location"><context context-type="linenumber">736</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">747</context></context-group>
</trans-unit>
- <trans-unit id="_msg729">
+ <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">740</context></context-group>
- </trans-unit>
- <trans-unit id="_msg730">
- <source xml:space="preserve">Payment request expired.</source>
- <context-group purpose="location"><context context-type="linenumber">743</context></context-group>
+ <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">867</context></context-group>
- <trans-unit id="_msg731[0]">
+ <context-group purpose="location"><context context-type="linenumber">874</context></context-group>
+ <trans-unit id="_msg753[0]">
<source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source>
</trans-unit>
- <trans-unit id="_msg731[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="_msg732">
+ <trans-unit id="_msg754">
<source xml:space="preserve">Warning: Invalid Bitcoin address</source>
- <context-group purpose="location"><context context-type="linenumber">968</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">975</context></context-group>
</trans-unit>
- <trans-unit id="_msg733">
+ <trans-unit id="_msg755">
<source xml:space="preserve">Warning: Unknown change address</source>
- <context-group purpose="location"><context context-type="linenumber">973</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">980</context></context-group>
</trans-unit>
- <trans-unit id="_msg734">
+ <trans-unit id="_msg756">
<source xml:space="preserve">Confirm custom change address</source>
- <context-group purpose="location"><context context-type="linenumber">976</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">983</context></context-group>
</trans-unit>
- <trans-unit id="_msg735">
+ <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">976</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">983</context></context-group>
</trans-unit>
- <trans-unit id="_msg736">
+ <trans-unit id="_msg758">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">997</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1004</context></context-group>
</trans-unit>
</group>
</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="_msg737">
+ <trans-unit id="_msg759">
<source xml:space="preserve">A&amp;mount:</source>
- <context-group purpose="location"><context context-type="linenumber">155</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">705</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1238</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">151</context></context-group>
</trans-unit>
- <trans-unit id="_msg738">
+ <trans-unit id="_msg760">
<source xml:space="preserve">Pay &amp;To:</source>
- <context-group purpose="location"><context context-type="linenumber">39</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">35</context></context-group>
</trans-unit>
- <trans-unit id="_msg739">
+ <trans-unit id="_msg761">
<source xml:space="preserve">&amp;Label:</source>
- <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
- <trans-unit id="_msg740">
+ <trans-unit id="_msg762">
<source xml:space="preserve">Choose previously used address</source>
- <context-group purpose="location"><context context-type="linenumber">64</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg741">
+ <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">57</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg742">
+ <trans-unit id="_msg764">
<source xml:space="preserve">Alt+A</source>
- <context-group purpose="location"><context context-type="linenumber">80</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">76</context></context-group>
</trans-unit>
- <trans-unit id="_msg743">
+ <trans-unit id="_msg765">
<source xml:space="preserve">Paste address from clipboard</source>
- <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg744">
+ <trans-unit id="_msg766">
<source xml:space="preserve">Alt+P</source>
- <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg745">
+ <trans-unit id="_msg767">
<source xml:space="preserve">Remove this entry</source>
- <context-group purpose="location"><context context-type="linenumber">110</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">672</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1205</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">106</context></context-group>
</trans-unit>
- <trans-unit id="_msg746">
+ <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">170</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">166</context></context-group>
</trans-unit>
- <trans-unit id="_msg747">
+ <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">177</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg748">
+ <trans-unit id="_msg770">
<source xml:space="preserve">S&amp;ubtract fee from amount</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg749">
+ <trans-unit id="_msg771">
<source xml:space="preserve">Use available balance</source>
- <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">183</context></context-group>
</trans-unit>
- <trans-unit id="_msg750">
+ <trans-unit id="_msg772">
<source xml:space="preserve">Message:</source>
- <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
- </trans-unit>
- <trans-unit id="_msg751">
- <source xml:space="preserve">This is an unauthenticated payment request.</source>
- <context-group purpose="location"><context context-type="linenumber">639</context></context-group>
- </trans-unit>
- <trans-unit id="_msg752">
- <source xml:space="preserve">This is an authenticated payment request.</source>
- <context-group purpose="location"><context context-type="linenumber">1168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
</trans-unit>
- <trans-unit id="_msg753">
+ <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">145</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">148</context></context-group>
+ <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="_msg754">
+ <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">206</context></context-group>
- </trans-unit>
- <trans-unit id="_msg755">
- <source xml:space="preserve">Pay To:</source>
- <context-group purpose="location"><context context-type="linenumber">654</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1183</context></context-group>
- </trans-unit>
- <trans-unit id="_msg756">
- <source xml:space="preserve">Memo:</source>
- <context-group purpose="location"><context context-type="linenumber">688</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1221</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../sendcoinsdialog.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendConfirmationDialog">
- <trans-unit id="_msg757">
+ <trans-unit id="_msg775">
<source xml:space="preserve">Send</source>
- <context-group purpose="location"><context context-type="linenumber">131</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">144</context></context-group>
</trans-unit>
- <trans-unit id="_msg758">
+ <trans-unit id="_msg776">
<source xml:space="preserve">Create Unsigned</source>
- <context-group purpose="location"><context context-type="linenumber">133</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
</group>
</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="_msg759">
+ <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="_msg760">
+ <trans-unit id="_msg778">
<source xml:space="preserve">&amp;Sign Message</source>
<context-group purpose="location"><context context-type="linenumber">27</context></context-group>
</trans-unit>
- <trans-unit id="_msg761">
+ <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="_msg762">
+ <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="_msg763">
+ <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="_msg764">
+ <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="_msg765">
+ <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="_msg766">
+ <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="_msg767">
+ <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="_msg768">
+ <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="_msg769">
+ <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="_msg770">
+ <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="_msg771">
+ <trans-unit id="_msg789">
<source xml:space="preserve">Sign &amp;Message</source>
<context-group purpose="location"><context context-type="linenumber">164</context></context-group>
</trans-unit>
- <trans-unit id="_msg772">
+ <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="_msg773">
+ <trans-unit id="_msg791">
<source xml:space="preserve">Clear &amp;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="_msg774">
+ <trans-unit id="_msg792">
<source xml:space="preserve">&amp;Verify Message</source>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg775">
+ <trans-unit id="_msg793">
<source xml:space="preserve">Enter the receiver&apos;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="_msg776">
+ <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="_msg777">
+ <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="_msg778">
+ <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="_msg779">
+ <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="_msg780">
+ <trans-unit id="_msg798">
<source xml:space="preserve">Verify &amp;Message</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg781">
+ <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="_msg782">
+ <trans-unit id="_msg800">
<source xml:space="preserve">Click &quot;Sign Message&quot; to generate signature</source>
<context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
@@ -3561,61 +3671,61 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../signverifymessagedialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SignVerifyMessageDialog">
- <trans-unit id="_msg783">
+ <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="_msg784">
+ <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="_msg785">
+ <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="_msg786">
+ <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="_msg787">
+ <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="_msg788">
+ <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="_msg789">
+ <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="_msg790">
+ <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="_msg791">
+ <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="_msg792">
+ <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="_msg793">
+ <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="_msg794">
+ <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="_msg795">
+ <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>
@@ -3623,11 +3733,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../splashscreen.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SplashScreen">
- <trans-unit id="_msg796">
+ <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="_msg797">
+ <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>
@@ -3635,7 +3745,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../trafficgraphwidget.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TrafficGraphWidget">
- <trans-unit id="_msg798">
+ <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>
@@ -3643,190 +3753,192 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../transactiondesc.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionDesc">
- <trans-unit id="_msg799">
+ <trans-unit id="_msg817">
<source xml:space="preserve">conflicted with a transaction with %1 confirmations</source>
- <context-group purpose="location"><context context-type="linenumber">40</context></context-group>
- </trans-unit>
- <trans-unit id="_msg800">
- <source xml:space="preserve">0/unconfirmed, %1</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="_msg801">
- <source xml:space="preserve">in memory pool</source>
- <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <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="_msg802">
- <source xml:space="preserve">not in memory pool</source>
- <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <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="_msg803">
+ <trans-unit id="_msg820">
<source xml:space="preserve">abandoned</source>
- <context-group purpose="location"><context context-type="linenumber">42</context></context-group>
+ <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="_msg804">
+ <trans-unit id="_msg821">
<source xml:space="preserve">%1/unconfirmed</source>
- <context-group purpose="location"><context context-type="linenumber">45</context></context-group>
+ <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="_msg805">
+ <trans-unit id="_msg822">
<source xml:space="preserve">%1 confirmations</source>
- <context-group purpose="location"><context context-type="linenumber">47</context></context-group>
+ <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="_msg806">
+ <trans-unit id="_msg823">
<source xml:space="preserve">Status</source>
- <context-group purpose="location"><context context-type="linenumber">98</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
- <trans-unit id="_msg807">
+ <trans-unit id="_msg824">
<source xml:space="preserve">Date</source>
- <context-group purpose="location"><context context-type="linenumber">101</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
</trans-unit>
- <trans-unit id="_msg808">
+ <trans-unit id="_msg825">
<source xml:space="preserve">Source</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg809">
+ <trans-unit id="_msg826">
<source xml:space="preserve">Generated</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg810">
+ <trans-unit id="_msg827">
<source xml:space="preserve">From</source>
- <context-group purpose="location"><context context-type="linenumber">113</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
+ <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="_msg811">
+ <trans-unit id="_msg828">
<source xml:space="preserve">unknown</source>
- <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg812">
+ <trans-unit id="_msg829">
<source xml:space="preserve">To</source>
- <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">148</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
+ <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="_msg813">
+ <trans-unit id="_msg830">
<source xml:space="preserve">own address</source>
- <context-group purpose="location"><context context-type="linenumber">130</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">156</context></context-group>
</trans-unit>
- <trans-unit id="_msg814">
+ <trans-unit id="_msg831">
<source xml:space="preserve">watch-only</source>
- <context-group purpose="location"><context context-type="linenumber">130</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
+ <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="_msg815">
+ <trans-unit id="_msg832">
<source xml:space="preserve">label</source>
- <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">158</context></context-group>
</trans-unit>
- <trans-unit id="_msg816">
+ <trans-unit id="_msg833">
<source xml:space="preserve">Credit</source>
- <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">234</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
- <trans-unit id="_msg817[0]">
+ <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
+ <trans-unit id="_msg834[0]">
<source xml:space="preserve">matures in %n more block(s)</source>
</trans-unit>
- <trans-unit id="_msg817[1]">
+ <trans-unit id="_msg834[1]">
<source xml:space="preserve">matures in %n more block(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg818">
+ <trans-unit id="_msg835">
<source xml:space="preserve">not accepted</source>
- <context-group purpose="location"><context context-type="linenumber">172</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">198</context></context-group>
</trans-unit>
- <trans-unit id="_msg819">
+ <trans-unit id="_msg836">
<source xml:space="preserve">Debit</source>
- <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
<context-group purpose="location"><context context-type="linenumber">258</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">321</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="_msg820">
+ <trans-unit id="_msg837">
<source xml:space="preserve">Total debit</source>
- <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
- <trans-unit id="_msg821">
+ <trans-unit id="_msg838">
<source xml:space="preserve">Total credit</source>
- <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg822">
+ <trans-unit id="_msg839">
<source xml:space="preserve">Transaction fee</source>
- <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
- <trans-unit id="_msg823">
+ <trans-unit id="_msg840">
<source xml:space="preserve">Net amount</source>
- <context-group purpose="location"><context context-type="linenumber">270</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
- <trans-unit id="_msg824">
+ <trans-unit id="_msg841">
<source xml:space="preserve">Message</source>
- <context-group purpose="location"><context context-type="linenumber">276</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
+ <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="_msg825">
+ <trans-unit id="_msg842">
<source xml:space="preserve">Comment</source>
- <context-group purpose="location"><context context-type="linenumber">278</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">304</context></context-group>
</trans-unit>
- <trans-unit id="_msg826">
+ <trans-unit id="_msg843">
<source xml:space="preserve">Transaction ID</source>
- <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
- <trans-unit id="_msg827">
+ <trans-unit id="_msg844">
<source xml:space="preserve">Transaction total size</source>
- <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
</trans-unit>
- <trans-unit id="_msg828">
+ <trans-unit id="_msg845">
<source xml:space="preserve">Transaction virtual size</source>
- <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
</trans-unit>
- <trans-unit id="_msg829">
+ <trans-unit id="_msg846">
<source xml:space="preserve">Output index</source>
- <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">309</context></context-group>
</trans-unit>
- <trans-unit id="_msg830">
+ <trans-unit id="_msg847">
<source xml:space="preserve"> (Certificate was not verified)</source>
- <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg831">
+ <trans-unit id="_msg848">
<source xml:space="preserve">Merchant</source>
- <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
</trans-unit>
- <trans-unit id="_msg832">
+ <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 &quot;not accepted&quot; and it won&apos;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">310</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
</trans-unit>
- <trans-unit id="_msg833">
+ <trans-unit id="_msg850">
<source xml:space="preserve">Debug information</source>
- <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg834">
+ <trans-unit id="_msg851">
<source xml:space="preserve">Transaction</source>
- <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
</trans-unit>
- <trans-unit id="_msg835">
+ <trans-unit id="_msg852">
<source xml:space="preserve">Inputs</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">355</context></context-group>
</trans-unit>
- <trans-unit id="_msg836">
+ <trans-unit id="_msg853">
<source xml:space="preserve">Amount</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
</trans-unit>
- <trans-unit id="_msg837">
+ <trans-unit id="_msg854">
<source xml:space="preserve">true</source>
- <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <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="_msg838">
+ <trans-unit id="_msg855">
<source xml:space="preserve">false</source>
- <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <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>
</group>
</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="_msg839">
+ <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>
@@ -3834,7 +3946,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../transactiondescdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionDescDialog">
- <trans-unit id="_msg840">
+ <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>
@@ -3842,266 +3954,266 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../transactiontablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionTableModel">
- <trans-unit id="_msg841">
+ <trans-unit id="_msg858">
<source xml:space="preserve">Date</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg842">
+ <trans-unit id="_msg859">
<source xml:space="preserve">Type</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg843">
+ <trans-unit id="_msg860">
<source xml:space="preserve">Label</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg844">
+ <trans-unit id="_msg861">
<source xml:space="preserve">Unconfirmed</source>
- <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg845">
+ <trans-unit id="_msg862">
<source xml:space="preserve">Abandoned</source>
- <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
- <trans-unit id="_msg846">
+ <trans-unit id="_msg863">
<source xml:space="preserve">Confirming (%1 of %2 recommended confirmations)</source>
- <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
</trans-unit>
- <trans-unit id="_msg847">
+ <trans-unit id="_msg864">
<source xml:space="preserve">Confirmed (%1 confirmations)</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
</trans-unit>
- <trans-unit id="_msg848">
+ <trans-unit id="_msg865">
<source xml:space="preserve">Conflicted</source>
- <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
- <trans-unit id="_msg849">
+ <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">335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
</trans-unit>
- <trans-unit id="_msg850">
+ <trans-unit id="_msg867">
<source xml:space="preserve">Generated but not accepted</source>
- <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
- <trans-unit id="_msg851">
+ <trans-unit id="_msg868">
<source xml:space="preserve">Received with</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="_msg852">
+ <trans-unit id="_msg869">
<source xml:space="preserve">Received from</source>
- <context-group purpose="location"><context context-type="linenumber">379</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">380</context></context-group>
</trans-unit>
- <trans-unit id="_msg853">
+ <trans-unit id="_msg870">
<source xml:space="preserve">Sent to</source>
- <context-group purpose="location"><context context-type="linenumber">382</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">383</context></context-group>
</trans-unit>
- <trans-unit id="_msg854">
+ <trans-unit id="_msg871">
<source xml:space="preserve">Payment to yourself</source>
- <context-group purpose="location"><context context-type="linenumber">384</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">385</context></context-group>
</trans-unit>
- <trans-unit id="_msg855">
+ <trans-unit id="_msg872">
<source xml:space="preserve">Mined</source>
- <context-group purpose="location"><context context-type="linenumber">386</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">387</context></context-group>
</trans-unit>
- <trans-unit id="_msg856">
+ <trans-unit id="_msg873">
<source xml:space="preserve">watch-only</source>
- <context-group purpose="location"><context context-type="linenumber">414</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">415</context></context-group>
</trans-unit>
- <trans-unit id="_msg857">
+ <trans-unit id="_msg874">
<source xml:space="preserve">(n/a)</source>
- <context-group purpose="location"><context context-type="linenumber">430</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">431</context></context-group>
</trans-unit>
- <trans-unit id="_msg858">
+ <trans-unit id="_msg875">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">637</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">638</context></context-group>
</trans-unit>
- <trans-unit id="_msg859">
+ <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">676</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">677</context></context-group>
</trans-unit>
- <trans-unit id="_msg860">
+ <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">678</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">679</context></context-group>
</trans-unit>
- <trans-unit id="_msg861">
+ <trans-unit id="_msg878">
<source xml:space="preserve">Type of transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">680</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">681</context></context-group>
</trans-unit>
- <trans-unit id="_msg862">
+ <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">682</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">683</context></context-group>
</trans-unit>
- <trans-unit id="_msg863">
+ <trans-unit id="_msg880">
<source xml:space="preserve">User-defined intent/purpose of the transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">684</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">685</context></context-group>
</trans-unit>
- <trans-unit id="_msg864">
+ <trans-unit id="_msg881">
<source xml:space="preserve">Amount removed from or added to balance.</source>
- <context-group purpose="location"><context context-type="linenumber">686</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">687</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../transactionview.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionView">
- <trans-unit id="_msg865">
+ <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="_msg866">
+ <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="_msg867">
+ <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="_msg868">
+ <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="_msg869">
+ <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="_msg870">
+ <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="_msg871">
+ <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="_msg872">
+ <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="_msg873">
+ <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="_msg874">
+ <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="_msg875">
+ <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="_msg876">
+ <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="_msg877">
+ <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="_msg878">
+ <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="_msg879">
+ <trans-unit id="_msg896">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">169</context></context-group>
</trans-unit>
- <trans-unit id="_msg880">
+ <trans-unit id="_msg897">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg881">
+ <trans-unit id="_msg898">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">171</context></context-group>
</trans-unit>
- <trans-unit id="_msg882">
+ <trans-unit id="_msg899">
<source xml:space="preserve">Copy transaction &amp;ID</source>
<context-group purpose="location"><context context-type="linenumber">172</context></context-group>
</trans-unit>
- <trans-unit id="_msg883">
+ <trans-unit id="_msg900">
<source xml:space="preserve">Copy &amp;raw transaction</source>
<context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg884">
+ <trans-unit id="_msg901">
<source xml:space="preserve">Copy full transaction &amp;details</source>
<context-group purpose="location"><context context-type="linenumber">174</context></context-group>
</trans-unit>
- <trans-unit id="_msg885">
+ <trans-unit id="_msg902">
<source xml:space="preserve">&amp;Show transaction details</source>
<context-group purpose="location"><context context-type="linenumber">175</context></context-group>
</trans-unit>
- <trans-unit id="_msg886">
+ <trans-unit id="_msg903">
<source xml:space="preserve">Increase transaction &amp;fee</source>
<context-group purpose="location"><context context-type="linenumber">177</context></context-group>
</trans-unit>
- <trans-unit id="_msg887">
+ <trans-unit id="_msg904">
<source xml:space="preserve">A&amp;bandon transaction</source>
<context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg888">
+ <trans-unit id="_msg905">
<source xml:space="preserve">&amp;Edit address label</source>
<context-group purpose="location"><context context-type="linenumber">181</context></context-group>
</trans-unit>
- <trans-unit id="_msg889">
+ <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="_msg890">
+ <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="_msg891">
+ <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="_msg892">
+ <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="_msg893">
+ <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="_msg894">
+ <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="_msg895">
+ <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="_msg896">
+ <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="_msg897">
+ <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="_msg898">
+ <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="_msg899">
+ <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="_msg900">
+ <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="_msg901">
+ <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="_msg902">
+ <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="_msg903">
+ <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="_msg904">
+ <trans-unit id="_msg921">
<source xml:space="preserve">to</source>
<context-group purpose="location"><context context-type="linenumber">566</context></context-group>
</trans-unit>
@@ -4109,810 +4221,838 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../walletframe.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletFrame">
- <trans-unit id="_msg905">
+ <trans-unit id="_msg922">
<source xml:space="preserve">No wallet has been loaded.
Go to File &gt; 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="_msg906">
+ <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="_msg907">
+ <trans-unit id="_msg924">
<source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <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="_msg908">
+ <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">204</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg909">
+ <trans-unit id="_msg926">
<source xml:space="preserve">Load Transaction Data</source>
- <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
</trans-unit>
- <trans-unit id="_msg910">
+ <trans-unit id="_msg927">
<source xml:space="preserve">Partially Signed Transaction (*.psbt)</source>
- <context-group purpose="location"><context context-type="linenumber">210</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg911">
+ <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">213</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
</trans-unit>
- <trans-unit id="_msg912">
+ <trans-unit id="_msg929">
<source xml:space="preserve">Unable to decode PSBT</source>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletmodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletModel">
- <trans-unit id="_msg913">
+ <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="_msg914">
+ <trans-unit id="_msg931">
<source xml:space="preserve">Fee bump error</source>
- <context-group purpose="location"><context context-type="linenumber">481</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">533</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">548</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
+ <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="_msg915">
+ <trans-unit id="_msg932">
<source xml:space="preserve">Increasing transaction fee failed</source>
- <context-group purpose="location"><context context-type="linenumber">481</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">484</context></context-group>
</trans-unit>
- <trans-unit id="_msg916">
+ <trans-unit id="_msg933">
<source xml:space="preserve">Do you want to increase the fee?</source>
- <context-group purpose="location"><context context-type="linenumber">488</context></context-group>
+ <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="_msg917">
+ <trans-unit id="_msg934">
<source xml:space="preserve">Current fee:</source>
- <context-group purpose="location"><context context-type="linenumber">492</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">495</context></context-group>
</trans-unit>
- <trans-unit id="_msg918">
+ <trans-unit id="_msg935">
<source xml:space="preserve">Increase:</source>
- <context-group purpose="location"><context context-type="linenumber">496</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">499</context></context-group>
</trans-unit>
- <trans-unit id="_msg919">
+ <trans-unit id="_msg936">
<source xml:space="preserve">New fee:</source>
- <context-group purpose="location"><context context-type="linenumber">500</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">503</context></context-group>
</trans-unit>
- <trans-unit id="_msg920">
+ <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">508</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
</trans-unit>
- <trans-unit id="_msg921">
+ <trans-unit id="_msg938">
<source xml:space="preserve">Confirm fee bump</source>
- <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">514</context></context-group>
</trans-unit>
- <trans-unit id="_msg922">
+ <trans-unit id="_msg939">
<source xml:space="preserve">Can&apos;t draft transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">533</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">536</context></context-group>
</trans-unit>
- <trans-unit id="_msg923">
+ <trans-unit id="_msg940">
<source xml:space="preserve">PSBT copied</source>
- <context-group purpose="location"><context context-type="linenumber">540</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">543</context></context-group>
</trans-unit>
- <trans-unit id="_msg924">
+ <trans-unit id="_msg941">
<source xml:space="preserve">Can&apos;t sign transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">548</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">551</context></context-group>
</trans-unit>
- <trans-unit id="_msg925">
+ <trans-unit id="_msg942">
<source xml:space="preserve">Could not commit transaction</source>
- <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">556</context></context-group>
</trans-unit>
- <trans-unit id="_msg926">
+ <trans-unit id="_msg943">
<source xml:space="preserve">Can&apos;t display address</source>
- <context-group purpose="location"><context context-type="linenumber">567</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">570</context></context-group>
</trans-unit>
- <trans-unit id="_msg927">
+ <trans-unit id="_msg944">
<source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">585</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">588</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletview.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletView">
- <trans-unit id="_msg928">
+ <trans-unit id="_msg945">
<source xml:space="preserve">&amp;Export</source>
- <context-group purpose="location"><context context-type="linenumber">52</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg929">
+ <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">53</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="_msg930">
+ <trans-unit id="_msg947">
<source xml:space="preserve">Backup Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
</trans-unit>
- <trans-unit id="_msg931">
+ <trans-unit id="_msg948">
<source xml:space="preserve">Wallet Data</source>
- <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
+ <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="_msg932">
+ <trans-unit id="_msg949">
<source xml:space="preserve">Backup Failed</source>
- <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg933">
+ <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">225</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg934">
+ <trans-unit id="_msg951">
<source xml:space="preserve">Backup Successful</source>
- <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg935">
+ <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">229</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg936">
+ <trans-unit id="_msg953">
<source xml:space="preserve">Cancel</source>
- <context-group purpose="location"><context context-type="linenumber">266</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../bitcoinstrings.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="bitcoin-core">
- <trans-unit id="_msg937">
+ <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="_msg938">
+ <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="_msg939">
+ <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">16</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">20</context></context-group>
</trans-unit>
- <trans-unit id="_msg940">
+ <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">19</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">38</context></context-group>
</trans-unit>
- <trans-unit id="_msg941">
+ <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">22</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">41</context></context-group>
</trans-unit>
- <trans-unit id="_msg942">
+ <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">27</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">46</context></context-group>
</trans-unit>
- <trans-unit id="_msg943">
+ <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">31</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg944">
+ <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">37</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">56</context></context-group>
</trans-unit>
- <trans-unit id="_msg945">
+ <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">40</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">59</context></context-group>
</trans-unit>
- <trans-unit id="_msg946">
+ <trans-unit id="_msg963">
<source xml:space="preserve">Error: Dumpfile format record is incorrect. Got &quot;%s&quot;, expected &quot;format&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">62</context></context-group>
</trans-unit>
- <trans-unit id="_msg947">
+ <trans-unit id="_msg964">
<source xml:space="preserve">Error: Dumpfile identifier record is incorrect. Got &quot;%s&quot;, expected &quot;%s&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">45</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">64</context></context-group>
</trans-unit>
- <trans-unit id="_msg948">
+ <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">47</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">66</context></context-group>
</trans-unit>
- <trans-unit id="_msg949">
+ <trans-unit id="_msg966">
<source xml:space="preserve">Error: Legacy wallets only support the &quot;legacy&quot;, &quot;p2sh-segwit&quot;, and &quot;bech32&quot; address types</source>
- <context-group purpose="location"><context context-type="linenumber">50</context></context-group>
- </trans-unit>
- <trans-unit id="_msg950">
- <source xml:space="preserve">Error: Listening for incoming connections failed (listen returned error %s)</source>
- <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">69</context></context-group>
</trans-unit>
- <trans-unit id="_msg951">
+ <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">55</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">75</context></context-group>
</trans-unit>
- <trans-unit id="_msg952">
+ <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">58</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">78</context></context-group>
</trans-unit>
- <trans-unit id="_msg953">
+ <trans-unit id="_msg969">
<source xml:space="preserve">Invalid amount for -maxtxfee=&lt;amount&gt;: &apos;%s&apos; (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <context-group purpose="location"><context context-type="linenumber">61</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">81</context></context-group>
</trans-unit>
- <trans-unit id="_msg954">
+ <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">64</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
</trans-unit>
- <trans-unit id="_msg955">
+ <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">68</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">88</context></context-group>
</trans-unit>
- <trans-unit id="_msg956">
+ <trans-unit id="_msg972">
<source xml:space="preserve">No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
- <context-group purpose="location"><context context-type="linenumber">71</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">91</context></context-group>
</trans-unit>
- <trans-unit id="_msg957">
+ <trans-unit id="_msg973">
<source xml:space="preserve">No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
- <context-group purpose="location"><context context-type="linenumber">74</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">94</context></context-group>
</trans-unit>
- <trans-unit id="_msg958">
+ <trans-unit id="_msg974">
<source xml:space="preserve">No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
- <context-group purpose="location"><context context-type="linenumber">76</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg959">
+ <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="_msg976">
<source xml:space="preserve">Please check that your computer&apos;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">79</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
</trans-unit>
- <trans-unit id="_msg960">
+ <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">82</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">106</context></context-group>
</trans-unit>
- <trans-unit id="_msg961">
+ <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">85</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">109</context></context-group>
</trans-unit>
- <trans-unit id="_msg962">
+ <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="_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">87</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">114</context></context-group>
</trans-unit>
- <trans-unit id="_msg963">
+ <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">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">117</context></context-group>
</trans-unit>
- <trans-unit id="_msg964">
+ <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&apos;s date and time being set incorrectly. Only rebuild the block database if you are sure that your computer&apos;s date and time are correct</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
- <trans-unit id="_msg965">
+ <trans-unit id="_msg983">
<source xml:space="preserve">The block index db contains a legacy &apos;txindex&apos;. 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">101</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
- <trans-unit id="_msg966">
+ <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">105</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
</trans-unit>
- <trans-unit id="_msg967">
+ <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">107</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg968">
+ <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">111</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
</trans-unit>
- <trans-unit id="_msg969">
+ <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">114</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">141</context></context-group>
</trans-unit>
- <trans-unit id="_msg970">
+ <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">117</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">144</context></context-group>
</trans-unit>
- <trans-unit id="_msg971">
+ <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">120</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">147</context></context-group>
</trans-unit>
- <trans-unit id="_msg972">
+ <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">122</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">149</context></context-group>
</trans-unit>
- <trans-unit id="_msg973">
+ <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">125</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg974">
+ <trans-unit id="_msg992">
<source xml:space="preserve">Unknown wallet file format &quot;%s&quot; provided. Please provide one of &quot;bdb&quot; or &quot;sqlite&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">155</context></context-group>
</trans-unit>
- <trans-unit id="_msg975">
+ <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="_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="_msg995">
<source xml:space="preserve">Warning: Dumpfile wallet format &quot;%s&quot; does not match command line specified format &quot;%s&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">131</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">165</context></context-group>
</trans-unit>
- <trans-unit id="_msg976">
+ <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">134</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
</trans-unit>
- <trans-unit id="_msg977">
+ <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">136</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg978">
+ <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">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg979">
+ <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">142</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg980">
+ <trans-unit id="_msg1000">
<source xml:space="preserve">%s is set very high!</source>
- <context-group purpose="location"><context context-type="linenumber">145</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">179</context></context-group>
</trans-unit>
- <trans-unit id="_msg981">
+ <trans-unit id="_msg1001">
<source xml:space="preserve">-maxmempool must be at least %d MB</source>
- <context-group purpose="location"><context context-type="linenumber">146</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg982">
+ <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">147</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
</trans-unit>
- <trans-unit id="_msg983">
+ <trans-unit id="_msg1003">
<source xml:space="preserve">Cannot resolve -%s address: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">148</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">182</context></context-group>
</trans-unit>
- <trans-unit id="_msg984">
+ <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">149</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">183</context></context-group>
</trans-unit>
- <trans-unit id="_msg985">
+ <trans-unit id="_msg1005">
<source xml:space="preserve">Cannot set -peerblockfilters without -blockfilterindex.</source>
- <context-group purpose="location"><context context-type="linenumber">150</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">184</context></context-group>
</trans-unit>
- <trans-unit id="_msg986">
+ <trans-unit id="_msg1006">
<source xml:space="preserve">Cannot write to data directory &apos;%s&apos;; check permissions.</source>
- <context-group purpose="location"><context context-type="linenumber">151</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
</trans-unit>
- <trans-unit id="_msg987">
+ <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">93</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">120</context></context-group>
</trans-unit>
- <trans-unit id="_msg988">
+ <trans-unit id="_msg1008">
+ <source xml:space="preserve">%s request to listen on port %u. This port is considered &quot;bad&quot; 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="_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="_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="_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="_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="_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">24</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
</trans-unit>
- <trans-unit id="_msg989">
+ <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">34</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg990">
+ <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="_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">152</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">186</context></context-group>
</trans-unit>
- <trans-unit id="_msg991">
+ <trans-unit id="_msg1017">
<source xml:space="preserve">Copyright (C) %i-%i</source>
- <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
</trans-unit>
- <trans-unit id="_msg992">
+ <trans-unit id="_msg1018">
<source xml:space="preserve">Corrupted block database detected</source>
- <context-group purpose="location"><context context-type="linenumber">154</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">188</context></context-group>
</trans-unit>
- <trans-unit id="_msg993">
+ <trans-unit id="_msg1019">
<source xml:space="preserve">Could not find asmap file %s</source>
- <context-group purpose="location"><context context-type="linenumber">155</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">189</context></context-group>
</trans-unit>
- <trans-unit id="_msg994">
+ <trans-unit id="_msg1020">
<source xml:space="preserve">Could not parse asmap file %s</source>
- <context-group purpose="location"><context context-type="linenumber">156</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">190</context></context-group>
</trans-unit>
- <trans-unit id="_msg995">
+ <trans-unit id="_msg1021">
<source xml:space="preserve">Disk space is too low!</source>
- <context-group purpose="location"><context context-type="linenumber">157</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">191</context></context-group>
</trans-unit>
- <trans-unit id="_msg996">
+ <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">158</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
</trans-unit>
- <trans-unit id="_msg997">
+ <trans-unit id="_msg1023">
<source xml:space="preserve">Done loading</source>
- <context-group purpose="location"><context context-type="linenumber">159</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">193</context></context-group>
</trans-unit>
- <trans-unit id="_msg998">
+ <trans-unit id="_msg1024">
<source xml:space="preserve">Dump file %s does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">160</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg999">
+ <trans-unit id="_msg1025">
<source xml:space="preserve">Error creating %s</source>
- <context-group purpose="location"><context context-type="linenumber">161</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">195</context></context-group>
</trans-unit>
- <trans-unit id="_msg1000">
+ <trans-unit id="_msg1026">
<source xml:space="preserve">Error initializing block database</source>
- <context-group purpose="location"><context context-type="linenumber">162</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
</trans-unit>
- <trans-unit id="_msg1001">
+ <trans-unit id="_msg1027">
<source xml:space="preserve">Error initializing wallet database environment %s!</source>
- <context-group purpose="location"><context context-type="linenumber">163</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
</trans-unit>
- <trans-unit id="_msg1002">
+ <trans-unit id="_msg1028">
<source xml:space="preserve">Error loading %s</source>
- <context-group purpose="location"><context context-type="linenumber">164</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">198</context></context-group>
</trans-unit>
- <trans-unit id="_msg1003">
+ <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">165</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
</trans-unit>
- <trans-unit id="_msg1004">
+ <trans-unit id="_msg1030">
<source xml:space="preserve">Error loading %s: Wallet corrupted</source>
- <context-group purpose="location"><context context-type="linenumber">166</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">200</context></context-group>
</trans-unit>
- <trans-unit id="_msg1005">
+ <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">167</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg1006">
+ <trans-unit id="_msg1032">
<source xml:space="preserve">Error loading block database</source>
- <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
- <trans-unit id="_msg1007">
+ <trans-unit id="_msg1033">
<source xml:space="preserve">Error opening block database</source>
- <context-group purpose="location"><context context-type="linenumber">169</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">203</context></context-group>
</trans-unit>
- <trans-unit id="_msg1008">
+ <trans-unit id="_msg1034">
<source xml:space="preserve">Error reading from database, shutting down.</source>
- <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
</trans-unit>
- <trans-unit id="_msg1009">
+ <trans-unit id="_msg1035">
<source xml:space="preserve">Error reading next record from wallet database</source>
- <context-group purpose="location"><context context-type="linenumber">171</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1010">
- <source xml:space="preserve">Error upgrading chainstate database</source>
- <context-group purpose="location"><context context-type="linenumber">172</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">205</context></context-group>
</trans-unit>
- <trans-unit id="_msg1011">
+ <trans-unit id="_msg1036">
<source xml:space="preserve">Error: Couldn&apos;t create cursor into database</source>
- <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
</trans-unit>
- <trans-unit id="_msg1012">
+ <trans-unit id="_msg1037">
<source xml:space="preserve">Error: Disk space is low for %s</source>
- <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
</trans-unit>
- <trans-unit id="_msg1013">
+ <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">175</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg1014">
+ <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">176</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
</trans-unit>
- <trans-unit id="_msg1015">
+ <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">177</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">210</context></context-group>
</trans-unit>
- <trans-unit id="_msg1016">
+ <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">178</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
</trans-unit>
- <trans-unit id="_msg1017">
+ <trans-unit id="_msg1042">
<source xml:space="preserve">Error: Missing checksum</source>
- <context-group purpose="location"><context context-type="linenumber">179</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg1018">
+ <trans-unit id="_msg1043">
<source xml:space="preserve">Error: No %s addresses available.</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
</trans-unit>
- <trans-unit id="_msg1019">
+ <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">181</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
</trans-unit>
- <trans-unit id="_msg1020">
+ <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">182</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
</trans-unit>
- <trans-unit id="_msg1021">
+ <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">183</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">216</context></context-group>
</trans-unit>
- <trans-unit id="_msg1022">
+ <trans-unit id="_msg1047">
<source xml:space="preserve">Failed to rescan the wallet during initialization</source>
- <context-group purpose="location"><context context-type="linenumber">184</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
</trans-unit>
- <trans-unit id="_msg1023">
+ <trans-unit id="_msg1048">
<source xml:space="preserve">Failed to verify database</source>
- <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
</trans-unit>
- <trans-unit id="_msg1024">
+ <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">186</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
</trans-unit>
- <trans-unit id="_msg1025">
+ <trans-unit id="_msg1050">
<source xml:space="preserve">Ignoring duplicate -wallet %s.</source>
- <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">220</context></context-group>
</trans-unit>
- <trans-unit id="_msg1026">
+ <trans-unit id="_msg1051">
<source xml:space="preserve">Importing…</source>
- <context-group purpose="location"><context context-type="linenumber">188</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">221</context></context-group>
</trans-unit>
- <trans-unit id="_msg1027">
+ <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">189</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg1028">
+ <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">190</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
</trans-unit>
- <trans-unit id="_msg1029">
+ <trans-unit id="_msg1054">
<source xml:space="preserve">Input not found or already spent</source>
- <context-group purpose="location"><context context-type="linenumber">191</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
</trans-unit>
- <trans-unit id="_msg1030">
+ <trans-unit id="_msg1055">
<source xml:space="preserve">Insufficient funds</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
</trans-unit>
- <trans-unit id="_msg1031">
+ <trans-unit id="_msg1056">
<source xml:space="preserve">Invalid -i2psam address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">193</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg1032">
+ <trans-unit id="_msg1057">
<source xml:space="preserve">Invalid -onion address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">227</context></context-group>
</trans-unit>
- <trans-unit id="_msg1033">
+ <trans-unit id="_msg1058">
<source xml:space="preserve">Invalid -proxy address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">195</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">228</context></context-group>
</trans-unit>
- <trans-unit id="_msg1034">
+ <trans-unit id="_msg1059">
<source xml:space="preserve">Invalid P2P permission: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
- <trans-unit id="_msg1035">
+ <trans-unit id="_msg1060">
<source xml:space="preserve">Invalid amount for -%s=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">230</context></context-group>
</trans-unit>
- <trans-unit id="_msg1036">
+ <trans-unit id="_msg1061">
<source xml:space="preserve">Invalid amount for -discardfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">198</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">231</context></context-group>
</trans-unit>
- <trans-unit id="_msg1037">
+ <trans-unit id="_msg1062">
<source xml:space="preserve">Invalid amount for -fallbackfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg1038">
+ <trans-unit id="_msg1063">
<source xml:space="preserve">Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos; (must be at least %s)</source>
- <context-group purpose="location"><context context-type="linenumber">200</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">233</context></context-group>
</trans-unit>
- <trans-unit id="_msg1039">
+ <trans-unit id="_msg1064">
<source xml:space="preserve">Invalid netmask specified in -whitelist: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">234</context></context-group>
</trans-unit>
- <trans-unit id="_msg1040">
+ <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="_msg1066">
<source xml:space="preserve">Loading P2P addresses…</source>
- <context-group purpose="location"><context context-type="linenumber">202</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">236</context></context-group>
</trans-unit>
- <trans-unit id="_msg1041">
+ <trans-unit id="_msg1067">
<source xml:space="preserve">Loading banlist…</source>
- <context-group purpose="location"><context context-type="linenumber">203</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">237</context></context-group>
</trans-unit>
- <trans-unit id="_msg1042">
+ <trans-unit id="_msg1068">
<source xml:space="preserve">Loading block index…</source>
- <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">238</context></context-group>
</trans-unit>
- <trans-unit id="_msg1043">
+ <trans-unit id="_msg1069">
<source xml:space="preserve">Loading wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">205</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">239</context></context-group>
</trans-unit>
- <trans-unit id="_msg1044">
+ <trans-unit id="_msg1070">
<source xml:space="preserve">Missing amount</source>
- <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg1045">
+ <trans-unit id="_msg1071">
<source xml:space="preserve">Missing solving data for estimating transaction size</source>
- <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg1046">
+ <trans-unit id="_msg1072">
<source xml:space="preserve">Need to specify a port with -whitebind: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
</trans-unit>
- <trans-unit id="_msg1047">
+ <trans-unit id="_msg1073">
<source xml:space="preserve">No addresses available</source>
- <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1048">
- <source xml:space="preserve">No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <context-group purpose="location"><context context-type="linenumber">210</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
</trans-unit>
- <trans-unit id="_msg1049">
+ <trans-unit id="_msg1074">
<source xml:space="preserve">Not enough file descriptors available.</source>
- <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
</trans-unit>
- <trans-unit id="_msg1050">
+ <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">212</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1051">
- <source xml:space="preserve">Prune mode is incompatible with -coinstatsindex.</source>
- <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">245</context></context-group>
</trans-unit>
- <trans-unit id="_msg1052">
+ <trans-unit id="_msg1076">
<source xml:space="preserve">Prune mode is incompatible with -txindex.</source>
- <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
</trans-unit>
- <trans-unit id="_msg1053">
+ <trans-unit id="_msg1077">
<source xml:space="preserve">Pruning blockstore…</source>
- <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
</trans-unit>
- <trans-unit id="_msg1054">
+ <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">216</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
</trans-unit>
- <trans-unit id="_msg1055">
+ <trans-unit id="_msg1079">
<source xml:space="preserve">Replaying blocks…</source>
- <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">249</context></context-group>
</trans-unit>
- <trans-unit id="_msg1056">
+ <trans-unit id="_msg1080">
<source xml:space="preserve">Rescanning…</source>
- <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg1057">
+ <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">219</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
</trans-unit>
- <trans-unit id="_msg1058">
+ <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">220</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">252</context></context-group>
</trans-unit>
- <trans-unit id="_msg1059">
+ <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">221</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
</trans-unit>
- <trans-unit id="_msg1060">
+ <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">222</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
</trans-unit>
- <trans-unit id="_msg1061">
+ <trans-unit id="_msg1085">
<source xml:space="preserve">Section [%s] is not recognized.</source>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">255</context></context-group>
</trans-unit>
- <trans-unit id="_msg1062">
+ <trans-unit id="_msg1086">
<source xml:space="preserve">Signing transaction failed</source>
- <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">256</context></context-group>
</trans-unit>
- <trans-unit id="_msg1063">
+ <trans-unit id="_msg1087">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; does not exist</source>
- <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
</trans-unit>
- <trans-unit id="_msg1064">
+ <trans-unit id="_msg1088">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; is a relative path</source>
- <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
</trans-unit>
- <trans-unit id="_msg1065">
+ <trans-unit id="_msg1089">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; is not a directory</source>
- <context-group purpose="location"><context context-type="linenumber">227</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">259</context></context-group>
</trans-unit>
- <trans-unit id="_msg1066">
+ <trans-unit id="_msg1090">
<source xml:space="preserve">Specified blocks directory &quot;%s&quot; does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">228</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg1067">
+ <trans-unit id="_msg1091">
<source xml:space="preserve">Starting network threads…</source>
- <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg1068">
+ <trans-unit id="_msg1092">
<source xml:space="preserve">The source code is available from %s.</source>
- <context-group purpose="location"><context context-type="linenumber">230</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">262</context></context-group>
</trans-unit>
- <trans-unit id="_msg1069">
+ <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">231</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
- <trans-unit id="_msg1070">
+ <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">232</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
</trans-unit>
- <trans-unit id="_msg1071">
+ <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">233</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
</trans-unit>
- <trans-unit id="_msg1072">
+ <trans-unit id="_msg1096">
<source xml:space="preserve">This is experimental software.</source>
- <context-group purpose="location"><context context-type="linenumber">234</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">266</context></context-group>
</trans-unit>
- <trans-unit id="_msg1073">
+ <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">235</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
- <trans-unit id="_msg1074">
+ <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">236</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
- <trans-unit id="_msg1075">
+ <trans-unit id="_msg1099">
<source xml:space="preserve">Transaction amount too small</source>
- <context-group purpose="location"><context context-type="linenumber">237</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg1076">
+ <trans-unit id="_msg1100">
<source xml:space="preserve">Transaction amounts must not be negative</source>
- <context-group purpose="location"><context context-type="linenumber">238</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">270</context></context-group>
</trans-unit>
- <trans-unit id="_msg1077">
+ <trans-unit id="_msg1101">
<source xml:space="preserve">Transaction change output index out of range</source>
- <context-group purpose="location"><context context-type="linenumber">239</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
</trans-unit>
- <trans-unit id="_msg1078">
+ <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">240</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">272</context></context-group>
</trans-unit>
- <trans-unit id="_msg1079">
+ <trans-unit id="_msg1103">
<source xml:space="preserve">Transaction must have at least one recipient</source>
- <context-group purpose="location"><context context-type="linenumber">241</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg1080">
+ <trans-unit id="_msg1104">
<source xml:space="preserve">Transaction needs a change address, but we can&apos;t generate it.</source>
- <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
- <trans-unit id="_msg1081">
+ <trans-unit id="_msg1105">
<source xml:space="preserve">Transaction too large</source>
- <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
- <trans-unit id="_msg1082">
+ <trans-unit id="_msg1106">
+ <source xml:space="preserve">Unable to allocate memory for -maxsigcachesize: &apos;%s&apos; MiB</source>
+ <context-group purpose="location"><context context-type="linenumber">276</context></context-group>
+ </trans-unit>
+ <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">244</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">277</context></context-group>
</trans-unit>
- <trans-unit id="_msg1083">
+ <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">245</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">278</context></context-group>
</trans-unit>
- <trans-unit id="_msg1084">
+ <trans-unit id="_msg1109">
<source xml:space="preserve">Unable to create the PID file &apos;%s&apos;: %s</source>
- <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg1085">
+ <trans-unit id="_msg1110">
<source xml:space="preserve">Unable to generate initial keys</source>
- <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
- <trans-unit id="_msg1086">
+ <trans-unit id="_msg1111">
<source xml:space="preserve">Unable to generate keys</source>
- <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
</trans-unit>
- <trans-unit id="_msg1087">
+ <trans-unit id="_msg1112">
<source xml:space="preserve">Unable to open %s for writing</source>
- <context-group purpose="location"><context context-type="linenumber">249</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
</trans-unit>
- <trans-unit id="_msg1088">
+ <trans-unit id="_msg1113">
<source xml:space="preserve">Unable to parse -maxuploadtarget: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
</trans-unit>
- <trans-unit id="_msg1089">
+ <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">251</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg1090">
+ <trans-unit id="_msg1115">
<source xml:space="preserve">Unknown -blockfilterindex value %s.</source>
- <context-group purpose="location"><context context-type="linenumber">252</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">285</context></context-group>
</trans-unit>
- <trans-unit id="_msg1091">
+ <trans-unit id="_msg1116">
<source xml:space="preserve">Unknown address type &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
</trans-unit>
- <trans-unit id="_msg1092">
+ <trans-unit id="_msg1117">
<source xml:space="preserve">Unknown change type &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">287</context></context-group>
</trans-unit>
- <trans-unit id="_msg1093">
+ <trans-unit id="_msg1118">
<source xml:space="preserve">Unknown network specified in -onlynet: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">255</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
</trans-unit>
- <trans-unit id="_msg1094">
+ <trans-unit id="_msg1119">
<source xml:space="preserve">Unknown new rules activated (versionbit %i)</source>
- <context-group purpose="location"><context context-type="linenumber">256</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
</trans-unit>
- <trans-unit id="_msg1095">
+ <trans-unit id="_msg1120">
<source xml:space="preserve">Unsupported logging category %s=%s.</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1096">
- <source xml:space="preserve">Upgrading UTXO database</source>
- <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
</trans-unit>
- <trans-unit id="_msg1097">
+ <trans-unit id="_msg1121">
<source xml:space="preserve">User Agent comment (%s) contains unsafe characters.</source>
- <context-group purpose="location"><context context-type="linenumber">259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
</trans-unit>
- <trans-unit id="_msg1098">
+ <trans-unit id="_msg1122">
<source xml:space="preserve">Verifying blocks…</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
</trans-unit>
- <trans-unit id="_msg1099">
+ <trans-unit id="_msg1123">
<source xml:space="preserve">Verifying wallet(s)…</source>
- <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">293</context></context-group>
</trans-unit>
- <trans-unit id="_msg1100">
+ <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">262</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
</group>
</body></file>
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..7e39829038 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
@@ -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/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index 01d84624e8..8762ba9ab3 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -262,9 +262,13 @@ void CreateWalletActivity::createWallet()
}
QTimer::singleShot(500ms, worker(), [this, name, flags] {
- std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().createWallet(name, m_passphrase, flags, m_error_message, m_warning_message);
+ auto wallet{node().walletLoader().createWallet(name, m_passphrase, flags, m_warning_message)};
- if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
+ if (wallet) {
+ m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(*wallet));
+ } else {
+ m_error_message = util::ErrorString(wallet);
+ }
QTimer::singleShot(500ms, this, &CreateWalletActivity::finish);
});
@@ -293,6 +297,10 @@ void CreateWalletActivity::create()
} catch (const std::runtime_error& e) {
QMessageBox::critical(nullptr, tr("Can't list signers"), e.what());
}
+ if (signers.size() > 1) {
+ QMessageBox::critical(nullptr, tr("Too many external signers found"), QString::fromStdString("More than one external signer found. Please connect only one at a time."));
+ signers.clear();
+ }
m_create_wallet_dialog->setSigners(signers);
m_create_wallet_dialog->setWindowModality(Qt::ApplicationModal);
@@ -343,9 +351,13 @@ void OpenWalletActivity::open(const std::string& path)
tr("Opening Wallet <b>%1</b>…").arg(name.toHtmlEscaped()));
QTimer::singleShot(0, worker(), [this, path] {
- std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().loadWallet(path, m_error_message, m_warning_message);
+ auto wallet{node().walletLoader().loadWallet(path, m_warning_message)};
- if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
+ if (wallet) {
+ m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(*wallet));
+ } else {
+ m_error_message = util::ErrorString(wallet);
+ }
QTimer::singleShot(0, this, &OpenWalletActivity::finish);
});
@@ -393,8 +405,11 @@ void RestoreWalletActivity::restore(const fs::path& backup_file, const std::stri
QTimer::singleShot(0, worker(), [this, backup_file, wallet_name] {
auto wallet{node().walletLoader().restoreWallet(backup_file, wallet_name, m_warning_message)};
- m_error_message = wallet ? bilingual_str{} : wallet.GetError();
- if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(wallet.ReleaseObj());
+ if (wallet) {
+ m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(*wallet));
+ } else {
+ m_error_message = util::ErrorString(wallet);
+ }
QTimer::singleShot(0, this, &RestoreWalletActivity::finish);
});
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index fde136b727..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)
{
@@ -207,7 +218,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
auto& newTx = transaction.getWtx();
const auto& res = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired);
- newTx = res ? res.GetObj() : nullptr;
+ newTx = res ? *res : nullptr;
transaction.setTransactionFee(nFeeRequired);
if (fSubtractFeeFromAmount && newTx)
transaction.reassignAmounts(nChangePosRet);
@@ -218,7 +229,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
- Q_EMIT message(tr("Send Coins"), QString::fromStdString(res.GetError().translated),
+ Q_EMIT message(tr("Send Coins"), QString::fromStdString(util::ErrorString(res).translated),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
@@ -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 43c248b03b..85815a9c8b 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -590,45 +590,31 @@ static bool rest_chaininfo(const std::any& context, HTTPRequest* req, const std:
}
}
-static bool rest_mempool_info(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
{
if (!CheckWarmup(req))
return false;
- const CTxMemPool* mempool = GetMemPool(context, req);
- if (!mempool) return false;
- std::string param;
- const RESTResponseFormat rf = ParseDataFormat(param, strURIPart);
-
- switch (rf) {
- case RESTResponseFormat::JSON: {
- UniValue mempoolInfoObject = MempoolInfoToJSON(*mempool);
- std::string strJSON = mempoolInfoObject.write() + "\n";
- req->WriteHeader("Content-Type", "application/json");
- req->WriteReply(HTTP_OK, strJSON);
- return true;
- }
- default: {
- return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
- }
+ std::string param;
+ const RESTResponseFormat rf = ParseDataFormat(param, str_uri_part);
+ if (param != "contents" && param != "info") {
+ return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/mempool/<info|contents>.json");
}
-}
-static bool rest_mempool_contents(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
-{
- if (!CheckWarmup(req)) return false;
const CTxMemPool* mempool = GetMemPool(context, req);
if (!mempool) return false;
- std::string param;
- const RESTResponseFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
case RESTResponseFormat::JSON: {
- UniValue mempoolObject = MempoolToJSON(*mempool, true);
+ std::string str_json;
+ if (param == "contents") {
+ str_json = MempoolToJSON(*mempool, true).write() + "\n";
+ } else {
+ str_json = MempoolInfoToJSON(*mempool).write() + "\n";
+ }
- std::string strJSON = mempoolObject.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
- req->WriteReply(HTTP_OK, strJSON);
+ req->WriteReply(HTTP_OK, str_json);
return true;
}
default: {
@@ -946,8 +932,7 @@ static const struct {
{"/rest/blockfilter/", rest_block_filter},
{"/rest/blockfilterheaders/", rest_filter_header},
{"/rest/chaininfo", rest_chaininfo},
- {"/rest/mempool/info", rest_mempool_info},
- {"/rest/mempool/contents", rest_mempool_contents},
+ {"/rest/mempool/", rest_mempool},
{"/rest/headers/", rest_headers},
{"/rest/getutxos", rest_getutxos},
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 9be3ab7df0..ee287656b6 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -147,6 +147,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendall", 1, "conf_target" },
{ "sendall", 3, "fee_rate"},
{ "sendall", 4, "options" },
+ { "simulaterawtransaction", 0, "rawtxs" },
+ { "simulaterawtransaction", 1, "options" },
{ "importprivkey", 2, "rescan" },
{ "importaddress", 2, "rescan" },
{ "importaddress", 3, "p2sh" },
diff --git a/src/rpc/fees.cpp b/src/rpc/fees.cpp
index 41f386d443..aa047bdea8 100644
--- a/src/rpc/fees.cpp
+++ b/src/rpc/fees.cpp
@@ -6,7 +6,6 @@
#include <core_io.h>
#include <policy/feerate.h>
#include <policy/fees.h>
-#include <policy/settings.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <rpc/server.h>
@@ -88,7 +87,7 @@ static RPCHelpMan estimatesmartfee()
CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
if (feeRate != CFeeRate(0)) {
CFeeRate min_mempool_feerate{mempool.GetMinFee()};
- CFeeRate min_relay_feerate{::minRelayTxFee};
+ CFeeRate min_relay_feerate{mempool.m_min_relay_feerate};
feeRate = std::max({feeRate, min_mempool_feerate, min_relay_feerate});
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
} else {
diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
index 0ae10b6c39..02b51ce0a0 100644
--- a/src/rpc/mempool.cpp
+++ b/src/rpc/mempool.cpp
@@ -666,9 +666,9 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool)
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
ret.pushKV("maxmempool", pool.m_max_size_bytes);
- ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), ::minRelayTxFee).GetFeePerK()));
- ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
- ret.pushKV("incrementalrelayfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
+ ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_min_relay_feerate).GetFeePerK()));
+ ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_min_relay_feerate.GetFeePerK()));
+ ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_incremental_relay_feerate.GetFeePerK()));
ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
ret.pushKV("fullrbf", pool.m_full_rbf);
return ret;
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 76cf8d8ea9..3b234bc317 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -23,6 +23,7 @@
#include <timedata.h>
#include <util/strencodings.h>
#include <util/string.h>
+#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <version.h>
@@ -645,8 +646,11 @@ static RPCHelpMan getnetworkinfo()
obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
}
obj.pushKV("networks", GetNetworksInfo());
- obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
- obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
+ if (node.mempool) {
+ // Those fields can be deprecated, to be replaced by the getmempoolinfo fields
+ obj.pushKV("relayfee", ValueFromAmount(node.mempool->m_min_relay_feerate.GetFeePerK()));
+ obj.pushKV("incrementalfee", ValueFromAmount(node.mempool->m_incremental_relay_feerate.GetFeePerK()));
+ }
UniValue localAddresses(UniValue::VARR);
{
LOCK(g_maplocalhost_mutex);
@@ -894,7 +898,7 @@ static RPCHelpMan getnodeaddresses()
for (const CAddress& addr : vAddr) {
UniValue obj(UniValue::VOBJ);
- obj.pushKV("time", (int)addr.nTime);
+ obj.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(addr.nTime)});
obj.pushKV("services", (uint64_t)addr.nServices);
obj.pushKV("address", addr.ToStringIP());
obj.pushKV("port", addr.GetPort());
@@ -942,7 +946,7 @@ static RPCHelpMan addpeeraddress()
if (LookupHost(addr_string, net_addr, false)) {
CAddress address{{net_addr, port}, ServiceFlags{NODE_NETWORK | NODE_WITNESS}};
- address.nTime = GetAdjustedTime();
+ address.nTime = Now<NodeSeconds>();
// The source address is set equal to the address. This is equivalent to the peer
// announcing itself.
if (node.addrman->Add({address}, address)) {
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 9ec506b0fb..7ffb499330 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -157,7 +157,7 @@ static std::vector<RPCArg> CreateTxDoc()
},
},
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
- {"replaceable", RPCArg::Type::BOOL, RPCArg::Default{false}, "Marks this transaction as BIP125-replaceable.\n"
+ {"replaceable", RPCArg::Type::BOOL, RPCArg::Default{true}, "Marks this transaction as BIP125-replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
};
}
@@ -302,7 +302,7 @@ static RPCHelpMan createrawtransaction()
}, true
);
- bool rbf = false;
+ std::optional<bool> rbf;
if (!request.params[3].isNull()) {
rbf = request.params[3].isTrue();
}
@@ -1451,7 +1451,7 @@ static RPCHelpMan createpsbt()
}, true
);
- bool rbf = false;
+ std::optional<bool> rbf;
if (!request.params[3].isNull()) {
rbf = request.params[3].isTrue();
}
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 86b5b7e960..b06e9f6e4b 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -21,7 +21,7 @@
#include <util/strencodings.h>
#include <util/translation.h>
-CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf)
+CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, std::optional<bool> rbf)
{
if (outputs_in.isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output argument must be non-null");
@@ -60,7 +60,8 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
uint32_t nSequence;
- if (rbf) {
+
+ if (rbf.value_or(true)) {
nSequence = MAX_BIP125_RBF_SEQUENCE; /* CTxIn::SEQUENCE_FINAL - 2 */
} else if (rawTx.nLockTime) {
nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; /* CTxIn::SEQUENCE_FINAL - 1 */
@@ -132,7 +133,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
}
}
- if (rbf && rawTx.vin.size() > 0 && !SignalsOptInRBF(CTransaction(rawTx))) {
+ if (rbf.has_value() && rbf.value() && rawTx.vin.size() > 0 && !SignalsOptInRBF(CTransaction(rawTx))) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option");
}
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index c3eb1417f8..9b5c9f08d4 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -7,6 +7,7 @@
#include <map>
#include <string>
+#include <optional>
struct bilingual_str;
class FillableSigningProvider;
@@ -38,6 +39,6 @@ void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins);
/** Create a transaction from univalue parameters */
-CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf);
+CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, std::optional<bool> rbf);
#endif // BITCOIN_RPC_RAWTRANSACTION_UTIL_H
diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp
index 304c265b31..8595fa78bb 100644
--- a/src/rpc/request.cpp
+++ b/src/rpc/request.cpp
@@ -66,16 +66,16 @@ UniValue JSONRPCError(int code, const std::string& message)
*/
static const std::string COOKIEAUTH_USER = "__cookie__";
/** Default name for auth cookie file */
-static const std::string COOKIEAUTH_FILE = ".cookie";
+static const char* const COOKIEAUTH_FILE = ".cookie";
/** Get name of RPC authentication cookie file */
static fs::path GetAuthCookieFile(bool temp=false)
{
- std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE);
+ fs::path arg = gArgs.GetPathArg("-rpccookiefile", COOKIEAUTH_FILE);
if (temp) {
arg += ".tmp";
}
- return AbsPathForConfigVal(fs::PathFromString(arg));
+ return AbsPathForConfigVal(arg);
}
bool GenerateAuthCookie(std::string *cookie_out)
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 34a4da74f8..9bcbe1ceef 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -328,7 +328,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
{
if (!GetExtKey(arg, xprv)) return false;
for (auto entry : m_path) {
- xprv.Derive(xprv, entry);
+ if (!xprv.Derive(xprv, entry)) return false;
if (entry >> 31) {
last_hardened = xprv;
}
@@ -388,14 +388,13 @@ public:
}
} else {
for (auto entry : m_path) {
- der = parent_extkey.Derive(parent_extkey, entry);
- assert(der);
+ if (!parent_extkey.Derive(parent_extkey, entry)) return false;
}
final_extkey = parent_extkey;
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
assert(m_derive != DeriveType::HARDENED);
}
- assert(der);
+ if (!der) return false;
final_info_out = final_info_out_tmp;
key_out = final_extkey.pubkey;
@@ -498,8 +497,8 @@ public:
CExtKey extkey;
CExtKey dummy;
if (!GetDerivedExtKey(arg, extkey, dummy)) return false;
- if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
- if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
+ if (m_derive == DeriveType::UNHARDENED && !extkey.Derive(extkey, pos)) return false;
+ if (m_derive == DeriveType::HARDENED && !extkey.Derive(extkey, pos | 0x80000000UL)) return false;
key = extkey.key;
return true;
}
@@ -1015,6 +1014,24 @@ public:
bool IsSingleType() const final { return true; }
};
+/** A parsed rawtr(...) descriptor. */
+class RawTRDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts, FlatSigningProvider& out) const override
+ {
+ assert(keys.size() == 1);
+ XOnlyPubKey xpk(keys[0]);
+ if (!xpk.IsFullyValid()) return {};
+ WitnessV1Taproot output{xpk};
+ return Vector(GetScriptForDestination(output));
+ }
+public:
+ RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(Vector(std::move(output_key)), "rawtr") {}
+ std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; }
+ bool IsSingleType() const final { return true; }
+};
+
////////////////////////////////////////////////////////////////////////////
// Parser //
////////////////////////////////////////////////////////////////////////////
@@ -1453,6 +1470,16 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
error = "Can only have tr at top level";
return nullptr;
}
+ if (ctx == ParseScriptContext::TOP && Func("rawtr", expr)) {
+ auto arg = Expr(expr);
+ auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, error);
+ if (!output_key) return nullptr;
+ ++key_exp_index;
+ return std::make_unique<RawTRDescriptor>(std::move(output_key));
+ } else if (Func("rawtr", expr)) {
+ error = "Can only have rawtr at top level";
+ return nullptr;
+ }
if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
std::string str(expr.begin(), expr.end());
if (!IsHex(str)) {
@@ -1626,6 +1653,13 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
}
}
}
+ // If the above doesn't work, construct a rawtr() descriptor with just the encoded x-only pubkey.
+ if (pubkey.IsFullyValid()) {
+ auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
+ if (key) {
+ return std::make_unique<RawTRDescriptor>(std::move(key));
+ }
+ }
}
if (ctx == ParseScriptContext::P2WSH) {
diff --git a/src/script/script.h b/src/script/script.h
index 3b799ad637..1e5f694d52 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -588,7 +588,6 @@ CScript BuildScript(Ts&&... inputs)
int cnt{0};
([&ret, &cnt] (Ts&& input) {
- cnt++;
if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<Ts>>, CScript>) {
// If it is a CScript, extend ret with it. Move or copy the first element instead.
if (cnt == 0) {
@@ -600,6 +599,7 @@ CScript BuildScript(Ts&&... inputs)
// Otherwise invoke CScript::operator<<.
ret << input;
}
+ cnt++;
} (std::forward<Ts>(inputs)), ...);
return ret;
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 4e2acc463a..e507ec7528 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -14,6 +14,7 @@
#include <algorithm>
#include <mutex>
+#include <optional>
#include <shared_mutex>
#include <vector>
@@ -75,7 +76,7 @@ public:
std::unique_lock<std::shared_mutex> lock(cs_sigcache);
setValid.insert(entry);
}
- uint32_t setup_bytes(size_t n)
+ std::optional<std::pair<uint32_t, size_t>> setup_bytes(size_t n)
{
return setValid.setup_bytes(n);
}
@@ -92,14 +93,15 @@ static CSignatureCache signatureCache;
// To be called once in AppInitMain/BasicTestingSetup to initialize the
// signatureCache.
-void InitSignatureCache()
+bool InitSignatureCache(size_t max_size_bytes)
{
- // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
- // setup_bytes creates the minimum possible cache (2 elements).
- size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) / 2), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
- size_t nElems = signatureCache.setup_bytes(nMaxCacheSize);
- LogPrintf("Using %zu MiB out of %zu/2 requested for signature cache, able to store %zu elements\n",
- (nElems*sizeof(uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
+ auto setup_results = signatureCache.setup_bytes(max_size_bytes);
+ if (!setup_results) return false;
+
+ const auto [num_elems, approx_size_bytes] = *setup_results;
+ LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n",
+ approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
+ return true;
}
bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 1e21d6f340..290955090d 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -10,14 +10,13 @@
#include <span.h>
#include <util/hasher.h>
+#include <optional>
#include <vector>
-// DoS prevention: limit cache size to 32MB (over 1000000 entries on 64-bit
+// DoS prevention: limit cache size to 32MiB (over 1000000 entries on 64-bit
// systems). Due to how we count cache size, actual memory usage is slightly
-// more (~32.25 MB)
-static const unsigned int DEFAULT_MAX_SIG_CACHE_SIZE = 32;
-// Maximum sig cache size allowed
-static const int64_t MAX_MAX_SIG_CACHE_SIZE = 16384;
+// more (~32.25 MiB)
+static constexpr size_t DEFAULT_MAX_SIG_CACHE_BYTES{32 << 20};
class CPubKey;
@@ -33,6 +32,6 @@ public:
bool VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const override;
};
-void InitSignatureCache();
+[[nodiscard]] bool InitSignatureCache(size_t max_size_bytes);
#endif // BITCOIN_SCRIPT_SIGCACHE_H
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 3b8071d9d1..4014ebadbc 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -243,6 +243,11 @@ static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCrea
sigdata.taproot_key_path_sig = sig;
}
}
+ if (sigdata.taproot_key_path_sig.size() == 0) {
+ if (creator.CreateSchnorrSig(provider, sig, output, nullptr, nullptr, SigVersion::TAPROOT)) {
+ sigdata.taproot_key_path_sig = sig;
+ }
+ }
if (sigdata.taproot_key_path_sig.size()) {
result = Vector(sigdata.taproot_key_path_sig);
return true;
@@ -627,25 +632,6 @@ public:
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
-bool IsSolvable(const SigningProvider& provider, const CScript& script)
-{
- // This check is to make sure that the script we created can actually be solved for and signed by us
- // if we were to have the private keys. This is just to make sure that the script is valid and that,
- // if found in a transaction, we would still accept and relay that transaction. In particular,
- // it will reject witness outputs that require signing with an uncompressed public key.
- SignatureData sigs;
- // Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most
- // important property this function is designed to test for.
- static_assert(STANDARD_SCRIPT_VERIFY_FLAGS & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, "IsSolvable requires standard script flags to include WITNESS_PUBKEYTYPE");
- if (ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, script, sigs)) {
- // VerifyScript check is just defensive, and should never fail.
- bool verified = VerifyScript(sigs.scriptSig, script, &sigs.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, DUMMY_CHECKER);
- assert(verified);
- return true;
- }
- return false;
-}
-
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
{
int version;
diff --git a/src/script/sign.h b/src/script/sign.h
index 5e58272154..958d673b9f 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -97,12 +97,6 @@ bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom,
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);
void UpdateInput(CTxIn& input, const SignatureData& data);
-/* Check whether we know how to sign for an output like this, assuming we
- * have all private keys. While this function does not need private keys, the passed
- * provider is used to look up public keys and redeemscripts by hash.
- * Solvability is unrelated to whether we consider this output to be ours. */
-bool IsSolvable(const SigningProvider& provider, const CScript& script);
-
/** Check whether a scriptPubKey is known to be segwit. */
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index b3f6a1b669..6101738061 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -16,9 +16,6 @@
typedef std::vector<unsigned char> valtype;
-bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
-unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
-
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
diff --git a/src/script/standard.h b/src/script/standard.h
index 448fdff010..1e6769782a 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -33,21 +33,12 @@ public:
};
/**
- * Default setting for nMaxDatacarrierBytes. 80 bytes of data, +1 for OP_RETURN,
+ * Default setting for -datacarriersize. 80 bytes of data, +1 for OP_RETURN,
* +2 for the pushdata opcodes.
*/
static const unsigned int MAX_OP_RETURN_RELAY = 83;
/**
- * A data carrying output is an unspendable output containing data. The script
- * type is designated as TxoutType::NULL_DATA.
- */
-extern bool fAcceptDatacarrier;
-
-/** Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. */
-extern unsigned nMaxDatacarrierBytes;
-
-/**
* Mandatory script verification flags that all new blocks must comply with for
* them to be valid. (but old blocks may not comply with) Currently just P2SH,
* but in the future other flags may be added.
diff --git a/src/serialize.h b/src/serialize.h
index a1cce78451..89a9f32240 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -520,6 +520,29 @@ struct CompactSizeFormatter
}
};
+template <typename U, bool LOSSY = false>
+struct ChronoFormatter {
+ template <typename Stream, typename Tp>
+ void Unser(Stream& s, Tp& tp)
+ {
+ U u;
+ s >> u;
+ // Lossy deserialization does not make sense, so force Wnarrowing
+ tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
+ }
+ template <typename Stream, typename Tp>
+ void Ser(Stream& s, Tp tp)
+ {
+ if constexpr (LOSSY) {
+ s << U(tp.time_since_epoch().count());
+ } else {
+ s << U{tp.time_since_epoch().count()};
+ }
+ }
+};
+template <typename U>
+using LossyChronoFormatter = ChronoFormatter<U, true>;
+
class CompactSizeWriter
{
protected:
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 12cf1176a6..b10d32ccec 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
CAddress addr{CAddress(ResolveService("253.3.3.3", 8333), NODE_NONE)};
- int64_t start_time{GetAdjustedTime()};
+ const auto start_time{Now<NodeSeconds>()};
addr.nTime = start_time;
// test that multiplicity stays at 1 if nTime doesn't increase
@@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
for (unsigned int i = 1; i < 400; ++i) {
std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
CNetAddr source{ResolveIP(addr_ip)};
- addr.nTime = start_time + i;
+ addr.nTime = start_time + std::chrono::seconds{i};
addrman->Add({addr}, source);
}
AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
@@ -295,15 +295,15 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
- addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
+ addr1.nTime = Now<NodeSeconds>(); // Set time so isTerrible = false
CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
- addr2.nTime = GetAdjustedTime();
+ addr2.nTime = Now<NodeSeconds>();
CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
- addr3.nTime = GetAdjustedTime();
+ addr3.nTime = Now<NodeSeconds>();
CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
- addr4.nTime = GetAdjustedTime();
+ addr4.nTime = Now<NodeSeconds>();
CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
- addr5.nTime = GetAdjustedTime();
+ addr5.nTime = Now<NodeSeconds>();
CNetAddr source1 = ResolveIP("250.1.2.1");
CNetAddr source2 = ResolveIP("250.2.3.3");
@@ -329,7 +329,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
// Ensure that for all addrs in addrman, isTerrible == false.
- addr.nTime = GetAdjustedTime();
+ addr.nTime = Now<NodeSeconds>();
addrman->Add({addr}, ResolveIP(strAddr));
if (i % 8 == 0)
addrman->Good(addr);
@@ -821,8 +821,8 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// Ensure test of address fails, so that it is evicted.
// Update entry in tried by setting last good connection in the deep past.
- BOOST_CHECK(!addrman->Good(info, /*nTime=*/1));
- addrman->Attempt(info, /*fCountFailure=*/false, /*nTime=*/GetAdjustedTime() - 61);
+ BOOST_CHECK(!addrman->Good(info, NodeSeconds{1s}));
+ addrman->Attempt(info, /*fCountFailure=*/false, Now<NodeSeconds>() - 61s);
// Should swap 36 for 19.
addrman->ResolveCollisions();
@@ -966,7 +966,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
CNetAddr source{ResolveIP("252.2.2.2")};
CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};
- int64_t start_time{GetAdjustedTime() - 10000};
+ const auto start_time{Now<NodeSeconds>() - 10000s};
addr.nTime = start_time;
BOOST_CHECK(addrman->Add({addr}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
@@ -978,7 +978,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
addrman->SetServices(addr_diff_port, NODE_NETWORK_LIMITED);
std::vector<CAddress> vAddr1{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
BOOST_CHECK_EQUAL(vAddr1.size(), 1U);
- BOOST_CHECK_EQUAL(vAddr1.at(0).nTime, start_time);
+ BOOST_CHECK(vAddr1.at(0).nTime == start_time);
BOOST_CHECK_EQUAL(vAddr1.at(0).nServices, NODE_NONE);
// Updating an addrman entry with the correct port is successful
@@ -986,7 +986,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
addrman->SetServices(addr, NODE_NETWORK_LIMITED);
std::vector<CAddress> vAddr2 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
BOOST_CHECK_EQUAL(vAddr2.size(), 1U);
- BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000);
+ BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000s);
BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
}
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 64cc924239..75b29ae0aa 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -184,4 +184,22 @@ BOOST_AUTO_TEST_CASE(bip32_test5) {
}
}
+BOOST_AUTO_TEST_CASE(bip32_max_depth) {
+ CExtKey key_parent{DecodeExtKey(test1.vDerive[0].prv)}, key_child;
+ CExtPubKey pubkey_parent{DecodeExtPubKey(test1.vDerive[0].pub)}, pubkey_child;
+
+ // We can derive up to the 255th depth..
+ for (auto i = 0; i++ < 255;) {
+ BOOST_CHECK(key_parent.Derive(key_child, 0));
+ std::swap(key_parent, key_child);
+ BOOST_CHECK(pubkey_parent.Derive(pubkey_child, 0));
+ std::swap(pubkey_parent, pubkey_child);
+ }
+
+ // But trying to derive a non-existent 256th depth will fail!
+ BOOST_CHECK(key_parent.nDepth == 255 && pubkey_parent.nDepth == 255);
+ BOOST_CHECK(!key_parent.Derive(key_child, 0));
+ BOOST_CHECK(!pubkey_parent.Derive(pubkey_child, 0));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index a8c666079d..1eb4b373b4 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -233,7 +233,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
for (const auto& xpub_pair : parent_xpub_cache) {
const CExtPubKey& xpub = xpub_pair.second;
CExtPubKey der;
- xpub.Derive(der, i);
+ BOOST_CHECK(xpub.Derive(der, i));
pubkeys.insert(der.pubkey);
}
int count_pks = 0;
@@ -265,7 +265,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
const CExtPubKey& xpub = xpub_pair.second;
pubkeys.insert(xpub.pubkey);
CExtPubKey der;
- xpub.Derive(der, i);
+ BOOST_CHECK(xpub.Derive(der, i));
pubkeys.insert(der.pubkey);
}
int count_pks = 0;
@@ -302,7 +302,6 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
// For each of the produced scripts, verify solvability, and when possible, try to sign a transaction spending it.
for (size_t n = 0; n < spks.size(); ++n) {
BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n]));
- BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0);
if (flags & SIGNABLE) {
CMutableTransaction spend;
@@ -324,7 +323,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
BOOST_CHECK(inferred->Expand(0, provider_inferred, spks_inferred, provider_inferred));
BOOST_CHECK_EQUAL(spks_inferred.size(), 1U);
BOOST_CHECK(spks_inferred[0] == spks[n]);
- BOOST_CHECK_EQUAL(IsSolvable(provider_inferred, spks_inferred[0]), !(flags & UNSOLVABLE));
+ BOOST_CHECK_EQUAL(InferDescriptor(spks_inferred[0], provider_inferred)->IsSolvable(), !(flags & UNSOLVABLE));
BOOST_CHECK(GetKeyOriginData(provider_inferred, flags) == GetKeyOriginData(script_provider, flags));
}
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index af7a282781..7668940cbc 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -113,11 +113,11 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
for (size_t j = 0; j < num_addresses; ++j) {
const auto addr = CAddress{CService{RandAddr(fuzzed_data_provider, fast_random_context), 8333}, NODE_NETWORK};
- const auto time_penalty = fast_random_context.randrange(100000001);
+ const std::chrono::seconds time_penalty{fast_random_context.randrange(100000001)};
addrman.Add({addr}, source, time_penalty);
if (n > 0 && addrman.size() % n == 0) {
- addrman.Good(addr, GetTime());
+ addrman.Good(addr, Now<NodeSeconds>());
}
// Add 10% of the addresses from more than one source.
@@ -161,7 +161,7 @@ public:
CSipHasher hasher(0, 0);
auto addr_key = a.GetKey();
auto source_key = a.source.GetAddrBytes();
- hasher.Write(a.nLastSuccess);
+ hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
hasher.Write(a.nAttempts);
hasher.Write(a.nRefCount);
hasher.Write(a.fInTried);
@@ -175,8 +175,8 @@ public:
};
auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
- return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.nLastSuccess, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
- std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.nLastSuccess, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
+ return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
+ std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
};
using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
@@ -269,25 +269,25 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
}
const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider);
if (opt_net_addr) {
- addr_man.Add(addresses, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000));
+ addr_man.Add(addresses, *opt_net_addr, std::chrono::seconds{ConsumeTime(fuzzed_data_provider, 0, 100000000)});
}
},
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.Good(*opt_service, ConsumeTime(fuzzed_data_provider));
+ addr_man.Good(*opt_service, NodeSeconds{std::chrono::seconds{ConsumeTime(fuzzed_data_provider)}});
}
},
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider));
+ addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), NodeSeconds{std::chrono::seconds{ConsumeTime(fuzzed_data_provider)}});
}
},
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.Connected(*opt_service, ConsumeTime(fuzzed_data_provider));
+ addr_man.Connected(*opt_service, NodeSeconds{std::chrono::seconds{ConsumeTime(fuzzed_data_provider)}});
}
},
[&] {
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
index 72574612a2..c52fca5fe8 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -87,9 +87,6 @@ FUZZ_TARGET_INIT(integer, initialize_integer)
}
(void)GetSizeOfCompactSize(u64);
(void)GetSpecialScriptSize(u32);
- if (!MultiplicationOverflow(i64, static_cast<int64_t>(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast<int64_t>(4))) {
- (void)GetVirtualTransactionSize(i64, i64);
- }
if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) {
(void)GetVirtualTransactionSize(i64, i64, u32);
}
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index bfea9778f4..a76901e473 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -138,8 +138,6 @@ FUZZ_TARGET_INIT(key, initialize_key)
assert(tx_multisig_script.size() == 37);
FillableSigningProvider fillable_signing_provider;
- assert(IsSolvable(fillable_signing_provider, tx_pubkey_script));
- assert(IsSolvable(fillable_signing_provider, tx_multisig_script));
assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
assert(fillable_signing_provider.GetKeys().size() == 0);
@@ -157,12 +155,12 @@ FUZZ_TARGET_INIT(key, initialize_key)
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
TxoutType which_type_tx_pubkey;
- const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
+ const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, std::nullopt, which_type_tx_pubkey);
assert(is_standard_tx_pubkey);
assert(which_type_tx_pubkey == TxoutType::PUBKEY);
TxoutType which_type_tx_multisig;
- const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
+ const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, std::nullopt, which_type_tx_multisig);
assert(is_standard_tx_multisig);
assert(which_type_tx_multisig == TxoutType::MULTISIG);
diff --git a/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp
index bfa977520b..f4b7dc08fd 100644
--- a/src/test/fuzz/load_external_block_file.cpp
+++ b/src/test/fuzz/load_external_block_file.cpp
@@ -31,6 +31,13 @@ FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
if (fuzzed_block_file == nullptr) {
return;
}
- FlatFilePos flat_file_pos;
- g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file, fuzzed_data_provider.ConsumeBool() ? &flat_file_pos : nullptr);
+ if (fuzzed_data_provider.ConsumeBool()) {
+ // Corresponds to the -reindex case (track orphan blocks across files).
+ FlatFilePos flat_file_pos;
+ std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
+ g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file, &flat_file_pos, &blocks_with_unknown_parent);
+ } else {
+ // Corresponds to the -loadblock= case (orphan blocks aren't tracked across files).
+ g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file);
+ }
}
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
index 4801635791..1a06ae886e 100644
--- a/src/test/fuzz/rbf.cpp
+++ b/src/test/fuzz/rbf.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <mempool_args.h>
+#include <node/mempool_args.h>
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <sync.h>
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index fdcd0da37d..00d7b7e29a 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -55,7 +55,7 @@ FUZZ_TARGET_INIT(script, initialize_script)
}
TxoutType which_type;
- bool is_standard_ret = IsStandard(script, which_type);
+ bool is_standard_ret = IsStandard(script, std::nullopt, which_type);
if (!is_standard_ret) {
assert(which_type == TxoutType::NONSTANDARD ||
which_type == TxoutType::NULL_DATA ||
@@ -89,7 +89,6 @@ FUZZ_TARGET_INIT(script, initialize_script)
const FlatSigningProvider signing_provider;
(void)InferDescriptor(script, signing_provider);
(void)IsSegWitOutput(signing_provider, script);
- (void)IsSolvable(signing_provider, script);
(void)RecursiveDynamicUsage(script);
diff --git a/src/test/fuzz/script_sigcache.cpp b/src/test/fuzz/script_sigcache.cpp
index f7e45d6889..f6af7947df 100644
--- a/src/test/fuzz/script_sigcache.cpp
+++ b/src/test/fuzz/script_sigcache.cpp
@@ -10,18 +10,21 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
+namespace {
+const BasicTestingSetup* g_setup;
+} // namespace
+
void initialize_script_sigcache()
{
- static const ECCVerifyHandle ecc_verify_handle;
- ECC_Start();
- SelectParams(CBaseChainParams::REGTEST);
- InitSignatureCache();
+ static const auto testing_setup = MakeNoLogFileContext<>();
+ g_setup = testing_setup.get();
}
FUZZ_TARGET_INIT(script_sigcache, initialize_script_sigcache)
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 273aa0dc5c..7fa4523800 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -69,8 +69,8 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
std::string reason;
- const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
- const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
+ const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
+ const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
if (is_standard_without_permit_bare_multisig) {
assert(is_standard_with_permit_bare_multisig);
}
@@ -92,7 +92,6 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
(void)GetTransactionWeight(tx);
(void)GetVirtualTransactionSize(tx);
(void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
- (void)IsStandardTx(tx, reason);
(void)RecursiveDynamicUsage(tx);
(void)SignalsOptInRBF(tx);
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
index cfb112879a..3191367870 100644
--- a/src/test/fuzz/tx_pool.cpp
+++ b/src/test/fuzz/tx_pool.cpp
@@ -3,8 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/validation.h>
-#include <mempool_args.h>
#include <node/context.h>
+#include <node/mempool_args.h>
#include <node/miner.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -116,7 +116,7 @@ void MockTime(FuzzedDataProvider& fuzzed_data_provider, const CChainState& chain
SetMockTime(time);
}
-CTxMemPool MakeMempool(const NodeContext& node)
+CTxMemPool MakeMempool(FuzzedDataProvider& fuzzed_data_provider, const NodeContext& node)
{
// Take the default options for tests...
CTxMemPool::Options mempool_opts{MemPoolOptionsForTest(node)};
@@ -124,6 +124,7 @@ CTxMemPool MakeMempool(const NodeContext& node)
// ...override specific options for this specific fuzz suite
mempool_opts.estimator = nullptr;
mempool_opts.check_ratio = 1;
+ mempool_opts.require_standard = fuzzed_data_provider.ConsumeBool();
// ...and construct a CTxMemPool from it
return CTxMemPool{mempool_opts};
@@ -150,7 +151,7 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN};
SetMempoolConstraints(*node.args, fuzzed_data_provider);
- CTxMemPool tx_pool_{MakeMempool(node)};
+ CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
chainstate.SetMempool(&tx_pool);
@@ -237,7 +238,6 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
auto txr = std::make_shared<TransactionsDelta>(removed, added);
RegisterSharedValidationInterface(txr);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
- ::fRequireStandard = fuzzed_data_provider.ConsumeBool();
// Make sure ProcessNewPackage on one transaction works.
// The result is not guaranteed to be the same as what is returned by ATMP.
@@ -325,7 +325,7 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
}
SetMempoolConstraints(*node.args, fuzzed_data_provider);
- CTxMemPool tx_pool_{MakeMempool(node)};
+ CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
@@ -348,7 +348,6 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
const auto tx = MakeTransactionRef(mut_tx);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
- ::fRequireStandard = fuzzed_data_provider.ConsumeBool();
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
if (accepted) {
diff --git a/src/test/fuzz/txorphan.cpp b/src/test/fuzz/txorphan.cpp
index 3fc6cde84e..7580651371 100644
--- a/src/test/fuzz/txorphan.cpp
+++ b/src/test/fuzz/txorphan.cpp
@@ -138,10 +138,8 @@ FUZZ_TARGET_INIT(txorphan, initialize_orphanage)
[&] {
// test mocktime and expiry
SetMockTime(ConsumeTime(fuzzed_data_provider));
- auto size_before = orphanage.Size();
auto limit = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
- auto n_evicted = WITH_LOCK(g_cs_orphans, return orphanage.LimitOrphans(limit));
- Assert(size_before - n_evicted <= limit);
+ WITH_LOCK(g_cs_orphans, orphanage.LimitOrphans(limit));
Assert(orphanage.Size() <= limit);
});
}
diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp
index fabcea22c3..ba1a634e41 100644
--- a/src/test/fuzz/util.cpp
+++ b/src/test/fuzz/util.cpp
@@ -527,6 +527,11 @@ CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
return net_addr;
}
+CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ return {ConsumeService(fuzzed_data_provider), ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS), NodeSeconds{std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}}};
+}
+
FILE* FuzzedFileProvider::open()
{
SetFuzzedErrNo(m_fuzzed_data_provider);
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index 60e2875953..33d9ab3cc3 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -287,10 +287,7 @@ inline CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcep
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
}
-inline CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
-{
- return {ConsumeService(fuzzed_data_provider), ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS), fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
-}
+CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept;
template <bool ReturnUniquePtr = false>
auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<NodeId>& node_id_in = std::nullopt) noexcept
diff --git a/src/test/fuzz/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp
index 90c1a71d9f..8241dff189 100644
--- a/src/test/fuzz/validation_load_mempool.cpp
+++ b/src/test/fuzz/validation_load_mempool.cpp
@@ -5,7 +5,7 @@
#include <kernel/mempool_persist.h>
#include <chainparamsbase.h>
-#include <mempool_args.h>
+#include <node/mempool_args.h>
#include <node/mempool_persist_args.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 20d670c1e1..d88aed7d4a 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -325,7 +325,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
next->BuildSkip();
- m_node.chainman->ActiveChain().SetTip(next);
+ m_node.chainman->ActiveChain().SetTip(*next);
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
// Extend to a 210000-long block chain.
@@ -337,7 +337,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
next->BuildSkip();
- m_node.chainman->ActiveChain().SetTip(next);
+ m_node.chainman->ActiveChain().SetTip(*next);
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
@@ -362,7 +362,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
// Delete the dummy blocks again.
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
CBlockIndex* del = m_node.chainman->ActiveChain().Tip();
- m_node.chainman->ActiveChain().SetTip(del->pprev);
+ m_node.chainman->ActiveChain().SetTip(*Assert(del->pprev));
m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
delete del->phashBlock;
delete del;
@@ -389,7 +389,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
tx.nLockTime = 0;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
- BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
{
@@ -403,7 +403,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
prevheights[0] = baseheight + 2;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
const int SEQUENCE_LOCK_TIME = 512; // Sequence locks pass 512 seconds later
@@ -426,7 +426,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
@@ -437,7 +437,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
prevheights[0] = baseheight + 4;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
@@ -446,7 +446,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
tx.nLockTime = 0;
tx.vin[0].nSequence = 0;
- BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
tx.vin[0].nSequence = 1;
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index dccc7ce795..ce23d6013d 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -141,23 +141,30 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
for (int i = 0; i < 4; i++)
key[i].MakeNewKey(true);
- TxoutType whichType;
+ const auto is_standard{[](const CScript& spk) {
+ TxoutType type;
+ bool res{::IsStandard(spk, std::nullopt, type)};
+ if (res) {
+ BOOST_CHECK_EQUAL(type, TxoutType::MULTISIG);
+ }
+ return res;
+ }};
CScript a_and_b;
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(::IsStandard(a_and_b, whichType));
+ BOOST_CHECK(is_standard(a_and_b));
CScript a_or_b;
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(::IsStandard(a_or_b, whichType));
+ BOOST_CHECK(is_standard(a_or_b));
CScript escrow;
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
- BOOST_CHECK(::IsStandard(escrow, whichType));
+ BOOST_CHECK(is_standard(escrow));
CScript one_of_four;
one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
- BOOST_CHECK(!::IsStandard(one_of_four, whichType));
+ BOOST_CHECK(!is_standard(one_of_four));
CScript malformed[6];
malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
@@ -167,8 +174,9 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
- for (int i = 0; i < 6; i++)
- BOOST_CHECK(!::IsStandard(malformed[i], whichType));
+ for (int i = 0; i < 6; i++) {
+ BOOST_CHECK(!is_standard(malformed[i]));
+ }
}
BOOST_AUTO_TEST_CASE(multisig_Sign)
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 224dc88d0f..c2d2fa37b4 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -480,21 +480,21 @@ BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
// try a few edge cases for port, service flags and time.
static const std::vector<CAddress> fixture_addresses({
- CAddress(
+ CAddress{
CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0 /* port */),
NODE_NONE,
- 0x4966bc61U /* Fri Jan 9 02:54:25 UTC 2009 */
- ),
- CAddress(
+ NodeSeconds{0x4966bc61s}, /* Fri Jan 9 02:54:25 UTC 2009 */
+ },
+ CAddress{
CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0x00f1 /* port */),
NODE_NETWORK,
- 0x83766279U /* Tue Nov 22 11:22:33 UTC 2039 */
- ),
- CAddress(
+ NodeSeconds{0x83766279s}, /* Tue Nov 22 11:22:33 UTC 2039 */
+ },
+ CAddress{
CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0xf1f2 /* port */),
static_cast<ServiceFlags>(NODE_WITNESS | NODE_COMPACT_FILTERS | NODE_NETWORK_LIMITED),
- 0xffffffffU /* Sun Feb 7 06:28:15 UTC 2106 */
- )
+ NodeSeconds{0xffffffffs}, /* Sun Feb 7 06:28:15 UTC 2106 */
+ },
});
// fixture_addresses should equal to this when serialized in V1 format.
diff --git a/src/test/rbf_tests.cpp b/src/test/rbf_tests.cpp
new file mode 100644
index 0000000000..c88cd36688
--- /dev/null
+++ b/src/test/rbf_tests.cpp
@@ -0,0 +1,230 @@
+// Copyright (c) 2021 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <policy/rbf.h>
+#include <random.h>
+#include <txmempool.h>
+#include <util/system.h>
+#include <util/time.h>
+
+#include <test/util/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+#include <optional>
+#include <vector>
+
+BOOST_FIXTURE_TEST_SUITE(rbf_tests, TestingSetup)
+
+static inline CTransactionRef make_tx(const std::vector<CTransactionRef>& inputs,
+ const std::vector<CAmount>& output_values)
+{
+ CMutableTransaction tx = CMutableTransaction();
+ tx.vin.resize(inputs.size());
+ tx.vout.resize(output_values.size());
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ tx.vin[i].prevout.hash = inputs[i]->GetHash();
+ tx.vin[i].prevout.n = 0;
+ // Add a witness so wtxid != txid
+ CScriptWitness witness;
+ witness.stack.push_back(std::vector<unsigned char>(i + 10));
+ tx.vin[i].scriptWitness = witness;
+ }
+ for (size_t i = 0; i < output_values.size(); ++i) {
+ tx.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx.vout[i].nValue = output_values[i];
+ }
+ return MakeTransactionRef(tx);
+}
+
+static void add_descendants(const CTransactionRef& tx, int32_t num_descendants, CTxMemPool& pool)
+ EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
+{
+ AssertLockHeld(::cs_main);
+ AssertLockHeld(pool.cs);
+ TestMemPoolEntryHelper entry;
+ // Assumes this isn't already spent in mempool
+ auto tx_to_spend = tx;
+ for (int32_t i{0}; i < num_descendants; ++i) {
+ auto next_tx = make_tx(/*inputs=*/{tx_to_spend}, /*output_values=*/{(50 - i) * CENT});
+ pool.addUnchecked(entry.FromTx(next_tx));
+ tx_to_spend = next_tx;
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(rbf_helper_functions, TestChain100Setup)
+{
+ CTxMemPool& pool = *Assert(m_node.mempool);
+ LOCK2(::cs_main, pool.cs);
+ TestMemPoolEntryHelper entry;
+
+ const CAmount low_fee{CENT/100};
+ const CAmount normal_fee{CENT/10};
+ const CAmount high_fee{CENT};
+
+ // Create a parent tx1 and child tx2 with normal fees:
+ const auto tx1 = make_tx(/*inputs=*/ {m_coinbase_txns[0]}, /*output_values=*/ {10 * COIN});
+ pool.addUnchecked(entry.Fee(normal_fee).FromTx(tx1));
+ const auto tx2 = make_tx(/*inputs=*/ {tx1}, /*output_values=*/ {995 * CENT});
+ pool.addUnchecked(entry.Fee(normal_fee).FromTx(tx2));
+
+ // Create a low-feerate parent tx3 and high-feerate child tx4 (cpfp)
+ const auto tx3 = make_tx(/*inputs=*/ {m_coinbase_txns[1]}, /*output_values=*/ {1099 * CENT});
+ pool.addUnchecked(entry.Fee(low_fee).FromTx(tx3));
+ const auto tx4 = make_tx(/*inputs=*/ {tx3}, /*output_values=*/ {999 * CENT});
+ pool.addUnchecked(entry.Fee(high_fee).FromTx(tx4));
+
+ // Create a parent tx5 and child tx6 where both have very low fees
+ const auto tx5 = make_tx(/*inputs=*/ {m_coinbase_txns[2]}, /*output_values=*/ {1099 * CENT});
+ pool.addUnchecked(entry.Fee(low_fee).FromTx(tx5));
+ const auto tx6 = make_tx(/*inputs=*/ {tx5}, /*output_values=*/ {1098 * CENT});
+ pool.addUnchecked(entry.Fee(low_fee).FromTx(tx6));
+ // Make tx6's modified fee much higher than its base fee. This should cause it to pass
+ // the fee-related checks despite being low-feerate.
+ pool.PrioritiseTransaction(tx6->GetHash(), 1 * COIN);
+
+ // Two independent high-feerate transactions, tx7 and tx8
+ const auto tx7 = make_tx(/*inputs=*/ {m_coinbase_txns[3]}, /*output_values=*/ {999 * CENT});
+ pool.addUnchecked(entry.Fee(high_fee).FromTx(tx7));
+ const auto tx8 = make_tx(/*inputs=*/ {m_coinbase_txns[4]}, /*output_values=*/ {999 * CENT});
+ pool.addUnchecked(entry.Fee(high_fee).FromTx(tx8));
+
+ const auto entry1 = pool.GetIter(tx1->GetHash()).value();
+ const auto entry2 = pool.GetIter(tx2->GetHash()).value();
+ const auto entry3 = pool.GetIter(tx3->GetHash()).value();
+ const auto entry4 = pool.GetIter(tx4->GetHash()).value();
+ const auto entry5 = pool.GetIter(tx5->GetHash()).value();
+ const auto entry6 = pool.GetIter(tx6->GetHash()).value();
+ const auto entry7 = pool.GetIter(tx7->GetHash()).value();
+ const auto entry8 = pool.GetIter(tx8->GetHash()).value();
+
+ BOOST_CHECK_EQUAL(entry1->GetFee(), normal_fee);
+ BOOST_CHECK_EQUAL(entry2->GetFee(), normal_fee);
+ BOOST_CHECK_EQUAL(entry3->GetFee(), low_fee);
+ BOOST_CHECK_EQUAL(entry4->GetFee(), high_fee);
+ BOOST_CHECK_EQUAL(entry5->GetFee(), low_fee);
+ BOOST_CHECK_EQUAL(entry6->GetFee(), low_fee);
+ BOOST_CHECK_EQUAL(entry7->GetFee(), high_fee);
+ BOOST_CHECK_EQUAL(entry8->GetFee(), high_fee);
+
+ CTxMemPool::setEntries set_12_normal{entry1, entry2};
+ CTxMemPool::setEntries set_34_cpfp{entry3, entry4};
+ CTxMemPool::setEntries set_56_low{entry5, entry6};
+ CTxMemPool::setEntries all_entries{entry1, entry2, entry3, entry4, entry5, entry6, entry7, entry8};
+ CTxMemPool::setEntries empty_set;
+
+ const auto unused_txid{GetRandHash()};
+
+ // Tests for PaysMoreThanConflicts
+ // These tests use feerate, not absolute fee.
+ BOOST_CHECK(PaysMoreThanConflicts(/*iters_conflicting=*/set_12_normal,
+ /*replacement_feerate=*/CFeeRate(entry1->GetModifiedFee() + 1, entry1->GetTxSize() + 2),
+ /*txid=*/unused_txid).has_value());
+ // Replacement must be strictly greater than the originals.
+ BOOST_CHECK(PaysMoreThanConflicts(set_12_normal, CFeeRate(entry1->GetModifiedFee(), entry1->GetTxSize()), unused_txid).has_value());
+ BOOST_CHECK(PaysMoreThanConflicts(set_12_normal, CFeeRate(entry1->GetModifiedFee() + 1, entry1->GetTxSize()), unused_txid) == std::nullopt);
+ // These tests use modified fees (including prioritisation), not base fees.
+ BOOST_CHECK(PaysMoreThanConflicts({entry5}, CFeeRate(entry5->GetModifiedFee() + 1, entry5->GetTxSize()), unused_txid) == std::nullopt);
+ BOOST_CHECK(PaysMoreThanConflicts({entry6}, CFeeRate(entry6->GetFee() + 1, entry6->GetTxSize()), unused_txid).has_value());
+ BOOST_CHECK(PaysMoreThanConflicts({entry6}, CFeeRate(entry6->GetModifiedFee() + 1, entry6->GetTxSize()), unused_txid) == std::nullopt);
+ // PaysMoreThanConflicts checks individual feerate, not ancestor feerate. This test compares
+ // replacement_feerate and entry4's feerate, which are the same. The replacement_feerate is
+ // considered too low even though entry4 has a low ancestor feerate.
+ BOOST_CHECK(PaysMoreThanConflicts(set_34_cpfp, CFeeRate(entry4->GetModifiedFee(), entry4->GetTxSize()), unused_txid).has_value());
+
+ // Tests for EntriesAndTxidsDisjoint
+ BOOST_CHECK(EntriesAndTxidsDisjoint(empty_set, {tx1->GetHash()}, unused_txid) == std::nullopt);
+ BOOST_CHECK(EntriesAndTxidsDisjoint(set_12_normal, {tx3->GetHash()}, unused_txid) == std::nullopt);
+ // EntriesAndTxidsDisjoint uses txids, not wtxids.
+ BOOST_CHECK(EntriesAndTxidsDisjoint({entry2}, {tx2->GetWitnessHash()}, unused_txid) == std::nullopt);
+ BOOST_CHECK(EntriesAndTxidsDisjoint({entry2}, {tx2->GetHash()}, unused_txid).has_value());
+ BOOST_CHECK(EntriesAndTxidsDisjoint(set_12_normal, {tx1->GetHash()}, unused_txid).has_value());
+ BOOST_CHECK(EntriesAndTxidsDisjoint(set_12_normal, {tx2->GetHash()}, unused_txid).has_value());
+ // EntriesAndTxidsDisjoint does not calculate descendants of iters_conflicting; it uses whatever
+ // the caller passed in. As such, no error is returned even though entry2 is a descendant of tx1.
+ BOOST_CHECK(EntriesAndTxidsDisjoint({entry2}, {tx1->GetHash()}, unused_txid) == std::nullopt);
+
+ // Tests for PaysForRBF
+ const CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ const CFeeRate higher_relay_feerate{2 * DEFAULT_INCREMENTAL_RELAY_FEE};
+ // Must pay at least as much as the original.
+ BOOST_CHECK(PaysForRBF(/*original_fees=*/high_fee,
+ /*replacement_fees=*/high_fee,
+ /*replacement_vsize=*/1,
+ /*relay_fee=*/CFeeRate(0),
+ /*txid=*/unused_txid)
+ == std::nullopt);
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee - 1, 1, CFeeRate(0), unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(high_fee + 1, high_fee, 1, CFeeRate(0), unused_txid).has_value());
+ // Additional fees must cover the replacement's vsize at incremental relay fee
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 1, 2, incremental_relay_feerate, unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 2, incremental_relay_feerate, unused_txid) == std::nullopt);
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 2, higher_relay_feerate, unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 4, 2, higher_relay_feerate, unused_txid) == std::nullopt);
+ BOOST_CHECK(PaysForRBF(low_fee, high_fee, 99999999, incremental_relay_feerate, unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(low_fee, high_fee + 99999999, 99999999, incremental_relay_feerate, unused_txid) == std::nullopt);
+
+ // Tests for GetEntriesForConflicts
+ CTxMemPool::setEntries all_parents{entry1, entry3, entry5, entry7, entry8};
+ CTxMemPool::setEntries all_children{entry2, entry4, entry6};
+ const std::vector<CTransactionRef> parent_inputs({m_coinbase_txns[0], m_coinbase_txns[1], m_coinbase_txns[2],
+ m_coinbase_txns[3], m_coinbase_txns[4]});
+ const auto conflicts_with_parents = make_tx(parent_inputs, {50 * CENT});
+ CTxMemPool::setEntries all_conflicts;
+ BOOST_CHECK(GetEntriesForConflicts(/*tx=*/ *conflicts_with_parents.get(),
+ /*pool=*/ pool,
+ /*iters_conflicting=*/ all_parents,
+ /*all_conflicts=*/ all_conflicts) == std::nullopt);
+ BOOST_CHECK(all_conflicts == all_entries);
+ auto conflicts_size = all_conflicts.size();
+ all_conflicts.clear();
+
+ add_descendants(tx2, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ all_conflicts.clear();
+
+ add_descendants(tx4, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ all_conflicts.clear();
+
+ add_descendants(tx6, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ all_conflicts.clear();
+
+ add_descendants(tx7, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ BOOST_CHECK_EQUAL(all_conflicts.size(), 100);
+ all_conflicts.clear();
+
+ // Exceeds maximum number of conflicts.
+ add_descendants(tx8, 1, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts).has_value());
+
+ // Tests for HasNoNewUnconfirmed
+ const auto spends_unconfirmed = make_tx({tx1}, {36 * CENT});
+ for (const auto& input : spends_unconfirmed->vin) {
+ // Spends unconfirmed inputs.
+ BOOST_CHECK(pool.exists(GenTxid::Txid(input.prevout.hash)));
+ }
+ BOOST_CHECK(HasNoNewUnconfirmed(/*tx=*/ *spends_unconfirmed.get(),
+ /*pool=*/ pool,
+ /*iters_conflicting=*/ all_entries) == std::nullopt);
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_unconfirmed.get(), pool, {entry2}) == std::nullopt);
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_unconfirmed.get(), pool, empty_set).has_value());
+
+ const auto spends_new_unconfirmed = make_tx({tx1, tx8}, {36 * CENT});
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_new_unconfirmed.get(), pool, {entry2}).has_value());
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_new_unconfirmed.get(), pool, all_entries).has_value());
+
+ const auto spends_conflicting_confirmed = make_tx({m_coinbase_txns[0], m_coinbase_txns[1]}, {45 * CENT});
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_conflicting_confirmed.get(), pool, {entry1, entry3}) == std::nullopt);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/result_tests.cpp b/src/test/result_tests.cpp
new file mode 100644
index 0000000000..6a23a7b895
--- /dev/null
+++ b/src/test/result_tests.cpp
@@ -0,0 +1,96 @@
+// 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.
+
+#include <util/result.h>
+
+#include <boost/test/unit_test.hpp>
+
+inline bool operator==(const bilingual_str& a, const bilingual_str& b)
+{
+ return a.original == b.original && a.translated == b.translated;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const bilingual_str& s)
+{
+ return os << "bilingual_str('" << s.original << "' , '" << s.translated << "')";
+}
+
+BOOST_AUTO_TEST_SUITE(result_tests)
+
+struct NoCopy {
+ NoCopy(int n) : m_n{std::make_unique<int>(n)} {}
+ std::unique_ptr<int> m_n;
+};
+
+bool operator==(const NoCopy& a, const NoCopy& b)
+{
+ return *a.m_n == *b.m_n;
+}
+
+std::ostream& operator<<(std::ostream& os, const NoCopy& o)
+{
+ return os << "NoCopy(" << *o.m_n << ")";
+}
+
+util::Result<int> IntFn(int i, bool success)
+{
+ if (success) return i;
+ return util::Error{Untranslated(strprintf("int %i error.", i))};
+}
+
+util::Result<bilingual_str> StrFn(bilingual_str s, bool success)
+{
+ if (success) return s;
+ return util::Error{strprintf(Untranslated("str %s error."), s.original)};
+}
+
+util::Result<NoCopy> NoCopyFn(int i, bool success)
+{
+ if (success) return {i};
+ return util::Error{Untranslated(strprintf("nocopy %i error.", i))};
+}
+
+template <typename T>
+void ExpectResult(const util::Result<T>& result, bool success, const bilingual_str& str)
+{
+ BOOST_CHECK_EQUAL(bool(result), success);
+ BOOST_CHECK_EQUAL(util::ErrorString(result), str);
+}
+
+template <typename T, typename... Args>
+void ExpectSuccess(const util::Result<T>& result, const bilingual_str& str, Args&&... args)
+{
+ ExpectResult(result, true, str);
+ BOOST_CHECK_EQUAL(result.has_value(), true);
+ BOOST_CHECK_EQUAL(result.value(), T{std::forward<Args>(args)...});
+ BOOST_CHECK_EQUAL(&result.value(), &*result);
+}
+
+template <typename T, typename... Args>
+void ExpectFail(const util::Result<T>& result, const bilingual_str& str)
+{
+ ExpectResult(result, false, str);
+}
+
+BOOST_AUTO_TEST_CASE(check_returned)
+{
+ ExpectSuccess(IntFn(5, true), {}, 5);
+ ExpectFail(IntFn(5, false), Untranslated("int 5 error."));
+ ExpectSuccess(NoCopyFn(5, true), {}, 5);
+ ExpectFail(NoCopyFn(5, false), Untranslated("nocopy 5 error."));
+ ExpectSuccess(StrFn(Untranslated("S"), true), {}, Untranslated("S"));
+ ExpectFail(StrFn(Untranslated("S"), false), Untranslated("str S error."));
+}
+
+BOOST_AUTO_TEST_CASE(check_value_or)
+{
+ BOOST_CHECK_EQUAL(IntFn(10, true).value_or(20), 10);
+ BOOST_CHECK_EQUAL(IntFn(10, false).value_or(20), 20);
+ BOOST_CHECK_EQUAL(NoCopyFn(10, true).value_or(20), 10);
+ BOOST_CHECK_EQUAL(NoCopyFn(10, false).value_or(20), 20);
+ BOOST_CHECK_EQUAL(StrFn(Untranslated("A"), true).value_or(Untranslated("B")), Untranslated("A"));
+ BOOST_CHECK_EQUAL(StrFn(Untranslated("A"), false).value_or(Untranslated("B")), Untranslated("B"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 3e9e04da25..a52530e179 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -181,10 +181,10 @@ BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min()).write(), "-92233720368.54775808");
}
-static UniValue ValueFromString(const std::string &str)
+static UniValue ValueFromString(const std::string& str) noexcept
{
UniValue value;
- BOOST_CHECK(value.setNumStr(str));
+ value.setNumStr(str);
return value;
}
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index a221e02d2f..a02d51eecc 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -18,15 +18,18 @@
#include <boost/test/unit_test.hpp>
// Helpers:
-static std::vector<unsigned char>
-Serialize(const CScript& s)
+static bool IsStandardTx(const CTransaction& tx, std::string& reason)
+{
+ return IsStandardTx(tx, std::nullopt, DEFAULT_PERMIT_BAREMULTISIG, CFeeRate{DUST_RELAY_TX_FEE}, reason);
+}
+
+static std::vector<unsigned char> Serialize(const CScript& s)
{
std::vector<unsigned char> sSerialized(s.begin(), s.end());
return sSerialized;
}
-static bool
-Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
+static bool Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
{
// Create dummy to/from transactions:
CMutableTransaction txFrom;
@@ -49,7 +52,6 @@ BOOST_FIXTURE_TEST_SUITE(script_p2sh_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sign)
{
- LOCK(cs_main);
// Pay-to-script-hash looks like this:
// scriptSig: <sig> <sig...> <serialized_script>
// scriptPubKey: HASH160 <hash> EQUAL
@@ -149,7 +151,6 @@ BOOST_AUTO_TEST_CASE(norecurse)
BOOST_AUTO_TEST_CASE(set)
{
- LOCK(cs_main);
// Test the CScript::Set* methods
FillableSigningProvider keystore;
CKey key[4];
@@ -263,7 +264,6 @@ BOOST_AUTO_TEST_CASE(switchover)
BOOST_AUTO_TEST_CASE(AreInputsStandard)
{
- LOCK(cs_main);
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
FillableSigningProvider keystore;
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 6dadf09176..3d3fd5d93d 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
// Build a CChain for the main branch.
CChain chain;
- chain.SetTip(&vBlocksMain.back());
+ chain.SetTip(vBlocksMain.back());
// Test 100 random starting points for locators.
for (int n=0; n<100; n++) {
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
// Build a CChain for the main branch.
CChain chain;
- chain.SetTip(&vBlocksMain.back());
+ chain.SetTip(vBlocksMain.back());
// Verify that FindEarliestAtLeast is correct.
for (unsigned int i=0; i<10000; ++i) {
@@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
}
CChain chain;
- chain.SetTip(&blocks.back());
+ chain.SetTip(blocks.back());
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50, 0)->nHeight, 0);
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100, 0)->nHeight, 0);
diff --git a/src/test/system_tests.cpp b/src/test/system_tests.cpp
index 3f5353b5a2..f160bb08a5 100644
--- a/src/test/system_tests.cpp
+++ b/src/test/system_tests.cpp
@@ -7,11 +7,6 @@
#include <univalue.h>
#ifdef ENABLE_EXTERNAL_SIGNER
-#if defined(WIN32) && !defined(__kernel_entry)
-// A workaround for boost 1.71 incompatibility with mingw-w64 compiler.
-// For details see https://github.com/bitcoin/bitcoin/pull/22348.
-#define __kernel_entry
-#endif
#if defined(__GNUC__)
// Boost 1.78 requires the following workaround.
// See: https://github.com/boostorg/process/issues/235
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 4e6c223ccc..cd6bf11327 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -40,6 +40,9 @@ typedef std::vector<unsigned char> valtype;
// In script_tests.cpp
UniValue read_json(const std::string& jsondata);
+static CFeeRate g_dust{DUST_RELAY_TX_FEE};
+static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
+
static std::map<std::string, unsigned int> mapFlagNames = {
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
{std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
@@ -745,7 +748,6 @@ BOOST_AUTO_TEST_CASE(test_witness)
BOOST_AUTO_TEST_CASE(test_IsStandard)
{
- LOCK(cs_main);
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
@@ -765,19 +767,19 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
constexpr auto CheckIsStandard = [](const auto& t) {
std::string reason;
- BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK(IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
BOOST_CHECK(reason.empty());
};
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
std::string reason;
- BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
BOOST_CHECK_EQUAL(reason_in, reason);
};
CheckIsStandard(t);
// Check dust with default relay fee:
- CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK() / 1000;
+ CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
BOOST_CHECK_EQUAL(nDustThreshold, 546);
// dust:
t.vout[0].nValue = nDustThreshold - 1;
@@ -805,14 +807,14 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
// Check dust with odd relay fee to verify rounding:
// nDustThreshold = 182 * 3702 / 1000
- dustRelayFee = CFeeRate(3702);
+ g_dust = CFeeRate(3702);
// dust:
t.vout[0].nValue = 674 - 1;
CheckIsNotStandard(t, "dust");
// not dust:
t.vout[0].nValue = 674;
CheckIsStandard(t);
- dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
+ g_dust = CFeeRate{DUST_RELAY_TX_FEE};
t.vout[0].scriptPubKey = CScript() << OP_1;
CheckIsNotStandard(t, "scriptpubkey");
@@ -924,16 +926,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
CheckIsNotStandard(t, "tx-size");
- // Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
- fIsBareMultisigStd = true;
+ // Check bare multisig (standard if policy flag g_bare_multi is set)
+ g_bare_multi = true;
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
t.vin.resize(1);
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
CheckIsStandard(t);
- fIsBareMultisigStd = false;
+ g_bare_multi = false;
CheckIsNotStandard(t, "bare-multisig");
- fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
+ g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
// Check P2WPKH outputs dust threshold
t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffff");
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index dd4bc5af75..633f75ff4f 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -161,11 +161,6 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, Dersig100Setup)
{
// Test that passing CheckInputScripts with one set of script flags doesn't imply
// that we would pass again with a different set of flags.
- {
- LOCK(cs_main);
- InitScriptExecutionCache();
- }
-
CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
CScript p2sh_scriptPubKey = GetScriptForDestination(ScriptHash(p2pk_scriptPubKey));
CScript p2pkh_scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 67984721a3..30d26ecf79 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -4,6 +4,8 @@
#include <test/util/setup_common.h>
+#include <kernel/validation_cache_sizes.h>
+
#include <addrman.h>
#include <banman.h>
#include <chainparams.h>
@@ -14,13 +16,14 @@
#include <init.h>
#include <init/common.h>
#include <interfaces/chain.h>
-#include <mempool_args.h>
#include <net.h>
#include <net_processing.h>
#include <node/blockstorage.h>
#include <node/chainstate.h>
#include <node/context.h>
+#include <node/mempool_args.h>
#include <node/miner.h>
+#include <node/validation_cache_args.h>
#include <noui.h>
#include <policy/fees.h>
#include <policy/fees_args.h>
@@ -52,6 +55,8 @@
#include <functional>
#include <stdexcept>
+using kernel::ValidationCacheSizes;
+using node::ApplyArgsManOptions;
using node::BlockAssembler;
using node::CalculateCacheSizes;
using node::LoadChainstate;
@@ -133,8 +138,12 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
m_node.kernel = std::make_unique<kernel::Context>();
SetupEnvironment();
SetupNetworking();
- InitSignatureCache();
- InitScriptExecutionCache();
+
+ ValidationCacheSizes validation_cache_sizes{};
+ ApplyArgsManOptions(*m_node.args, validation_cache_sizes);
+ Assert(InitSignatureCache(validation_cache_sizes.signature_cache_bytes));
+ Assert(InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes));
+
m_node.chain = interfaces::MakeChain(m_node);
fCheckBlockIndex = true;
static bool noui_connected = false;
@@ -160,7 +169,8 @@ CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node)
// chainparams.DefaultConsistencyChecks for tests
.check_ratio = 1,
};
- ApplyArgsManOptions(*node.args, mempool_opts);
+ const auto err{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)};
+ Assert(!err);
return mempool_opts;
}
diff --git a/src/test/util/wallet.cpp b/src/test/util/wallet.cpp
index 7a00ac9e1f..b54774cbb9 100644
--- a/src/test/util/wallet.cpp
+++ b/src/test/util/wallet.cpp
@@ -8,6 +8,7 @@
#include <outputtype.h>
#include <script/standard.h>
#ifdef ENABLE_WALLET
+#include <util/check.h>
#include <util/translation.h>
#include <wallet/wallet.h>
#endif
@@ -20,10 +21,7 @@ const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqq
std::string getnewaddress(CWallet& w)
{
constexpr auto output_type = OutputType::BECH32;
- auto op_dest = w.GetNewDestination(output_type, "");
- assert(op_dest.HasRes());
-
- return EncodeDestination(op_dest.GetObj());
+ return EncodeDestination(*Assert(w.GetNewDestination(output_type, "")));
}
#endif // ENABLE_WALLET
diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
index 78adb521ac..ee60f9aa4d 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -9,7 +9,6 @@
#include <sync.h>
#include <test/util/chainstate.h>
#include <test/util/setup_common.h>
-#include <timedata.h>
#include <uint256.h>
#include <validation.h>
@@ -17,19 +16,13 @@
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, ChainTestingSetup)
//! Test resizing coins-related CChainState caches during runtime.
//!
BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
{
- const ChainstateManager::Options chainman_opts{
- .chainparams = Params(),
- .adjusted_time_callback = GetAdjustedTime,
- };
- ChainstateManager manager{chainman_opts};
-
- WITH_LOCK(::cs_main, manager.m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(1 << 20, true));
+ ChainstateManager& manager = *Assert(m_node.chainman);
CTxMemPool& mempool = *Assert(m_node.mempool);
//! Create and add a Coin with DynamicMemoryUsage of 80 bytes to the given view.
diff --git a/src/test/validation_flush_tests.cpp b/src/test/validation_flush_tests.cpp
index 012169b17e..74b2af6858 100644
--- a/src/test/validation_flush_tests.cpp
+++ b/src/test/validation_flush_tests.cpp
@@ -4,14 +4,11 @@
//
#include <sync.h>
#include <test/util/setup_common.h>
-#include <txmempool.h>
#include <validation.h>
#include <boost/test/unit_test.hpp>
-using node::BlockManager;
-
-BOOST_FIXTURE_TEST_SUITE(validation_flush_tests, ChainTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_flush_tests, TestingSetup)
//! Test utilities for detecting when we need to flush the coins cache based
//! on estimated memory usage.
@@ -20,11 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(validation_flush_tests, ChainTestingSetup)
//!
BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
{
- CTxMemPool& mempool = *Assert(m_node.mempool);
- BlockManager blockman{};
- CChainState chainstate{&mempool, blockman, *Assert(m_node.chainman)};
- chainstate.InitCoinsDB(/*cache_size_bytes=*/1 << 10, /*in_memory=*/true, /*should_wipe=*/false);
- WITH_LOCK(::cs_main, chainstate.InitCoinsCache(1 << 10));
+ CChainState& chainstate{m_node.chainman->ActiveChainstate()};
constexpr bool is_64_bit = sizeof(void*) == 8;
diff --git a/src/timedata.h b/src/timedata.h
index 2f039d5465..cfe5111644 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -5,9 +5,12 @@
#ifndef BITCOIN_TIMEDATA_H
#define BITCOIN_TIMEDATA_H
+#include <util/time.h>
+
#include <algorithm>
-#include <assert.h>
-#include <stdint.h>
+#include <cassert>
+#include <chrono>
+#include <cstdint>
#include <vector>
static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 70 * 60;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 7eff6bdbe3..b151953d0d 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -106,7 +106,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
size_t CTxMemPoolEntry::GetTxSize() const
{
- return GetVirtualTransactionSize(nTxWeight, sigOpCost);
+ return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp);
}
void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
@@ -458,6 +458,12 @@ CTxMemPool::CTxMemPool(const Options& opts)
minerPolicyEstimator{opts.estimator},
m_max_size_bytes{opts.max_size_bytes},
m_expiry{opts.expiry},
+ m_incremental_relay_feerate{opts.incremental_relay_feerate},
+ m_min_relay_feerate{opts.min_relay_feerate},
+ m_dust_relay_feerate{opts.dust_relay_feerate},
+ m_permit_bare_multisig{opts.permit_bare_multisig},
+ m_max_datacarrier_bytes{opts.max_datacarrier_bytes},
+ m_require_standard{opts.require_standard},
m_full_rbf{opts.full_rbf},
m_limits{opts.limits}
{
@@ -1117,12 +1123,12 @@ CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
lastRollingFeeUpdate = time;
- if (rollingMinimumFeeRate < (double)incrementalRelayFee.GetFeePerK() / 2) {
+ if (rollingMinimumFeeRate < (double)m_incremental_relay_feerate.GetFeePerK() / 2) {
rollingMinimumFeeRate = 0;
return CFeeRate(0);
}
}
- return std::max(CFeeRate(llround(rollingMinimumFeeRate)), incrementalRelayFee);
+ return std::max(CFeeRate(llround(rollingMinimumFeeRate)), m_incremental_relay_feerate);
}
void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
@@ -1146,7 +1152,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
// equal to txn which were removed with no block in between.
CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
- removed += incrementalRelayFee;
+ removed += m_incremental_relay_feerate;
trackPackageRemoved(removed);
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
diff --git a/src/txmempool.h b/src/txmempool.h
index d7d308038c..73904cc370 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -568,6 +568,12 @@ public:
const int64_t m_max_size_bytes;
const std::chrono::seconds m_expiry;
+ const CFeeRate m_incremental_relay_feerate;
+ const CFeeRate m_min_relay_feerate;
+ const CFeeRate m_dust_relay_feerate;
+ const bool m_permit_bare_multisig;
+ const std::optional<unsigned> m_max_datacarrier_bytes;
+ const bool m_require_standard;
const bool m_full_rbf;
using Limits = kernel::MemPoolLimits;
@@ -702,11 +708,11 @@ public:
void CalculateDescendants(txiter it, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** The minimum fee to get into the mempool, which may itself not be enough
- * for larger-sized transactions.
- * The incrementalRelayFee policy variable is used to bound the time it
- * takes the fee rate to go back down all the way to 0. When the feerate
- * would otherwise be half of this, it is set to 0 instead.
- */
+ * for larger-sized transactions.
+ * The m_incremental_relay_feerate policy variable is used to bound the time it
+ * takes the fee rate to go back down all the way to 0. When the feerate
+ * would otherwise be half of this, it is set to 0 instead.
+ */
CFeeRate GetMinFee() const {
return GetMinFee(m_max_size_bytes);
}
diff --git a/src/txorphanage.cpp b/src/txorphanage.cpp
index ed4783f1a5..69ae8ea582 100644
--- a/src/txorphanage.cpp
+++ b/src/txorphanage.cpp
@@ -102,7 +102,7 @@ void TxOrphanage::EraseForPeer(NodeId peer)
if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx from peer=%d\n", nErased, peer);
}
-unsigned int TxOrphanage::LimitOrphans(unsigned int max_orphans)
+void TxOrphanage::LimitOrphans(unsigned int max_orphans)
{
AssertLockHeld(g_cs_orphans);
@@ -135,7 +135,7 @@ unsigned int TxOrphanage::LimitOrphans(unsigned int max_orphans)
EraseTx(m_orphan_list[randompos]->first);
++nEvicted;
}
- return nEvicted;
+ if (nEvicted > 0) LogPrint(BCLog::MEMPOOL, "orphanage overflow, removed %u tx\n", nEvicted);
}
void TxOrphanage::AddChildrenToWorkSet(const CTransaction& tx, std::set<uint256>& orphan_work_set) const
diff --git a/src/txorphanage.h b/src/txorphanage.h
index 24c8318f36..9363e6f733 100644
--- a/src/txorphanage.h
+++ b/src/txorphanage.h
@@ -41,7 +41,7 @@ public:
void EraseForBlock(const CBlock& block) LOCKS_EXCLUDED(::g_cs_orphans);
/** Limit the orphanage to the given maximum */
- unsigned int LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
+ void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
/** Add any orphans that list a particular tx as a parent into a peer's work set
* (ie orphans that may have found their final missing parent, and so should be reconsidered for the mempool) */
diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h
index 230a5fd096..8ba6fd5425 100644
--- a/src/univalue/include/univalue.h
+++ b/src/univalue/include/univalue.h
@@ -47,16 +47,16 @@ public:
void clear();
- bool setNull();
- bool setBool(bool val);
- bool setNumStr(const std::string& val);
- bool setInt(uint64_t val);
- bool setInt(int64_t val);
- bool setInt(int val_) { return setInt((int64_t)val_); }
- bool setFloat(double val);
- bool setStr(const std::string& val);
- bool setArray();
- bool setObject();
+ void setNull();
+ void setBool(bool val);
+ void setNumStr(const std::string& val);
+ void setInt(uint64_t val);
+ void setInt(int64_t val);
+ void setInt(int val_) { return setInt(int64_t{val_}); }
+ void setFloat(double val);
+ void setStr(const std::string& val);
+ void setArray();
+ void setObject();
enum VType getType() const { return typ; }
const std::string& getValStr() const { return val; }
diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp
index 051bc8eba6..55e777b8ae 100644
--- a/src/univalue/lib/univalue.cpp
+++ b/src/univalue/lib/univalue.cpp
@@ -23,19 +23,17 @@ void UniValue::clear()
values.clear();
}
-bool UniValue::setNull()
+void UniValue::setNull()
{
clear();
- return true;
}
-bool UniValue::setBool(bool val_)
+void UniValue::setBool(bool val_)
{
clear();
typ = VBOOL;
if (val_)
val = "1";
- return true;
}
static bool validNumStr(const std::string& s)
@@ -46,18 +44,18 @@ static bool validNumStr(const std::string& s)
return (tt == JTOK_NUMBER);
}
-bool UniValue::setNumStr(const std::string& val_)
+void UniValue::setNumStr(const std::string& val_)
{
- if (!validNumStr(val_))
- return false;
+ if (!validNumStr(val_)) {
+ throw std::runtime_error{"The string '" + val_ + "' is not a valid JSON number"};
+ }
clear();
typ = VNUM;
val = val_;
- return true;
}
-bool UniValue::setInt(uint64_t val_)
+void UniValue::setInt(uint64_t val_)
{
std::ostringstream oss;
@@ -66,7 +64,7 @@ bool UniValue::setInt(uint64_t val_)
return setNumStr(oss.str());
}
-bool UniValue::setInt(int64_t val_)
+void UniValue::setInt(int64_t val_)
{
std::ostringstream oss;
@@ -75,37 +73,32 @@ bool UniValue::setInt(int64_t val_)
return setNumStr(oss.str());
}
-bool UniValue::setFloat(double val_)
+void UniValue::setFloat(double val_)
{
std::ostringstream oss;
oss << std::setprecision(16) << val_;
- bool ret = setNumStr(oss.str());
- typ = VNUM;
- return ret;
+ return setNumStr(oss.str());
}
-bool UniValue::setStr(const std::string& val_)
+void UniValue::setStr(const std::string& val_)
{
clear();
typ = VSTR;
val = val_;
- return true;
}
-bool UniValue::setArray()
+void UniValue::setArray()
{
clear();
typ = VARR;
- return true;
}
-bool UniValue::setObject()
+void UniValue::setObject()
{
clear();
typ = VOBJ;
- return true;
}
void UniValue::push_back(const UniValue& val_)
diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp
index cf8c29ec67..94d7343ff3 100644
--- a/src/univalue/test/object.cpp
+++ b/src/univalue/test/object.cpp
@@ -45,7 +45,7 @@ void univalue_constructor()
BOOST_CHECK_EQUAL(v3.getValStr(), "foo");
UniValue numTest;
- BOOST_CHECK(numTest.setNumStr("82"));
+ numTest.setNumStr("82");
BOOST_CHECK(numTest.isNum());
BOOST_CHECK_EQUAL(numTest.getValStr(), "82");
@@ -93,33 +93,33 @@ void univalue_push_throw()
void univalue_typecheck()
{
UniValue v1;
- BOOST_CHECK(v1.setNumStr("1"));
+ v1.setNumStr("1");
BOOST_CHECK(v1.isNum());
BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error);
{
UniValue v_negative;
- BOOST_CHECK(v_negative.setNumStr("-1"));
+ v_negative.setNumStr("-1");
BOOST_CHECK_THROW(v_negative.getInt<uint8_t>(), std::runtime_error);
BOOST_CHECK_EQUAL(v_negative.getInt<int8_t>(), -1);
}
UniValue v2;
- BOOST_CHECK(v2.setBool(true));
+ v2.setBool(true);
BOOST_CHECK_EQUAL(v2.get_bool(), true);
BOOST_CHECK_THROW(v2.getInt<int>(), std::runtime_error);
UniValue v3;
- BOOST_CHECK(v3.setNumStr("32482348723847471234"));
+ v3.setNumStr("32482348723847471234");
BOOST_CHECK_THROW(v3.getInt<int64_t>(), std::runtime_error);
- BOOST_CHECK(v3.setNumStr("1000"));
+ v3.setNumStr("1000");
BOOST_CHECK_EQUAL(v3.getInt<int64_t>(), 1000);
UniValue v4;
- BOOST_CHECK(v4.setNumStr("2147483648"));
+ v4.setNumStr("2147483648");
BOOST_CHECK_EQUAL(v4.getInt<int64_t>(), 2147483648);
BOOST_CHECK_THROW(v4.getInt<int>(), std::runtime_error);
- BOOST_CHECK(v4.setNumStr("1000"));
+ v4.setNumStr("1000");
BOOST_CHECK_EQUAL(v4.getInt<int>(), 1000);
BOOST_CHECK_THROW(v4.get_str(), std::runtime_error);
BOOST_CHECK_EQUAL(v4.get_real(), 1000);
@@ -146,55 +146,55 @@ void univalue_set()
BOOST_CHECK(v.isNull());
BOOST_CHECK_EQUAL(v.getValStr(), "");
- BOOST_CHECK(v.setObject());
+ v.setObject();
BOOST_CHECK(v.isObject());
BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
BOOST_CHECK(v.empty());
- BOOST_CHECK(v.setArray());
+ v.setArray();
BOOST_CHECK(v.isArray());
BOOST_CHECK_EQUAL(v.size(), 0);
- BOOST_CHECK(v.setStr("zum"));
+ v.setStr("zum");
BOOST_CHECK(v.isStr());
BOOST_CHECK_EQUAL(v.getValStr(), "zum");
- BOOST_CHECK(v.setFloat(-1.01));
+ v.setFloat(-1.01);
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
- BOOST_CHECK(v.setInt((int)1023));
+ v.setInt(int{1023});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "1023");
- BOOST_CHECK(v.setInt((int64_t)-1023LL));
+ v.setInt(int64_t{-1023LL});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1023");
- BOOST_CHECK(v.setInt((uint64_t)1023ULL));
+ v.setInt(uint64_t{1023ULL});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "1023");
- BOOST_CHECK(v.setNumStr("-688"));
+ v.setNumStr("-688");
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-688");
- BOOST_CHECK(v.setBool(false));
+ v.setBool(false);
BOOST_CHECK_EQUAL(v.isBool(), true);
BOOST_CHECK_EQUAL(v.isTrue(), false);
BOOST_CHECK_EQUAL(v.isFalse(), true);
BOOST_CHECK_EQUAL(v.getBool(), false);
- BOOST_CHECK(v.setBool(true));
+ v.setBool(true);
BOOST_CHECK_EQUAL(v.isBool(), true);
BOOST_CHECK_EQUAL(v.isTrue(), true);
BOOST_CHECK_EQUAL(v.isFalse(), false);
BOOST_CHECK_EQUAL(v.getBool(), true);
- BOOST_CHECK(!v.setNumStr("zombocom"));
+ BOOST_CHECK_THROW(v.setNumStr("zombocom"), std::runtime_error);
- BOOST_CHECK(v.setNull());
+ v.setNull();
BOOST_CHECK(v.isNull());
}
@@ -352,7 +352,7 @@ void univalue_object()
BOOST_CHECK_EQUAL(obj.size(), 0);
BOOST_CHECK_EQUAL(obj.getType(), UniValue::VNULL);
- BOOST_CHECK_EQUAL(obj.setObject(), true);
+ obj.setObject();
UniValue uv;
uv.setInt(42);
obj.__pushKV("age", uv);
@@ -419,7 +419,7 @@ void univalue_readwrite()
BOOST_CHECK(!v.read("{} 42"));
}
-int main (int argc, char *argv[])
+int main(int argc, char* argv[])
{
univalue_constructor();
univalue_push_throw();
@@ -430,4 +430,3 @@ int main (int argc, char *argv[])
univalue_readwrite();
return 0;
}
-
diff --git a/src/util/result.h b/src/util/result.h
index 2f586a4c9b..972b1aada0 100644
--- a/src/util/result.h
+++ b/src/util/result.h
@@ -5,45 +5,80 @@
#ifndef BITCOIN_UTIL_RESULT_H
#define BITCOIN_UTIL_RESULT_H
+#include <attributes.h>
#include <util/translation.h>
#include <variant>
-/*
- * 'BResult' is a generic class useful for wrapping a return object
- * (in case of success) or propagating the error cause.
-*/
-template<class T>
-class BResult {
+namespace util {
+
+struct Error {
+ bilingual_str message;
+};
+
+//! The util::Result class provides a standard way for functions to return
+//! either error messages or result values.
+//!
+//! It is intended for high-level functions that need to report error strings to
+//! end users. Lower-level functions that don't need this error-reporting and
+//! only need error-handling should avoid util::Result and instead use standard
+//! classes like std::optional, std::variant, and std::tuple, or custom structs
+//! and enum types to return function results.
+//!
+//! Usage examples can be found in \example ../test/result_tests.cpp, but in
+//! general code returning `util::Result<T>` values is very similar to code
+//! returning `std::optional<T>` values. Existing functions returning
+//! `std::optional<T>` can be updated to return `util::Result<T>` and return
+//! error strings usually just replacing `return std::nullopt;` with `return
+//! util::Error{error_string};`.
+template <class T>
+class Result
+{
private:
std::variant<bilingual_str, T> m_variant;
-public:
- BResult() : m_variant{Untranslated("")} {}
- BResult(T obj) : m_variant{std::move(obj)} {}
- BResult(bilingual_str error) : m_variant{std::move(error)} {}
+ template <typename FT>
+ friend bilingual_str ErrorString(const Result<FT>& result);
- /* Whether the function succeeded or not */
- bool HasRes() const { return std::holds_alternative<T>(m_variant); }
+public:
+ Result(T obj) : m_variant{std::in_place_index_t<1>{}, std::move(obj)} {}
+ Result(Error error) : m_variant{std::in_place_index_t<0>{}, std::move(error.message)} {}
- /* In case of success, the result object */
- const T& GetObj() const {
- assert(HasRes());
- return std::get<T>(m_variant);
+ //! std::optional methods, so functions returning optional<T> can change to
+ //! return Result<T> with minimal changes to existing code, and vice versa.
+ bool has_value() const noexcept { return m_variant.index() == 1; }
+ const T& value() const LIFETIMEBOUND
+ {
+ assert(has_value());
+ return std::get<1>(m_variant);
}
- T ReleaseObj()
+ T& value() LIFETIMEBOUND
{
- assert(HasRes());
- return std::move(std::get<T>(m_variant));
+ assert(has_value());
+ return std::get<1>(m_variant);
}
-
- /* In case of failure, the error cause */
- const bilingual_str& GetError() const {
- assert(!HasRes());
- return std::get<bilingual_str>(m_variant);
+ template <class U>
+ T value_or(U&& default_value) const&
+ {
+ return has_value() ? value() : std::forward<U>(default_value);
}
-
- explicit operator bool() const { return HasRes(); }
+ template <class U>
+ T value_or(U&& default_value) &&
+ {
+ return has_value() ? std::move(value()) : std::forward<U>(default_value);
+ }
+ explicit operator bool() const noexcept { return has_value(); }
+ const T* operator->() const LIFETIMEBOUND { return &value(); }
+ const T& operator*() const LIFETIMEBOUND { return value(); }
+ T* operator->() LIFETIMEBOUND { return &value(); }
+ T& operator*() LIFETIMEBOUND { return value(); }
};
+template <typename T>
+bilingual_str ErrorString(const Result<T>& result)
+{
+ return result ? bilingual_str{} : std::get<0>(result.m_variant);
+}
+} // namespace util
+
#endif // BITCOIN_UTIL_RESULT_H
diff --git a/src/util/system.cpp b/src/util/system.cpp
index f6f2828fc8..1953a9f836 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -522,7 +522,7 @@ bool ArgsManager::InitSettings(std::string& error)
bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp, bool backup) const
{
- fs::path settings = GetPathArg("-settings", fs::path{BITCOIN_SETTINGS_FILENAME});
+ fs::path settings = GetPathArg("-settings", BITCOIN_SETTINGS_FILENAME);
if (settings.empty()) {
return false;
}
@@ -740,7 +740,7 @@ std::string ArgsManager::GetHelpMessage() const
{
const bool show_debug = GetBoolArg("-help-debug", false);
- std::string usage = "";
+ std::string usage;
LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
switch(arg_map.first) {
@@ -885,9 +885,9 @@ bool CheckDataDirOption()
return datadir.empty() || fs::is_directory(fs::absolute(datadir));
}
-fs::path GetConfigFile(const std::string& confPath)
+fs::path GetConfigFile(const fs::path& configuration_file_path)
{
- return AbsPathForConfigVal(fs::PathFromString(confPath), false);
+ return AbsPathForConfigVal(configuration_file_path, /*net_specific=*/false);
}
static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
@@ -971,17 +971,17 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
m_config_sections.clear();
}
- const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
- std::ifstream stream{GetConfigFile(confPath)};
+ const fs::path conf_path = GetPathArg("-conf", BITCOIN_CONF_FILENAME);
+ std::ifstream stream{GetConfigFile(conf_path)};
// not ok to have a config file specified that cannot be opened
if (IsArgSet("-conf") && !stream.good()) {
- error = strprintf("specified config file \"%s\" could not be opened.", confPath);
+ error = strprintf("specified config file \"%s\" could not be opened.", fs::PathToString(conf_path));
return false;
}
// ok to not have a config file
if (stream.good()) {
- if (!ReadConfigStream(stream, confPath, error, ignore_invalid_keys)) {
+ if (!ReadConfigStream(stream, fs::PathToString(conf_path), error, ignore_invalid_keys)) {
return false;
}
// `-includeconf` cannot be included in the command line arguments except
@@ -1019,7 +1019,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
const size_t default_includes = add_includes({});
for (const std::string& conf_file_name : conf_file_names) {
- std::ifstream conf_file_stream{GetConfigFile(conf_file_name)};
+ std::ifstream conf_file_stream{GetConfigFile(fs::PathFromString(conf_file_name))};
if (conf_file_stream.good()) {
if (!ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) {
return false;
diff --git a/src/util/system.h b/src/util/system.h
index fa03e88920..756e6642f2 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -97,7 +97,7 @@ bool TryCreateDirectories(const fs::path& p);
fs::path GetDefaultDataDir();
// Return true if -datadir option points to a valid directory or is not specified.
bool CheckDataDirOption();
-fs::path GetConfigFile(const std::string& confPath);
+fs::path GetConfigFile(const fs::path& configuration_file_path);
#ifdef WIN32
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
diff --git a/src/util/time.h b/src/util/time.h
index c75b1e94ed..4f9bde5d56 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -55,6 +55,7 @@ constexpr int64_t count_seconds(std::chrono::seconds t) { return t.count(); }
constexpr int64_t count_milliseconds(std::chrono::milliseconds t) { return t.count(); }
constexpr int64_t count_microseconds(std::chrono::microseconds t) { return t.count(); }
+using HoursDouble = std::chrono::duration<double, std::chrono::hours::period>;
using SecondsDouble = std::chrono::duration<double, std::chrono::seconds::period>;
/**
diff --git a/src/validation.cpp b/src/validation.cpp
index d64ef4df0b..d276cea2f7 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -57,6 +57,7 @@
#include <warnings.h>
#include <algorithm>
+#include <cassert>
#include <chrono>
#include <deque>
#include <numeric>
@@ -123,7 +124,6 @@ GlobalMutex g_best_block_mutex;
std::condition_variable g_best_block_cv;
uint256 g_best_block;
bool g_parallel_script_checks{false};
-bool fRequireStandard = true;
bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
@@ -157,10 +157,9 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
std::vector<CScriptCheck>* pvChecks = nullptr)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx)
+bool CheckFinalTxAtTip(const CBlockIndex& active_chain_tip, const CTransaction& tx)
{
AssertLockHeld(cs_main);
- assert(active_chain_tip); // TODO: Make active_chain_tip a reference
// CheckFinalTxAtTip() uses active_chain_tip.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
@@ -168,14 +167,14 @@ bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction&
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
// IsFinalTx() with one more than active_chain_tip.Height().
- const int nBlockHeight = active_chain_tip->nHeight + 1;
+ const int nBlockHeight = active_chain_tip.nHeight + 1;
// BIP113 requires that time-locked transactions have nLockTime set to
// less than the median time of the previous block they're contained in.
// When the next block is created its previous block will be the current
// chain tip, so we use that to calculate the median time passed to
// IsFinalTx().
- const int64_t nBlockTime{active_chain_tip->GetMedianTimePast()};
+ const int64_t nBlockTime{active_chain_tip.GetMedianTimePast()};
return IsFinalTx(tx, nBlockHeight, nBlockTime);
}
@@ -337,7 +336,7 @@ void CChainState::MaybeUpdateMempoolForReorg(
const CTransaction& tx = it->GetTx();
// The transaction must be final.
- if (!CheckFinalTxAtTip(m_chain.Tip(), tx)) return true;
+ if (!CheckFinalTxAtTip(*Assert(m_chain.Tip()), tx)) return true;
LockPoints lp = it->GetLockPoints();
const bool validLP{TestLockPointValidity(m_chain, lp)};
CCoinsViewMemPool view_mempool(&CoinsTip(), *m_mempool);
@@ -646,8 +645,9 @@ private:
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
}
- if (package_fee < ::minRelayTxFee.GetFee(package_size)) {
- return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size)));
+ if (package_fee < m_pool.m_min_relay_feerate.GetFee(package_size)) {
+ return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
+ strprintf("%d < %d", package_fee, m_pool.m_min_relay_feerate.GetFee(package_size)));
}
return true;
}
@@ -699,8 +699,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
std::string reason;
- if (fRequireStandard && !IsStandardTx(tx, reason))
+ if (m_pool.m_require_standard && !IsStandardTx(tx, m_pool.m_max_datacarrier_bytes, m_pool.m_permit_bare_multisig, m_pool.m_dust_relay_feerate, reason)) {
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
+ }
// Do not work on transactions that are too small.
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
@@ -712,7 +713,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
- if (!CheckFinalTxAtTip(m_active_chainstate.m_chain.Tip(), tx)) {
+ if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
}
@@ -806,13 +807,14 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return false; // state filled in by CheckTxInputs
}
- if (fRequireStandard && !AreInputsStandard(tx, m_view)) {
+ if (m_pool.m_require_standard && !AreInputsStandard(tx, m_view)) {
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
}
// Check for non-standard witnesses.
- if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view))
+ if (tx.HasWitness() && m_pool.m_require_standard && !IsWitnessStandard(tx, m_view)) {
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
+ }
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -839,7 +841,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
strprintf("%d", nSigOpsCost));
- // No individual transactions are allowed below minRelayTxFee and mempool min fee except from
+ // No individual transactions are allowed below the min relay feerate and mempool min feerate except from
// disconnected blocks and transactions in a package. Package transactions will be checked using
// package feerate later.
if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
@@ -957,7 +959,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
ws.m_conflicting_size += it->GetTxSize();
}
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
- ::incrementalRelayFee, hash)}) {
+ m_pool.m_incremental_relay_feerate, hash)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
}
return true;
@@ -1653,7 +1655,8 @@ bool CScriptCheck::operator()() {
static CuckooCache::cache<uint256, SignatureCacheHasher> g_scriptExecutionCache;
static CSHA256 g_scriptExecutionCacheHasher;
-void InitScriptExecutionCache() {
+bool InitScriptExecutionCache(size_t max_size_bytes)
+{
// Setup the salted hasher
uint256 nonce = GetRandHash();
// We want the nonce to be 64 bytes long to force the hasher to process
@@ -1661,12 +1664,14 @@ void InitScriptExecutionCache() {
// just write our 32-byte entropy twice to fill the 64 bytes.
g_scriptExecutionCacheHasher.Write(nonce.begin(), 32);
g_scriptExecutionCacheHasher.Write(nonce.begin(), 32);
- // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
- // setup_bytes creates the minimum possible cache (2 elements).
- size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) / 2), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
- size_t nElems = g_scriptExecutionCache.setup_bytes(nMaxCacheSize);
- LogPrintf("Using %zu MiB out of %zu/2 requested for script execution cache, able to store %zu elements\n",
- (nElems*sizeof(uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
+
+ auto setup_results = g_scriptExecutionCache.setup_bytes(max_size_bytes);
+ if (!setup_results) return false;
+
+ const auto [num_elems, approx_size_bytes] = *setup_results;
+ LogPrintf("Using %zu MiB out of %zu MiB requested for script execution cache, able to store %zu elements\n",
+ approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
+ return true;
}
/**
@@ -2577,6 +2582,7 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
CBlockIndex *pindexDelete = m_chain.Tip();
assert(pindexDelete);
+ assert(pindexDelete->pprev);
// Read block from disk.
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
CBlock& block = *pblock;
@@ -2624,7 +2630,7 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
}
}
- m_chain.SetTip(pindexDelete->pprev);
+ m_chain.SetTip(*pindexDelete->pprev);
UpdateTip(pindexDelete->pprev);
// Let wallets know transactions went from 1-confirmed to
@@ -2738,7 +2744,7 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew
disconnectpool.removeForBlock(blockConnecting.vtx);
}
// Update m_chain & related variables.
- m_chain.SetTip(pindexNew);
+ m_chain.SetTip(*pindexNew);
UpdateTip(pindexNew);
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
@@ -3886,7 +3892,7 @@ bool CChainState::LoadChainTip()
if (!pindex) {
return false;
}
- m_chain.SetTip(pindex);
+ m_chain.SetTip(*pindex);
PruneBlockIndexCandidates();
tip = m_chain.Tip();
@@ -4256,11 +4262,16 @@ bool CChainState::LoadGenesisBlock()
return true;
}
-void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
+void CChainState::LoadExternalBlockFile(
+ FILE* fileIn,
+ FlatFilePos* dbp,
+ std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent)
{
AssertLockNotHeld(m_chainstate_mutex);
- // Map of disk positions for blocks with unknown parent (only used for reindex)
- static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
+
+ // Either both should be specified (-reindex), or neither (-loadblock).
+ assert(!dbp == !blocks_with_unknown_parent);
+
int64_t nStart = GetTimeMillis();
int nLoaded = 0;
@@ -4310,8 +4321,9 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
if (hash != m_params.GetConsensus().hashGenesisBlock && !m_blockman.LookupBlockIndex(block.hashPrevBlock)) {
LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
block.hashPrevBlock.ToString());
- if (dbp)
- mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
+ if (dbp && blocks_with_unknown_parent) {
+ blocks_with_unknown_parent->emplace(block.hashPrevBlock, *dbp);
+ }
continue;
}
@@ -4340,13 +4352,15 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
NotifyHeaderTip(*this);
+ if (!blocks_with_unknown_parent) continue;
+
// Recursively process earlier encountered successors of this block
std::deque<uint256> queue;
queue.push_back(hash);
while (!queue.empty()) {
uint256 head = queue.front();
queue.pop_front();
- std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
+ auto range = blocks_with_unknown_parent->equal_range(head);
while (range.first != range.second) {
std::multimap<uint256, FlatFilePos>::iterator it = range.first;
std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
@@ -4361,7 +4375,7 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
}
}
range.first++;
- mapBlocksUnknownParent.erase(it);
+ blocks_with_unknown_parent->erase(it);
NotifyHeaderTip(*this);
}
}
@@ -4955,7 +4969,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
return false;
}
- snapshot_chainstate.m_chain.SetTip(snapshot_start_block);
+ snapshot_chainstate.m_chain.SetTip(*snapshot_start_block);
// The remainder of this function requires modifying data protected by cs_main.
LOCK(::cs_main);
diff --git a/src/validation.h b/src/validation.h
index a44dbd9c7a..17286c7910 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -100,7 +100,6 @@ extern uint256 g_best_block;
* False indicates all script checking is done on the main threadMessageHandler thread.
*/
extern bool g_parallel_script_checks;
-extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
@@ -257,12 +256,12 @@ PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTx
const Package& txns, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/* Transaction policy functions */
+/* Mempool validation helper functions */
/**
* Check if transaction will be final in the next block to be created.
*/
-bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+bool CheckFinalTxAtTip(const CBlockIndex& active_chain_tip, const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/**
* Check if transaction will be BIP68 final in the next block to be created on top of tip.
@@ -324,7 +323,7 @@ public:
};
/** Initializes the script-execution cache */
-void InitScriptExecutionCache();
+[[nodiscard]] bool InitScriptExecutionCache(size_t max_size_bytes);
/** Functions for validating blocks and updating the block tree */
@@ -575,8 +574,36 @@ public:
bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- /** Import blocks from an external file */
- void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr)
+ /**
+ * Import blocks from an external file
+ *
+ * During reindexing, this function is called for each block file (datadir/blocks/blk?????.dat).
+ * It reads all blocks contained in the given file and attempts to process them (add them to the
+ * block index). The blocks may be out of order within each file and across files. Often this
+ * function reads a block but finds that its parent hasn't been read yet, so the block can't be
+ * processed yet. The function will add an entry to the blocks_with_unknown_parent map (which is
+ * passed as an argument), so that when the block's parent is later read and processed, this
+ * function can re-read the child block from disk and process it.
+ *
+ * Because a block's parent may be in a later file, not just later in the same file, the
+ * blocks_with_unknown_parent map must be passed in and out with each call. It's a multimap,
+ * rather than just a map, because multiple blocks may have the same parent (when chain splits
+ * or stale blocks exist). It maps from parent-hash to child-disk-position.
+ *
+ * This function can also be used to read blocks from user-specified block files using the
+ * -loadblock= option. There's no unknown-parent tracking, so the last two arguments are omitted.
+ *
+ *
+ * @param[in] fileIn FILE handle to file containing blocks to read
+ * @param[in] dbp (optional) Disk block position (only for reindex)
+ * @param[in,out] blocks_with_unknown_parent (optional) Map of disk positions for blocks with
+ * unknown parent, key is parent block hash
+ * (only used for reindex)
+ * */
+ void LoadExternalBlockFile(
+ FILE* fileIn,
+ FlatFilePos* dbp = nullptr,
+ std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent = nullptr)
EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex);
/**
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 9135e48104..e257d3f7c7 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -125,8 +125,6 @@ struct CoinSelectionParams {
CAmount m_min_change_target{0};
/** Cost of creating the change output. */
CAmount m_change_fee{0};
- /** The pre-determined minimum value to target when funding a change output. */
- CAmount m_change_target{0};
/** Cost of creating the change output + cost of spending the change output in the future. */
CAmount m_cost_of_change{0};
/** The targeted feerate of the transaction being built. */
diff --git a/src/wallet/external_signer_scriptpubkeyman.cpp b/src/wallet/external_signer_scriptpubkeyman.cpp
index 9d5f58b784..76de51ac3e 100644
--- a/src/wallet/external_signer_scriptpubkeyman.cpp
+++ b/src/wallet/external_signer_scriptpubkeyman.cpp
@@ -45,7 +45,8 @@ ExternalSigner ExternalSignerScriptPubKeyMan::GetExternalSigner() {
std::vector<ExternalSigner> signers;
ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
if (signers.empty()) throw std::runtime_error(std::string(__func__) + ": No external signers found");
- // TODO: add fingerprint argument in case of multiple signers
+ // TODO: add fingerprint argument instead of failing in case of multiple signers.
+ if (signers.size() > 1) throw std::runtime_error(std::string(__func__) + ": More than one external signer found. Please connect only one at a time.");
return signers[0];
}
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 43fdcee48d..c2b8082eae 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -21,7 +21,7 @@ namespace wallet {
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWalletTx& wtx, std::vector<bilingual_str>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
- if (wallet.HasWalletSpend(wtx.GetHash())) {
+ if (wallet.HasWalletSpend(wtx.tx)) {
errors.push_back(Untranslated("Transaction has descendants in the wallet"));
return feebumper::Result::INVALID_PARAMETER;
}
@@ -221,11 +221,11 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
constexpr int RANDOM_CHANGE_POSITION = -1;
auto res = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, new_coin_control, false);
if (!res) {
- errors.push_back(Untranslated("Unable to create transaction.") + Untranslated(" ") + res.GetError());
+ errors.push_back(Untranslated("Unable to create transaction.") + Untranslated(" ") + util::ErrorString(res));
return Result::WALLET_ERROR;
}
- const auto& txr = res.GetObj();
+ const auto& txr = *res;
// Write back new fee if successful
new_fee = txr.fee;
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 6f81fa30a1..3514d018b7 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -87,7 +87,7 @@ CFeeRate GetDiscardRate(const CWallet& wallet)
CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */);
// Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
- // Discard rate must be at least dustRelayFee
+ // Discard rate must be at least dust relay feerate
discard_rate = std::max(discard_rate, wallet.chain().relayDustFee());
return discard_rate;
}
diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp
index 23f91d9b3a..4fbc519e39 100644
--- a/src/wallet/interfaces.cpp
+++ b/src/wallet/interfaces.cpp
@@ -48,6 +48,8 @@ using interfaces::WalletTxStatus;
using interfaces::WalletValueMap;
namespace wallet {
+// All members of the classes in this namespace are intentionally public, as the
+// classes themselves are private.
namespace {
//! Construct wallet tx struct.
WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
@@ -146,7 +148,7 @@ public:
void abortRescan() override { m_wallet->AbortRescan(); }
bool backupWallet(const std::string& filename) override { return m_wallet->BackupWallet(filename); }
std::string getWalletName() override { return m_wallet->GetName(); }
- BResult<CTxDestination> getNewDestination(const OutputType type, const std::string label) override
+ util::Result<CTxDestination> getNewDestination(const OutputType type, const std::string& label) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->GetNewDestination(type, label);
@@ -249,17 +251,17 @@ public:
LOCK(m_wallet->cs_wallet);
return m_wallet->ListLockedCoins(outputs);
}
- BResult<CTransactionRef> createTransaction(const std::vector<CRecipient>& recipients,
+ util::Result<CTransactionRef> createTransaction(const std::vector<CRecipient>& recipients,
const CCoinControl& coin_control,
bool sign,
int& change_pos,
CAmount& fee) override
{
LOCK(m_wallet->cs_wallet);
- const auto& res = CreateTransaction(*m_wallet, recipients, change_pos,
+ auto res = CreateTransaction(*m_wallet, recipients, change_pos,
coin_control, sign);
- if (!res) return res.GetError();
- const auto& txr = res.GetObj();
+ if (!res) return util::Error{util::ErrorString(res)};
+ const auto& txr = *res;
fee = txr.fee;
change_pos = txr.change_pos;
@@ -318,13 +320,12 @@ public:
}
return {};
}
- std::vector<WalletTx> getWalletTxs() override
+ std::set<WalletTx> getWalletTxs() override
{
LOCK(m_wallet->cs_wallet);
- std::vector<WalletTx> result;
- result.reserve(m_wallet->mapWallet.size());
+ std::set<WalletTx> result;
for (const auto& entry : m_wallet->mapWallet) {
- result.emplace_back(MakeWalletTx(*m_wallet, entry.second));
+ result.emplace(MakeWalletTx(*m_wallet, entry.second));
}
return result;
}
@@ -550,32 +551,34 @@ public:
void setMockTime(int64_t time) override { return SetMockTime(time); }
//! WalletLoader methods
- std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) override
+ util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) override
{
- std::shared_ptr<CWallet> wallet;
DatabaseOptions options;
DatabaseStatus status;
ReadDatabaseArgs(*m_context.args, options);
options.require_create = true;
options.create_flags = wallet_creation_flags;
options.create_passphrase = passphrase;
- return MakeWallet(m_context, CreateWallet(m_context, name, true /* load_on_start */, options, status, error, warnings));
+ bilingual_str error;
+ util::Result<std::unique_ptr<Wallet>> wallet{MakeWallet(m_context, CreateWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};
+ return wallet ? std::move(wallet) : util::Error{error};
}
- std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
+ util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) override
{
DatabaseOptions options;
DatabaseStatus status;
ReadDatabaseArgs(*m_context.args, options);
options.require_existing = true;
- return MakeWallet(m_context, LoadWallet(m_context, name, true /* load_on_start */, options, status, error, warnings));
+ bilingual_str error;
+ util::Result<std::unique_ptr<Wallet>> wallet{MakeWallet(m_context, LoadWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};
+ return wallet ? std::move(wallet) : util::Error{error};
}
- BResult<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) override
+ util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) override
{
DatabaseStatus status;
bilingual_str error;
- BResult<std::unique_ptr<Wallet>> wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings))};
- if (!wallet) return error;
- return wallet;
+ util::Result<std::unique_ptr<Wallet>> wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings))};
+ return wallet ? std::move(wallet) : util::Error{error};
}
std::string getWalletDir() override
{
diff --git a/src/wallet/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp
index 2a6eb96871..903a569cb9 100644
--- a/src/wallet/rpc/addresses.cpp
+++ b/src/wallet/rpc/addresses.cpp
@@ -60,10 +60,10 @@ RPCHelpMan getnewaddress()
auto op_dest = pwallet->GetNewDestination(output_type, label);
if (!op_dest) {
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, op_dest.GetError().original);
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, util::ErrorString(op_dest).original);
}
- return EncodeDestination(op_dest.GetObj());
+ return EncodeDestination(*op_dest);
},
};
}
@@ -107,9 +107,9 @@ RPCHelpMan getrawchangeaddress()
auto op_dest = pwallet->GetNewChangeDestination(output_type);
if (!op_dest) {
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, op_dest.GetError().original);
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, util::ErrorString(op_dest).original);
}
- return EncodeDestination(op_dest.GetObj());
+ return EncodeDestination(*op_dest);
},
};
}
@@ -578,7 +578,7 @@ RPCHelpMan getaddressinfo()
if (provider) {
auto inferred = InferDescriptor(scriptPubKey, *provider);
- bool solvable = inferred->IsSolvable() || IsSolvable(*provider, scriptPubKey);
+ bool solvable = inferred->IsSolvable();
ret.pushKV("solvable", solvable);
if (solvable) {
ret.pushKV("desc", inferred->ToString());
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index 57c3bcc68b..306053fd0c 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -140,7 +140,7 @@ RPCHelpMan importprivkey()
EnsureWalletIsUnlocked(*pwallet);
std::string strSecret = request.params[0].get_str();
- std::string strLabel = "";
+ std::string strLabel;
if (!request.params[1].isNull())
strLabel = request.params[1].get_str();
diff --git a/src/wallet/rpc/coins.cpp b/src/wallet/rpc/coins.cpp
index 9e992294ff..d40d800f28 100644
--- a/src/wallet/rpc/coins.cpp
+++ b/src/wallet/rpc/coins.cpp
@@ -638,7 +638,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).coins;
+ vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount).all();
}
LOCK(pwallet->cs_wallet);
diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
index b5472efa61..da0615ed1c 100644
--- a/src/wallet/rpc/spend.cpp
+++ b/src/wallet/rpc/spend.cpp
@@ -158,14 +158,14 @@ UniValue SendMoney(CWallet& wallet, const CCoinControl &coin_control, std::vecto
constexpr int RANDOM_CHANGE_POSITION = -1;
auto res = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, coin_control, true);
if (!res) {
- throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, res.GetError().original);
+ throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, util::ErrorString(res).original);
}
- const CTransactionRef& tx = res.GetObj().tx;
+ const CTransactionRef& tx = res->tx;
wallet.CommitTransaction(tx, std::move(map_value), {} /* orderForm */);
if (verbose) {
UniValue entry(UniValue::VOBJ);
entry.pushKV("txid", tx->GetHash().GetHex());
- entry.pushKV("fee_reason", StringForFeeReason(res.GetObj().fee_calc.reason));
+ entry.pushKV("fee_reason", StringForFeeReason(res->fee_calc.reason));
return entry;
}
return tx->GetHash().GetHex();
@@ -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"
@@ -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).coins) {
+ 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/wallet.cpp b/src/wallet/rpc/wallet.cpp
index b474236e58..eb275f9951 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -241,7 +241,7 @@ static RPCHelpMan loadwallet()
static RPCHelpMan setwalletflag()
{
- std::string flags = "";
+ std::string flags;
for (auto& it : WALLET_FLAG_MAP)
if (it.second & MUTABLE_WALLET_FLAGS)
flags += (flags == "" ? "" : ", ") + it.first;
@@ -590,6 +590,117 @@ static RPCHelpMan upgradewallet()
};
}
+RPCHelpMan simulaterawtransaction()
+{
+ return RPCHelpMan{"simulaterawtransaction",
+ "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
+ {
+ {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "An array of hex strings of raw transactions.\n",
+ {
+ {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
+ },
+ },
+ {"options", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::OMITTED_NAMED_ARG, "Options",
+ {
+ {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
+ },
+ },
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
+ }
+ },
+ RPCExamples{
+ HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
+ + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+{
+ const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
+ if (!rpc_wallet) return UniValue::VNULL;
+ const CWallet& wallet = *rpc_wallet;
+
+ RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ}, true);
+
+ LOCK(wallet.cs_wallet);
+
+ UniValue include_watchonly(UniValue::VNULL);
+ if (request.params[1].isObject()) {
+ UniValue options = request.params[1];
+ RPCTypeCheckObj(options,
+ {
+ {"include_watchonly", UniValueType(UniValue::VBOOL)},
+ },
+ true, true);
+
+ include_watchonly = options["include_watchonly"];
+ }
+
+ isminefilter filter = ISMINE_SPENDABLE;
+ if (ParseIncludeWatchonly(include_watchonly, wallet)) {
+ filter |= ISMINE_WATCH_ONLY;
+ }
+
+ const auto& txs = request.params[0].get_array();
+ CAmount changes{0};
+ std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
+ std::set<COutPoint> spent;
+
+ for (size_t i = 0; i < txs.size(); ++i) {
+ CMutableTransaction mtx;
+ if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
+ }
+
+ // Fetch previous transactions (inputs)
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : mtx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ wallet.chain().findCoins(coins);
+
+ // Fetch debit; we are *spending* these; if the transaction is signed and
+ // broadcast, we will lose everything in these
+ for (const auto& txin : mtx.vin) {
+ const auto& outpoint = txin.prevout;
+ if (spent.count(outpoint)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
+ }
+ if (new_utxos.count(outpoint)) {
+ changes -= new_utxos.at(outpoint);
+ new_utxos.erase(outpoint);
+ } else {
+ if (coins.at(outpoint).IsSpent()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
+ }
+ changes -= wallet.GetDebit(txin, filter);
+ }
+ spent.insert(outpoint);
+ }
+
+ // Iterate over outputs; we are *receiving* these, if the wallet considers
+ // them "mine"; if the transaction is signed and broadcast, we will receive
+ // everything in these
+ // Also populate new_utxos in case these are spent in later transactions
+
+ const auto& hash = mtx.GetHash();
+ for (size_t i = 0; i < mtx.vout.size(); ++i) {
+ const auto& txout = mtx.vout[i];
+ bool is_mine = 0 < (wallet.IsMine(txout) & filter);
+ changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
+ }
+ }
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("balance_change", ValueFromAmount(changes));
+
+ return result;
+}
+ };
+}
+
// addresses
RPCHelpMan getaddressinfo();
RPCHelpMan getnewaddress();
@@ -721,6 +832,7 @@ Span<const CRPCCommand> GetWalletRPCCommands()
{"wallet", &setwalletflag},
{"wallet", &signmessage},
{"wallet", &signrawtransactionwithwallet},
+ {"wallet", &simulaterawtransaction},
{"wallet", &sendall},
{"wallet", &unloadwallet},
{"wallet", &upgradewallet},
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index bba31dfe0b..7ff017775e 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -21,10 +21,10 @@ namespace wallet {
//! Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value. See BIP 32 for more details.
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
-BResult<CTxDestination> LegacyScriptPubKeyMan::GetNewDestination(const OutputType type)
+util::Result<CTxDestination> LegacyScriptPubKeyMan::GetNewDestination(const OutputType type)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
- return _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");;
+ return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
}
assert(type != OutputType::BECH32M);
@@ -33,7 +33,7 @@ BResult<CTxDestination> LegacyScriptPubKeyMan::GetNewDestination(const OutputTyp
// Generate a new key that is added to wallet
CPubKey new_key;
if (!GetKeyFromPool(new_key, type)) {
- return _("Error: Keypool ran out, please call keypoolrefill first");
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
LearnRelatedScripts(new_key, type);
return GetDestinationForKey(new_key, type);
@@ -292,26 +292,22 @@ bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBat
return true;
}
-bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
+util::Result<CTxDestination> LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
- error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
- return false;
+ return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
}
assert(type != OutputType::BECH32M);
LOCK(cs_KeyStore);
if (!CanGetAddresses(internal)) {
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
- address = GetDestinationForKey(keypool.vchPubKey, type);
- return true;
+ return GetDestinationForKey(keypool.vchPubKey, type);
}
bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
@@ -1084,6 +1080,13 @@ CPubKey LegacyScriptPubKeyMan::GenerateNewKey(WalletBatch &batch, CHDChain& hd_c
return pubkey;
}
+//! Try to derive an extended key, throw if it fails.
+static void DeriveExtKey(CExtKey& key_in, unsigned int index, CExtKey& key_out) {
+ if (!key_in.Derive(key_out, index)) {
+ throw std::runtime_error("Could not derive extended key");
+ }
+}
+
void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal)
{
// for now we use a fixed keypath scheme of m/0'/0'/k
@@ -1101,11 +1104,11 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
// derive m/0'
// use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
- masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT);
+ DeriveExtKey(masterKey, BIP32_HARDENED_KEY_LIMIT, accountKey);
// derive m/0'/0' (external chain) OR m/0'/1' (internal chain)
assert(internal ? m_storage.CanSupportFeature(FEATURE_HD_SPLIT) : true);
- accountKey.Derive(chainChildKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0));
+ DeriveExtKey(accountKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0), chainChildKey);
// derive child key at next index, skip keys already known to the wallet
do {
@@ -1113,7 +1116,7 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
// childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
if (internal) {
- chainChildKey.Derive(childKey, hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
+ DeriveExtKey(chainChildKey, hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT, childKey);
metadata.hdKeypath = "m/0'/1'/" + ToString(hd_chain.nInternalChainCounter) + "'";
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
@@ -1121,7 +1124,7 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
hd_chain.nInternalChainCounter++;
}
else {
- chainChildKey.Derive(childKey, hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
+ DeriveExtKey(chainChildKey, hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT, childKey);
metadata.hdKeypath = "m/0'/0'/" + ToString(hd_chain.nExternalChainCounter) + "'";
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
@@ -1453,7 +1456,8 @@ void LegacyScriptPubKeyMan::LearnRelatedScripts(const CPubKey& key, OutputType t
CTxDestination witdest = WitnessV0KeyHash(key.GetID());
CScript witprog = GetScriptForDestination(witdest);
// Make sure the resulting program is solvable.
- assert(IsSolvable(*this, witprog));
+ const auto desc = InferDescriptor(witprog, *this);
+ assert(desc && desc->IsSolvable());
AddCScript(witprog);
}
}
@@ -1654,11 +1658,11 @@ std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
return set_address;
}
-BResult<CTxDestination> DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type)
+util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type)
{
// Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later
if (!CanGetAddresses()) {
- return _("No addresses available");
+ return util::Error{_("No addresses available")};
}
{
LOCK(cs_desc_man);
@@ -1676,11 +1680,11 @@ BResult<CTxDestination> DescriptorScriptPubKeyMan::GetNewDestination(const Outpu
std::vector<CScript> scripts_temp;
if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
// We can't generate anymore keys
- return _("Error: Keypool ran out, please call keypoolrefill first");
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
// We can't generate anymore keys
- return _("Error: Keypool ran out, please call keypoolrefill first");
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
CTxDestination dest;
@@ -1760,17 +1764,12 @@ bool DescriptorScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, Walle
return true;
}
-bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
+util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
{
LOCK(cs_desc_man);
auto op_dest = GetNewDestination(type);
index = m_wallet_descriptor.next_index - 1;
- if (op_dest) {
- address = op_dest.GetObj();
- } else {
- error = op_dest.GetError();
- }
- return op_dest.HasRes();
+ return op_dest;
}
void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
@@ -2075,10 +2074,21 @@ std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvid
std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
{
AssertLockHeld(cs_desc_man);
- // Get the scripts, keys, and key origins for this script
+
std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();
- std::vector<CScript> scripts_temp;
- if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
+
+ // 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);
+ } else {
+ // Get the scripts, keys, and key origins for this script
+ std::vector<CScript> scripts_temp;
+ if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
+
+ // Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again
+ m_map_signing_providers[index] = *out_keys;
+ }
if (HavePrivateKeys() && include_private) {
FlatSigningProvider master_provider;
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index eebc05330f..408d162eba 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -172,14 +172,14 @@ protected:
public:
explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
virtual ~ScriptPubKeyMan() {};
- virtual BResult<CTxDestination> GetNewDestination(const OutputType type) { return Untranslated("Not supported"); }
+ virtual util::Result<CTxDestination> GetNewDestination(const OutputType type) { return util::Error{Untranslated("Not supported")}; }
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
//! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it.
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) { return false; }
virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
- virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) { return false; }
+ virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return util::Error{Untranslated("Not supported")}; }
virtual void KeepDestination(int64_t index, const OutputType& type) {}
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
@@ -360,13 +360,13 @@ private:
public:
using ScriptPubKeyMan::ScriptPubKeyMan;
- BResult<CTxDestination> GetNewDestination(const OutputType type) override;
+ util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
isminetype IsMine(const CScript& script) const override;
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
- bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
+ util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
void KeepDestination(int64_t index, const OutputType& type) override;
void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
@@ -547,6 +547,8 @@ private:
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
+ // Cached FlatSigningProviders to avoid regenerating them each time they are needed.
+ mutable std::map<int32_t, FlatSigningProvider> m_map_signing_providers;
// Fetch the SigningProvider for the given script and optionally include private keys
std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
// Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.
@@ -568,13 +570,13 @@ public:
mutable RecursiveMutex cs_desc_man;
- BResult<CTxDestination> GetNewDestination(const OutputType type) override;
+ util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
isminetype IsMine(const CScript& script) const override;
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
- bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
+ util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
// Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 9be29c4709..61d86844df 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -79,6 +79,32 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle
return CalculateMaximumSignedTxSize(tx, wallet, txouts, coin_control);
}
+uint64_t CoinsResult::size() const
+{
+ return bech32m.size() + bech32.size() + P2SH_segwit.size() + legacy.size() + other.size();
+}
+
+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());
+ return all;
+}
+
+void CoinsResult::clear()
+{
+ bech32m.clear();
+ bech32.clear();
+ P2SH_segwit.clear();
+ legacy.clear();
+ other.clear();
+}
+
CoinsResult AvailableCoins(const CWallet& wallet,
const CCoinControl* coinControl,
std::optional<CFeeRate> feerate,
@@ -187,16 +213,63 @@ CoinsResult AvailableCoins(const CWallet& wallet,
std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);
- bool solvable = provider ? IsSolvable(*provider, output.scriptPubKey) : false;
+ int input_bytes = CalculateMaximumSignedInputSize(output, COutPoint(), provider.get(), coinControl);
+ // Because CalculateMaximumSignedInputSize just uses ProduceSignature and makes a dummy signature,
+ // it is safe to assume that this input is solvable if input_bytes is greater -1.
+ bool solvable = input_bytes > -1;
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
// Filter by spendable outputs only
if (!spendable && only_spendable) continue;
- int input_bytes = CalculateMaximumSignedInputSize(output, COutPoint(), provider.get(), coinControl);
- result.coins.emplace_back(outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate);
- result.total_amount += output.nValue;
+ // 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
+ 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))
+ continue;
+ type = Solver(redeemScript, return_values_unused);
+ is_from_p2sh = true;
+ } else {
+ type = Solver(output.scriptPubKey, return_values_unused);
+ }
+ 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);
+ };
+
+ // Cache total amount as we go
+ result.total_amount += output.nValue;
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
if (result.total_amount >= nMinimumSumAmount) {
@@ -205,7 +278,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
}
// Checks the maximum number of UTXO's.
- if (nMaximumCount > 0 && result.coins.size() >= nMaximumCount) {
+ if (nMaximumCount > 0 && result.size() >= nMaximumCount) {
return result;
}
}
@@ -261,7 +334,7 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
std::map<CTxDestination, std::vector<COutput>> result;
- for (const COutput& coin : AvailableCoinsListUnspent(wallet).coins) {
+ 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)) {
@@ -379,20 +452,51 @@ std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<C
return groups_out;
}
-std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins,
- const CoinSelectionParams& coin_selection_params)
+std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
+ const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types)
+{
+ // 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);
+ }
+
+ // 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;
+ }
+ }
+ return std::optional<SelectionResult>();
+ };
+ std::optional<SelectionResult> result{*std::min_element(results.begin(), results.end())};
+ return result;
+};
+
+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)
{
// Vector of results. We will choose the best one based on waste.
std::vector<SelectionResult> results;
// Note that unlike KnapsackSolver, we do not include the fee for creating a change output as BnB will not create a change output.
- std::vector<OutputGroup> positive_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, true /* positive_only */);
+ std::vector<OutputGroup> positive_groups = GroupOutputs(wallet, available_coins, coin_selection_params, eligibility_filter, true /* positive_only */);
if (auto bnb_result{SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change)}) {
results.push_back(*bnb_result);
}
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
- std::vector<OutputGroup> all_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, false /* positive_only */);
+ std::vector<OutputGroup> all_groups = GroupOutputs(wallet, available_coins, coin_selection_params, eligibility_filter, false /* positive_only */);
CAmount target_with_change = nTargetValue;
// While nTargetValue includes the transaction fees for non-input things, it does not include the fee for creating a change output.
// So we need to include that for KnapsackSolver and SRD as well, as we are expecting to create a change output.
@@ -425,9 +529,8 @@ std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAm
return best_result;
}
-std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
+std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
{
- std::vector<COutput> vCoins(vAvailableCoins);
CAmount value_to_select = nTargetValue;
OutputGroup preset_inputs(coin_selection_params);
@@ -487,13 +590,13 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
return result;
}
- // remove preset inputs from vCoins so that Coin Selection doesn't pick them.
- for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coin_control.HasSelected();)
- {
- if (preset_coins.count(it->outpoint))
- it = vCoins.erase(it);
- else
- ++it;
+ // 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());
}
unsigned int limit_ancestor_count = 0;
@@ -505,11 +608,15 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
// 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 && vCoins.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(vCoins.begin(), vCoins.end(), coin_selection_params.rng_fast);
+ 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);
}
// Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
@@ -521,26 +628,27 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
// If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
// confirmations on outputs received from other wallets and only spend confirmed change.
- if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, coin_selection_params)}) return r1;
- if (auto r2{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, coin_selection_params)}) return r2;
+ if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/false)}) return r1;
+ // Allow mixing only if no solution from any single output type can be found
+ if (auto r2{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 1, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) return r2;
// Fall back to using zero confirmation change (but with as few ancestors in the mempool as
// possible) if we cannot fund the transaction otherwise.
if (wallet.m_spend_zero_conf_change) {
- if (auto r3{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, coin_selection_params)}) return r3;
+ if (auto r3{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, 2), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) return r3;
if (auto r4{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r4;
}
if (auto r5{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r5;
}
// If partial groups are allowed, relax the requirement of spending OutputGroups (groups
// of UTXOs sent to the same address, which are obviously controlled by a single wallet)
// in their entirety.
if (auto r6{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r6;
}
// Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
@@ -548,7 +656,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (coin_control.m_include_unsafe_inputs) {
if (auto r7{AttemptSelection(wallet, value_to_select,
CoinEligibilityFilter(0 /* conf_mine */, 0 /* conf_theirs */, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r7;
}
}
@@ -558,7 +666,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (!fRejectLongChains) {
if (auto r8{AttemptSelection(wallet, value_to_select,
CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r8;
}
}
@@ -652,7 +760,7 @@ static void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng
}
}
-static BResult<CreatedTransactionResult> CreateTransactionInternal(
+static util::Result<CreatedTransactionResult> CreateTransactionInternal(
CWallet& wallet,
const std::vector<CRecipient>& vecSend,
int change_pos,
@@ -686,7 +794,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
coin_selection_params.m_subtract_fee_outputs = true;
}
}
- coin_selection_params.m_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), rng_fast);
+ coin_selection_params.m_min_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), rng_fast);
// Create change script that will be used if we need change
CScript scriptChange;
@@ -706,11 +814,13 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
// Reserve a new key pair from key pool. If it fails, provide a dummy
// destination in case we don't need change.
CTxDestination dest;
- bilingual_str dest_err;
- if (!reservedest.GetReservedDestination(dest, true, dest_err)) {
- error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + dest_err;
+ auto op_dest = reservedest.GetReservedDestination(true);
+ if (!op_dest) {
+ error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + util::ErrorString(op_dest);
+ } else {
+ dest = *op_dest;
+ scriptChange = GetScriptForDestination(dest);
}
- scriptChange = GetScriptForDestination(dest);
// A valid destination implies a change script (and
// vice-versa). An empty change script will abort later, if the
// change keypool ran out, but change is required.
@@ -738,11 +848,11 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
// Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
// provided one
if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
- return strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), coin_selection_params.m_effective_feerate.ToString(FeeEstimateMode::SAT_VB));
+ return util::Error{strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), coin_selection_params.m_effective_feerate.ToString(FeeEstimateMode::SAT_VB))};
}
if (feeCalc.reason == FeeReason::FALLBACK && !wallet.m_allow_fallback_fee) {
// eventually allow a fallback fee
- return _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
+ return util::Error{_("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.")};
}
// Calculate the cost of change
@@ -768,7 +878,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
}
if (IsDust(txout, wallet.chain().relayDustFee())) {
- return _("Transaction amount too small");
+ return util::Error{_("Transaction amount too small")};
}
txNew.vout.push_back(txout);
}
@@ -778,7 +888,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
CAmount selection_target = recipients_sum + not_input_fees;
// Get available coins
- auto res_available_coins = AvailableCoins(wallet,
+ auto available_coins = AvailableCoins(wallet,
&coin_control,
coin_selection_params.m_effective_feerate,
1, /*nMinimumAmount*/
@@ -787,9 +897,9 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
0); /*nMaximumCount*/
// Choose coins to use
- std::optional<SelectionResult> result = SelectCoins(wallet, res_available_coins.coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
+ std::optional<SelectionResult> result = SelectCoins(wallet, available_coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
if (!result) {
- return _("Insufficient funds");
+ return util::Error{_("Insufficient funds")};
}
TRACE5(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result->m_algo).c_str(), result->m_target, result->GetWaste(), result->GetSelectedValue());
@@ -804,7 +914,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
nChangePosInOut = rng_fast.randrange(txNew.vout.size() + 1);
}
else if ((unsigned int)nChangePosInOut > txNew.vout.size()) {
- return _("Transaction change output index out of range");
+ return util::Error{_("Transaction change output index out of range")};
}
assert(nChangePosInOut != -1);
@@ -831,7 +941,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
TxSize tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control);
int nBytes = tx_sizes.vsize;
if (nBytes == -1) {
- return _("Missing solving data for estimating transaction size");
+ return util::Error{_("Missing solving data for estimating transaction size")};
}
nFeeRet = coin_selection_params.m_effective_feerate.GetFee(nBytes);
@@ -891,9 +1001,9 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
// Error if this output is reduced to be below dust
if (IsDust(txout, wallet.chain().relayDustFee())) {
if (txout.nValue < 0) {
- return _("The transaction amount is too small to pay the fee");
+ return util::Error{_("The transaction amount is too small to pay the fee")};
} else {
- return _("The transaction amount is too small to send after the fee has been deducted");
+ return util::Error{_("The transaction amount is too small to send after the fee has been deducted")};
}
}
}
@@ -904,11 +1014,11 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
// Give up if change keypool ran out and change is required
if (scriptChange.empty() && nChangePosInOut != -1) {
- return error;
+ return util::Error{error};
}
if (sign && !wallet.SignTransaction(txNew)) {
- return _("Signing transaction failed");
+ return util::Error{_("Signing transaction failed")};
}
// Return the constructed transaction data.
@@ -918,17 +1028,17 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
if ((sign && GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT) ||
(!sign && tx_sizes.weight > MAX_STANDARD_TX_WEIGHT))
{
- return _("Transaction too large");
+ return util::Error{_("Transaction too large")};
}
if (nFeeRet > wallet.m_default_max_tx_fee) {
- return TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED);
+ return util::Error{TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED)};
}
if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
// Lastly, ensure this tx will pass the mempool's chain limits
if (!wallet.chain().checkChainLimits(tx)) {
- return _("Transaction has too long of a mempool chain");
+ return util::Error{_("Transaction has too long of a mempool chain")};
}
}
@@ -947,7 +1057,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
return CreatedTransactionResult(tx, nFeeRet, nChangePosInOut, feeCalc);
}
-BResult<CreatedTransactionResult> CreateTransaction(
+util::Result<CreatedTransactionResult> CreateTransaction(
CWallet& wallet,
const std::vector<CRecipient>& vecSend,
int change_pos,
@@ -955,28 +1065,26 @@ BResult<CreatedTransactionResult> CreateTransaction(
bool sign)
{
if (vecSend.empty()) {
- return _("Transaction must have at least one recipient");
+ return util::Error{_("Transaction must have at least one recipient")};
}
if (std::any_of(vecSend.cbegin(), vecSend.cend(), [](const auto& recipient){ return recipient.nAmount < 0; })) {
- return _("Transaction amounts must not be negative");
+ return util::Error{_("Transaction amounts must not be negative")};
}
LOCK(wallet.cs_wallet);
auto res = CreateTransactionInternal(wallet, vecSend, change_pos, coin_control, sign);
- TRACE4(coin_selection, normal_create_tx_internal, wallet.GetName().c_str(), res.HasRes(),
- res ? res.GetObj().fee : 0, res ? res.GetObj().change_pos : 0);
+ TRACE4(coin_selection, normal_create_tx_internal, wallet.GetName().c_str(), bool(res),
+ res ? res->fee : 0, res ? res->change_pos : 0);
if (!res) return res;
- const auto& txr_ungrouped = res.GetObj();
+ const auto& txr_ungrouped = *res;
// try with avoidpartialspends unless it's enabled already
if (txr_ungrouped.fee > 0 /* 0 means non-functional fee rate estimation */ && wallet.m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) {
TRACE1(coin_selection, attempting_aps_create_tx, wallet.GetName().c_str());
CCoinControl tmp_cc = coin_control;
tmp_cc.m_avoid_partial_spends = true;
- auto res_tx_grouped = CreateTransactionInternal(wallet, vecSend, change_pos, tmp_cc, sign);
- // Helper optional class for now
- std::optional<CreatedTransactionResult> txr_grouped{res_tx_grouped.HasRes() ? std::make_optional(res_tx_grouped.GetObj()) : std::nullopt};
+ auto txr_grouped = CreateTransactionInternal(wallet, vecSend, change_pos, tmp_cc, sign);
// if fee of this alternative one is within the range of the max fee, we use this one
const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped.fee + wallet.m_max_aps_fee) : false};
TRACE5(coin_selection, aps_create_tx_internal, wallet.GetName().c_str(), use_aps, txr_grouped.has_value(),
@@ -984,7 +1092,7 @@ BResult<CreatedTransactionResult> CreateTransaction(
if (txr_grouped) {
wallet.WalletLogPrintf("Fee non-grouped = %lld, grouped = %lld, using %s\n",
txr_ungrouped.fee, txr_grouped->fee, use_aps ? "grouped" : "non-grouped");
- if (use_aps) return res_tx_grouped;
+ if (use_aps) return txr_grouped;
}
}
return res;
@@ -1025,10 +1133,10 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet,
auto res = CreateTransaction(wallet, vecSend, nChangePosInOut, coinControl, false);
if (!res) {
- error = res.GetError();
+ error = util::ErrorString(res);
return false;
}
- const auto& txr = res.GetObj();
+ const auto& txr = *res;
CTransactionRef tx_new = txr.tx;
nFeeRet = txr.fee;
nChangePosInOut = txr.change_pos;
diff --git a/src/wallet/spend.h b/src/wallet/spend.h
index ab0ff1ee58..fdb5113ba4 100644
--- a/src/wallet/spend.h
+++ b/src/wallet/spend.h
@@ -29,14 +29,38 @@ struct TxSize {
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control = nullptr);
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const CCoinControl* coin_control = nullptr) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
+/**
+ * COutputs available for spending, stored by OutputType.
+ * 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
+ */
struct CoinsResult {
- std::vector<COutput> coins;
- // Sum of all the coins amounts
+ /** 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;
+
+ /** Concatenate and return all COutputs as one vector */
+ 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();
+
+ /** Sum of all available coins */
CAmount total_amount{0};
};
+
/**
- * Return vector of available COutputs.
- * By default, returns only the spendable coins.
+ * Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
*/
CoinsResult AvailableCoins(const CWallet& wallet,
const CCoinControl* coinControl = nullptr,
@@ -67,35 +91,52 @@ const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint&
std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<COutput>& outputs, const CoinSelectionParams& coin_sel_params, const CoinEligibilityFilter& filter, bool positive_only);
+/**
+ * Attempt to find a valid input set that preserves privacy by not mixing OutputTypes.
+ * `ChooseSelectionResult()` will be called on each OutputType individually and the best
+ * the solution (according to the waste metric) will be chosen. If a valid input cannot be found from any
+ * single OutputType, fallback to running `ChooseSelectionResult()` over all available coins.
+ *
+ * param@[in] wallet The wallet which provides solving data for the coins
+ * param@[in] nTargetValue The target value
+ * param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
+ * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
+ * param@[in] coin_selection_params Parameters for the coin selection
+ * param@[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType
+ * returns If successful, a SelectionResult containing the input set
+ * If failed, a nullopt
+ */
+std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
+ const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types);
/**
* Attempt to find a valid input set that meets the provided eligibility filter and target.
* Multiple coin selection algorithms will be run and the input set that produces the least waste
* (according to the waste metric) will be chosen.
*
- * param@[in] wallet The wallet which provides solving data for the coins
- * param@[in] nTargetValue The target value
- * param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
- * param@[in] coins The vector of coins available for selection prior to filtering
- * param@[in] coin_selection_params Parameters for the coin selection
- * returns If successful, a SelectionResult containing the input set
- * If failed, a nullopt
+ * param@[in] wallet The wallet which provides solving data for the coins
+ * param@[in] nTargetValue The target value
+ * param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
+ * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
+ * param@[in] coin_selection_params Parameters for the coin selection
+ * returns If successful, a SelectionResult containing the input set
+ * If failed, a nullopt
*/
-std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins,
+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);
/**
* Select a set of coins such that nTargetValue is met and at least
* all coins from coin_control are selected; never select unconfirmed coins if they are not ours
* param@[in] wallet The wallet which provides data necessary to spend the selected coins
- * param@[in] vAvailableCoins The vector of coins available to be spent
+ * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
* param@[in] nTargetValue The target value
* param@[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
* and whether to subtract the fee from the outputs.
* returns If successful, a SelectionResult containing the selected coins
* If failed, a nullopt.
*/
-std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, const CCoinControl& coin_control,
+std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control,
const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
struct CreatedTransactionResult
@@ -114,7 +155,7 @@ struct CreatedTransactionResult
* selected by SelectCoins(); Also create the change output, when needed
* @note passing change_pos as -1 will result in setting a random position
*/
-BResult<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, int change_pos, const CCoinControl& coin_control, bool sign = true);
+util::Result<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, int change_pos, const CCoinControl& coin_control, bool sign = true);
/**
* Insert additional inputs into the transaction by
diff --git a/src/wallet/test/availablecoins_tests.cpp b/src/wallet/test/availablecoins_tests.cpp
new file mode 100644
index 0000000000..3356128112
--- /dev/null
+++ b/src/wallet/test/availablecoins_tests.cpp
@@ -0,0 +1,105 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or https://www.opensource.org/licenses/mit-license.php.
+
+#include <validation.h>
+#include <wallet/coincontrol.h>
+#include <wallet/spend.h>
+#include <wallet/test/util.h>
+#include <wallet/test/wallet_test_fixture.h>
+
+#include <boost/test/unit_test.hpp>
+
+namespace wallet {
+BOOST_FIXTURE_TEST_SUITE(availablecoins_tests, WalletTestingSetup)
+class AvailableCoinsTestingSetup : public TestChain100Setup
+{
+public:
+ AvailableCoinsTestingSetup()
+ {
+ CreateAndProcessBlock({}, {});
+ wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey);
+ }
+
+ ~AvailableCoinsTestingSetup()
+ {
+ wallet.reset();
+ }
+ CWalletTx& AddTx(CRecipient recipient)
+ {
+ CTransactionRef tx;
+ CCoinControl dummy;
+ {
+ constexpr int RANDOM_CHANGE_POSITION = -1;
+ auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, dummy);
+ BOOST_CHECK(res);
+ tx = res->tx;
+ }
+ wallet->CommitTransaction(tx, {}, {});
+ CMutableTransaction blocktx;
+ {
+ LOCK(wallet->cs_wallet);
+ blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx);
+ }
+ CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+
+ LOCK(wallet->cs_wallet);
+ wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
+ auto it = wallet->mapWallet.find(tx->GetHash());
+ BOOST_CHECK(it != wallet->mapWallet.end());
+ it->second.m_state = TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/1};
+ return it->second;
+ }
+
+ std::unique_ptr<CWallet> wallet;
+};
+
+BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, AvailableCoinsTestingSetup)
+{
+ CoinsResult available_coins;
+ util::Result<CTxDestination> dest{util::Error{}};
+ LOCK(wallet->cs_wallet);
+
+ // 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);
+
+ // We will create a self transfer for each of the OutputTypes and
+ // verify it is put in the correct bucket after running GetAvailablecoins
+ //
+ // For each OutputType, We expect 2 UTXOs in our wallet following the self transfer:
+ // 1. One UTXO as the recipient
+ // 2. One UTXO from the change, due to payment address matching logic
+
+ // Bech32m
+ dest = wallet->GetNewDestination(OutputType::BECH32M, "");
+ BOOST_ASSERT(dest);
+ AddTx(CRecipient{{GetScriptForDestination(*dest)}, 1 * COIN, /*fSubtractFeeFromAmount=*/true});
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.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);
+
+ // P2SH-SEGWIT
+ dest = wallet->GetNewDestination(OutputType::P2SH_SEGWIT, "");
+ AddTx(CRecipient{{GetScriptForDestination(*dest)}, 3 * COIN, /*fSubtractFeeFromAmount=*/true});
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.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_AUTO_TEST_SUITE_END()
+} // namespace wallet
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index a418105ee1..a4a7216436 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -67,16 +67,14 @@ static void add_coin(const CAmount& nValue, int nInput, CoinSet& set, CAmount fe
set.insert(coin);
}
-static void add_coin(std::vector<COutput>& coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0), int nAge = 6*24, bool fIsFromMe = false, int nInput=0, bool spendable = false)
+static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0), int nAge = 6*24, bool fIsFromMe = false, int nInput =0, bool spendable = false)
{
CMutableTransaction tx;
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
tx.vout.resize(nInput + 1);
tx.vout[nInput].nValue = nValue;
if (spendable) {
- auto op_dest = wallet.GetNewDestination(OutputType::BECH32, "");
- assert(op_dest.HasRes());
- tx.vout[nInput].scriptPubKey = GetScriptForDestination(op_dest.GetObj());
+ tx.vout[nInput].scriptPubKey = GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, "")));
}
uint256 txid = tx.GetHash();
@@ -85,7 +83,7 @@ static void add_coin(std::vector<COutput>& coins, CWallet& wallet, const CAmount
assert(ret.second);
CWalletTx& wtx = (*ret.first).second;
const auto& txout = wtx.tx->vout.at(nInput);
- coins.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.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.
@@ -129,18 +127,18 @@ static CAmount make_hard_case(int utxos, std::vector<COutput>& utxo_pool)
return target;
}
-inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& coins)
+inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& available_coins)
{
static std::vector<OutputGroup> static_groups;
static_groups.clear();
- for (auto& coin : coins) {
+ for (auto& coin : available_coins) {
static_groups.emplace_back();
static_groups.back().Insert(coin, /*ancestors=*/ 0, /*descendants=*/ 0, /*positive_only=*/ false);
}
return static_groups;
}
-inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>& coins, CWallet& wallet, const CoinEligibilityFilter& filter)
+inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>& available_coins, CWallet& wallet, const CoinEligibilityFilter& filter)
{
FastRandomContext rand{};
CoinSelectionParams coin_selection_params{
@@ -155,7 +153,7 @@ inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>
/*avoid_partial=*/ false,
};
static std::vector<OutputGroup> static_groups;
- static_groups = GroupOutputs(wallet, coins, coin_selection_params, filter, /*positive_only=*/false);
+ static_groups = GroupOutputs(wallet, available_coins, coin_selection_params, filter, /*positive_only=*/false);
return static_groups;
}
@@ -307,18 +305,18 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
- add_coin(coins, *wallet, 1, coin_selection_params_bnb.m_effective_feerate);
- coins.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(coins), 1 * CENT, coin_selection_params_bnb.m_cost_of_change));
+ 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));
// Test fees subtracted from output:
- coins.clear();
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate);
- coins.at(0).input_bytes = 40;
+ 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;
coin_selection_params_bnb.m_subtract_fee_outputs = true;
- const auto result9 = SelectCoinsBnB(GroupCoins(coins), 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);
}
@@ -330,16 +328,16 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
- add_coin(coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 2 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ 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(coins.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, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ const auto result10 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(result10);
}
{
@@ -349,52 +347,52 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
// single coin should be selected when effective fee > long term fee
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
- add_coin(coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
expected_result.Clear();
add_coin(10 * CENT, 2, expected_result);
CCoinControl coin_control;
- const auto result11 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ const auto result11 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(EquivalentResult(expected_result, *result11));
- 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);
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(5000);
- add_coin(coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
expected_result.Clear();
add_coin(9 * CENT, 2, expected_result);
add_coin(1 * CENT, 2, expected_result);
- const auto result12 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ const auto result12 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(EquivalentResult(expected_result, *result12));
- coins.clear();
+ available_coins.clear();
// pre selected coin should be selected even if disadvantageous
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
- add_coin(coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
expected_result.Clear();
add_coin(9 * CENT, 2, expected_result);
add_coin(1 * CENT, 2, expected_result);
coin_control.m_allow_other_inputs = true;
- coin_control.Select(coins.at(1).outpoint); // pre select 9 coin
- const auto result13 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ 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));
}
}
@@ -410,175 +408,175 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
// test multiple times to allow for differences in the shuffle order
for (int i = 0; i < RUN_TESTS; i++)
{
- coins.clear();
+ available_coins.clear();
// with an empty wallet we can't even pay one cent
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 1 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.all(), *wallet, filter_standard), 1 * CENT, CENT));
- add_coin(coins, *wallet, 1*CENT, CFeeRate(0), 4); // add a new 1 cent coin
+ 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(coins, *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(coins, *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(coins, *wallet, 2*CENT); // add a mature 2 cent coin
+ 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(coins, *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(coins, *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);
- add_coin(coins, *wallet, 5*CENT); // add a mature 5 cent coin,
- add_coin(coins, *wallet, 10*CENT, CFeeRate(0), 3, true); // a new 10 cent coin sent from one of our own addresses
- add_coin(coins, *wallet, 20*CENT); // and a mature 20 cent coin
+ add_coin(available_coins, *wallet, 5*CENT); // add a mature 5 cent coin,
+ add_coin(available_coins, *wallet, 10*CENT, CFeeRate(0), 3, true); // a new 10 cent coin sent from one of our own addresses
+ add_coin(available_coins, *wallet, 20*CENT); // and a mature 20 cent coin
// 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(coins, *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(coins, *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(coins, *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(coins, *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(coins, *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(coins, *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(coins, *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(coins, *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
- coins.clear();
+ available_coins.clear();
- add_coin(coins, *wallet, 6*CENT);
- add_coin(coins, *wallet, 7*CENT);
- add_coin(coins, *wallet, 8*CENT);
- add_coin(coins, *wallet, 20*CENT);
- add_coin(coins, *wallet, 30*CENT); // now we have 6+7+8+20+30 = 71 cents total
+ add_coin(available_coins, *wallet, 6*CENT);
+ add_coin(available_coins, *wallet, 7*CENT);
+ add_coin(available_coins, *wallet, 8*CENT);
+ add_coin(available_coins, *wallet, 20*CENT);
+ 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(coins, *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(coins, *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(coins, *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);
- add_coin(coins, *wallet, 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total
+ 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(coins, *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);
- add_coin(coins, *wallet, 18*CENT); // now we have 5+6+7+8+18+20+30
+ 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(coins, *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(coins, *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);
// check that the smallest bigger coin is used
- add_coin(coins, *wallet, 1*COIN);
- add_coin(coins, *wallet, 2*COIN);
- add_coin(coins, *wallet, 3*COIN);
- add_coin(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(coins, *wallet, filter_confirmed), 95 * CENT, CENT);
+ add_coin(available_coins, *wallet, 1*COIN);
+ 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);
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(coins, *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
- coins.clear();
- add_coin(coins, *wallet, CENT * 1 / 10);
- add_coin(coins, *wallet, CENT * 2 / 10);
- add_coin(coins, *wallet, CENT * 3 / 10);
- add_coin(coins, *wallet, CENT * 4 / 10);
- add_coin(coins, *wallet, CENT * 5 / 10);
+ 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);
+ add_coin(available_coins, *wallet, CENT * 4 / 10);
+ add_coin(available_coins, *wallet, CENT * 5 / 10);
// 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(coins, *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);
// but if we add a bigger coin, small change is avoided
- add_coin(coins, *wallet, 1111*CENT);
+ 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(coins, *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
// if we add more small coins:
- add_coin(coins, *wallet, CENT * 6 / 10);
- add_coin(coins, *wallet, CENT * 7 / 10);
+ add_coin(available_coins, *wallet, CENT * 6 / 10);
+ add_coin(available_coins, *wallet, CENT * 7 / 10);
// and try again to make 1.0 * CENT
- const auto result18 = KnapsackSolver(KnapsackGroupOutputs(coins, *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
- coins.clear();
+ available_coins.clear();
for (int j = 0; j < 20; j++)
- add_coin(coins, *wallet, 50000 * COIN);
+ add_coin(available_coins, *wallet, 50000 * COIN);
- const auto result19 = KnapsackSolver(KnapsackGroupOutputs(coins, *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
@@ -587,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:
- coins.clear();
- add_coin(coins, *wallet, CENT * 5 / 10);
- add_coin(coins, *wallet, CENT * 6 / 10);
- add_coin(coins, *wallet, CENT * 7 / 10);
- add_coin(coins, *wallet, 1111 * CENT);
- const auto result20 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 1 * CENT, CENT);
+ 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);
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)
- coins.clear();
- add_coin(coins, *wallet, CENT * 4 / 10);
- add_coin(coins, *wallet, CENT * 6 / 10);
- add_coin(coins, *wallet, CENT * 8 / 10);
- add_coin(coins, *wallet, 1111 * CENT);
- const auto result21 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), CENT, CENT);
+ 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);
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
- coins.clear();
- add_coin(coins, *wallet, CENT * 5 / 100);
- add_coin(coins, *wallet, CENT * 1);
- add_coin(coins, *wallet, CENT * 100);
+ 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(coins, *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(coins, *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);
@@ -629,14 +627,14 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// test with many inputs
for (CAmount amt=1500; amt < COIN; amt*=10) {
- 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(coins, *wallet, amt);
+ 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(coins, *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) {
@@ -655,17 +653,17 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// test randomness
{
- coins.clear();
+ available_coins.clear();
for (int i2 = 0; i2 < 100; i2++)
- add_coin(coins, *wallet, COIN);
+ add_coin(available_coins, *wallet, COIN);
// Again, 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++) {
// 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(coins), 50 * COIN, CENT);
+ const auto result25 = KnapsackSolver(GroupCoins(available_coins.all()), 50 * COIN, CENT);
BOOST_CHECK(result25);
- const auto result26 = KnapsackSolver(GroupCoins(coins), 50 * COIN, CENT);
+ const auto result26 = KnapsackSolver(GroupCoins(available_coins.all()), 50 * COIN, CENT);
BOOST_CHECK(result26);
BOOST_CHECK(!EqualResult(*result25, *result26));
@@ -676,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(coins), COIN, CENT);
+ const auto result27 = KnapsackSolver(GroupCoins(available_coins.all()), COIN, CENT);
BOOST_CHECK(result27);
- const auto result28 = KnapsackSolver(GroupCoins(coins), COIN, CENT);
+ const auto result28 = KnapsackSolver(GroupCoins(available_coins.all()), COIN, CENT);
BOOST_CHECK(result28);
if (EqualResult(*result27, *result28))
fails++;
@@ -689,19 +687,19 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// add 75 cents in small change. not enough to make 90 cents,
// then try making 90 cents. there are multiple competing "smallest bigger" coins,
// one of which should be picked at random
- add_coin(coins, *wallet, 5 * CENT);
- add_coin(coins, *wallet, 10 * CENT);
- add_coin(coins, *wallet, 15 * CENT);
- add_coin(coins, *wallet, 20 * CENT);
- add_coin(coins, *wallet, 25 * CENT);
+ add_coin(available_coins, *wallet, 5 * CENT);
+ add_coin(available_coins, *wallet, 10 * CENT);
+ add_coin(available_coins, *wallet, 15 * CENT);
+ add_coin(available_coins, *wallet, 20 * CENT);
+ add_coin(available_coins, *wallet, 25 * CENT);
for (int i = 0; i < RUN_TESTS; i++) {
int fails = 0;
for (int j = 0; j < RANDOM_REPEATS; j++)
{
- const auto result29 = KnapsackSolver(GroupCoins(coins), 90 * CENT, CENT);
+ const auto result29 = KnapsackSolver(GroupCoins(available_coins.all()), 90 * CENT, CENT);
BOOST_CHECK(result29);
- const auto result30 = KnapsackSolver(GroupCoins(coins), 90 * CENT, CENT);
+ const auto result30 = KnapsackSolver(GroupCoins(available_coins.all()), 90 * CENT, CENT);
BOOST_CHECK(result30);
if (EqualResult(*result29, *result30))
fails++;
@@ -720,14 +718,14 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
// Test vValue sort order
for (int i = 0; i < 1000; i++)
- add_coin(coins, *wallet, 1000 * COIN);
- add_coin(coins, *wallet, 3 * COIN);
+ add_coin(available_coins, *wallet, 1000 * COIN);
+ add_coin(available_coins, *wallet, 3 * COIN);
- const auto result = KnapsackSolver(KnapsackGroupOutputs(coins, *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);
@@ -750,14 +748,14 @@ BOOST_AUTO_TEST_CASE(SelectCoins_test)
// Run this test 100 times
for (int i = 0; i < 100; ++i)
{
- std::vector<COutput> coins;
+ CoinsResult available_coins;
CAmount balance{0};
// Make a wallet with 1000 exponentially distributed random inputs
for (int j = 0; j < 1000; ++j)
{
CAmount val = distribution(generator)*10000000;
- add_coin(coins, *wallet, val);
+ add_coin(available_coins, *wallet, val);
balance += val;
}
@@ -780,7 +778,7 @@ BOOST_AUTO_TEST_CASE(SelectCoins_test)
/*avoid_partial=*/ false,
};
CCoinControl cc;
- const auto result = SelectCoins(*wallet, coins, target, cc, cs_params);
+ const auto result = SelectCoins(*wallet, available_coins, target, cc, cs_params);
BOOST_CHECK(result);
BOOST_CHECK_GE(result->GetSelectedValue(), target);
}
diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp
index 5c173773e4..5e9cd4001b 100644
--- a/src/wallet/test/fuzz/notifications.cpp
+++ b/src/wallet/test/fuzz/notifications.cpp
@@ -69,14 +69,13 @@ struct FuzzedWallet {
CScript GetScriptPubKey(FuzzedDataProvider& fuzzed_data_provider)
{
auto type{fuzzed_data_provider.PickValueInArray(OUTPUT_TYPES)};
- BResult<CTxDestination> op_dest;
+ util::Result<CTxDestination> op_dest{util::Error{}};
if (fuzzed_data_provider.ConsumeBool()) {
op_dest = wallet->GetNewDestination(type, "");
} else {
op_dest = wallet->GetNewChangeDestination(type);
}
- assert(op_dest.HasRes());
- return GetScriptForDestination(op_dest.GetObj());
+ return GetScriptForDestination(*Assert(op_dest));
}
};
diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp
index 53c3b5d2ae..dc935a1a04 100644
--- a/src/wallet/test/spend_tests.cpp
+++ b/src/wallet/test/spend_tests.cpp
@@ -35,7 +35,7 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
coin_control.m_change_type = OutputType::LEGACY;
auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, coin_control);
BOOST_CHECK(res);
- const auto& txr = res.GetObj();
+ const auto& txr = *res;
BOOST_CHECK_EQUAL(txr.tx->vout.size(), 1);
BOOST_CHECK_EQUAL(txr.tx->vout[0].nValue, recipient.nAmount + leftover_input_amount - txr.fee);
BOOST_CHECK_GT(txr.fee, 0);
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 7377a36f5e..093f510945 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -536,7 +536,7 @@ public:
constexpr int RANDOM_CHANGE_POSITION = -1;
auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, dummy);
BOOST_CHECK(res);
- tx = res.GetObj().tx;
+ tx = res->tx;
}
wallet->CommitTransaction(tx, {}, {});
CMutableTransaction blocktx;
@@ -591,7 +591,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).coins.size(), 2U);
+ BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).size(), 2U);
}
for (const auto& group : list) {
for (const auto& coin : group.second) {
@@ -601,7 +601,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
}
{
LOCK(wallet->cs_wallet);
- BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).coins.size(), 0U);
+ BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).size(), 0U);
}
// Confirm ListCoins still returns same result as before, despite coins
// being locked.
@@ -843,21 +843,126 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
auto block_hash = block_tx.GetHash();
- auto prev_hash = m_coinbase_txns[0]->GetHash();
+ auto prev_tx = m_coinbase_txns[0];
LOCK(wallet->cs_wallet);
- BOOST_CHECK(wallet->HasWalletSpend(prev_hash));
+ BOOST_CHECK(wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 1u);
std::vector<uint256> vHashIn{ block_hash }, vHashOut;
BOOST_CHECK_EQUAL(wallet->ZapSelectTx(vHashIn, vHashOut), DBErrors::LOAD_OK);
- BOOST_CHECK(!wallet->HasWalletSpend(prev_hash));
+ BOOST_CHECK(!wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 0u);
}
TestUnloadWallet(std::move(wallet));
}
+/** RAII class that provides access to a FailDatabase. Which fails if needed. */
+class FailBatch : public DatabaseBatch
+{
+private:
+ bool m_pass{true};
+ bool ReadKey(CDataStream&& key, CDataStream& value) override { return m_pass; }
+ bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return m_pass; }
+ bool EraseKey(CDataStream&& key) override { return m_pass; }
+ bool HasKey(CDataStream&& key) override { return m_pass; }
+
+public:
+ explicit FailBatch(bool pass) : m_pass(pass) {}
+ void Flush() override {}
+ void Close() override {}
+
+ bool StartCursor() override { return true; }
+ bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return false; }
+ void CloseCursor() override {}
+ bool TxnBegin() override { return false; }
+ bool TxnCommit() override { return false; }
+ bool TxnAbort() override { return false; }
+};
+
+/** A dummy WalletDatabase that does nothing, only fails if needed.**/
+class FailDatabase : public WalletDatabase
+{
+public:
+ bool m_pass{true}; // false when this db should fail
+
+ void Open() override {};
+ void AddRef() override {}
+ void RemoveRef() override {}
+ bool Rewrite(const char* pszSkip=nullptr) override { return true; }
+ bool Backup(const std::string& strDest) const override { return true; }
+ void Close() override {}
+ void Flush() override {}
+ bool PeriodicFlush() override { return true; }
+ void IncrementUpdateCounter() override { ++nUpdateCounter; }
+ void ReloadDbEnv() override {}
+ std::string Filename() override { return "faildb"; }
+ std::string Format() override { return "faildb"; }
+ std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override { return std::make_unique<FailBatch>(m_pass); }
+};
+
+/**
+ * Checks a wallet invalid state where the inputs (prev-txs) of a new arriving transaction are not marked dirty,
+ * while the transaction that spends them exist inside the in-memory wallet tx map (not stored on db due a db write failure).
+ */
+BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
+{
+ CWallet wallet(m_node.chain.get(), "", m_args, std::make_unique<FailDatabase>());
+ {
+ LOCK(wallet.cs_wallet);
+ wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ wallet.SetupDescriptorScriptPubKeyMans();
+ }
+
+ // Add tx to wallet
+ const auto& op_dest = wallet.GetNewDestination(OutputType::BECH32M, "");
+ BOOST_ASSERT(op_dest);
+
+ CMutableTransaction mtx;
+ mtx.vout.push_back({COIN, GetScriptForDestination(*op_dest)});
+ mtx.vin.push_back(CTxIn(g_insecure_rand_ctx.rand256(), 0));
+ const auto& tx_id_to_spend = wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInMempool{})->GetHash();
+
+ {
+ // Cache and verify available balance for the wtx
+ LOCK(wallet.cs_wallet);
+ const CWalletTx* wtx_to_spend = wallet.GetWalletTx(tx_id_to_spend);
+ BOOST_CHECK_EQUAL(CachedTxGetAvailableCredit(wallet, *wtx_to_spend), 1 * COIN);
+ }
+
+ // Now the good case:
+ // 1) Add a transaction that spends the previously created transaction
+ // 2) Verify that the available balance of this new tx and the old one is updated (prev tx is marked dirty)
+
+ mtx.vin.clear();
+ mtx.vin.push_back(CTxIn(tx_id_to_spend, 0));
+ wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0);
+ const uint256& good_tx_id = mtx.GetHash();
+
+ {
+ // Verify balance update for the new tx and the old one
+ LOCK(wallet.cs_wallet);
+ const CWalletTx* new_wtx = wallet.GetWalletTx(good_tx_id);
+ BOOST_CHECK_EQUAL(CachedTxGetAvailableCredit(wallet, *new_wtx), 1 * COIN);
+
+ // Now the old wtx
+ const CWalletTx* wtx_to_spend = wallet.GetWalletTx(tx_id_to_spend);
+ BOOST_CHECK_EQUAL(CachedTxGetAvailableCredit(wallet, *wtx_to_spend), 0 * COIN);
+ }
+
+ // Now the bad case:
+ // 1) Make db always fail
+ // 2) Try to add a transaction that spends the previously created transaction and
+ // verify that we are not moving forward if the wallet cannot store it
+ static_cast<FailDatabase&>(wallet.GetDatabase()).m_pass = false;
+ mtx.vin.clear();
+ mtx.vin.push_back(CTxIn(good_tx_id, 0));
+ BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0),
+ std::runtime_error,
+ HasReason("DB error adding transaction to wallet, write failed"));
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 54a3221e2d..de1078e646 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -414,7 +414,7 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& b
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
{
AssertLockHeld(cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
+ const auto it = mapWallet.find(hash);
if (it == mapWallet.end())
return nullptr;
return &(it->second);
@@ -551,7 +551,7 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
std::set<uint256> result;
AssertLockHeld(cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
+ const auto it = mapWallet.find(txid);
if (it == mapWallet.end())
return result;
const CWalletTx& wtx = it->second;
@@ -569,11 +569,17 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
return result;
}
-bool CWallet::HasWalletSpend(const uint256& txid) const
+bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
{
AssertLockHeld(cs_wallet);
- auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
- return (iter != mapTxSpends.end() && iter->first.hash == txid);
+ const uint256& txid = tx->GetHash();
+ for (unsigned int i = 0; i < tx->vout.size(); ++i) {
+ auto iter = mapTxSpends.find(COutPoint(txid, i));
+ if (iter != mapTxSpends.end()) {
+ return true;
+ }
+ }
+ return false;
}
void CWallet::Flush()
@@ -636,7 +642,7 @@ bool CWallet::IsSpent(const COutPoint& outpoint) const
for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
const uint256& wtxid = it->second;
- std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
+ const auto mit = mapWallet.find(wtxid);
if (mit != mapWallet.end()) {
int depth = GetTxDepthInMainChain(mit->second);
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
@@ -1130,7 +1136,13 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const SyncTxS
// Block disconnection override an abandoned tx as unconfirmed
// which means user may have to call abandontransaction again
TxState tx_state = std::visit([](auto&& s) -> TxState { return s; }, state);
- return AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, rescanning_old_block);
+ CWalletTx* wtx = AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, rescanning_old_block);
+ if (!wtx) {
+ // Can only be nullptr if there was a db write error (missing db, read-only db or a db engine internal writing error).
+ // As we only store arriving transaction in this process, and we don't want an inconsistent state, let's throw an error.
+ throw std::runtime_error("DB error adding transaction to wallet, write failed");
+ }
+ return true;
}
}
return false;
@@ -1191,12 +1203,13 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
batch.WriteTx(wtx);
NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
// Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
- TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
- while (iter != mapTxSpends.end() && iter->first.hash == now) {
- if (!done.count(iter->second)) {
- todo.insert(iter->second);
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
+ for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
+ if (!done.count(iter->second)) {
+ todo.insert(iter->second);
+ }
}
- iter++;
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
@@ -1242,12 +1255,13 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
wtx.MarkDirty();
batch.WriteTx(wtx);
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
- TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
- while (iter != mapTxSpends.end() && iter->first.hash == now) {
- if (!done.count(iter->second)) {
- todo.insert(iter->second);
- }
- iter++;
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
+ for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
+ if (!done.count(iter->second)) {
+ todo.insert(iter->second);
+ }
+ }
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
@@ -1364,7 +1378,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
{
{
LOCK(cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
+ const auto mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
@@ -1953,7 +1967,7 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const
// Build coins map
std::map<COutPoint, Coin> coins;
for (auto& input : tx.vin) {
- std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
+ const auto mi = mapWallet.find(input.prevout.hash);
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
return false;
}
@@ -2324,36 +2338,32 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
return res;
}
-BResult<CTxDestination> CWallet::GetNewDestination(const OutputType type, const std::string label)
+util::Result<CTxDestination> CWallet::GetNewDestination(const OutputType type, const std::string label)
{
LOCK(cs_wallet);
auto spk_man = GetScriptPubKeyMan(type, false /* internal */);
if (!spk_man) {
- return strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
+ return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
}
spk_man->TopUp();
auto op_dest = spk_man->GetNewDestination(type);
if (op_dest) {
- SetAddressBook(op_dest.GetObj(), label, "receive");
+ SetAddressBook(*op_dest, label, "receive");
}
return op_dest;
}
-BResult<CTxDestination> CWallet::GetNewChangeDestination(const OutputType type)
+util::Result<CTxDestination> CWallet::GetNewChangeDestination(const OutputType type)
{
LOCK(cs_wallet);
- CTxDestination dest;
- bilingual_str error;
ReserveDestination reservedest(this, type);
- if (!reservedest.GetReservedDestination(dest, true, error)) {
- return error;
- }
+ auto op_dest = reservedest.GetReservedDestination(true);
+ if (op_dest) reservedest.KeepDestination();
- reservedest.KeepDestination();
- return dest;
+ return op_dest;
}
std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
@@ -2423,27 +2433,24 @@ std::set<std::string> CWallet::ListAddrBookLabels(const std::string& purpose) co
return label_set;
}
-bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, bilingual_str& error)
+util::Result<CTxDestination> ReserveDestination::GetReservedDestination(bool internal)
{
m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
if (!m_spk_man) {
- error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
- return false;
+ return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
}
-
if (nIndex == -1)
{
m_spk_man->TopUp();
CKeyPool keypool;
- if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool, error)) {
- return false;
- }
+ auto op_address = m_spk_man->GetReservedDestination(type, internal, nIndex, keypool);
+ if (!op_address) return op_address;
+ address = *op_address;
fInternal = keypool.fInternal;
}
- dest = address;
- return true;
+ return address;
}
void ReserveDestination::KeepDestination()
@@ -3470,7 +3477,7 @@ void CWallet::LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool intern
// Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
- WalletLogPrintf("Setting spkMan to active: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
+ WalletLogPrintf("Setting spkMan to active: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
auto spk_man = m_spk_managers.at(id).get();
@@ -3488,7 +3495,7 @@ void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool intern
{
auto spk_man = GetScriptPubKeyMan(type, internal);
if (spk_man != nullptr && spk_man->GetID() == id) {
- WalletLogPrintf("Deactivate spkMan: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
+ WalletLogPrintf("Deactivate spkMan: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
WalletBatch batch(GetDatabase());
if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 15f5917040..cf33ea21f2 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -14,6 +14,7 @@
#include <policy/feerate.h>
#include <psbt.h>
#include <tinyformat.h>
+#include <util/hasher.h>
#include <util/message.h>
#include <util/result.h>
#include <util/strencodings.h>
@@ -37,6 +38,7 @@
#include <stdint.h>
#include <string>
#include <utility>
+#include <unordered_map>
#include <vector>
#include <boost/signals2/signal.hpp>
@@ -99,7 +101,7 @@ static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS{true};
//! -txconfirmtarget default
static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
//! -walletrbf default
-static const bool DEFAULT_WALLET_RBF = false;
+static const bool DEFAULT_WALLET_RBF = true;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;
static const bool DEFAULT_WALLETCROSSCHAIN = false;
@@ -189,7 +191,7 @@ public:
}
//! Reserve an address
- bool GetReservedDestination(CTxDestination& pubkey, bool internal, bilingual_str& error);
+ util::Result<CTxDestination> GetReservedDestination(bool internal);
//! Return reserved address
void ReturnDestination();
//! Keep the address. Do not return it's key to the keypool when this object goes out of scope
@@ -259,7 +261,7 @@ private:
* detect and report conflicts (double-spends or
* mutated transactions where the mutant gets mined).
*/
- typedef std::multimap<COutPoint, uint256> TxSpends;
+ typedef std::unordered_multimap<COutPoint, uint256, SaltedOutpointHasher> TxSpends;
TxSpends mapTxSpends GUARDED_BY(cs_wallet);
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void AddToSpends(const CWalletTx& wtx, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -390,7 +392,7 @@ public:
/** Map from txid to CWalletTx for all transactions this wallet is
* interested in, including received and sent transactions. */
- std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
+ std::unordered_map<uint256, CWalletTx, SaltedTxidHasher> mapWallet GUARDED_BY(cs_wallet);
typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems wtxOrdered;
@@ -505,6 +507,10 @@ public:
//! @return true if wtx is changed and needs to be saved to disk, otherwise false
using UpdateWalletTxFn = std::function<bool(CWalletTx& wtx, bool new_tx)>;
+ /**
+ * Add the transaction to the wallet, wrapping it up inside a CWalletTx
+ * @return the recently added wtx pointer or nullptr if there was a db write error.
+ */
CWalletTx* AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block = false);
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override;
@@ -666,8 +672,8 @@ public:
*/
void MarkDestinationsDirty(const std::set<CTxDestination>& destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- BResult<CTxDestination> GetNewDestination(const OutputType type, const std::string label);
- BResult<CTxDestination> GetNewChangeDestination(const OutputType type);
+ util::Result<CTxDestination> GetNewDestination(const OutputType type, const std::string label);
+ util::Result<CTxDestination> GetNewChangeDestination(const OutputType type);
isminetype IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
isminetype IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -708,7 +714,7 @@ public:
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
- bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool HasWalletSpend(const CTransactionRef& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Flush wallet (bitdb flush)
void Flush();