aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.bear-tidy-config2
-rw-r--r--src/.clang-tidy2
-rw-r--r--src/Makefile.qt.include7
-rw-r--r--src/addrman.cpp2
-rw-r--r--src/bench/block_assemble.cpp2
-rw-r--r--src/bench/disconnected_transactions.cpp4
-rw-r--r--src/bench/wallet_loading.cpp4
-rw-r--r--src/chain.h4
-rw-r--r--src/coins.cpp16
-rw-r--r--src/coins.h1
-rw-r--r--src/common/args.cpp2
-rw-r--r--src/external_signer.cpp2
-rw-r--r--src/headerssync.cpp6
-rw-r--r--src/httpserver.cpp12
-rw-r--r--src/init.cpp13
-rw-r--r--src/kernel/chainparams.cpp42
-rw-r--r--src/net_permissions.cpp14
-rw-r--r--src/net_processing.cpp52
-rw-r--r--src/net_processing.h3
-rw-r--r--src/node/blockstorage.cpp10
-rw-r--r--src/node/chainstate.cpp2
-rw-r--r--src/node/interfaces.cpp2
-rw-r--r--src/node/utxo_snapshot.h3
-rw-r--r--src/policy/fees.cpp5
-rw-r--r--src/policy/fees.h4
-rw-r--r--src/policy/packages.cpp15
-rw-r--r--src/policy/packages.h4
-rw-r--r--src/psbt.cpp2
-rw-r--r--src/psbt.h2
-rw-r--r--src/pubkey.cpp7
-rw-r--r--src/pubkey.h8
-rw-r--r--src/qt/android/gradle.properties4
-rw-r--r--src/qt/bitcoingui.cpp44
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/bitcoinstrings.cpp10
-rw-r--r--src/qt/coincontroldialog.cpp14
-rw-r--r--src/qt/createwalletdialog.cpp20
-rw-r--r--src/qt/createwalletdialog.h1
-rw-r--r--src/qt/forms/createwalletdialog.ui72
-rw-r--r--src/qt/locale/bitcoin_en.ts315
-rw-r--r--src/qt/locale/bitcoin_en.xlf3181
-rw-r--r--src/qt/rpcconsole.cpp8
-rw-r--r--src/qt/walletcontroller.cpp5
-rw-r--r--src/rest.cpp2
-rw-r--r--src/rpc/blockchain.cpp44
-rw-r--r--src/rpc/mempool.cpp14
-rw-r--r--src/rpc/net.cpp98
-rw-r--r--src/rpc/rawtransaction.cpp8
-rw-r--r--src/rpc/server.cpp2
-rw-r--r--src/rpc/server_util.cpp13
-rw-r--r--src/rpc/server_util.h3
-rw-r--r--src/script/bitcoinconsensus.cpp42
-rw-r--r--src/script/bitcoinconsensus.h19
-rw-r--r--src/script/descriptor.cpp141
-rw-r--r--src/script/miniscript.cpp34
-rw-r--r--src/script/miniscript.h668
-rw-r--r--src/script/sign.cpp284
-rw-r--r--src/script/sign.h1
-rw-r--r--src/script/signingprovider.cpp4
-rw-r--r--src/serialize.h2
-rw-r--r--src/test/addrman_tests.cpp4
-rw-r--r--src/test/bip32_tests.cpp2
-rw-r--r--src/test/descriptor_tests.cpp88
-rw-r--r--src/test/fuzz/chain.cpp2
-rw-r--r--src/test/fuzz/fees.cpp3
-rw-r--r--src/test/fuzz/mini_miner.cpp20
-rw-r--r--src/test/fuzz/miniscript.cpp348
-rw-r--r--src/test/fuzz/script_bitcoin_consensus.cpp19
-rw-r--r--src/test/headers_sync_chainwork_tests.cpp2
-rw-r--r--src/test/miniscript_tests.cpp447
-rw-r--r--src/test/net_tests.cpp4
-rw-r--r--src/test/policy_fee_tests.cpp3
-rw-r--r--src/test/rbf_tests.cpp2
-rw-r--r--src/test/rpc_tests.cpp38
-rw-r--r--src/test/script_tests.cpp65
-rw-r--r--src/test/settings_tests.cpp16
-rw-r--r--src/test/sighash_tests.cpp4
-rw-r--r--src/test/sigopcount_tests.cpp20
-rw-r--r--src/test/txpackage_tests.cpp53
-rw-r--r--src/test/util/setup_common.cpp11
-rw-r--r--src/test/util_tests.cpp4
-rw-r--r--src/test/util_threadnames_tests.cpp2
-rw-r--r--src/test/validation_block_tests.cpp4
-rw-r--r--src/test/validation_tests.cpp4
-rw-r--r--src/txmempool.cpp2
-rw-r--r--src/validation.cpp48
-rw-r--r--src/validation.h20
-rw-r--r--src/wallet/rpc/backup.cpp6
-rw-r--r--src/wallet/rpc/wallet.cpp9
-rw-r--r--src/wallet/salvage.cpp2
-rw-r--r--src/wallet/scriptpubkeyman.cpp8
-rw-r--r--src/wallet/spend.cpp2
-rw-r--r--src/wallet/test/wallet_tests.cpp10
-rw-r--r--src/wallet/transaction.h11
-rw-r--r--src/wallet/wallet.cpp6
95 files changed, 3969 insertions, 2629 deletions
diff --git a/src/.bear-tidy-config b/src/.bear-tidy-config
index 9b6b9d2cf7..0ab30a8d9d 100644
--- a/src/.bear-tidy-config
+++ b/src/.bear-tidy-config
@@ -8,6 +8,8 @@
"src/crypto/ctaes",
"src/leveldb",
"src/minisketch",
+ "src/bench/nanobench.cpp",
+ "src/bench/nanobench.h",
"src/secp256k1"
]
},
diff --git a/src/.clang-tidy b/src/.clang-tidy
index 4deb5a85a5..0318bd01ce 100644
--- a/src/.clang-tidy
+++ b/src/.clang-tidy
@@ -5,9 +5,11 @@ bugprone-argument-comment,
bugprone-use-after-move,
misc-unused-using-decls,
modernize-use-default-member-init,
+modernize-use-emplace,
modernize-use-noexcept,
modernize-use-nullptr,
performance-*,
+-performance-avoid-endl,
-performance-inefficient-string-concatenation,
-performance-no-int-to-ptr,
-performance-noexcept-move-constructor,
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 7852d1a2fa..c235c3c4da 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -358,11 +358,14 @@ SECONDARY: $(QT_QM)
$(srcdir)/qt/bitcoinstrings.cpp: FORCE
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
- $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $(libbitcoin_node_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES)
+ $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py \
+ $(libbitcoin_node_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) \
+ $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES) \
+ $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
# The resulted bitcoin_en.xlf source file should follow Transifex requirements.
# See: https://docs.transifex.com/formats/xliff#how-to-distinguish-between-a-source-file-and-a-translation-file
-translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) qt/bitcoin.cpp $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
+translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) -no-obsolete -I $(srcdir) -locations relative $^ -ts $(srcdir)/qt/locale/bitcoin_en.ts
@test -n $(LCONVERT) || echo "lconvert is required for updating translations"
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 6ce9c81c63..b001365ab3 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -854,7 +854,7 @@ std::vector<std::pair<AddrInfo, AddressPosition>> AddrManImpl::GetEntries_(bool
/*multiplicity_in=*/from_tried ? 1 : info.nRefCount,
bucket,
position);
- infos.push_back(std::make_pair(info, location));
+ infos.emplace_back(info, location);
}
}
}
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 0737144b84..ba8ec16119 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -28,7 +28,7 @@ static void AssembleBlock(benchmark::Bench& bench)
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
CMutableTransaction tx;
- tx.vin.push_back(CTxIn{MineBlock(test_setup->m_node, P2WSH_OP_TRUE)});
+ tx.vin.emplace_back(MineBlock(test_setup->m_node, P2WSH_OP_TRUE));
tx.vin.back().scriptWitness = witness;
tx.vout.emplace_back(1337, P2WSH_OP_TRUE);
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
diff --git a/src/bench/disconnected_transactions.cpp b/src/bench/disconnected_transactions.cpp
index 0a7344b248..264c0aa1e8 100644
--- a/src/bench/disconnected_transactions.cpp
+++ b/src/bench/disconnected_transactions.cpp
@@ -36,8 +36,8 @@ static BlockTxns CreateRandomTransactions(size_t num_txns)
CScript spk = CScript() << OP_TRUE;
for (uint32_t i = 0; i < num_txns; ++i) {
CMutableTransaction tx;
- tx.vin.emplace_back(CTxIn{COutPoint{prevout_hash, 0}});
- tx.vout.emplace_back(CTxOut{CENT, spk});
+ tx.vin.emplace_back(COutPoint{prevout_hash, 0});
+ tx.vout.emplace_back(CENT, spk);
auto ptx{MakeTransactionRef(tx)};
txns.emplace_back(ptx);
prevout_hash = ptx->GetHash();
diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
index 5453238728..b17c7fe05a 100644
--- a/src/bench/wallet_loading.cpp
+++ b/src/bench/wallet_loading.cpp
@@ -20,8 +20,8 @@ namespace wallet{
static void AddTx(CWallet& wallet)
{
CMutableTransaction mtx;
- mtx.vout.push_back({COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, "")))});
- mtx.vin.push_back(CTxIn());
+ mtx.vout.emplace_back(COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, ""))));
+ mtx.vin.emplace_back();
wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{});
}
diff --git a/src/chain.h b/src/chain.h
index 78b06719f4..4bf2001f74 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -280,10 +280,8 @@ public:
* Note that this will be true for the snapshot base block, if one is loaded (and
* all subsequent assumed-valid blocks) since its nChainTx value will have been set
* manually based on the related AssumeutxoData entry.
- *
- * TODO: potentially change the name of this based on the fact above.
*/
- bool HaveTxsDownloaded() const { return nChainTx != 0; }
+ bool HaveNumChainTxs() const { return nChainTx != 0; }
NodeSeconds Time() const
{
diff --git a/src/coins.cpp b/src/coins.cpp
index 0fe642e46b..b44d920ee1 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -353,11 +353,13 @@ const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
return coinEmpty;
}
-bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const {
+template <typename Func>
+static bool ExecuteBackedWrapper(Func func, const std::vector<std::function<void()>>& err_callbacks)
+{
try {
- return CCoinsViewBacked::GetCoin(outpoint, coin);
+ return func();
} catch(const std::runtime_error& e) {
- for (const auto& f : m_err_callbacks) {
+ for (const auto& f : err_callbacks) {
f();
}
LogPrintf("Error reading from database: %s\n", e.what());
@@ -368,3 +370,11 @@ bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) cons
std::abort();
}
}
+
+bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const {
+ return ExecuteBackedWrapper([&]() { return CCoinsViewBacked::GetCoin(outpoint, coin); }, m_err_callbacks);
+}
+
+bool CCoinsViewErrorCatcher::HaveCoin(const COutPoint &outpoint) const {
+ return ExecuteBackedWrapper([&]() { return CCoinsViewBacked::HaveCoin(outpoint); }, m_err_callbacks);
+}
diff --git a/src/coins.h b/src/coins.h
index 039a07054d..a6cbb03133 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -383,6 +383,7 @@ public:
}
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
+ bool HaveCoin(const COutPoint &outpoint) const override;
private:
/** A list of callbacks to execute upon leveldb read error. */
diff --git a/src/common/args.cpp b/src/common/args.cpp
index 643838399f..ca04175696 100644
--- a/src/common/args.cpp
+++ b/src/common/args.cpp
@@ -216,7 +216,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
m_command.push_back(key);
while (++i < argc) {
// The remaining args are command args
- m_command.push_back(argv[i]);
+ m_command.emplace_back(argv[i]);
}
break;
}
diff --git a/src/external_signer.cpp b/src/external_signer.cpp
index 6b1e1f0241..102c58b56a 100644
--- a/src/external_signer.cpp
+++ b/src/external_signer.cpp
@@ -54,7 +54,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
if (model_field.isStr() && model_field.getValStr() != "") {
name += model_field.getValStr();
}
- signers.push_back(ExternalSigner(command, chain, fingerprintStr, name));
+ signers.emplace_back(command, chain, fingerprintStr, name);
}
return true;
}
diff --git a/src/headerssync.cpp b/src/headerssync.cpp
index 1b5d7305e8..234fc8da60 100644
--- a/src/headerssync.cpp
+++ b/src/headerssync.cpp
@@ -13,11 +13,11 @@
// contrib/devtools/headerssync-params.py.
//! Store one header commitment per HEADER_COMMITMENT_PERIOD blocks.
-constexpr size_t HEADER_COMMITMENT_PERIOD{600};
+constexpr size_t HEADER_COMMITMENT_PERIOD{606};
//! Only feed headers to validation once this many headers on top have been
//! received and validated against commitments.
-constexpr size_t REDOWNLOAD_BUFFER_SIZE{14308}; // 14308/600 = ~23.8 commitments
+constexpr size_t REDOWNLOAD_BUFFER_SIZE{14441}; // 14441/606 = ~23.8 commitments
// Our memory analysis assumes 48 bytes for a CompressedHeader (so we should
// re-calculate parameters if we compress further)
@@ -271,7 +271,7 @@ bool HeadersSyncState::ValidateAndStoreRedownloadedHeader(const CBlockHeader& he
}
// Store this header for later processing.
- m_redownloaded_headers.push_back(header);
+ m_redownloaded_headers.emplace_back(header);
m_redownload_buffer_last_height = next_height;
m_redownload_buffer_last_hash = header.GetHash();
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index eb3f4a1c2b..647e36adb3 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -221,8 +221,8 @@ static bool ClientAllowed(const CNetAddr& netaddr)
static bool InitHTTPAllowList()
{
rpc_allow_subnets.clear();
- rpc_allow_subnets.push_back(CSubNet{LookupHost("127.0.0.1", false).value(), 8}); // always allow IPv4 local subnet
- rpc_allow_subnets.push_back(CSubNet{LookupHost("::1", false).value()}); // always allow IPv6 localhost
+ rpc_allow_subnets.emplace_back(LookupHost("127.0.0.1", false).value(), 8); // always allow IPv4 local subnet
+ rpc_allow_subnets.emplace_back(LookupHost("::1", false).value()); // always allow IPv6 localhost
for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) {
CSubNet subnet;
LookupSubNet(strAllow, subnet);
@@ -364,8 +364,8 @@ static bool HTTPBindAddresses(struct evhttp* http)
// Determine what addresses to bind to
if (!(gArgs.IsArgSet("-rpcallowip") && gArgs.IsArgSet("-rpcbind"))) { // Default to loopback if not allowing external IPs
- endpoints.push_back(std::make_pair("::1", http_port));
- endpoints.push_back(std::make_pair("127.0.0.1", http_port));
+ endpoints.emplace_back("::1", http_port);
+ endpoints.emplace_back("127.0.0.1", http_port);
if (gArgs.IsArgSet("-rpcallowip")) {
LogPrintf("WARNING: option -rpcallowip was specified without -rpcbind; this doesn't usually make sense\n");
}
@@ -377,7 +377,7 @@ static bool HTTPBindAddresses(struct evhttp* http)
uint16_t port{http_port};
std::string host;
SplitHostPort(strRPCBind, port, host);
- endpoints.push_back(std::make_pair(host, port));
+ endpoints.emplace_back(host, port);
}
}
@@ -746,7 +746,7 @@ void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPR
{
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
LOCK(g_httppathhandlers_mutex);
- pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler));
+ pathHandlers.emplace_back(prefix, exactMatch, handler);
}
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
diff --git a/src/init.cpp b/src/init.cpp
index b289851e5d..42331d37e8 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -462,8 +462,8 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
"(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk. This will also rebuild active optional indexes.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks. When in pruning mode or if blocks on disk might be corrupted, use full -reindex instead.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-reindex", "If enabled, wipe chain state and block index, and rebuild them from blk*.dat files on disk. Also wipe and rebuild other optional indexes that are active. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-reindex-chainstate", "If enabled, wipe chain state, and rebuild it from blk*.dat files on disk. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-settings=<file>", strprintf("Specify path to dynamic settings data file. Can be disabled with -nosettings. File is written at runtime and not meant to be edited by users (use %s instead for custom settings). Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME, BITCOIN_SETTINGS_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#if HAVE_SYSTEM
argsman.AddArg("-startupnotify=<cmd>", "Execute command on startup.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -1138,6 +1138,15 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
RandAddPeriodic();
}, std::chrono::minutes{1});
+ // Check disk space every 5 minutes to avoid db corruption.
+ node.scheduler->scheduleEvery([&args]{
+ constexpr uint64_t min_disk_space = 50 << 20; // 50 MB
+ if (!CheckDiskSpace(args.GetBlocksDirPath(), min_disk_space)) {
+ LogPrintf("Shutting down due to lack of disk space!\n");
+ StartShutdown();
+ }
+ }, std::chrono::minutes{5});
+
GetMainSignals().RegisterBackgroundSignalScheduler(*node.scheduler);
// Create client interfaces for wallets that are supposed to be loaded
diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp
index 5e893a3f58..3ac8756e41 100644
--- a/src/kernel/chainparams.cpp
+++ b/src/kernel/chainparams.cpp
@@ -104,8 +104,8 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 709632; // Approximately November 12th, 2021
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000044a50fe819c39ad624021859");
- consensus.defaultAssumeValid = uint256S("0x000000000000000000035c3f0d31e71a5ee24c5aaf3354689f65bd7b07dee632"); // 784000
+ consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000052b2559353df4117b7348b64");
+ consensus.defaultAssumeValid = uint256S("0x00000000000000000001a0a448d6cf2546b06801389cc030b2b18c6491266815"); // 804000
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -118,8 +118,8 @@ public:
pchMessageStart[3] = 0xd9;
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
- m_assumed_blockchain_size = 540;
- m_assumed_chain_state_size = 7;
+ m_assumed_blockchain_size = 590;
+ m_assumed_chain_state_size = 9;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -177,10 +177,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 000000000000000000035c3f0d31e71a5ee24c5aaf3354689f65bd7b07dee632
- .nTime = 1680665245,
- .nTxCount = 820876044,
- .dTxRate = 3.672283614033389,
+ // Data from RPC: getchaintxstats 4096 00000000000000000001a0a448d6cf2546b06801389cc030b2b18c6491266815
+ .nTime = 1692502494,
+ .nTxCount = 881818374,
+ .dTxRate = 5.521964628130412,
};
}
};
@@ -222,8 +222,8 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000977edb0244170858d07");
- consensus.defaultAssumeValid = uint256S("0x0000000000000021bc50a89cde4870d4a81ffe0153b3c8de77b435a2fd3f6761"); // 2429000
+ consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000b6a51f415a67c0da307");
+ consensus.defaultAssumeValid = uint256S("0x0000000000000093bcb68c03a9a168ae252572d348a2eaeba2cdf9231d73206f"); // 2500000
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@@ -276,10 +276,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 0000000000000021bc50a89cde4870d4a81ffe0153b3c8de77b435a2fd3f6761
- .nTime = 1681542696,
- .nTxCount = 65345929,
- .dTxRate = 0.09855282814711661,
+ // Data from RPC: getchaintxstats 4096 0000000000000093bcb68c03a9a168ae252572d348a2eaeba2cdf9231d73206f
+ .nTime = 1694733634,
+ .nTxCount = 66484552,
+ .dTxRate = 0.1804908356632494,
};
}
};
@@ -302,15 +302,15 @@ public:
vSeeds.emplace_back("178.128.221.177");
vSeeds.emplace_back("v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333");
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000001899d8142b0");
- consensus.defaultAssumeValid = uint256S("0x0000004429ef154f7e00b4f6b46bfbe2d2678ecd351d95bbfca437ab9a5b84ec"); // 138000
+ consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000001ad46be4862");
+ consensus.defaultAssumeValid = uint256S("0x0000013d778ba3f914530f11f6b69869c9fab54acff85acd7b8201d111f19b7f"); // 150000
m_assumed_blockchain_size = 1;
m_assumed_chain_state_size = 0;
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 0000004429ef154f7e00b4f6b46bfbe2d2678ecd351d95bbfca437ab9a5b84ec
- .nTime = 1681127428,
- .nTxCount = 2226359,
- .dTxRate = 0.006424463050600656,
+ // Data from RPC: getchaintxstats 4096 0000013d778ba3f914530f11f6b69869c9fab54acff85acd7b8201d111f19b7f
+ .nTime = 1688366339,
+ .nTxCount = 2262750,
+ .dTxRate = 0.003414084572046456,
};
} else {
bin = *options.challenge;
@@ -495,7 +495,7 @@ public:
{
.height = 110,
.hash_serialized = AssumeutxoHash{uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")},
- .nChainTx = 110,
+ .nChainTx = 111,
.blockhash = uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c")
},
{
diff --git a/src/net_permissions.cpp b/src/net_permissions.cpp
index 23226bbb4f..cf6b58e08d 100644
--- a/src/net_permissions.cpp
+++ b/src/net_permissions.cpp
@@ -71,13 +71,13 @@ bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output,
std::vector<std::string> NetPermissions::ToStrings(NetPermissionFlags flags)
{
std::vector<std::string> strings;
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.push_back("bloomfilter");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.push_back("noban");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.push_back("forcerelay");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.push_back("relay");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.push_back("mempool");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.push_back("download");
- if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.push_back("addr");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.emplace_back("bloomfilter");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.emplace_back("noban");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.emplace_back("forcerelay");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.emplace_back("relay");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.emplace_back("mempool");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.emplace_back("download");
+ if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.emplace_back("addr");
return strings;
}
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 298531f66f..3bfb606037 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -696,6 +696,10 @@ private:
/** Send `feefilter` message. */
void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
+ FastRandomContext m_rng GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
+
+ FeeFilterRounder m_fee_filter_rounder GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
+
const CChainParams& m_chainparams;
CConnman& m_connman;
AddrMan& m_addrman;
@@ -1053,7 +1057,7 @@ private:
bool SetupAddressRelay(const CNode& node, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
void AddAddressKnown(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
- void PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
+ void PushAddress(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
};
const CNodeState* PeerManagerImpl::State(NodeId pnode) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -1085,7 +1089,7 @@ void PeerManagerImpl::AddAddressKnown(Peer& peer, const CAddress& addr)
peer.m_addr_known->insert(addr.GetKey());
}
-void PeerManagerImpl::PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand)
+void PeerManagerImpl::PushAddress(Peer& peer, const CAddress& addr)
{
// Known checking here is only to save space from duplicates.
// Before sending, we'll filter it again for known addresses that were
@@ -1093,7 +1097,7 @@ void PeerManagerImpl::PushAddress(Peer& peer, const CAddress& addr, FastRandomCo
assert(peer.m_addr_known);
if (addr.IsValid() && !peer.m_addr_known->contains(addr.GetKey()) && IsAddrCompatible(peer, addr)) {
if (peer.m_addrs_to_send.size() >= MAX_ADDR_TO_SEND) {
- peer.m_addrs_to_send[insecure_rand.randrange(peer.m_addrs_to_send.size())] = addr;
+ peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
} else {
peer.m_addrs_to_send.push_back(addr);
}
@@ -1444,7 +1448,7 @@ void PeerManagerImpl::FindNextBlocks(std::vector<const CBlockIndex*>& vBlocks, c
return;
}
if (pindex->nStatus & BLOCK_HAVE_DATA || (activeChain && activeChain->Contains(pindex))) {
- if (activeChain && pindex->HaveTxsDownloaded())
+ if (activeChain && pindex->HaveNumChainTxs())
state->pindexLastCommonBlock = pindex;
} else if (!IsBlockRequested(pindex->GetBlockHash())) {
// The block is not already downloaded, and not yet in flight.
@@ -1877,7 +1881,9 @@ std::unique_ptr<PeerManager> PeerManager::make(CConnman& connman, AddrMan& addrm
PeerManagerImpl::PeerManagerImpl(CConnman& connman, AddrMan& addrman,
BanMan* banman, ChainstateManager& chainman,
CTxMemPool& pool, Options opts)
- : m_chainparams(chainman.GetParams()),
+ : m_rng{opts.deterministic_rng},
+ m_fee_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}, m_rng},
+ m_chainparams(chainman.GetParams()),
m_connman(connman),
m_addrman(addrman),
m_banman(banman),
@@ -1931,6 +1937,8 @@ void PeerManagerImpl::BlockConnected(
}
}
+ // The following task can be skipped since we don't maintain a mempool for
+ // the ibd/background chainstate.
if (role == ChainstateRole::BACKGROUND) {
return;
}
@@ -2183,7 +2191,6 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
const CSipHasher hasher{m_connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY)
.Write(hash_addr)
.Write(time_addr)};
- FastRandomContext insecure_rand;
// Relay reachable addresses to 2 peers. Unreachable addresses are relayed randomly to 1 or 2 peers.
unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
@@ -2207,7 +2214,7 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
};
for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
- PushAddress(*best[i].second, addr, insecure_rand);
+ PushAddress(*best[i].second, addr);
}
}
@@ -2226,7 +2233,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
LOCK(cs_main);
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash);
if (pindex) {
- if (pindex->HaveTxsDownloaded() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
+ if (pindex->HaveNumChainTxs() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
pindex->IsValid(BLOCK_VALID_TREE)) {
// If we have the block and all of its parents, but have not yet validated it,
// we might be in the middle of connecting it (ie in the unlock of cs_main
@@ -2352,7 +2359,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
// and we want it right after the last block so they don't
// wait for other stuff first.
std::vector<CInv> vInv;
- vInv.push_back(CInv(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
+ vInv.emplace_back(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash());
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
peer.m_continuation_block.SetNull();
}
@@ -2754,7 +2761,7 @@ void PeerManagerImpl::HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, c
break;
}
uint32_t nFetchFlags = GetFetchFlags(peer);
- vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ vGetData.emplace_back(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash());
BlockRequested(pfrom.GetId(), *pindex);
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
pindex->GetBlockHash().ToString(), pfrom.GetId());
@@ -3292,7 +3299,7 @@ void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer, const Bl
if (first_in_flight) {
// Might have collided, fall back to getdata now :(
std::vector<CInv> invs;
- invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(peer), block_transactions.blockhash));
+ invs.emplace_back(MSG_BLOCK | GetFetchFlags(peer), block_transactions.blockhash);
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
} else {
RemoveBlockRequest(block_transactions.blockhash, pfrom.GetId());
@@ -3793,7 +3800,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
const bool rate_limited = !pfrom.HasPermission(NetPermissionFlags::Addr);
uint64_t num_proc = 0;
uint64_t num_rate_limit = 0;
- Shuffle(vAddr.begin(), vAddr.end(), FastRandomContext());
+ Shuffle(vAddr.begin(), vAddr.end(), m_rng);
for (CAddress& addr : vAddr)
{
if (interruptMsgProc)
@@ -4143,7 +4150,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom.GetId());
for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
{
- vHeaders.push_back(pindex->GetBlockHeader());
+ vHeaders.emplace_back(pindex->GetBlockHeader());
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
break;
}
@@ -4736,9 +4743,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
} else {
vAddr = m_connman.GetAddresses(pfrom, MAX_ADDR_TO_SEND, MAX_PCT_ADDR_TO_SEND);
}
- FastRandomContext insecure_rand;
for (const CAddress &addr : vAddr) {
- PushAddress(*peer, addr, insecure_rand);
+ PushAddress(*peer, addr);
}
return;
}
@@ -5340,8 +5346,7 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
}
if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
- FastRandomContext insecure_rand;
- PushAddress(peer, local_addr, insecure_rand);
+ PushAddress(peer, local_addr);
}
peer.m_next_local_addr_send = GetExponentialRand(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
@@ -5420,14 +5425,13 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
if (pto.IsBlockOnlyConn()) return;
CAmount currentFilter = m_mempool.GetMinFee().GetFeePerK();
- static FeeFilterRounder g_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}};
if (m_chainman.IsInitialBlockDownload()) {
// Received tx-inv messages are discarded when the active
// chainstate is in IBD, so tell the peer to not send them.
currentFilter = MAX_MONEY;
} else {
- static const CAmount MAX_FILTER{g_filter_rounder.round(MAX_MONEY)};
+ static const CAmount MAX_FILTER{m_fee_filter_rounder.round(MAX_MONEY)};
if (peer.m_fee_filter_sent == MAX_FILTER) {
// Send the current filter if we sent MAX_FILTER previously
// and made it out of IBD.
@@ -5435,7 +5439,7 @@ 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);
+ CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
// 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) {
@@ -5646,14 +5650,14 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
pBestIndex = pindex;
if (fFoundStartingHeader) {
// add this to the headers message
- vHeaders.push_back(pindex->GetBlockHeader());
+ vHeaders.emplace_back(pindex->GetBlockHeader());
} else if (PeerHasHeader(&state, pindex)) {
continue; // keep looking for the first new block
} else if (pindex->pprev == nullptr || PeerHasHeader(&state, pindex->pprev)) {
// Peer doesn't have this header but they do have the prior one.
// Start sending headers.
fFoundStartingHeader = true;
- vHeaders.push_back(pindex->GetBlockHeader());
+ vHeaders.emplace_back(pindex->GetBlockHeader());
} else {
// Peer doesn't have this header or the prior one -- nothing will
// connect, so bail out.
@@ -5739,7 +5743,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Add blocks
for (const uint256& hash : peer->m_blocks_for_inv_relay) {
- vInv.push_back(CInv(MSG_BLOCK, hash));
+ vInv.emplace_back(MSG_BLOCK, hash);
if (vInv.size() == MAX_INV_SZ) {
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
@@ -5945,7 +5949,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
}
for (const CBlockIndex *pindex : vToDownload) {
uint32_t nFetchFlags = GetFetchFlags(*peer);
- vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ vGetData.emplace_back(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash());
BlockRequested(pto->GetId(), *pindex);
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
pindex->nHeight, pto->GetId());
diff --git a/src/net_processing.h b/src/net_processing.h
index 837e308617..80d07648a4 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -58,6 +58,9 @@ public:
uint32_t max_extra_txs{DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN};
//! Whether all P2P messages are captured to disk
bool capture_messages{false};
+ //! Whether or not the internal RNG behaves deterministically (this is
+ //! a test-only option).
+ bool deterministic_rng{false};
};
static std::unique_ptr<PeerManager> make(CConnman& connman, AddrMan& addrman,
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index 706b62ea9b..f8f1aab551 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -458,7 +458,7 @@ bool BlockManager::WriteBlockIndexDB()
std::vector<std::pair<int, const CBlockFileInfo*>> vFiles;
vFiles.reserve(m_dirty_fileinfo.size());
for (std::set<int>::iterator it = m_dirty_fileinfo.begin(); it != m_dirty_fileinfo.end();) {
- vFiles.push_back(std::make_pair(*it, &m_blockfile_info[*it]));
+ vFiles.emplace_back(*it, &m_blockfile_info[*it]);
m_dirty_fileinfo.erase(it++);
}
std::vector<const CBlockIndex*> vBlocks;
@@ -761,12 +761,14 @@ bool BlockManager::FlushChainstateBlockFile(int tip_height)
{
LOCK(cs_LastBlockFile);
auto& cursor = m_blockfile_cursors[BlockfileTypeForHeight(tip_height)];
+ // If the cursor does not exist, it means an assumeutxo snapshot is loaded,
+ // but no blocks past the snapshot height have been written yet, so there
+ // is no data associated with the chainstate, and it is safe not to flush.
if (cursor) {
- // The cursor may not exist after a snapshot has been loaded but before any
- // blocks have been downloaded.
return FlushBlockFile(cursor->file_num, /*fFinalize=*/false, /*finalize_undo=*/false);
}
- return false;
+ // No need to log warnings in this case.
+ return true;
}
uint64_t BlockManager::CalculateCurrentUsage()
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index 16ca1d9156..eb1994177a 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -185,7 +185,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
chainman.InitializeChainstate(options.mempool);
// Load a chain created from a UTXO snapshot, if any exist.
- bool has_snapshot = chainman.DetectSnapshotChainstate(options.mempool);
+ bool has_snapshot = chainman.DetectSnapshotChainstate();
if (has_snapshot && (options.reindex || options.reindex_chainstate)) {
LogPrintf("[snapshot] deleting snapshot chainstate due to reindexing\n");
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 4baa0da67c..f6dbe4f008 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -674,7 +674,7 @@ public:
if (!m_node.mempool) {
std::map<COutPoint, CAmount> bump_fees;
for (const auto& outpoint : outpoints) {
- bump_fees.emplace(std::make_pair(outpoint, 0));
+ bump_fees.emplace(outpoint, 0);
}
return bump_fees;
}
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index a6dd3f3f13..1160bb55f0 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -35,8 +35,7 @@ public:
SnapshotMetadata() { }
SnapshotMetadata(
const uint256& base_blockhash,
- uint64_t coins_count,
- unsigned int nchaintx) :
+ uint64_t coins_count) :
m_base_blockhash(base_blockhash),
m_coins_count(coins_count) { }
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 553c88fddc..87bfa4cfc3 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -1054,8 +1054,9 @@ static std::set<double> MakeFeeSet(const CFeeRate& min_incremental_fee,
return fee_set;
}
-FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
- : m_fee_set{MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)}
+FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee, FastRandomContext& rng)
+ : m_fee_set{MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},
+ insecure_rand{rng}
{
}
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 8ed13482e9..69bda195be 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -320,7 +320,7 @@ private:
public:
/** Create new FeeFilterRounder */
- explicit FeeFilterRounder(const CFeeRate& min_incremental_fee);
+ explicit FeeFilterRounder(const CFeeRate& min_incremental_fee, FastRandomContext& rng);
/** Quantize a minimum fee for privacy purpose before broadcast. */
CAmount round(CAmount currentMinFee) EXCLUSIVE_LOCKS_REQUIRED(!m_insecure_rand_mutex);
@@ -328,7 +328,7 @@ public:
private:
const std::set<double> m_fee_set;
Mutex m_insecure_rand_mutex;
- FastRandomContext insecure_rand GUARDED_BY(m_insecure_rand_mutex);
+ FastRandomContext& insecure_rand GUARDED_BY(m_insecure_rand_mutex);
};
#endif // BITCOIN_POLICY_FEES_H
diff --git a/src/policy/packages.cpp b/src/policy/packages.cpp
index fd272a2642..47a9274a31 100644
--- a/src/policy/packages.cpp
+++ b/src/policy/packages.cpp
@@ -88,3 +88,18 @@ bool IsChildWithParents(const Package& package)
return std::all_of(package.cbegin(), package.cend() - 1,
[&input_txids](const auto& ptx) { return input_txids.count(ptx->GetHash()) > 0; });
}
+
+bool IsChildWithParentsTree(const Package& package)
+{
+ if (!IsChildWithParents(package)) return false;
+ std::unordered_set<uint256, SaltedTxidHasher> parent_txids;
+ std::transform(package.cbegin(), package.cend() - 1, std::inserter(parent_txids, parent_txids.end()),
+ [](const auto& ptx) { return ptx->GetHash(); });
+ // Each parent must not have an input who is one of the other parents.
+ return std::all_of(package.cbegin(), package.cend() - 1, [&](const auto& ptx) {
+ for (const auto& input : ptx->vin) {
+ if (parent_txids.count(input.prevout.hash) > 0) return false;
+ }
+ return true;
+ });
+}
diff --git a/src/policy/packages.h b/src/policy/packages.h
index 702667b8ad..cf37857e4b 100644
--- a/src/policy/packages.h
+++ b/src/policy/packages.h
@@ -63,4 +63,8 @@ bool CheckPackage(const Package& txns, PackageValidationState& state);
*/
bool IsChildWithParents(const Package& package);
+/** Context-free check that a package IsChildWithParents() and none of the parents depend on each
+ * other (the package is a "tree").
+ */
+bool IsChildWithParentsTree(const Package& package);
#endif // BITCOIN_POLICY_PACKAGES_H
diff --git a/src/psbt.cpp b/src/psbt.cpp
index 7ec9b9c136..76a2fd8241 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -132,6 +132,7 @@ void PSBTInput::FillSignatureData(SignatureData& sigdata) const
}
for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
+ sigdata.tap_pubkeys.emplace(Hash160(pubkey), pubkey);
}
for (const auto& [hash, preimage] : ripemd160_preimages) {
sigdata.ripemd160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);
@@ -246,6 +247,7 @@ void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
}
for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
+ sigdata.tap_pubkeys.emplace(Hash160(pubkey), pubkey);
}
}
diff --git a/src/psbt.h b/src/psbt.h
index 48e0453084..5b4daafed5 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -874,7 +874,7 @@ struct PSBTOutput
if ((leaf_ver & ~TAPROOT_LEAF_MASK) != 0) {
throw std::ios_base::failure("Output Taproot tree has a leaf with an invalid leaf version");
}
- m_tap_tree.push_back(std::make_tuple(depth, leaf_ver, script));
+ m_tap_tree.emplace_back(depth, leaf_ver, script);
builder.Add((int)depth, script, (int)leaf_ver, /*track=*/true);
}
if (!builder.IsComplete()) {
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 05808e4c22..11e1b4abb5 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -204,6 +204,13 @@ std::vector<CKeyID> XOnlyPubKey::GetKeyIDs() const
return out;
}
+CPubKey XOnlyPubKey::GetEvenCorrespondingCPubKey() const
+{
+ unsigned char full_key[CPubKey::COMPRESSED_SIZE] = {0x02};
+ std::copy(begin(), end(), full_key + 1);
+ return CPubKey{full_key};
+}
+
bool XOnlyPubKey::IsFullyValid() const
{
secp256k1_xonly_pubkey pubkey;
diff --git a/src/pubkey.h b/src/pubkey.h
index 274779f9a4..2b655c3f73 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -191,6 +191,12 @@ public:
return size() > 0;
}
+ /** Check if a public key is a syntactically valid compressed or uncompressed key. */
+ bool IsValidNonHybrid() const noexcept
+ {
+ return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04);
+ }
+
//! fully validate whether this is a valid public key (more expensive than IsValid())
bool IsFullyValid() const;
@@ -276,6 +282,8 @@ public:
*/
std::vector<CKeyID> GetKeyIDs() const;
+ CPubKey GetEvenCorrespondingCPubKey() const;
+
const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
const unsigned char* data() const { return m_keydata.begin(); }
static constexpr size_t size() { return decltype(m_keydata)::size(); }
diff --git a/src/qt/android/gradle.properties b/src/qt/android/gradle.properties
index 838870f62d..468f4757c0 100644
--- a/src/qt/android/gradle.properties
+++ b/src/qt/android/gradle.properties
@@ -1,4 +1,4 @@
-androidBuildToolsVersion=28.0.3
-androidCompileSdkVersion=28
+androidBuildToolsVersion=30.0.3
+androidCompileSdkVersion=30
qt5AndroidDir=new File(".").absolutePath
org.gradle.jvmargs=-Xmx4608M
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 8a46d46437..720f5584d6 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -109,10 +109,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
{
/** Create wallet frame and make it the central widget */
walletFrame = new WalletFrame(_platformStyle, this);
- connect(walletFrame, &WalletFrame::createWalletButtonClicked, [this] {
- auto activity = new CreateWalletActivity(getWalletController(), this);
- activity->create();
- });
+ connect(walletFrame, &WalletFrame::createWalletButtonClicked, this, &BitcoinGUI::createWallet);
connect(walletFrame, &WalletFrame::message, [this](const QString& title, const QString& message, unsigned int style) {
this->message(title, message, style);
});
@@ -395,7 +392,7 @@ void BitcoinGUI::createActions()
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
- connect(m_open_wallet_menu, &QMenu::aboutToShow, [this] {
+ connect(m_open_wallet_menu, &QMenu::aboutToShow, m_wallet_controller, [this] {
m_open_wallet_menu->clear();
for (const std::pair<const std::string, bool>& i : m_wallet_controller->listWalletDir()) {
const std::string& path = i.first;
@@ -412,7 +409,7 @@ void BitcoinGUI::createActions()
continue;
}
- connect(action, &QAction::triggered, [this, path] {
+ connect(action, &QAction::triggered, m_wallet_controller, [this, path] {
auto activity = new OpenWalletActivity(m_wallet_controller, this);
connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
connect(activity, &OpenWalletActivity::opened, rpcConsole, &RPCConsole::setCurrentWallet, Qt::QueuedConnection);
@@ -424,7 +421,7 @@ void BitcoinGUI::createActions()
action->setEnabled(false);
}
});
- connect(m_restore_wallet_action, &QAction::triggered, [this] {
+ connect(m_restore_wallet_action, &QAction::triggered, m_wallet_controller, [this] {
//: Name of the wallet data file format.
QString name_data_file = tr("Wallet Data");
@@ -450,19 +447,14 @@ void BitcoinGUI::createActions()
auto backup_file_path = fs::PathFromString(backup_file.toStdString());
activity->restore(backup_file_path, wallet_name.toStdString());
});
- connect(m_close_wallet_action, &QAction::triggered, [this] {
+ connect(m_close_wallet_action, &QAction::triggered, m_wallet_controller, [this] {
m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
});
- connect(m_create_wallet_action, &QAction::triggered, [this] {
- auto activity = new CreateWalletActivity(m_wallet_controller, this);
- connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
- connect(activity, &CreateWalletActivity::created, rpcConsole, &RPCConsole::setCurrentWallet);
- activity->create();
- });
- connect(m_close_all_wallets_action, &QAction::triggered, [this] {
+ connect(m_create_wallet_action, &QAction::triggered, this, &BitcoinGUI::createWallet);
+ connect(m_close_all_wallets_action, &QAction::triggered, m_wallet_controller, [this] {
m_wallet_controller->closeAllWallets(this);
});
- connect(m_migrate_wallet_action, &QAction::triggered, [this] {
+ connect(m_migrate_wallet_action, &QAction::triggered, m_wallet_controller, [this] {
auto activity = new MigrateWalletActivity(m_wallet_controller, this);
connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
activity->migrate(walletFrame->currentWalletModel());
@@ -658,7 +650,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
} else {
- if(trayIconMenu)
+ // Shutdown requested, disable menus
+ if (trayIconMenu)
{
// Disable context menu on tray icon
trayIconMenu->clear();
@@ -672,6 +665,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
}
#endif // ENABLE_WALLET
unitDisplayControl->setOptionsModel(nullptr);
+ // Disable top bar menu actions
+ appMenuBar->clear();
}
}
@@ -1191,6 +1186,21 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
progressBar->setToolTip(tooltip);
}
+void BitcoinGUI::createWallet()
+{
+#ifdef ENABLE_WALLET
+#ifndef USE_SQLITE
+ // Compiled without sqlite support (required for descriptor wallets)
+ message(tr("Error creating wallet"), tr("Cannot create new wallet, the software was compiled without sqlite support (required for descriptor wallets)"), CClientUIInterface::MSG_ERROR);
+ return;
+#endif // USE_SQLITE
+ auto activity = new CreateWalletActivity(getWalletController(), this);
+ connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
+ connect(activity, &CreateWalletActivity::created, rpcConsole, &RPCConsole::setCurrentWallet);
+ activity->create();
+#endif // ENABLE_WALLET
+}
+
void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret, const QString& detailed_message)
{
// Default title. On macOS, the window title is ignored (as required by the macOS Guidelines).
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 510561454b..6fdc4c60d8 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -230,6 +230,8 @@ public Q_SLOTS:
void setNetworkActive(bool network_active);
/** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state);
+ /** Launch the wallet creation modal (no-op if wallet is not compiled) **/
+ void createWallet();
/** Notify the user of an event from the core network or transaction handling code.
@param[in] title the message box / notification title
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 92fb3912d1..d7b1c70c59 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -84,6 +84,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: Unable to produce descriptors for this legacy wallet. Make sure to "
"provide the wallet's passphrase if it is encrypted."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Failed to calculate bump fees, because unconfirmed UTXOs depend on enormous "
+"cluster of unconfirmed transactions."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Failed to rename invalid peers.dat file. Please move or delete it and try "
"again."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -148,18 +151,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is "
"supported"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"The -txindex upgrade started by a previous version cannot be completed. "
-"Restart with the previous version or run a full -reindex."),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"The block database contains a block which appears to be from the future. "
"This may be due to your computer's date and time being set incorrectly. Only "
"rebuild the block database if you are sure that your computer's date and "
"time are correct"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"The block index db contains a legacy 'txindex'. To clear the occupied disk "
-"space, run a full -reindex, otherwise ignore this error. This error message "
-"will not be displayed again."),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"The inputs size exceeds the maximum weight. Please try sending a smaller "
"amount or manually consolidating your wallet's UTXOs"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 38c7656e00..70aa9bc8da 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -421,7 +421,19 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
std::vector<unsigned char> witnessprogram;
if (out.txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram))
{
- nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
+ // add input skeleton bytes (outpoint, scriptSig size, nSequence)
+ nBytesInputs += (32 + 4 + 1 + 4);
+
+ if (witnessversion == 0) { // P2WPKH
+ // 1 WU (witness item count) + 72 WU (ECDSA signature with len byte) + 34 WU (pubkey with len byte)
+ nBytesInputs += 107 / WITNESS_SCALE_FACTOR;
+ } else if (witnessversion == 1) { // P2TR key-path spend
+ // 1 WU (witness item count) + 65 WU (Schnorr signature with len byte)
+ nBytesInputs += 66 / WITNESS_SCALE_FACTOR;
+ } else {
+ // not supported, should be unreachable
+ throw std::runtime_error("Trying to spend future segwit version script");
+ }
fWitness = true;
}
else if(ExtractDestination(out.txout.scriptPubKey, address))
diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp
index 3e8be3e675..6557280d89 100644
--- a/src/qt/createwalletdialog.cpp
+++ b/src/qt/createwalletdialog.cpp
@@ -50,12 +50,10 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
ui->encrypt_wallet_checkbox->setEnabled(!checked);
ui->blank_wallet_checkbox->setEnabled(!checked);
ui->disable_privkeys_checkbox->setEnabled(!checked);
- ui->descriptor_checkbox->setEnabled(!checked);
// The external signer checkbox is only enabled when a device is detected.
// In that case it is checked by default. Toggling it restores the other
// options to their default.
- ui->descriptor_checkbox->setChecked(checked);
ui->encrypt_wallet_checkbox->setChecked(false);
ui->disable_privkeys_checkbox->setChecked(checked);
ui->blank_wallet_checkbox->setChecked(false);
@@ -87,19 +85,6 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
}
});
-#ifndef USE_SQLITE
- ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)"));
- ui->descriptor_checkbox->setEnabled(false);
- ui->descriptor_checkbox->setChecked(false);
- ui->external_signer_checkbox->setEnabled(false);
- ui->external_signer_checkbox->setChecked(false);
-#endif
-
-#ifndef USE_BDB
- ui->descriptor_checkbox->setEnabled(false);
- ui->descriptor_checkbox->setChecked(true);
-#endif
-
#ifndef ENABLE_EXTERNAL_SIGNER
//: "External signing" means using devices such as hardware wallets.
ui->external_signer_checkbox->setToolTip(tr("Compiled without external signing support (required for external signing)"));
@@ -155,11 +140,6 @@ bool CreateWalletDialog::isMakeBlankWalletChecked() const
return ui->blank_wallet_checkbox->isChecked();
}
-bool CreateWalletDialog::isDescriptorWalletChecked() const
-{
- return ui->descriptor_checkbox->isChecked();
-}
-
bool CreateWalletDialog::isExternalSignerChecked() const
{
return ui->external_signer_checkbox->isChecked();
diff --git a/src/qt/createwalletdialog.h b/src/qt/createwalletdialog.h
index 939b82ff78..24ee97385b 100644
--- a/src/qt/createwalletdialog.h
+++ b/src/qt/createwalletdialog.h
@@ -35,7 +35,6 @@ public:
bool isEncryptWalletChecked() const;
bool isDisablePrivateKeysChecked() const;
bool isMakeBlankWalletChecked() const;
- bool isDescriptorWalletChecked() const;
bool isExternalSignerChecked() const;
private:
diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui
index 56adbe17a5..1d6f0ed530 100644
--- a/src/qt/forms/createwalletdialog.ui
+++ b/src/qt/forms/createwalletdialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>364</width>
- <height>249</height>
+ <width>371</width>
+ <height>298</height>
</rect>
</property>
<property name="windowTitle">
@@ -18,6 +18,48 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
+ <widget class="QLabel" name="label_description">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>You are one step away from creating your new wallet!</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_subdescription">
+ <property name="text">
+ <string>Please provide a name and, if desired, enable any advanced options</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>3</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="wallet_name_label">
@@ -75,7 +117,19 @@
<property name="title">
<string>Advanced Options</string>
</property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
<layout class="QVBoxLayout" name="verticalLayout_groupbox">
+ <property name="spacing">
+ <number>9</number>
+ </property>
<item>
<widget class="QCheckBox" name="disable_privkeys_checkbox">
<property name="enabled">
@@ -100,19 +154,6 @@
</widget>
</item>
<item>
- <widget class="QCheckBox" name="descriptor_checkbox">
- <property name="toolTip">
- <string>Use descriptors for scriptPubKey management</string>
- </property>
- <property name="text">
- <string>Descriptor Wallet</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
<widget class="QCheckBox" name="external_signer_checkbox">
<property name="toolTip">
<string>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</string>
@@ -155,7 +196,6 @@
<tabstop>encrypt_wallet_checkbox</tabstop>
<tabstop>disable_privkeys_checkbox</tabstop>
<tabstop>blank_wallet_checkbox</tabstop>
- <tabstop>descriptor_checkbox</tabstop>
<tabstop>external_signer_checkbox</tabstop>
</tabstops>
<resources/>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 8cb5ffbc65..fcba44f809 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -55,12 +55,12 @@
</message>
<message>
<location line="-30"/>
- <location filename="../addressbookpage.cpp" line="+127"/>
+ <location filename="../addressbookpage.cpp" line="+117"/>
<source>&amp;Delete</source>
<translation>&amp;Delete</translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="-38"/>
+ <location filename="../addressbookpage.cpp" line="-30"/>
<source>Choose the address to send coins to</source>
<translation type="unfinished"></translation>
</message>
@@ -76,16 +76,6 @@
</message>
<message>
<location line="+6"/>
- <source>Sending addresses</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Receiving addresses</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+7"/>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
<translation type="unfinished"></translation>
</message>
@@ -111,7 +101,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+164"/>
+ <location line="+165"/>
<source>Export Address List</source>
<translation type="unfinished"></translation>
</message>
@@ -128,7 +118,17 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-3"/>
+ <location line="+32"/>
+ <source>Sending addresses - %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Receiving addresses - %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-36"/>
<source>Exporting Failed</source>
<translation type="unfinished"></translation>
</message>
@@ -215,12 +215,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
<message>
<location line="+18"/>
- <location line="+55"/>
+ <location line="+58"/>
<source>Wallet encrypted</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-135"/>
+ <location line="-138"/>
<source>Enter the new passphrase for the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation type="unfinished"></translation>
</message>
@@ -257,41 +257,41 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<message>
<location line="+6"/>
<location line="+8"/>
- <location line="+59"/>
+ <location line="+62"/>
<source>Wallet encryption failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-66"/>
+ <location line="-69"/>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+8"/>
- <location line="+59"/>
+ <location line="+62"/>
<source>The supplied passphrases do not match.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-46"/>
+ <location line="-49"/>
<location line="+3"/>
- <location line="+12"/>
+ <location line="+15"/>
<source>Wallet unlock failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-14"/>
- <location line="+31"/>
+ <location line="-17"/>
+ <location line="+34"/>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-28"/>
+ <location line="-31"/>
<source>The passphrase entered for the wallet decryption is incorrect. It contains a null character (ie - a zero byte). If the passphrase was set with a version of this software prior to 25.0, please try again with only the characters up to — but not including — the first null character. If this is successful, please set a new passphrase to avoid this issue in the future.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+23"/>
<source>Wallet passphrase was successfully changed.</source>
<translation type="unfinished"></translation>
</message>
@@ -357,7 +357,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+254"/>
+ <location filename="../bitcoingui.cpp" line="+250"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -417,7 +417,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+164"/>
+ <location line="+163"/>
<source>&amp;Minimize</source>
<translation type="unfinished"></translation>
</message>
@@ -427,18 +427,18 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+407"/>
+ <location line="+412"/>
<source>Network activity disabled.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+436"/>
+ <location line="+451"/>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1175"/>
+ <location line="-1194"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -533,12 +533,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+123"/>
+ <location line="+121"/>
<source>&amp;File</source>
<translation>&amp;File</translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+21"/>
<source>&amp;Settings</source>
<translation>&amp;Settings</translation>
</message>
@@ -553,7 +553,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="+471"/>
+ <location line="+476"/>
<source>Syncing Headers (%1%)…</source>
<translation type="unfinished"></translation>
</message>
@@ -578,7 +578,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-848"/>
+ <location line="-852"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
@@ -593,7 +593,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+26"/>
+ <location line="+30"/>
<source>&amp;Command-line options</source>
<translation type="unfinished"></translation>
</message>
@@ -626,7 +626,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Transactions after this will not yet be visible.</translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+40"/>
<source>Error</source>
<translation>Error</translation>
</message>
@@ -641,12 +641,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Information</translation>
</message>
<message>
- <location line="-78"/>
+ <location line="-93"/>
<source>Up to date</source>
<translation>Up to date</translation>
</message>
<message>
- <location line="-833"/>
+ <location line="-837"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
@@ -723,6 +723,16 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+2"/>
+ <source>Migrate Wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Migrate a wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+4"/>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation type="unfinished"></translation>
@@ -772,7 +782,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+74"/>
+ <location line="+69"/>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Window</translation>
</message>
@@ -792,12 +802,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="+274"/>
<source>%1 client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+65"/>
+ <location line="+68"/>
<source>&amp;Hide</source>
<translation type="unfinished"></translation>
</message>
@@ -845,7 +855,17 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+149"/>
+ <location line="+139"/>
+ <source>Error creating wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Cannot create new wallet, the software was compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+25"/>
<source>Error: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1115,7 +1135,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+33"/>
+ <location line="+32"/>
<source>Create wallet failed</source>
<translation type="unfinished"></translation>
</message>
@@ -1143,7 +1163,17 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+15"/>
+ <source>You are one step away from creating your new wallet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Please provide a name and, if desired, enable any advanced options</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+25"/>
<source>Wallet Name</source>
<translation type="unfinished"></translation>
</message>
@@ -1168,7 +1198,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+21"/>
<source>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>
<translation type="unfinished"></translation>
</message>
@@ -1189,16 +1219,6 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
<message>
<location line="+7"/>
- <source>Use descriptors for scriptPubKey management</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
- <source>Descriptor Wallet</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+10"/>
<source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
<translation type="unfinished"></translation>
</message>
@@ -1214,11 +1234,6 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
<message>
<location line="+68"/>
- <source>Compiled without sqlite support (required for descriptor wallets)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+14"/>
<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>
@@ -1485,6 +1500,63 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
</context>
<context>
+ <name>MigrateWalletActivity</name>
+ <message>
+ <location line="+63"/>
+ <source>Migrate wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Are you sure you wish to migrate the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Migrating the wallet will convert this wallet to one or more descriptor wallets. A new wallet backup will need to be made.
+If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts.
+If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.
+
+The migration process will create a backup of the wallet before migrating. This backup file will be named &lt;wallet name&gt;-&lt;timestamp&gt;.legacy.bak and can be found in the directory for this wallet. In the event of an incorrect migration, the backup can be restored with the &quot;Restore Wallet&quot; functionality.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Migrate Wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Migrating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>The wallet &apos;%1&apos; was migrated successfully.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source> Watchonly scripts have been migrated to a new wallet named &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source> Solvable but not watched scripts have been migrated to a new wallet named &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Migration failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Migration Successful</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>ModalOverlay</name>
<message>
<location filename="../forms/modaloverlay.ui" line="+14"/>
@@ -1587,7 +1659,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>OpenWalletActivity</name>
<message>
- <location filename="../walletcontroller.cpp" line="-46"/>
+ <location filename="../walletcontroller.cpp" line="-161"/>
<source>Open wallet failed</source>
<translation type="unfinished"></translation>
</message>
@@ -2675,7 +2747,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<location line="+2"/>
- <location filename="../rpcconsole.cpp" line="+994"/>
+ <location filename="../rpcconsole.cpp" line="+1004"/>
<source>%1 kB</source>
<translation type="unfinished"></translation>
</message>
@@ -2774,6 +2846,8 @@ If you are receiving this error you should request the merchant provide a BIP21
<location line="+692"/>
<location line="+26"/>
<location line="+26"/>
+ <location line="+26"/>
+ <location line="+26"/>
<location line="+23"/>
<location line="+23"/>
<location line="+23"/>
@@ -2802,7 +2876,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation>N/A</translation>
</message>
<message>
- <location line="-1597"/>
+ <location line="-1649"/>
<source>Client version</source>
<translation>Client version</translation>
</message>
@@ -2843,12 +2917,12 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<location line="+29"/>
- <location line="+892"/>
+ <location line="+944"/>
<source>Network</source>
<translation>Network</translation>
</message>
<message>
- <location line="-885"/>
+ <location line="-937"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
@@ -2894,18 +2968,18 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<location line="+80"/>
- <location line="+708"/>
+ <location line="+760"/>
<source>Received</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-628"/>
- <location line="+605"/>
+ <location line="-680"/>
+ <location line="+657"/>
<source>Sent</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-564"/>
+ <location line="-616"/>
<source>&amp;Peers</source>
<translation type="unfinished"></translation>
</message>
@@ -2921,7 +2995,27 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+106"/>
+ <location line="+80"/>
+ <source>The transport layer version: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Transport</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>The BIP324 session ID string in hex, if any.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Session ID</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+49"/>
<source>Version</source>
<translation type="unfinished"></translation>
</message>
@@ -3002,13 +3096,13 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1564"/>
- <location line="+1051"/>
+ <location line="-1616"/>
+ <location line="+1103"/>
<source>User Agent</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1125"/>
+ <location line="-1177"/>
<source>Node window</source>
<translation type="unfinished"></translation>
</message>
@@ -3048,7 +3142,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+23"/>
+ <location line="+75"/>
<source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
<translation type="unfinished"></translation>
</message>
@@ -3124,7 +3218,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1258"/>
+ <location line="-1310"/>
<source>Last block time</source>
<translation>Last block time</translation>
</message>
@@ -3199,7 +3293,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="-464"/>
+ <location filename="../rpcconsole.cpp" line="-473"/>
<source>Inbound: initiated by peer</source>
<extracomment>Explanatory text for an inbound peer connection.</extracomment>
<translation type="unfinished"></translation>
@@ -3235,6 +3329,24 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+5"/>
+ <source>detecting: peer could be v1 or v2</source>
+ <extracomment>Explanatory text for &quot;detecting&quot; transport type.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>v1: unencrypted, plaintext transport protocol</source>
+ <extracomment>Explanatory text for v1 transport type.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>v2: BIP324 encrypted transport protocol</source>
+ <extracomment>Explanatory text for v2 transport type.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+4"/>
<source>we selected the peer for high bandwidth relay</source>
<translation type="unfinished"></translation>
@@ -3326,7 +3438,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+316"/>
+ <location line="+325"/>
<source>Ctrl+I</source>
<translation type="unfinished"></translation>
</message>
@@ -3346,7 +3458,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-321"/>
+ <location line="-330"/>
<source>Executing command using &quot;%1&quot; wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4721,7 +4833,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="+257"/>
+ <location filename="../transactiontablemodel.cpp" line="+258"/>
<source>Date</source>
<translation type="unfinished">Date</translation>
</message>
@@ -4787,11 +4899,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</message>
<message>
<location line="+2"/>
- <source>Payment to yourself</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
<source>Mined</source>
<translation type="unfinished"></translation>
</message>
@@ -4801,12 +4908,12 @@ 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="+16"/>
+ <location line="+14"/>
<source>(n/a)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+207"/>
+ <location line="+205"/>
<source>(no label)</source>
<translation type="unfinished"></translation>
</message>
@@ -4886,11 +4993,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</message>
<message>
<location line="+2"/>
- <source>To yourself</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Mined</source>
<translation type="unfinished"></translation>
</message>
@@ -4910,12 +5012,12 @@ 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="-26"/>
+ <location line="-25"/>
<source>Range…</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+90"/>
+ <location line="+89"/>
<source>&amp;Copy address</source>
<translation type="unfinished"></translation>
</message>
@@ -5058,7 +5160,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="-347"/>
+ <location filename="../walletcontroller.cpp" line="-346"/>
<source>Close wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -5351,7 +5453,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+12"/>
<source>File %s already exists. If you are sure this is what you want, move it out of the way first.</source>
<translation type="unfinished"></translation>
</message>
@@ -5416,17 +5518,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+3"/>
<source>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>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
- <source>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>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+11"/>
+ <location line="+12"/>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished"></translation>
</message>
@@ -5551,12 +5648,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-105"/>
- <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="-124"/>
+ <location line="-225"/>
<source>%s is set very high! Fees this large could be paid on a single transaction.</source>
<translation type="unfinished"></translation>
</message>
@@ -5592,6 +5684,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+6"/>
+ <source>Failed to calculate bump fees, because unconfirmed UTXOs depend on enormous cluster of unconfirmed transactions.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
<translation type="unfinished"></translation>
</message>
@@ -5631,7 +5728,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+36"/>
+ <location line="+29"/>
<source>The inputs size exceeds the maximum weight. Please try sending a smaller amount or manually consolidating your wallet&apos;s UTXOs</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/qt/locale/bitcoin_en.xlf b/src/qt/locale/bitcoin_en.xlf
index 9d4a989cf0..b1a01cb4a1 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">127</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../addressbookpage.cpp</context><context context-type="linenumber">117</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">89</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">87</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">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">88</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">95</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">93</context></context-group>
</trans-unit>
<trans-unit id="_msg15">
- <source xml:space="preserve">Sending addresses</source>
- <context-group purpose="location"><context context-type="linenumber">101</context></context-group>
- </trans-unit>
- <trans-unit id="_msg16">
- <source xml:space="preserve">Receiving addresses</source>
- <context-group purpose="location"><context context-type="linenumber">102</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">109</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg18">
+ <trans-unit id="_msg16">
<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">114</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">104</context></context-group>
</trans-unit>
- <trans-unit id="_msg19">
+ <trans-unit id="_msg17">
<source xml:space="preserve">&amp;Copy Address</source>
- <context-group purpose="location"><context context-type="linenumber">122</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">112</context></context-group>
</trans-unit>
- <trans-unit id="_msg20">
+ <trans-unit id="_msg18">
<source xml:space="preserve">Copy &amp;Label</source>
- <context-group purpose="location"><context context-type="linenumber">123</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">113</context></context-group>
</trans-unit>
- <trans-unit id="_msg21">
+ <trans-unit id="_msg19">
<source xml:space="preserve">&amp;Edit</source>
- <context-group purpose="location"><context context-type="linenumber">124</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">114</context></context-group>
</trans-unit>
- <trans-unit id="_msg22">
+ <trans-unit id="_msg20">
<source xml:space="preserve">Export Address List</source>
- <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg23">
+ <trans-unit id="_msg21">
<source xml:space="preserve">Comma separated file</source>
- <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">282</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">
+ <trans-unit id="_msg22">
<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">307</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">298</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="_msg23">
+ <source xml:space="preserve">Sending addresses - %1</source>
+ <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg24">
+ <source xml:space="preserve">Receiving addresses - %1</source>
+ <context-group purpose="location"><context context-type="linenumber">331</context></context-group>
+ </trans-unit>
<trans-unit id="_msg25">
<source xml:space="preserve">Exporting Failed</source>
- <context-group purpose="location"><context context-type="linenumber">304</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">295</context></context-group>
</trans-unit>
</group>
</body></file>
@@ -185,7 +185,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<trans-unit id="_msg41">
<source xml:space="preserve">Wallet encrypted</source>
<context-group purpose="location"><context context-type="linenumber">126</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">184</context></context-group>
</trans-unit>
<trans-unit id="_msg42">
<source xml:space="preserve">Enter the new passphrase for the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
@@ -219,7 +219,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<source xml:space="preserve">Wallet encryption failed</source>
<context-group purpose="location"><context context-type="linenumber">136</context></context-group>
<context-group purpose="location"><context context-type="linenumber">144</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">203</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
</trans-unit>
<trans-unit id="_msg50">
<source xml:space="preserve">Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
@@ -228,18 +228,18 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<trans-unit id="_msg51">
<source xml:space="preserve">The supplied passphrases do not match.</source>
<context-group purpose="location"><context context-type="linenumber">145</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
</trans-unit>
<trans-unit id="_msg52">
<source xml:space="preserve">Wallet unlock failed</source>
<context-group purpose="location"><context context-type="linenumber">158</context></context-group>
<context-group purpose="location"><context context-type="linenumber">161</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
<trans-unit id="_msg53">
<source xml:space="preserve">The passphrase entered for the wallet decryption was incorrect.</source>
<context-group purpose="location"><context context-type="linenumber">159</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">190</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">193</context></context-group>
</trans-unit>
<trans-unit id="_msg54">
<source xml:space="preserve">The passphrase entered for the wallet decryption is incorrect. It contains a null character (ie - a zero byte). If the passphrase was set with a version of this software prior to 25.0, please try again with only the characters up to — but not including — the first null character. If this is successful, please set a new passphrase to avoid this issue in the future.</source>
@@ -247,21 +247,21 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</trans-unit>
<trans-unit id="_msg55">
<source xml:space="preserve">Wallet passphrase was successfully changed.</source>
- <context-group purpose="location"><context context-type="linenumber">182</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
</trans-unit>
<trans-unit id="_msg56">
<source xml:space="preserve">Passphrase change failed</source>
- <context-group purpose="location"><context context-type="linenumber">189</context></context-group>
<context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">195</context></context-group>
</trans-unit>
<trans-unit id="_msg57">
<source xml:space="preserve">The old passphrase entered for the wallet decryption is incorrect. It contains a null character (ie - a zero byte). If the passphrase was set with a version of this software prior to 25.0, please try again with only the characters up to — but not including — the first null character.</source>
- <context-group purpose="location"><context context-type="linenumber">193</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
</trans-unit>
<trans-unit id="_msg58">
<source xml:space="preserve">Warning: The Caps Lock key is on!</source>
- <context-group purpose="location"><context context-type="linenumber">238</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">241</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
</group>
</body></file>
@@ -325,59 +325,59 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<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">254</context></context-group>
+ <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">255</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
</trans-unit>
<trans-unit id="_msg72">
<source xml:space="preserve">&amp;Transactions</source>
- <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">271</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">276</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">272</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">295</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
</trans-unit>
<trans-unit id="_msg75">
<source xml:space="preserve">Quit application</source>
- <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
</trans-unit>
<trans-unit id="_msg76">
<source xml:space="preserve">&amp;About %1</source>
- <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <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">300</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
<trans-unit id="_msg78">
<source xml:space="preserve">About &amp;Qt</source>
- <context-group purpose="location"><context context-type="linenumber">303</context></context-group>
+ <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">304</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
</trans-unit>
<trans-unit id="_msg80">
<source xml:space="preserve">Modify configuration options for %1</source>
- <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
+ <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">351</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
</trans-unit>
<trans-unit id="_msg82">
<source xml:space="preserve">&amp;Minimize</source>
- <context-group purpose="location"><context context-type="linenumber">515</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">510</context></context-group>
</trans-unit>
<trans-unit id="_msg83">
<source xml:space="preserve">Wallet:</source>
- <context-group purpose="location"><context context-type="linenumber">594</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">589</context></context-group>
</trans-unit>
<trans-unit id="_msg84">
<source xml:space="preserve">Network activity disabled.</source>
@@ -386,99 +386,99 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</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">1437</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1452</context></context-group>
</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">262</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</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">315</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">311</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">317</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
</trans-unit>
<trans-unit id="_msg89">
<source xml:space="preserve">&amp;Send</source>
- <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
</trans-unit>
<trans-unit id="_msg90">
<source xml:space="preserve">&amp;Receive</source>
- <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
</trans-unit>
<trans-unit id="_msg91">
<source xml:space="preserve">&amp;Options…</source>
- <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">302</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">311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">307</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">312</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</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">314</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">310</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">316</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">312</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">318</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">314</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">319</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">315</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">320</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">316</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">321</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">317</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">322</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">318</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">338</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
<trans-unit id="_msg102">
<source xml:space="preserve">Close Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">346</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
</trans-unit>
<trans-unit id="_msg103">
<source xml:space="preserve">Create Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">349</context></context-group>
+ <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">359</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">355</context></context-group>
</trans-unit>
<trans-unit id="_msg105">
<source xml:space="preserve">&amp;File</source>
- <context-group purpose="location"><context context-type="linenumber">482</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">476</context></context-group>
</trans-unit>
<trans-unit id="_msg106">
<source xml:space="preserve">&amp;Settings</source>
- <context-group purpose="location"><context context-type="linenumber">502</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">497</context></context-group>
</trans-unit>
<trans-unit id="_msg107">
<source xml:space="preserve">&amp;Help</source>
- <context-group purpose="location"><context context-type="linenumber">563</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">558</context></context-group>
</trans-unit>
<trans-unit id="_msg108">
<source xml:space="preserve">Tabs toolbar</source>
- <context-group purpose="location"><context context-type="linenumber">574</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">569</context></context-group>
</trans-unit>
<trans-unit id="_msg109">
<source xml:space="preserve">Syncing Headers (%1%)…</source>
@@ -502,15 +502,15 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</trans-unit>
<trans-unit id="_msg114">
<source xml:space="preserve">Request payments (generates QR codes and bitcoin: URIs)</source>
- <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
</trans-unit>
<trans-unit id="_msg115">
<source xml:space="preserve">Show the list of used sending addresses and labels</source>
- <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
</trans-unit>
<trans-unit id="_msg116">
<source xml:space="preserve">Show the list of used receiving addresses and labels</source>
- <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
<trans-unit id="_msg117">
<source xml:space="preserve">&amp;Command-line options</source>
@@ -543,15 +543,15 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</trans-unit>
<trans-unit id="_msg123">
<source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">1200</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1215</context></context-group>
</trans-unit>
<trans-unit id="_msg124">
<source xml:space="preserve">Warning</source>
- <context-group purpose="location"><context context-type="linenumber">1204</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1219</context></context-group>
</trans-unit>
<trans-unit id="_msg125">
<source xml:space="preserve">Information</source>
- <context-group purpose="location"><context context-type="linenumber">1208</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1223</context></context-group>
</trans-unit>
<trans-unit id="_msg126">
<source xml:space="preserve">Up to date</source>
@@ -559,309 +559,325 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</trans-unit>
<trans-unit id="_msg127">
<source xml:space="preserve">Ctrl+Q</source>
- <context-group purpose="location"><context context-type="linenumber">297</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">293</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">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">319</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">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">320</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">325</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
<trans-unit id="_msg131">
<source xml:space="preserve">Node window</source>
- <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
+ <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>
- <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
+ <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">333</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">329</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">335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">331</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">339</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
<trans-unit id="_msg136">
<source xml:space="preserve">Open Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">341</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">337</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">343</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
<trans-unit id="_msg138">
<source xml:space="preserve">Close wallet</source>
- <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">343</context></context-group>
</trans-unit>
<trans-unit id="_msg139">
<source xml:space="preserve">Restore Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">354</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">350</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="_msg140">
<source xml:space="preserve">Restore a wallet from a backup file</source>
- <context-group purpose="location"><context context-type="linenumber">357</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">353</context></context-group>
<note annotates="source" from="developer">Status tip for Restore Wallet menu item</note>
</trans-unit>
<trans-unit id="_msg141">
<source xml:space="preserve">Close all wallets</source>
- <context-group purpose="location"><context context-type="linenumber">360</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
</trans-unit>
<trans-unit id="_msg142">
+ <source xml:space="preserve">Migrate Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg143">
+ <source xml:space="preserve">Migrate a wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">360</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg144">
<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">364</context></context-group>
</trans-unit>
- <trans-unit id="_msg143">
+ <trans-unit id="_msg145">
<source xml:space="preserve">&amp;Mask values</source>
<context-group purpose="location"><context context-type="linenumber">366</context></context-group>
</trans-unit>
- <trans-unit id="_msg144">
+ <trans-unit id="_msg146">
<source xml:space="preserve">Mask the values in the Overview tab</source>
<context-group purpose="location"><context context-type="linenumber">368</context></context-group>
</trans-unit>
- <trans-unit id="_msg145">
+ <trans-unit id="_msg147">
<source xml:space="preserve">default wallet</source>
<context-group purpose="location"><context context-type="linenumber">399</context></context-group>
</trans-unit>
- <trans-unit id="_msg146">
+ <trans-unit id="_msg148">
<source xml:space="preserve">No wallets available</source>
<context-group purpose="location"><context context-type="linenumber">420</context></context-group>
</trans-unit>
- <trans-unit id="_msg147">
+ <trans-unit id="_msg149">
<source xml:space="preserve">Wallet Data</source>
<context-group purpose="location"><context context-type="linenumber">426</context></context-group>
<note annotates="source" from="developer">Name of the wallet data file format.</note>
</trans-unit>
- <trans-unit id="_msg148">
+ <trans-unit id="_msg150">
<source xml:space="preserve">Load Wallet Backup</source>
<context-group purpose="location"><context context-type="linenumber">429</context></context-group>
<note annotates="source" from="developer">The title for Restore Wallet File Windows</note>
</trans-unit>
- <trans-unit id="_msg149">
+ <trans-unit id="_msg151">
<source xml:space="preserve">Restore Wallet</source>
<context-group purpose="location"><context context-type="linenumber">437</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="_msg150">
+ <trans-unit id="_msg152">
<source xml:space="preserve">Wallet Name</source>
<context-group purpose="location"><context context-type="linenumber">439</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="_msg151">
+ <trans-unit id="_msg153">
<source xml:space="preserve">&amp;Window</source>
- <context-group purpose="location"><context context-type="linenumber">513</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">508</context></context-group>
</trans-unit>
- <trans-unit id="_msg152">
+ <trans-unit id="_msg154">
<source xml:space="preserve">Ctrl+M</source>
- <context-group purpose="location"><context context-type="linenumber">516</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
</trans-unit>
- <trans-unit id="_msg153">
+ <trans-unit id="_msg155">
<source xml:space="preserve">Zoom</source>
- <context-group purpose="location"><context context-type="linenumber">525</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">520</context></context-group>
</trans-unit>
- <trans-unit id="_msg154">
+ <trans-unit id="_msg156">
<source xml:space="preserve">Main Window</source>
- <context-group purpose="location"><context context-type="linenumber">543</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">538</context></context-group>
</trans-unit>
- <trans-unit id="_msg155">
+ <trans-unit id="_msg157">
<source xml:space="preserve">%1 client</source>
- <context-group purpose="location"><context context-type="linenumber">815</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">812</context></context-group>
</trans-unit>
- <trans-unit id="_msg156">
+ <trans-unit id="_msg158">
<source xml:space="preserve">&amp;Hide</source>
<context-group purpose="location"><context context-type="linenumber">880</context></context-group>
</trans-unit>
- <trans-unit id="_msg157">
+ <trans-unit id="_msg159">
<source xml:space="preserve">S&amp;how</source>
<context-group purpose="location"><context context-type="linenumber">881</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">998</context></context-group>
<note annotates="source" from="developer">A substring of the tooltip.</note>
- <trans-unit id="_msg158[0]">
+ <trans-unit id="_msg160[0]">
<source xml:space="preserve">%n active connection(s) to Bitcoin network.</source>
</trans-unit>
- <trans-unit id="_msg158[1]">
+ <trans-unit id="_msg160[1]">
<source xml:space="preserve">%n active connection(s) to Bitcoin network.</source>
</trans-unit>
</group>
- <trans-unit id="_msg159">
+ <trans-unit id="_msg161">
<source xml:space="preserve">Click for more actions.</source>
<context-group purpose="location"><context context-type="linenumber">1008</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="_msg160">
+ <trans-unit id="_msg162">
<source xml:space="preserve">Show Peers tab</source>
<context-group purpose="location"><context context-type="linenumber">1025</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="_msg161">
+ <trans-unit id="_msg163">
<source xml:space="preserve">Disable network activity</source>
<context-group purpose="location"><context context-type="linenumber">1033</context></context-group>
<note annotates="source" from="developer">A context menu item.</note>
</trans-unit>
- <trans-unit id="_msg162">
+ <trans-unit id="_msg164">
<source xml:space="preserve">Enable network activity</source>
<context-group purpose="location"><context context-type="linenumber">1035</context></context-group>
<note annotates="source" from="developer">A context menu item. The network activity was disabled previously.</note>
</trans-unit>
- <trans-unit id="_msg163">
+ <trans-unit id="_msg165">
<source xml:space="preserve">Pre-syncing Headers (%1%)…</source>
<context-group purpose="location"><context context-type="linenumber">1052</context></context-group>
</trans-unit>
- <trans-unit id="_msg164">
+ <trans-unit id="_msg166">
+ <source xml:space="preserve">Error creating wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">1191</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg167">
+ <source xml:space="preserve">Cannot create new wallet, the software was compiled without sqlite support (required for descriptor wallets)</source>
+ <context-group purpose="location"><context context-type="linenumber">1191</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg168">
<source xml:space="preserve">Error: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1201</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1216</context></context-group>
</trans-unit>
- <trans-unit id="_msg165">
+ <trans-unit id="_msg169">
<source xml:space="preserve">Warning: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1205</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1220</context></context-group>
</trans-unit>
- <trans-unit id="_msg166">
+ <trans-unit id="_msg170">
<source xml:space="preserve">Date: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1313</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1328</context></context-group>
</trans-unit>
- <trans-unit id="_msg167">
+ <trans-unit id="_msg171">
<source xml:space="preserve">Amount: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1314</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1329</context></context-group>
</trans-unit>
- <trans-unit id="_msg168">
+ <trans-unit id="_msg172">
<source xml:space="preserve">Wallet: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1316</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1331</context></context-group>
</trans-unit>
- <trans-unit id="_msg169">
+ <trans-unit id="_msg173">
<source xml:space="preserve">Type: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1318</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1333</context></context-group>
</trans-unit>
- <trans-unit id="_msg170">
+ <trans-unit id="_msg174">
<source xml:space="preserve">Label: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1320</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1335</context></context-group>
</trans-unit>
- <trans-unit id="_msg171">
+ <trans-unit id="_msg175">
<source xml:space="preserve">Address: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1322</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1337</context></context-group>
</trans-unit>
- <trans-unit id="_msg172">
+ <trans-unit id="_msg176">
<source xml:space="preserve">Sent transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1338</context></context-group>
</trans-unit>
- <trans-unit id="_msg173">
+ <trans-unit id="_msg177">
<source xml:space="preserve">Incoming transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1338</context></context-group>
</trans-unit>
- <trans-unit id="_msg174">
+ <trans-unit id="_msg178">
<source xml:space="preserve">HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1375</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1390</context></context-group>
</trans-unit>
- <trans-unit id="_msg175">
+ <trans-unit id="_msg179">
<source xml:space="preserve">HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1375</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1390</context></context-group>
</trans-unit>
- <trans-unit id="_msg176">
+ <trans-unit id="_msg180">
<source xml:space="preserve">Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1375</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1390</context></context-group>
</trans-unit>
- <trans-unit id="_msg177">
+ <trans-unit id="_msg181">
<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">1398</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1413</context></context-group>
</trans-unit>
- <trans-unit id="_msg178">
+ <trans-unit id="_msg182">
<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">1406</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1421</context></context-group>
</trans-unit>
- <trans-unit id="_msg179">
+ <trans-unit id="_msg183">
<source xml:space="preserve">Original message:</source>
- <context-group purpose="location"><context context-type="linenumber">1525</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1540</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="UnitDisplayStatusBarControl">
- <trans-unit id="_msg180">
+ <trans-unit id="_msg184">
<source xml:space="preserve">Unit to show amounts in. Click to select another unit.</source>
- <context-group purpose="location"><context context-type="linenumber">1564</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1579</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="_msg181">
+ <trans-unit id="_msg185">
<source xml:space="preserve">Coin Selection</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg182">
+ <trans-unit id="_msg186">
<source xml:space="preserve">Quantity:</source>
<context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg183">
+ <trans-unit id="_msg187">
<source xml:space="preserve">Bytes:</source>
<context-group purpose="location"><context context-type="linenumber">80</context></context-group>
</trans-unit>
- <trans-unit id="_msg184">
+ <trans-unit id="_msg188">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
- <trans-unit id="_msg185">
+ <trans-unit id="_msg189">
<source xml:space="preserve">Fee:</source>
<context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg186">
+ <trans-unit id="_msg190">
<source xml:space="preserve">After Fee:</source>
<context-group purpose="location"><context context-type="linenumber">218</context></context-group>
</trans-unit>
- <trans-unit id="_msg187">
+ <trans-unit id="_msg191">
<source xml:space="preserve">Change:</source>
<context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg188">
+ <trans-unit id="_msg192">
<source xml:space="preserve">(un)select all</source>
<context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
- <trans-unit id="_msg189">
+ <trans-unit id="_msg193">
<source xml:space="preserve">Tree mode</source>
<context-group purpose="location"><context context-type="linenumber">322</context></context-group>
</trans-unit>
- <trans-unit id="_msg190">
+ <trans-unit id="_msg194">
<source xml:space="preserve">List mode</source>
<context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg191">
+ <trans-unit id="_msg195">
<source xml:space="preserve">Amount</source>
<context-group purpose="location"><context context-type="linenumber">391</context></context-group>
</trans-unit>
- <trans-unit id="_msg192">
+ <trans-unit id="_msg196">
<source xml:space="preserve">Received with label</source>
<context-group purpose="location"><context context-type="linenumber">396</context></context-group>
</trans-unit>
- <trans-unit id="_msg193">
+ <trans-unit id="_msg197">
<source xml:space="preserve">Received with address</source>
<context-group purpose="location"><context context-type="linenumber">401</context></context-group>
</trans-unit>
- <trans-unit id="_msg194">
+ <trans-unit id="_msg198">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">406</context></context-group>
</trans-unit>
- <trans-unit id="_msg195">
+ <trans-unit id="_msg199">
<source xml:space="preserve">Confirmations</source>
<context-group purpose="location"><context context-type="linenumber">411</context></context-group>
</trans-unit>
- <trans-unit id="_msg196">
+ <trans-unit id="_msg200">
<source xml:space="preserve">Confirmed</source>
<context-group purpose="location"><context context-type="linenumber">414</context></context-group>
</trans-unit>
@@ -869,72 +885,72 @@ 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="_msg197">
+ <trans-unit id="_msg201">
<source xml:space="preserve">Copy amount</source>
<context-group purpose="location"><context context-type="linenumber">69</context></context-group>
</trans-unit>
- <trans-unit id="_msg198">
+ <trans-unit id="_msg202">
<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="_msg199">
+ <trans-unit id="_msg203">
<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="_msg200">
+ <trans-unit id="_msg204">
<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="_msg201">
+ <trans-unit id="_msg205">
<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="_msg202">
+ <trans-unit id="_msg206">
<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="_msg203">
+ <trans-unit id="_msg207">
<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="_msg204">
+ <trans-unit id="_msg208">
<source xml:space="preserve">Copy quantity</source>
<context-group purpose="location"><context context-type="linenumber">68</context></context-group>
</trans-unit>
- <trans-unit id="_msg205">
+ <trans-unit id="_msg209">
<source xml:space="preserve">Copy fee</source>
<context-group purpose="location"><context context-type="linenumber">70</context></context-group>
</trans-unit>
- <trans-unit id="_msg206">
+ <trans-unit id="_msg210">
<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="_msg207">
+ <trans-unit id="_msg211">
<source xml:space="preserve">Copy bytes</source>
<context-group purpose="location"><context context-type="linenumber">72</context></context-group>
</trans-unit>
- <trans-unit id="_msg208">
+ <trans-unit id="_msg212">
<source xml:space="preserve">Copy change</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
- <trans-unit id="_msg209">
+ <trans-unit id="_msg213">
<source xml:space="preserve">(%1 locked)</source>
<context-group purpose="location"><context context-type="linenumber">371</context></context-group>
</trans-unit>
- <trans-unit id="_msg210">
+ <trans-unit id="_msg214">
<source xml:space="preserve">Can vary +/- %1 satoshi(s) per input.</source>
<context-group purpose="location"><context context-type="linenumber">524</context></context-group>
</trans-unit>
- <trans-unit id="_msg211">
+ <trans-unit id="_msg215">
<source xml:space="preserve">(no label)</source>
<context-group purpose="location"><context context-type="linenumber">569</context></context-group>
<context-group purpose="location"><context context-type="linenumber">623</context></context-group>
</trans-unit>
- <trans-unit id="_msg212">
+ <trans-unit id="_msg216">
<source xml:space="preserve">change from %1 (%2)</source>
<context-group purpose="location"><context context-type="linenumber">616</context></context-group>
</trans-unit>
- <trans-unit id="_msg213">
+ <trans-unit id="_msg217">
<source xml:space="preserve">(change)</source>
<context-group purpose="location"><context context-type="linenumber">617</context></context-group>
</trans-unit>
@@ -942,114 +958,160 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../walletcontroller.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletActivity">
- <trans-unit id="_msg214">
+ <trans-unit id="_msg218">
<source xml:space="preserve">Create Wallet</source>
<context-group purpose="location"><context context-type="linenumber">246</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="_msg215">
+ <trans-unit id="_msg219">
<source xml:space="preserve">Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
<context-group purpose="location"><context context-type="linenumber">249</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="_msg216">
+ <trans-unit id="_msg220">
<source xml:space="preserve">Create wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
</trans-unit>
- <trans-unit id="_msg217">
+ <trans-unit id="_msg221">
<source xml:space="preserve">Create wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">284</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
</trans-unit>
- <trans-unit id="_msg218">
+ <trans-unit id="_msg222">
<source xml:space="preserve">Can&apos;t list signers</source>
- <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
</trans-unit>
- <trans-unit id="_msg219">
+ <trans-unit id="_msg223">
<source xml:space="preserve">Too many external signers found</source>
- <context-group purpose="location"><context context-type="linenumber">303</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="LoadWalletsActivity">
- <trans-unit id="_msg220">
+ <trans-unit id="_msg224">
<source xml:space="preserve">Load Wallets</source>
- <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">376</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="_msg221">
+ <trans-unit id="_msg225">
<source xml:space="preserve">Loading wallets…</source>
- <context-group purpose="location"><context context-type="linenumber">380</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">379</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="MigrateWalletActivity">
+ <trans-unit id="_msg226">
+ <source xml:space="preserve">Migrate wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">442</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg227">
+ <source xml:space="preserve">Are you sure you wish to migrate the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <context-group purpose="location"><context context-type="linenumber">443</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg228">
+ <source xml:space="preserve">Migrating the wallet will convert this wallet to one or more descriptor wallets. A new wallet backup will need to be made.
+If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts.
+If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.
+
+The migration process will create a backup of the wallet before migrating. This backup file will be named &lt;wallet name&gt;-&lt;timestamp&gt;.legacy.bak and can be found in the directory for this wallet. In the event of an incorrect migration, the backup can be restored with the &quot;Restore Wallet&quot; functionality.</source>
+ <context-group purpose="location"><context context-type="linenumber">444</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg229">
+ <source xml:space="preserve">Migrate Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">467</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg230">
+ <source xml:space="preserve">Migrating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <context-group purpose="location"><context context-type="linenumber">467</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg231">
+ <source xml:space="preserve">The wallet &apos;%1&apos; was migrated successfully.</source>
+ <context-group purpose="location"><context context-type="linenumber">473</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg232">
+ <source xml:space="preserve"> Watchonly scripts have been migrated to a new wallet named &apos;%1&apos;.</source>
+ <context-group purpose="location"><context context-type="linenumber">475</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg233">
+ <source xml:space="preserve"> Solvable but not watched scripts have been migrated to a new wallet named &apos;%1&apos;.</source>
+ <context-group purpose="location"><context context-type="linenumber">478</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg234">
+ <source xml:space="preserve">Migration failed</source>
+ <context-group purpose="location"><context context-type="linenumber">492</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg235">
+ <source xml:space="preserve">Migration Successful</source>
+ <context-group purpose="location"><context context-type="linenumber">494</context></context-group>
+ </trans-unit>
+ </group>
<group restype="x-trolltech-linguist-context" resname="OpenWalletActivity">
- <trans-unit id="_msg222">
+ <trans-unit id="_msg236">
<source xml:space="preserve">Open wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
- <trans-unit id="_msg223">
+ <trans-unit id="_msg237">
<source xml:space="preserve">Open wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg224">
+ <trans-unit id="_msg238">
<source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">346</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
- <trans-unit id="_msg225">
+ <trans-unit id="_msg239">
<source xml:space="preserve">Open Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">349</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="_msg226">
+ <trans-unit id="_msg240">
<source xml:space="preserve">Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <context-group purpose="location"><context context-type="linenumber">353</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">352</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="_msg227">
+ <trans-unit id="_msg241">
<source xml:space="preserve">Restore Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">403</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">402</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="_msg228">
+ <trans-unit id="_msg242">
<source xml:space="preserve">Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <context-group purpose="location"><context context-type="linenumber">406</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">405</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="_msg229">
+ <trans-unit id="_msg243">
<source xml:space="preserve">Restore wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">425</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">424</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="_msg230">
+ <trans-unit id="_msg244">
<source xml:space="preserve">Restore wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">428</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">427</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="_msg231">
+ <trans-unit id="_msg245">
<source xml:space="preserve">Restore wallet message</source>
- <context-group purpose="location"><context context-type="linenumber">431</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">430</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="_msg232">
+ <trans-unit id="_msg246">
<source xml:space="preserve">Close wallet</source>
<context-group purpose="location"><context context-type="linenumber">84</context></context-group>
</trans-unit>
- <trans-unit id="_msg233">
+ <trans-unit id="_msg247">
<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">85</context></context-group>
</trans-unit>
- <trans-unit id="_msg234">
+ <trans-unit id="_msg248">
<source xml:space="preserve">Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg235">
+ <trans-unit id="_msg249">
<source xml:space="preserve">Close all wallets</source>
<context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg236">
+ <trans-unit id="_msg250">
<source xml:space="preserve">Are you sure you wish to close all wallets?</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
@@ -1057,100 +1119,96 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/createwalletdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletDialog">
- <trans-unit id="_msg237">
+ <trans-unit id="_msg251">
<source xml:space="preserve">Create Wallet</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg238">
+ <trans-unit id="_msg252">
+ <source xml:space="preserve">You are one step away from creating your new wallet!</source>
+ <context-group purpose="location"><context context-type="linenumber">29</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg253">
+ <source xml:space="preserve">Please provide a name and, if desired, enable any advanced options</source>
+ <context-group purpose="location"><context context-type="linenumber">42</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg254">
<source xml:space="preserve">Wallet Name</source>
- <context-group purpose="location"><context context-type="linenumber">25</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">67</context></context-group>
</trans-unit>
- <trans-unit id="_msg239">
+ <trans-unit id="_msg255">
<source xml:space="preserve">Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">38</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">80</context></context-group>
</trans-unit>
- <trans-unit id="_msg240">
+ <trans-unit id="_msg256">
<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>
+ <context-group purpose="location"><context context-type="linenumber">89</context></context-group>
</trans-unit>
- <trans-unit id="_msg241">
+ <trans-unit id="_msg257">
<source xml:space="preserve">Encrypt Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">50</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">92</context></context-group>
</trans-unit>
- <trans-unit id="_msg242">
+ <trans-unit id="_msg258">
<source xml:space="preserve">Advanced Options</source>
- <context-group purpose="location"><context context-type="linenumber">76</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">118</context></context-group>
</trans-unit>
- <trans-unit id="_msg243">
+ <trans-unit id="_msg259">
<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>
+ <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
- <trans-unit id="_msg244">
+ <trans-unit id="_msg260">
<source xml:space="preserve">Disable Private Keys</source>
- <context-group purpose="location"><context context-type="linenumber">88</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg245">
+ <trans-unit id="_msg261">
<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>
+ <context-group purpose="location"><context context-type="linenumber">149</context></context-group>
</trans-unit>
- <trans-unit id="_msg246">
+ <trans-unit id="_msg262">
<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="_msg247">
- <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="_msg248">
- <source xml:space="preserve">Descriptor Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg249">
+ <trans-unit id="_msg263">
<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>
+ <context-group purpose="location"><context context-type="linenumber">159</context></context-group>
</trans-unit>
- <trans-unit id="_msg250">
+ <trans-unit id="_msg264">
<source xml:space="preserve">External signer</source>
- <context-group purpose="location"><context context-type="linenumber">121</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">162</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../createwalletdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletDialog">
- <trans-unit id="_msg251">
+ <trans-unit id="_msg265">
<source xml:space="preserve">Create</source>
<context-group purpose="location"><context context-type="linenumber">22</context></context-group>
</trans-unit>
- <trans-unit id="_msg252">
- <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="_msg253">
+ <trans-unit id="_msg266">
<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>
+ <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
<note annotates="source" from="developer">&quot;External signing&quot; means using devices such as hardware wallets.</note>
</trans-unit>
</group>
</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="_msg254">
+ <trans-unit id="_msg267">
<source xml:space="preserve">Edit Address</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg255">
+ <trans-unit id="_msg268">
<source xml:space="preserve">&amp;Label</source>
<context-group purpose="location"><context context-type="linenumber">25</context></context-group>
</trans-unit>
- <trans-unit id="_msg256">
+ <trans-unit id="_msg269">
<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="_msg257">
+ <trans-unit id="_msg270">
<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="_msg258">
+ <trans-unit id="_msg271">
<source xml:space="preserve">&amp;Address</source>
<context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
@@ -1158,35 +1216,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="_msg259">
+ <trans-unit id="_msg272">
<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="_msg260">
+ <trans-unit id="_msg273">
<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="_msg261">
+ <trans-unit id="_msg274">
<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="_msg262">
+ <trans-unit id="_msg275">
<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="_msg263">
+ <trans-unit id="_msg276">
<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="_msg264">
+ <trans-unit id="_msg277">
<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="_msg265">
+ <trans-unit id="_msg278">
<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="_msg266">
+ <trans-unit id="_msg279">
<source xml:space="preserve">New key generation failed.</source>
<context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
@@ -1194,94 +1252,94 @@ 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="_msg267">
+ <trans-unit id="_msg280">
<source xml:space="preserve">A new data directory will be created.</source>
<context-group purpose="location"><context context-type="linenumber">75</context></context-group>
</trans-unit>
- <trans-unit id="_msg268">
+ <trans-unit id="_msg281">
<source xml:space="preserve">name</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
</trans-unit>
- <trans-unit id="_msg269">
+ <trans-unit id="_msg282">
<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">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg270">
+ <trans-unit id="_msg283">
<source xml:space="preserve">Path already exists, and is not a directory.</source>
<context-group purpose="location"><context context-type="linenumber">102</context></context-group>
</trans-unit>
- <trans-unit id="_msg271">
+ <trans-unit id="_msg284">
<source xml:space="preserve">Cannot create data directory here.</source>
<context-group purpose="location"><context context-type="linenumber">109</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="Intro">
- <trans-unit id="_msg272">
+ <trans-unit id="_msg285">
<source xml:space="preserve">Bitcoin</source>
<context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">301</context></context-group>
- <trans-unit id="_msg273[0]">
+ <trans-unit id="_msg286[0]">
<source xml:space="preserve">%n GB of space available</source>
</trans-unit>
- <trans-unit id="_msg273[1]">
+ <trans-unit id="_msg286[1]">
<source xml:space="preserve">%n GB of space available</source>
</trans-unit>
</group>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">303</context></context-group>
- <trans-unit id="_msg274[0]">
+ <trans-unit id="_msg287[0]">
<source xml:space="preserve">(of %n GB needed)</source>
</trans-unit>
- <trans-unit id="_msg274[1]">
+ <trans-unit id="_msg287[1]">
<source xml:space="preserve">(of %n GB needed)</source>
</trans-unit>
</group>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">306</context></context-group>
- <trans-unit id="_msg275[0]">
+ <trans-unit id="_msg288[0]">
<source xml:space="preserve">(%n GB needed for full chain)</source>
</trans-unit>
- <trans-unit id="_msg275[1]">
+ <trans-unit id="_msg288[1]">
<source xml:space="preserve">(%n GB needed for full chain)</source>
</trans-unit>
</group>
- <trans-unit id="_msg276">
+ <trans-unit id="_msg289">
<source xml:space="preserve">Choose data directory</source>
<context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
- <trans-unit id="_msg277">
+ <trans-unit id="_msg290">
<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="_msg278">
+ <trans-unit id="_msg291">
<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="_msg279[0]">
+ <trans-unit id="_msg292[0]">
<source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source>
</trans-unit>
- <trans-unit id="_msg279[1]">
+ <trans-unit id="_msg292[1]">
<source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source>
</trans-unit>
</group>
- <trans-unit id="_msg280">
+ <trans-unit id="_msg293">
<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="_msg281">
+ <trans-unit id="_msg294">
<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="_msg282">
+ <trans-unit id="_msg295">
<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="_msg283">
+ <trans-unit id="_msg296">
<source xml:space="preserve">Error</source>
<context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
@@ -1289,25 +1347,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="_msg284">
+ <trans-unit id="_msg297">
<source xml:space="preserve">version</source>
<context-group purpose="location"><context context-type="linenumber">38</context></context-group>
</trans-unit>
- <trans-unit id="_msg285">
+ <trans-unit id="_msg298">
<source xml:space="preserve">About %1</source>
<context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
- <trans-unit id="_msg286">
+ <trans-unit id="_msg299">
<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="_msg287">
+ <trans-unit id="_msg300">
<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="_msg288">
+ <trans-unit id="_msg301">
<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>
@@ -1315,47 +1373,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="_msg289">
+ <trans-unit id="_msg302">
<source xml:space="preserve">Welcome</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg290">
+ <trans-unit id="_msg303">
<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="_msg291">
+ <trans-unit id="_msg304">
<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="_msg292">
+ <trans-unit id="_msg305">
<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="_msg293">
+ <trans-unit id="_msg306">
<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="_msg294">
+ <trans-unit id="_msg307">
<source xml:space="preserve"> GB</source>
<context-group purpose="location"><context context-type="linenumber">248</context></context-group>
</trans-unit>
- <trans-unit id="_msg295">
+ <trans-unit id="_msg308">
<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="_msg296">
+ <trans-unit id="_msg309">
<source xml:space="preserve">When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
<context-group purpose="location"><context context-type="linenumber">206</context></context-group>
</trans-unit>
- <trans-unit id="_msg297">
+ <trans-unit id="_msg310">
<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="_msg298">
+ <trans-unit id="_msg311">
<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="_msg299">
+ <trans-unit id="_msg312">
<source xml:space="preserve">Use a custom data directory:</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
@@ -1363,54 +1421,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="_msg300">
+ <trans-unit id="_msg313">
<source xml:space="preserve">Form</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg301">
+ <trans-unit id="_msg314">
<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="_msg302">
+ <trans-unit id="_msg315">
<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="_msg303">
+ <trans-unit id="_msg316">
<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="_msg304">
+ <trans-unit id="_msg317">
<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="_msg305">
+ <trans-unit id="_msg318">
<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="_msg306">
+ <trans-unit id="_msg319">
<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="_msg307">
+ <trans-unit id="_msg320">
<source xml:space="preserve">Progress</source>
<context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg308">
+ <trans-unit id="_msg321">
<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="_msg309">
+ <trans-unit id="_msg322">
<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="_msg310">
+ <trans-unit id="_msg323">
<source xml:space="preserve">Hide</source>
<context-group purpose="location"><context context-type="linenumber">342</context></context-group>
</trans-unit>
- <trans-unit id="_msg311">
+ <trans-unit id="_msg324">
<source xml:space="preserve">Esc</source>
<context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
@@ -1418,21 +1476,21 @@ 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="_msg312">
+ <trans-unit id="_msg325">
<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">31</context></context-group>
</trans-unit>
- <trans-unit id="_msg313">
+ <trans-unit id="_msg326">
<source xml:space="preserve">Unknown. Syncing Headers (%1, %2%)…</source>
<context-group purpose="location"><context context-type="linenumber">158</context></context-group>
</trans-unit>
- <trans-unit id="_msg314">
+ <trans-unit id="_msg327">
<source xml:space="preserve">Unknown. Pre-syncing Headers (%1, %2%)…</source>
<context-group purpose="location"><context context-type="linenumber">163</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg315">
+ <trans-unit id="_msg328">
<source xml:space="preserve">unknown</source>
<context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
@@ -1440,15 +1498,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="_msg316">
+ <trans-unit id="_msg329">
<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="_msg317">
+ <trans-unit id="_msg330">
<source xml:space="preserve">URI:</source>
<context-group purpose="location"><context context-type="linenumber">22</context></context-group>
</trans-unit>
- <trans-unit id="_msg318">
+ <trans-unit id="_msg331">
<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>
@@ -1457,310 +1515,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="_msg319">
+ <trans-unit id="_msg332">
<source xml:space="preserve">Options</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg320">
+ <trans-unit id="_msg333">
<source xml:space="preserve">&amp;Main</source>
<context-group purpose="location"><context context-type="linenumber">27</context></context-group>
</trans-unit>
- <trans-unit id="_msg321">
+ <trans-unit id="_msg334">
<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="_msg322">
+ <trans-unit id="_msg335">
<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="_msg323">
+ <trans-unit id="_msg336">
<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="_msg324">
+ <trans-unit id="_msg337">
<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="_msg325">
+ <trans-unit id="_msg338">
<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="_msg326">
+ <trans-unit id="_msg339">
<source xml:space="preserve">Full path to a %1 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="_msg327">
+ <trans-unit id="_msg340">
<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="_msg328">
+ <trans-unit id="_msg341">
<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="_msg329">
+ <trans-unit id="_msg342">
<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="_msg330">
+ <trans-unit id="_msg343">
<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="_msg331">
+ <trans-unit id="_msg344">
<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="_msg332">
+ <trans-unit id="_msg345">
<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="_msg333">
+ <trans-unit id="_msg346">
<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="_msg334">
+ <trans-unit id="_msg347">
<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="_msg335">
+ <trans-unit id="_msg348">
<source xml:space="preserve">&amp;Network</source>
<context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
- <trans-unit id="_msg336">
+ <trans-unit id="_msg349">
<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="_msg337">
+ <trans-unit id="_msg350">
<source xml:space="preserve">GB</source>
<context-group purpose="location"><context context-type="linenumber">71</context></context-group>
</trans-unit>
- <trans-unit id="_msg338">
+ <trans-unit id="_msg351">
<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="_msg339">
+ <trans-unit id="_msg352">
<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="_msg340">
+ <trans-unit id="_msg353">
<source xml:space="preserve">MiB</source>
<context-group purpose="location"><context context-type="linenumber">127</context></context-group>
</trans-unit>
- <trans-unit id="_msg341">
+ <trans-unit id="_msg354">
<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="_msg342">
+ <trans-unit id="_msg355">
<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="_msg343">
+ <trans-unit id="_msg356">
<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="_msg344">
+ <trans-unit id="_msg357">
<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="_msg345">
+ <trans-unit id="_msg358">
<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="_msg346">
+ <trans-unit id="_msg359">
<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="_msg347">
+ <trans-unit id="_msg360">
<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="_msg348">
+ <trans-unit id="_msg361">
<source xml:space="preserve">Expert</source>
<context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg349">
+ <trans-unit id="_msg362">
<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="_msg350">
+ <trans-unit id="_msg363">
<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="_msg351">
+ <trans-unit id="_msg364">
<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="_msg352">
+ <trans-unit id="_msg365">
<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="_msg353">
+ <trans-unit id="_msg366">
<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="_msg354">
+ <trans-unit id="_msg367">
<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="_msg355">
+ <trans-unit id="_msg368">
<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="_msg356">
+ <trans-unit id="_msg369">
<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="_msg357">
+ <trans-unit id="_msg370">
<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="_msg358">
+ <trans-unit id="_msg371">
<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="_msg359">
+ <trans-unit id="_msg372">
<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="_msg360">
+ <trans-unit id="_msg373">
<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="_msg361">
+ <trans-unit id="_msg374">
<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="_msg362">
+ <trans-unit id="_msg375">
<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="_msg363">
+ <trans-unit id="_msg376">
<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="_msg364">
+ <trans-unit id="_msg377">
<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="_msg365">
+ <trans-unit id="_msg378">
<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="_msg366">
+ <trans-unit id="_msg379">
<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="_msg367">
+ <trans-unit id="_msg380">
<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="_msg368">
+ <trans-unit id="_msg381">
<source xml:space="preserve">IPv4</source>
<context-group purpose="location"><context context-type="linenumber">467</context></context-group>
</trans-unit>
- <trans-unit id="_msg369">
+ <trans-unit id="_msg382">
<source xml:space="preserve">IPv6</source>
<context-group purpose="location"><context context-type="linenumber">490</context></context-group>
</trans-unit>
- <trans-unit id="_msg370">
+ <trans-unit id="_msg383">
<source xml:space="preserve">Tor</source>
<context-group purpose="location"><context context-type="linenumber">513</context></context-group>
</trans-unit>
- <trans-unit id="_msg371">
+ <trans-unit id="_msg384">
<source xml:space="preserve">&amp;Window</source>
<context-group purpose="location"><context context-type="linenumber">643</context></context-group>
</trans-unit>
- <trans-unit id="_msg372">
+ <trans-unit id="_msg385">
<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="_msg373">
+ <trans-unit id="_msg386">
<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="_msg374">
+ <trans-unit id="_msg387">
<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="_msg375">
+ <trans-unit id="_msg388">
<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="_msg376">
+ <trans-unit id="_msg389">
<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="_msg377">
+ <trans-unit id="_msg390">
<source xml:space="preserve">&amp;Display</source>
<context-group purpose="location"><context context-type="linenumber">696</context></context-group>
</trans-unit>
- <trans-unit id="_msg378">
+ <trans-unit id="_msg391">
<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="_msg379">
+ <trans-unit id="_msg392">
<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="_msg380">
+ <trans-unit id="_msg393">
<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="_msg381">
+ <trans-unit id="_msg394">
<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="_msg382">
+ <trans-unit id="_msg395">
<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="_msg383">
+ <trans-unit id="_msg396">
<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="_msg384">
+ <trans-unit id="_msg397">
<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="_msg385">
+ <trans-unit id="_msg398">
<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="_msg386">
+ <trans-unit id="_msg399">
<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="_msg387">
+ <trans-unit id="_msg400">
<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="_msg388">
+ <trans-unit id="_msg401">
<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="_msg389">
+ <trans-unit id="_msg402">
<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="_msg390">
+ <trans-unit id="_msg403">
<source xml:space="preserve">&amp;OK</source>
<context-group purpose="location"><context context-type="linenumber">1040</context></context-group>
</trans-unit>
- <trans-unit id="_msg391">
+ <trans-unit id="_msg404">
<source xml:space="preserve">&amp;Cancel</source>
<context-group purpose="location"><context context-type="linenumber">1053</context></context-group>
</trans-unit>
@@ -1768,71 +1826,71 @@ 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="_msg392">
+ <trans-unit id="_msg405">
<source xml:space="preserve">Compiled without external signing support (required for external signing)</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
<note annotates="source" from="developer">&quot;External signing&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg393">
+ <trans-unit id="_msg406">
<source xml:space="preserve">default</source>
<context-group purpose="location"><context context-type="linenumber">108</context></context-group>
</trans-unit>
- <trans-unit id="_msg394">
+ <trans-unit id="_msg407">
<source xml:space="preserve">none</source>
<context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg395">
+ <trans-unit id="_msg408">
<source xml:space="preserve">Confirm options reset</source>
<context-group purpose="location"><context context-type="linenumber">301</context></context-group>
<note annotates="source" from="developer">Window title text of pop-up window shown when the user has chosen to reset options.</note>
</trans-unit>
- <trans-unit id="_msg396">
+ <trans-unit id="_msg409">
<source xml:space="preserve">Client restart required to activate changes.</source>
<context-group purpose="location"><context context-type="linenumber">292</context></context-group>
<context-group purpose="location"><context context-type="linenumber">371</context></context-group>
<note annotates="source" from="developer">Text explaining that the settings changed will not come into effect until the client is restarted.</note>
</trans-unit>
- <trans-unit id="_msg397">
+ <trans-unit id="_msg410">
<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="_msg398">
+ <trans-unit id="_msg411">
<source xml:space="preserve">Client will be shut down. Do you want to proceed?</source>
<context-group purpose="location"><context context-type="linenumber">299</context></context-group>
<note annotates="source" from="developer">Text asking the user to confirm if they would like to proceed with a client shutdown.</note>
</trans-unit>
- <trans-unit id="_msg399">
+ <trans-unit id="_msg412">
<source xml:space="preserve">Configuration options</source>
<context-group purpose="location"><context context-type="linenumber">319</context></context-group>
<note annotates="source" from="developer">Window title text of pop-up box that allows opening up of configuration file.</note>
</trans-unit>
- <trans-unit id="_msg400">
+ <trans-unit id="_msg413">
<source xml:space="preserve">The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
<context-group purpose="location"><context context-type="linenumber">322</context></context-group>
<note annotates="source" from="developer">Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</note>
</trans-unit>
- <trans-unit id="_msg401">
+ <trans-unit id="_msg414">
<source xml:space="preserve">Continue</source>
<context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg402">
+ <trans-unit id="_msg415">
<source xml:space="preserve">Cancel</source>
<context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg403">
+ <trans-unit id="_msg416">
<source xml:space="preserve">Error</source>
<context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg404">
+ <trans-unit id="_msg417">
<source xml:space="preserve">The configuration file could not be opened.</source>
<context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg405">
+ <trans-unit id="_msg418">
<source xml:space="preserve">This change would require a client restart.</source>
<context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg406">
+ <trans-unit id="_msg419">
<source xml:space="preserve">The supplied proxy address is invalid.</source>
<context-group purpose="location"><context context-type="linenumber">403</context></context-group>
</trans-unit>
@@ -1840,7 +1898,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../optionsmodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OptionsModel">
- <trans-unit id="_msg407">
+ <trans-unit id="_msg420">
<source xml:space="preserve">Could not read setting &quot;%1&quot;, %2.</source>
<context-group purpose="location"><context context-type="linenumber">198</context></context-group>
</trans-unit>
@@ -1848,76 +1906,76 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/overviewpage.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OverviewPage">
- <trans-unit id="_msg408">
+ <trans-unit id="_msg421">
<source xml:space="preserve">Form</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg409">
+ <trans-unit id="_msg422">
<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="_msg410">
+ <trans-unit id="_msg423">
<source xml:space="preserve">Watch-only:</source>
<context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg411">
+ <trans-unit id="_msg424">
<source xml:space="preserve">Available:</source>
<context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
- <trans-unit id="_msg412">
+ <trans-unit id="_msg425">
<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="_msg413">
+ <trans-unit id="_msg426">
<source xml:space="preserve">Pending:</source>
<context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
- <trans-unit id="_msg414">
+ <trans-unit id="_msg427">
<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="_msg415">
+ <trans-unit id="_msg428">
<source xml:space="preserve">Immature:</source>
<context-group purpose="location"><context context-type="linenumber">239</context></context-group>
</trans-unit>
- <trans-unit id="_msg416">
+ <trans-unit id="_msg429">
<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="_msg417">
+ <trans-unit id="_msg430">
<source xml:space="preserve">Balances</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg418">
+ <trans-unit id="_msg431">
<source xml:space="preserve">Total:</source>
<context-group purpose="location"><context context-type="linenumber">200</context></context-group>
</trans-unit>
- <trans-unit id="_msg419">
+ <trans-unit id="_msg432">
<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="_msg420">
+ <trans-unit id="_msg433">
<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="_msg421">
+ <trans-unit id="_msg434">
<source xml:space="preserve">Spendable:</source>
<context-group purpose="location"><context context-type="linenumber">346</context></context-group>
</trans-unit>
- <trans-unit id="_msg422">
+ <trans-unit id="_msg435">
<source xml:space="preserve">Recent transactions</source>
<context-group purpose="location"><context context-type="linenumber">395</context></context-group>
</trans-unit>
- <trans-unit id="_msg423">
+ <trans-unit id="_msg436">
<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="_msg424">
+ <trans-unit id="_msg437">
<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="_msg425">
+ <trans-unit id="_msg438">
<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>
@@ -1925,7 +1983,7 @@ 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="_msg426">
+ <trans-unit id="_msg439">
<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">184</context></context-group>
</trans-unit>
@@ -1933,27 +1991,27 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/psbtoperationsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PSBTOperationsDialog">
- <trans-unit id="_msg427">
+ <trans-unit id="_msg440">
<source xml:space="preserve">PSBT Operations</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg428">
+ <trans-unit id="_msg441">
<source xml:space="preserve">Sign Tx</source>
<context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg429">
+ <trans-unit id="_msg442">
<source xml:space="preserve">Broadcast Tx</source>
<context-group purpose="location"><context context-type="linenumber">102</context></context-group>
</trans-unit>
- <trans-unit id="_msg430">
+ <trans-unit id="_msg443">
<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="_msg431">
+ <trans-unit id="_msg444">
<source xml:space="preserve">Save…</source>
<context-group purpose="location"><context context-type="linenumber">129</context></context-group>
</trans-unit>
- <trans-unit id="_msg432">
+ <trans-unit id="_msg445">
<source xml:space="preserve">Close</source>
<context-group purpose="location"><context context-type="linenumber">136</context></context-group>
</trans-unit>
@@ -1961,112 +2019,112 @@ 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="_msg433">
+ <trans-unit id="_msg446">
<source xml:space="preserve">Failed to load transaction: %1</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg434">
+ <trans-unit id="_msg447">
<source xml:space="preserve">Failed to sign transaction: %1</source>
<context-group purpose="location"><context context-type="linenumber">85</context></context-group>
</trans-unit>
- <trans-unit id="_msg435">
+ <trans-unit id="_msg448">
<source xml:space="preserve">Cannot sign inputs while wallet is locked.</source>
<context-group purpose="location"><context context-type="linenumber">93</context></context-group>
</trans-unit>
- <trans-unit id="_msg436">
+ <trans-unit id="_msg449">
<source xml:space="preserve">Could not sign any more inputs.</source>
<context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg437">
+ <trans-unit id="_msg450">
<source xml:space="preserve">Signed %1 inputs, but more signatures are still required.</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
</trans-unit>
- <trans-unit id="_msg438">
+ <trans-unit id="_msg451">
<source xml:space="preserve">Signed transaction successfully. Transaction is ready to broadcast.</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg439">
+ <trans-unit id="_msg452">
<source xml:space="preserve">Unknown error processing transaction.</source>
<context-group purpose="location"><context context-type="linenumber">112</context></context-group>
</trans-unit>
- <trans-unit id="_msg440">
+ <trans-unit id="_msg453">
<source xml:space="preserve">Transaction broadcast successfully! Transaction ID: %1</source>
<context-group purpose="location"><context context-type="linenumber">122</context></context-group>
</trans-unit>
- <trans-unit id="_msg441">
+ <trans-unit id="_msg454">
<source xml:space="preserve">Transaction broadcast failed: %1</source>
<context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
- <trans-unit id="_msg442">
+ <trans-unit id="_msg455">
<source xml:space="preserve">PSBT copied to clipboard.</source>
<context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg443">
+ <trans-unit id="_msg456">
<source xml:space="preserve">Save Transaction Data</source>
<context-group purpose="location"><context context-type="linenumber">157</context></context-group>
</trans-unit>
- <trans-unit id="_msg444">
+ <trans-unit id="_msg457">
<source xml:space="preserve">Partially Signed Transaction (Binary)</source>
<context-group purpose="location"><context context-type="linenumber">159</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="_msg445">
+ <trans-unit id="_msg458">
<source xml:space="preserve">PSBT saved to disk.</source>
<context-group purpose="location"><context context-type="linenumber">166</context></context-group>
</trans-unit>
- <trans-unit id="_msg446">
+ <trans-unit id="_msg459">
<source xml:space="preserve"> * Sends %1 to %2</source>
<context-group purpose="location"><context context-type="linenumber">182</context></context-group>
</trans-unit>
- <trans-unit id="_msg447">
+ <trans-unit id="_msg460">
<source xml:space="preserve">own address</source>
<context-group purpose="location"><context context-type="linenumber">186</context></context-group>
</trans-unit>
- <trans-unit id="_msg448">
+ <trans-unit id="_msg461">
<source xml:space="preserve">Unable to calculate transaction fee or total transaction amount.</source>
<context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg449">
+ <trans-unit id="_msg462">
<source xml:space="preserve">Pays transaction fee: </source>
<context-group purpose="location"><context context-type="linenumber">196</context></context-group>
</trans-unit>
- <trans-unit id="_msg450">
+ <trans-unit id="_msg463">
<source xml:space="preserve">Total Amount</source>
<context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg451">
+ <trans-unit id="_msg464">
<source xml:space="preserve">or</source>
<context-group purpose="location"><context context-type="linenumber">211</context></context-group>
</trans-unit>
- <trans-unit id="_msg452">
+ <trans-unit id="_msg465">
<source xml:space="preserve">Transaction has %1 unsigned inputs.</source>
<context-group purpose="location"><context context-type="linenumber">217</context></context-group>
</trans-unit>
- <trans-unit id="_msg453">
+ <trans-unit id="_msg466">
<source xml:space="preserve">Transaction is missing some information about inputs.</source>
<context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
- <trans-unit id="_msg454">
+ <trans-unit id="_msg467">
<source xml:space="preserve">Transaction still needs signature(s).</source>
<context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
- <trans-unit id="_msg455">
+ <trans-unit id="_msg468">
<source xml:space="preserve">(But no wallet is loaded.)</source>
<context-group purpose="location"><context context-type="linenumber">270</context></context-group>
</trans-unit>
- <trans-unit id="_msg456">
+ <trans-unit id="_msg469">
<source xml:space="preserve">(But this wallet cannot sign transactions.)</source>
<context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg457">
+ <trans-unit id="_msg470">
<source xml:space="preserve">(But this wallet does not have the right keys.)</source>
<context-group purpose="location"><context context-type="linenumber">276</context></context-group>
</trans-unit>
- <trans-unit id="_msg458">
+ <trans-unit id="_msg471">
<source xml:space="preserve">Transaction is fully signed and ready for broadcast.</source>
<context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg459">
+ <trans-unit id="_msg472">
<source xml:space="preserve">Transaction status is unknown.</source>
<context-group purpose="location"><context context-type="linenumber">288</context></context-group>
</trans-unit>
@@ -2074,37 +2132,37 @@ 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="_msg460">
+ <trans-unit id="_msg473">
<source xml:space="preserve">Payment request error</source>
<context-group purpose="location"><context context-type="linenumber">149</context></context-group>
</trans-unit>
- <trans-unit id="_msg461">
+ <trans-unit id="_msg474">
<source xml:space="preserve">Cannot start bitcoin: click-to-pay handler</source>
<context-group purpose="location"><context context-type="linenumber">150</context></context-group>
</trans-unit>
- <trans-unit id="_msg462">
+ <trans-unit id="_msg475">
<source xml:space="preserve">URI handling</source>
<context-group purpose="location"><context context-type="linenumber">198</context></context-group>
<context-group purpose="location"><context context-type="linenumber">214</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="_msg463">
+ <trans-unit id="_msg476">
<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">198</context></context-group>
</trans-unit>
- <trans-unit id="_msg464">
+ <trans-unit id="_msg477">
<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">215</context></context-group>
<context-group purpose="location"><context context-type="linenumber">238</context></context-group>
</trans-unit>
- <trans-unit id="_msg465">
+ <trans-unit id="_msg478">
<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">228</context></context-group>
</trans-unit>
- <trans-unit id="_msg466">
+ <trans-unit id="_msg479">
<source xml:space="preserve">Payment request file handling</source>
<context-group purpose="location"><context context-type="linenumber">237</context></context-group>
</trans-unit>
@@ -2112,52 +2170,52 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../peertablemodel.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PeerTableModel">
- <trans-unit id="_msg467">
+ <trans-unit id="_msg480">
<source xml:space="preserve">User Agent</source>
<context-group purpose="location"><context context-type="linenumber">112</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which contains the peer&apos;s User Agent string.</note>
</trans-unit>
- <trans-unit id="_msg468">
+ <trans-unit id="_msg481">
<source xml:space="preserve">Ping</source>
<context-group purpose="location"><context context-type="linenumber">103</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the current latency of the connection with the peer.</note>
</trans-unit>
- <trans-unit id="_msg469">
+ <trans-unit id="_msg482">
<source xml:space="preserve">Peer</source>
<context-group purpose="location"><context context-type="linenumber">85</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which contains a unique number used to identify a connection.</note>
</trans-unit>
- <trans-unit id="_msg470">
+ <trans-unit id="_msg483">
<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="_msg471">
+ <trans-unit id="_msg484">
<source xml:space="preserve">Direction</source>
<context-group purpose="location"><context context-type="linenumber">94</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the direction the peer connection was initiated from.</note>
</trans-unit>
- <trans-unit id="_msg472">
+ <trans-unit id="_msg485">
<source xml:space="preserve">Sent</source>
<context-group purpose="location"><context context-type="linenumber">106</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</note>
</trans-unit>
- <trans-unit id="_msg473">
+ <trans-unit id="_msg486">
<source xml:space="preserve">Received</source>
<context-group purpose="location"><context context-type="linenumber">109</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the total amount of network information we have received from the peer.</note>
</trans-unit>
- <trans-unit id="_msg474">
+ <trans-unit id="_msg487">
<source xml:space="preserve">Address</source>
<context-group purpose="location"><context context-type="linenumber">91</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</note>
</trans-unit>
- <trans-unit id="_msg475">
+ <trans-unit id="_msg488">
<source xml:space="preserve">Type</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which describes the type of peer connection. The &quot;type&quot; describes why the connection exists.</note>
</trans-unit>
- <trans-unit id="_msg476">
+ <trans-unit id="_msg489">
<source xml:space="preserve">Network</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which states the network the peer connected through.</note>
@@ -2166,12 +2224,12 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../peertablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PeerTableModel">
- <trans-unit id="_msg477">
+ <trans-unit id="_msg490">
<source xml:space="preserve">Inbound</source>
<context-group purpose="location"><context context-type="linenumber">77</context></context-group>
<note annotates="source" from="developer">An Inbound Connection from a Peer.</note>
</trans-unit>
- <trans-unit id="_msg478">
+ <trans-unit id="_msg491">
<source xml:space="preserve">Outbound</source>
<context-group purpose="location"><context context-type="linenumber">79</context></context-group>
<note annotates="source" from="developer">An Outbound Connection to a Peer.</note>
@@ -2180,7 +2238,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../bitcoinunits.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg479">
+ <trans-unit id="_msg492">
<source xml:space="preserve">Amount</source>
<context-group purpose="location"><context context-type="linenumber">197</context></context-group>
</trans-unit>
@@ -2188,190 +2246,190 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../guiutil.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg480">
+ <trans-unit id="_msg493">
<source xml:space="preserve">Enter a Bitcoin address (e.g. %1)</source>
<context-group purpose="location"><context context-type="linenumber">133</context></context-group>
</trans-unit>
- <trans-unit id="_msg481">
+ <trans-unit id="_msg494">
<source xml:space="preserve">Ctrl+W</source>
<context-group purpose="location"><context context-type="linenumber">421</context></context-group>
</trans-unit>
- <trans-unit id="_msg482">
+ <trans-unit id="_msg495">
<source xml:space="preserve">Unroutable</source>
<context-group purpose="location"><context context-type="linenumber">678</context></context-group>
</trans-unit>
- <trans-unit id="_msg483">
+ <trans-unit id="_msg496">
<source xml:space="preserve">IPv4</source>
<context-group purpose="location"><context context-type="linenumber">680</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">network name</context></context-group>
<note annotates="source" from="developer">Name of IPv4 network in peer info</note>
</trans-unit>
- <trans-unit id="_msg484">
+ <trans-unit id="_msg497">
<source xml:space="preserve">IPv6</source>
<context-group purpose="location"><context context-type="linenumber">682</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">network name</context></context-group>
<note annotates="source" from="developer">Name of IPv6 network in peer info</note>
</trans-unit>
- <trans-unit id="_msg485">
+ <trans-unit id="_msg498">
<source xml:space="preserve">Onion</source>
<context-group purpose="location"><context context-type="linenumber">684</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">network name</context></context-group>
<note annotates="source" from="developer">Name of Tor network in peer info</note>
</trans-unit>
- <trans-unit id="_msg486">
+ <trans-unit id="_msg499">
<source xml:space="preserve">I2P</source>
<context-group purpose="location"><context context-type="linenumber">686</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">network name</context></context-group>
<note annotates="source" from="developer">Name of I2P network in peer info</note>
</trans-unit>
- <trans-unit id="_msg487">
+ <trans-unit id="_msg500">
<source xml:space="preserve">CJDNS</source>
<context-group purpose="location"><context context-type="linenumber">688</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">network name</context></context-group>
<note annotates="source" from="developer">Name of CJDNS network in peer info</note>
</trans-unit>
- <trans-unit id="_msg488">
+ <trans-unit id="_msg501">
<source xml:space="preserve">Inbound</source>
<context-group purpose="location"><context context-type="linenumber">702</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="_msg489">
+ <trans-unit id="_msg502">
<source xml:space="preserve">Outbound</source>
<context-group purpose="location"><context context-type="linenumber">705</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="_msg490">
+ <trans-unit id="_msg503">
<source xml:space="preserve">Full Relay</source>
<context-group purpose="location"><context context-type="linenumber">710</context></context-group>
<note annotates="source" from="developer">Peer connection type that relays all network information.</note>
</trans-unit>
- <trans-unit id="_msg491">
+ <trans-unit id="_msg504">
<source xml:space="preserve">Block Relay</source>
<context-group purpose="location"><context context-type="linenumber">713</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="_msg492">
+ <trans-unit id="_msg505">
<source xml:space="preserve">Manual</source>
<context-group purpose="location"><context context-type="linenumber">715</context></context-group>
<note annotates="source" from="developer">Peer connection type established manually through one of several methods.</note>
</trans-unit>
- <trans-unit id="_msg493">
+ <trans-unit id="_msg506">
<source xml:space="preserve">Feeler</source>
<context-group purpose="location"><context context-type="linenumber">717</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="_msg494">
+ <trans-unit id="_msg507">
<source xml:space="preserve">Address Fetch</source>
<context-group purpose="location"><context context-type="linenumber">719</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="_msg495">
+ <trans-unit id="_msg508">
<source xml:space="preserve">%1 d</source>
<context-group purpose="location"><context context-type="linenumber">732</context></context-group>
<context-group purpose="location"><context context-type="linenumber">744</context></context-group>
</trans-unit>
- <trans-unit id="_msg496">
+ <trans-unit id="_msg509">
<source xml:space="preserve">%1 h</source>
<context-group purpose="location"><context context-type="linenumber">733</context></context-group>
<context-group purpose="location"><context context-type="linenumber">745</context></context-group>
</trans-unit>
- <trans-unit id="_msg497">
+ <trans-unit id="_msg510">
<source xml:space="preserve">%1 m</source>
<context-group purpose="location"><context context-type="linenumber">734</context></context-group>
<context-group purpose="location"><context context-type="linenumber">746</context></context-group>
</trans-unit>
- <trans-unit id="_msg498">
+ <trans-unit id="_msg511">
<source xml:space="preserve">%1 s</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>
<context-group purpose="location"><context context-type="linenumber">773</context></context-group>
</trans-unit>
- <trans-unit id="_msg499">
+ <trans-unit id="_msg512">
<source xml:space="preserve">None</source>
<context-group purpose="location"><context context-type="linenumber">761</context></context-group>
</trans-unit>
- <trans-unit id="_msg500">
+ <trans-unit id="_msg513">
<source xml:space="preserve">N/A</source>
<context-group purpose="location"><context context-type="linenumber">767</context></context-group>
</trans-unit>
- <trans-unit id="_msg501">
+ <trans-unit id="_msg514">
<source xml:space="preserve">%1 ms</source>
<context-group purpose="location"><context context-type="linenumber">768</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">786</context></context-group>
- <trans-unit id="_msg502[0]">
+ <trans-unit id="_msg515[0]">
<source xml:space="preserve">%n second(s)</source>
</trans-unit>
- <trans-unit id="_msg502[1]">
+ <trans-unit id="_msg515[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">790</context></context-group>
- <trans-unit id="_msg503[0]">
+ <trans-unit id="_msg516[0]">
<source xml:space="preserve">%n minute(s)</source>
</trans-unit>
- <trans-unit id="_msg503[1]">
+ <trans-unit id="_msg516[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">794</context></context-group>
- <trans-unit id="_msg504[0]">
+ <trans-unit id="_msg517[0]">
<source xml:space="preserve">%n hour(s)</source>
</trans-unit>
- <trans-unit id="_msg504[1]">
+ <trans-unit id="_msg517[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">798</context></context-group>
- <trans-unit id="_msg505[0]">
+ <trans-unit id="_msg518[0]">
<source xml:space="preserve">%n day(s)</source>
</trans-unit>
- <trans-unit id="_msg505[1]">
+ <trans-unit id="_msg518[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">802</context></context-group>
<context-group purpose="location"><context context-type="linenumber">808</context></context-group>
- <trans-unit id="_msg506[0]">
+ <trans-unit id="_msg519[0]">
<source xml:space="preserve">%n week(s)</source>
</trans-unit>
- <trans-unit id="_msg506[1]">
+ <trans-unit id="_msg519[1]">
<source xml:space="preserve">%n week(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg507">
+ <trans-unit id="_msg520">
<source xml:space="preserve">%1 and %2</source>
<context-group purpose="location"><context context-type="linenumber">808</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">808</context></context-group>
- <trans-unit id="_msg508[0]">
+ <trans-unit id="_msg521[0]">
<source xml:space="preserve">%n year(s)</source>
</trans-unit>
- <trans-unit id="_msg508[1]">
+ <trans-unit id="_msg521[1]">
<source xml:space="preserve">%n year(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg509">
+ <trans-unit id="_msg522">
<source xml:space="preserve">%1 B</source>
<context-group purpose="location"><context context-type="linenumber">816</context></context-group>
</trans-unit>
- <trans-unit id="_msg510">
+ <trans-unit id="_msg523">
<source xml:space="preserve">%1 kB</source>
<context-group purpose="location"><context context-type="linenumber">818</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">994</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">1004</context></context-group>
</trans-unit>
- <trans-unit id="_msg511">
+ <trans-unit id="_msg524">
<source xml:space="preserve">%1 MB</source>
<context-group purpose="location"><context context-type="linenumber">820</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">996</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">1006</context></context-group>
</trans-unit>
- <trans-unit id="_msg512">
+ <trans-unit id="_msg525">
<source xml:space="preserve">%1 GB</source>
<context-group purpose="location"><context context-type="linenumber">822</context></context-group>
</trans-unit>
@@ -2379,31 +2437,31 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../qrimagewidget.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QRImageWidget">
- <trans-unit id="_msg513">
+ <trans-unit id="_msg526">
<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="_msg514">
+ <trans-unit id="_msg527">
<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="_msg515">
+ <trans-unit id="_msg528">
<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="_msg516">
+ <trans-unit id="_msg529">
<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="_msg517">
+ <trans-unit id="_msg530">
<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="_msg518">
+ <trans-unit id="_msg531">
<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="_msg519">
+ <trans-unit id="_msg532">
<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>
@@ -2412,7 +2470,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="_msg520">
+ <trans-unit id="_msg533">
<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>
@@ -2428,316 +2486,334 @@ If you are receiving this error you should request the merchant provide a BIP21
<context-group purpose="location"><context context-type="linenumber">1051</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1077</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1103</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1126</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1149</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1172</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1129</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1155</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1178</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1201</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1227</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1250</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1273</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1296</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1319</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1345</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1224</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1253</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1279</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1325</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1348</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1371</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1394</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1417</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1440</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1463</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1486</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1512</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1535</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1558</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1584</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1397</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1423</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1446</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1469</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1492</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1515</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1538</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1564</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1587</context></context-group>
<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="linenumber">1688</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1714</context></context-group>
<context-group purpose="location"><context context-type="sourcefile">../rpcconsole.h</context><context context-type="linenumber">147</context></context-group>
</trans-unit>
- <trans-unit id="_msg521">
+ <trans-unit id="_msg534">
<source xml:space="preserve">Client version</source>
<context-group purpose="location"><context context-type="linenumber">65</context></context-group>
</trans-unit>
- <trans-unit id="_msg522">
+ <trans-unit id="_msg535">
<source xml:space="preserve">&amp;Information</source>
<context-group purpose="location"><context context-type="linenumber">43</context></context-group>
</trans-unit>
- <trans-unit id="_msg523">
+ <trans-unit id="_msg536">
<source xml:space="preserve">General</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
</trans-unit>
- <trans-unit id="_msg524">
+ <trans-unit id="_msg537">
<source xml:space="preserve">Datadir</source>
<context-group purpose="location"><context context-type="linenumber">114</context></context-group>
</trans-unit>
- <trans-unit id="_msg525">
+ <trans-unit id="_msg538">
<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="_msg526">
+ <trans-unit id="_msg539">
<source xml:space="preserve">Blocksdir</source>
<context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
- <trans-unit id="_msg527">
+ <trans-unit id="_msg540">
<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="_msg528">
+ <trans-unit id="_msg541">
<source xml:space="preserve">Startup time</source>
<context-group purpose="location"><context context-type="linenumber">172</context></context-group>
</trans-unit>
- <trans-unit id="_msg529">
+ <trans-unit id="_msg542">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1145</context></context-group>
</trans-unit>
- <trans-unit id="_msg530">
+ <trans-unit id="_msg543">
<source xml:space="preserve">Name</source>
<context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg531">
+ <trans-unit id="_msg544">
<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="_msg532">
+ <trans-unit id="_msg545">
<source xml:space="preserve">Block chain</source>
<context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg533">
+ <trans-unit id="_msg546">
<source xml:space="preserve">Memory Pool</source>
<context-group purpose="location"><context context-type="linenumber">319</context></context-group>
</trans-unit>
- <trans-unit id="_msg534">
+ <trans-unit id="_msg547">
<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="_msg535">
+ <trans-unit id="_msg548">
<source xml:space="preserve">Memory usage</source>
<context-group purpose="location"><context context-type="linenumber">349</context></context-group>
</trans-unit>
- <trans-unit id="_msg536">
+ <trans-unit id="_msg549">
<source xml:space="preserve">Wallet: </source>
<context-group purpose="location"><context context-type="linenumber">443</context></context-group>
</trans-unit>
- <trans-unit id="_msg537">
+ <trans-unit id="_msg550">
<source xml:space="preserve">(none)</source>
<context-group purpose="location"><context context-type="linenumber">454</context></context-group>
</trans-unit>
- <trans-unit id="_msg538">
+ <trans-unit id="_msg551">
<source xml:space="preserve">&amp;Reset</source>
<context-group purpose="location"><context context-type="linenumber">665</context></context-group>
</trans-unit>
- <trans-unit id="_msg539">
+ <trans-unit id="_msg552">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1505</context></context-group>
</trans-unit>
- <trans-unit id="_msg540">
+ <trans-unit id="_msg553">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1482</context></context-group>
</trans-unit>
- <trans-unit id="_msg541">
+ <trans-unit id="_msg554">
<source xml:space="preserve">&amp;Peers</source>
<context-group purpose="location"><context context-type="linenumber">866</context></context-group>
</trans-unit>
- <trans-unit id="_msg542">
+ <trans-unit id="_msg555">
<source xml:space="preserve">Banned peers</source>
<context-group purpose="location"><context context-type="linenumber">942</context></context-group>
</trans-unit>
- <trans-unit id="_msg543">
+ <trans-unit id="_msg556">
<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">1161</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">1171</context></context-group>
</trans-unit>
- <trans-unit id="_msg544">
- <source xml:space="preserve">Version</source>
+ <trans-unit id="_msg557">
+ <source xml:space="preserve">The transport layer version: %1</source>
+ <context-group purpose="location"><context context-type="linenumber">1090</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg558">
+ <source xml:space="preserve">Transport</source>
+ <context-group purpose="location"><context context-type="linenumber">1093</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg559">
+ <source xml:space="preserve">The BIP324 session ID string in hex, if any.</source>
<context-group purpose="location"><context context-type="linenumber">1116</context></context-group>
</trans-unit>
- <trans-unit id="_msg545">
+ <trans-unit id="_msg560">
+ <source xml:space="preserve">Session ID</source>
+ <context-group purpose="location"><context context-type="linenumber">1119</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg561">
+ <source xml:space="preserve">Version</source>
+ <context-group purpose="location"><context context-type="linenumber">1168</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg562">
<source xml:space="preserve">Whether we relay transactions to this peer.</source>
- <context-group purpose="location"><context context-type="linenumber">1188</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1240</context></context-group>
</trans-unit>
- <trans-unit id="_msg546">
+ <trans-unit id="_msg563">
<source xml:space="preserve">Transaction Relay</source>
- <context-group purpose="location"><context context-type="linenumber">1191</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1243</context></context-group>
</trans-unit>
- <trans-unit id="_msg547">
+ <trans-unit id="_msg564">
<source xml:space="preserve">Starting Block</source>
- <context-group purpose="location"><context context-type="linenumber">1240</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1292</context></context-group>
</trans-unit>
- <trans-unit id="_msg548">
+ <trans-unit id="_msg565">
<source xml:space="preserve">Synced Headers</source>
- <context-group purpose="location"><context context-type="linenumber">1263</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1315</context></context-group>
</trans-unit>
- <trans-unit id="_msg549">
+ <trans-unit id="_msg566">
<source xml:space="preserve">Synced Blocks</source>
- <context-group purpose="location"><context context-type="linenumber">1286</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1338</context></context-group>
</trans-unit>
- <trans-unit id="_msg550">
+ <trans-unit id="_msg567">
<source xml:space="preserve">Last Transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1361</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1413</context></context-group>
</trans-unit>
- <trans-unit id="_msg551">
+ <trans-unit id="_msg568">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1623</context></context-group>
</trans-unit>
- <trans-unit id="_msg552">
+ <trans-unit id="_msg569">
<source xml:space="preserve">Mapped AS</source>
- <context-group purpose="location"><context context-type="linenumber">1574</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1626</context></context-group>
</trans-unit>
- <trans-unit id="_msg553">
+ <trans-unit id="_msg570">
<source xml:space="preserve">Whether we relay addresses to this peer.</source>
- <context-group purpose="location"><context context-type="linenumber">1597</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1649</context></context-group>
<note annotates="source" from="developer">Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</note>
</trans-unit>
- <trans-unit id="_msg554">
+ <trans-unit id="_msg571">
<source xml:space="preserve">Address Relay</source>
- <context-group purpose="location"><context context-type="linenumber">1600</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1652</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="_msg555">
+ <trans-unit id="_msg572">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1675</context></context-group>
<note annotates="source" from="developer">Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</note>
</trans-unit>
- <trans-unit id="_msg556">
+ <trans-unit id="_msg573">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1701</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="_msg557">
+ <trans-unit id="_msg574">
<source xml:space="preserve">Addresses Processed</source>
- <context-group purpose="location"><context context-type="linenumber">1626</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1678</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="_msg558">
+ <trans-unit id="_msg575">
<source xml:space="preserve">Addresses Rate-Limited</source>
- <context-group purpose="location"><context context-type="linenumber">1652</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1704</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="_msg559">
+ <trans-unit id="_msg576">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1191</context></context-group>
</trans-unit>
- <trans-unit id="_msg560">
+ <trans-unit id="_msg577">
<source xml:space="preserve">Node window</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg561">
+ <trans-unit id="_msg578">
<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="_msg562">
+ <trans-unit id="_msg579">
<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="_msg563">
+ <trans-unit id="_msg580">
<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="_msg564">
+ <trans-unit id="_msg581">
<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="_msg565">
+ <trans-unit id="_msg582">
<source xml:space="preserve">Permissions</source>
<context-group purpose="location"><context context-type="linenumber">1041</context></context-group>
</trans-unit>
- <trans-unit id="_msg566">
+ <trans-unit id="_msg583">
<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="_msg567">
+ <trans-unit id="_msg584">
<source xml:space="preserve">Direction/Type</source>
<context-group purpose="location"><context context-type="linenumber">1067</context></context-group>
</trans-unit>
- <trans-unit id="_msg568">
+ <trans-unit id="_msg585">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1142</context></context-group>
</trans-unit>
- <trans-unit id="_msg569">
+ <trans-unit id="_msg586">
<source xml:space="preserve">Services</source>
- <context-group purpose="location"><context context-type="linenumber">1162</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1214</context></context-group>
</trans-unit>
- <trans-unit id="_msg570">
+ <trans-unit id="_msg587">
<source xml:space="preserve">High bandwidth BIP152 compact block relay: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1214</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1266</context></context-group>
</trans-unit>
- <trans-unit id="_msg571">
+ <trans-unit id="_msg588">
<source xml:space="preserve">High Bandwidth</source>
- <context-group purpose="location"><context context-type="linenumber">1217</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1269</context></context-group>
</trans-unit>
- <trans-unit id="_msg572">
+ <trans-unit id="_msg589">
<source xml:space="preserve">Connection Time</source>
- <context-group purpose="location"><context context-type="linenumber">1309</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1361</context></context-group>
</trans-unit>
- <trans-unit id="_msg573">
+ <trans-unit id="_msg590">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1384</context></context-group>
</trans-unit>
- <trans-unit id="_msg574">
+ <trans-unit id="_msg591">
<source xml:space="preserve">Last Block</source>
- <context-group purpose="location"><context context-type="linenumber">1335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1387</context></context-group>
</trans-unit>
- <trans-unit id="_msg575">
+ <trans-unit id="_msg592">
<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>
+ <context-group purpose="location"><context context-type="linenumber">1410</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="_msg576">
+ <trans-unit id="_msg593">
<source xml:space="preserve">Last Send</source>
- <context-group purpose="location"><context context-type="linenumber">1384</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1436</context></context-group>
</trans-unit>
- <trans-unit id="_msg577">
+ <trans-unit id="_msg594">
<source xml:space="preserve">Last Receive</source>
- <context-group purpose="location"><context context-type="linenumber">1407</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1459</context></context-group>
</trans-unit>
- <trans-unit id="_msg578">
+ <trans-unit id="_msg595">
<source xml:space="preserve">Ping Time</source>
- <context-group purpose="location"><context context-type="linenumber">1476</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1528</context></context-group>
</trans-unit>
- <trans-unit id="_msg579">
+ <trans-unit id="_msg596">
<source xml:space="preserve">The duration of a currently outstanding ping.</source>
- <context-group purpose="location"><context context-type="linenumber">1499</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1551</context></context-group>
</trans-unit>
- <trans-unit id="_msg580">
+ <trans-unit id="_msg597">
<source xml:space="preserve">Ping Wait</source>
- <context-group purpose="location"><context context-type="linenumber">1502</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1554</context></context-group>
</trans-unit>
- <trans-unit id="_msg581">
+ <trans-unit id="_msg598">
<source xml:space="preserve">Min Ping</source>
- <context-group purpose="location"><context context-type="linenumber">1525</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1577</context></context-group>
</trans-unit>
- <trans-unit id="_msg582">
+ <trans-unit id="_msg599">
<source xml:space="preserve">Time Offset</source>
- <context-group purpose="location"><context context-type="linenumber">1548</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1600</context></context-group>
</trans-unit>
- <trans-unit id="_msg583">
+ <trans-unit id="_msg600">
<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="_msg584">
+ <trans-unit id="_msg601">
<source xml:space="preserve">&amp;Open</source>
<context-group purpose="location"><context context-type="linenumber">400</context></context-group>
</trans-unit>
- <trans-unit id="_msg585">
+ <trans-unit id="_msg602">
<source xml:space="preserve">&amp;Console</source>
<context-group purpose="location"><context context-type="linenumber">426</context></context-group>
</trans-unit>
- <trans-unit id="_msg586">
+ <trans-unit id="_msg603">
<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="_msg587">
+ <trans-unit id="_msg604">
<source xml:space="preserve">Totals</source>
<context-group purpose="location"><context context-type="linenumber">681</context></context-group>
</trans-unit>
- <trans-unit id="_msg588">
+ <trans-unit id="_msg605">
<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="_msg589">
+ <trans-unit id="_msg606">
<source xml:space="preserve">Clear console</source>
<context-group purpose="location"><context context-type="linenumber">515</context></context-group>
</trans-unit>
@@ -2745,139 +2821,154 @@ 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="_msg590">
+ <trans-unit id="_msg607">
<source xml:space="preserve">In:</source>
- <context-group purpose="location"><context context-type="linenumber">958</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">968</context></context-group>
</trans-unit>
- <trans-unit id="_msg591">
+ <trans-unit id="_msg608">
<source xml:space="preserve">Out:</source>
- <context-group purpose="location"><context context-type="linenumber">959</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">969</context></context-group>
</trans-unit>
- <trans-unit id="_msg592">
+ <trans-unit id="_msg609">
<source xml:space="preserve">Inbound: initiated by peer</source>
- <context-group purpose="location"><context context-type="linenumber">495</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="_msg593">
+ <trans-unit id="_msg610">
<source xml:space="preserve">Outbound Full Relay: default</source>
- <context-group purpose="location"><context context-type="linenumber">499</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="_msg594">
+ <trans-unit id="_msg611">
<source xml:space="preserve">Outbound Block Relay: does not relay transactions or addresses</source>
- <context-group purpose="location"><context context-type="linenumber">502</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="_msg595">
+ <trans-unit id="_msg612">
<source xml:space="preserve">Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
- <context-group purpose="location"><context context-type="linenumber">507</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="_msg596">
+ <trans-unit id="_msg613">
<source xml:space="preserve">Outbound Feeler: short-lived, for testing addresses</source>
- <context-group purpose="location"><context context-type="linenumber">513</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="_msg597">
+ <trans-unit id="_msg614">
<source xml:space="preserve">Outbound Address Fetch: short-lived, for soliciting addresses</source>
- <context-group purpose="location"><context context-type="linenumber">516</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="_msg598">
+ <trans-unit id="_msg615">
+ <source xml:space="preserve">detecting: peer could be v1 or v2</source>
+ <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
+ <note annotates="source" from="developer">Explanatory text for &quot;detecting&quot; transport type.</note>
+ </trans-unit>
+ <trans-unit id="_msg616">
+ <source xml:space="preserve">v1: unencrypted, plaintext transport protocol</source>
+ <context-group purpose="location"><context context-type="linenumber">524</context></context-group>
+ <note annotates="source" from="developer">Explanatory text for v1 transport type.</note>
+ </trans-unit>
+ <trans-unit id="_msg617">
+ <source xml:space="preserve">v2: BIP324 encrypted transport protocol</source>
+ <context-group purpose="location"><context context-type="linenumber">526</context></context-group>
+ <note annotates="source" from="developer">Explanatory text for v2 transport type.</note>
+ </trans-unit>
+ <trans-unit id="_msg618">
<source xml:space="preserve">we selected the peer for high bandwidth relay</source>
- <context-group purpose="location"><context context-type="linenumber">520</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">530</context></context-group>
</trans-unit>
- <trans-unit id="_msg599">
+ <trans-unit id="_msg619">
<source xml:space="preserve">the peer selected us for high bandwidth relay</source>
- <context-group purpose="location"><context context-type="linenumber">521</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">531</context></context-group>
</trans-unit>
- <trans-unit id="_msg600">
+ <trans-unit id="_msg620">
<source xml:space="preserve">no high bandwidth relay selected</source>
- <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">532</context></context-group>
</trans-unit>
- <trans-unit id="_msg601">
+ <trans-unit id="_msg621">
<source xml:space="preserve">Ctrl++</source>
- <context-group purpose="location"><context context-type="linenumber">535</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">545</context></context-group>
<note annotates="source" from="developer">Main shortcut to increase the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg602">
+ <trans-unit id="_msg622">
<source xml:space="preserve">Ctrl+=</source>
- <context-group purpose="location"><context context-type="linenumber">537</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">547</context></context-group>
<note annotates="source" from="developer">Secondary shortcut to increase the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg603">
+ <trans-unit id="_msg623">
<source xml:space="preserve">Ctrl+-</source>
- <context-group purpose="location"><context context-type="linenumber">541</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">551</context></context-group>
<note annotates="source" from="developer">Main shortcut to decrease the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg604">
+ <trans-unit id="_msg624">
<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">553</context></context-group>
<note annotates="source" from="developer">Secondary shortcut to decrease the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg605">
+ <trans-unit id="_msg625">
<source xml:space="preserve">&amp;Copy address</source>
- <context-group purpose="location"><context context-type="linenumber">694</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">704</context></context-group>
<note annotates="source" from="developer">Context menu action to copy the address of a peer.</note>
</trans-unit>
- <trans-unit id="_msg606">
+ <trans-unit id="_msg626">
<source xml:space="preserve">&amp;Disconnect</source>
- <context-group purpose="location"><context context-type="linenumber">698</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">708</context></context-group>
</trans-unit>
- <trans-unit id="_msg607">
+ <trans-unit id="_msg627">
<source xml:space="preserve">1 &amp;hour</source>
- <context-group purpose="location"><context context-type="linenumber">699</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">709</context></context-group>
</trans-unit>
- <trans-unit id="_msg608">
+ <trans-unit id="_msg628">
<source xml:space="preserve">1 d&amp;ay</source>
- <context-group purpose="location"><context context-type="linenumber">700</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">710</context></context-group>
</trans-unit>
- <trans-unit id="_msg609">
+ <trans-unit id="_msg629">
<source xml:space="preserve">1 &amp;week</source>
- <context-group purpose="location"><context context-type="linenumber">701</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">711</context></context-group>
</trans-unit>
- <trans-unit id="_msg610">
+ <trans-unit id="_msg630">
<source xml:space="preserve">1 &amp;year</source>
- <context-group purpose="location"><context context-type="linenumber">702</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">712</context></context-group>
</trans-unit>
- <trans-unit id="_msg611">
+ <trans-unit id="_msg631">
<source xml:space="preserve">&amp;Copy IP/Netmask</source>
- <context-group purpose="location"><context context-type="linenumber">728</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">738</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="_msg612">
+ <trans-unit id="_msg632">
<source xml:space="preserve">&amp;Unban</source>
- <context-group purpose="location"><context context-type="linenumber">732</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">742</context></context-group>
</trans-unit>
- <trans-unit id="_msg613">
+ <trans-unit id="_msg633">
<source xml:space="preserve">Network activity disabled</source>
- <context-group purpose="location"><context context-type="linenumber">962</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">972</context></context-group>
</trans-unit>
- <trans-unit id="_msg614">
+ <trans-unit id="_msg634">
<source xml:space="preserve">Executing command without any wallet</source>
- <context-group purpose="location"><context context-type="linenumber">1041</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1051</context></context-group>
</trans-unit>
- <trans-unit id="_msg615">
+ <trans-unit id="_msg635">
<source xml:space="preserve">Ctrl+I</source>
- <context-group purpose="location"><context context-type="linenumber">1357</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1376</context></context-group>
</trans-unit>
- <trans-unit id="_msg616">
+ <trans-unit id="_msg636">
<source xml:space="preserve">Ctrl+T</source>
- <context-group purpose="location"><context context-type="linenumber">1358</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1377</context></context-group>
</trans-unit>
- <trans-unit id="_msg617">
+ <trans-unit id="_msg637">
<source xml:space="preserve">Ctrl+N</source>
- <context-group purpose="location"><context context-type="linenumber">1359</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1378</context></context-group>
</trans-unit>
- <trans-unit id="_msg618">
+ <trans-unit id="_msg638">
<source xml:space="preserve">Ctrl+P</source>
- <context-group purpose="location"><context context-type="linenumber">1360</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1379</context></context-group>
</trans-unit>
- <trans-unit id="_msg619">
+ <trans-unit id="_msg639">
<source xml:space="preserve">Executing command using &quot;%1&quot; wallet</source>
- <context-group purpose="location"><context context-type="linenumber">1039</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1049</context></context-group>
</trans-unit>
- <trans-unit id="_msg620">
+ <trans-unit id="_msg640">
<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.
@@ -2885,51 +2976,51 @@ 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">892</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">902</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="_msg621">
+ <trans-unit id="_msg641">
<source xml:space="preserve">Executing…</source>
- <context-group purpose="location"><context context-type="linenumber">1049</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1059</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="_msg622">
+ <trans-unit id="_msg642">
<source xml:space="preserve">(peer: %1)</source>
- <context-group purpose="location"><context context-type="linenumber">1167</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1177</context></context-group>
</trans-unit>
- <trans-unit id="_msg623">
+ <trans-unit id="_msg643">
<source xml:space="preserve">via %1</source>
- <context-group purpose="location"><context context-type="linenumber">1169</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1179</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="_msg624">
+ <trans-unit id="_msg644">
<source xml:space="preserve">Yes</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg625">
+ <trans-unit id="_msg645">
<source xml:space="preserve">No</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg626">
+ <trans-unit id="_msg646">
<source xml:space="preserve">To</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg627">
+ <trans-unit id="_msg647">
<source xml:space="preserve">From</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg628">
+ <trans-unit id="_msg648">
<source xml:space="preserve">Ban for</source>
<context-group purpose="location"><context context-type="linenumber">147</context></context-group>
</trans-unit>
- <trans-unit id="_msg629">
+ <trans-unit id="_msg649">
<source xml:space="preserve">Never</source>
<context-group purpose="location"><context context-type="linenumber">189</context></context-group>
</trans-unit>
- <trans-unit id="_msg630">
+ <trans-unit id="_msg650">
<source xml:space="preserve">Unknown</source>
<context-group purpose="location"><context context-type="linenumber">147</context></context-group>
</trans-unit>
@@ -2937,72 +3028,72 @@ For more information on using this console, type %6.
</body></file>
<file original="../forms/receivecoinsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ReceiveCoinsDialog">
- <trans-unit id="_msg631">
+ <trans-unit id="_msg651">
<source xml:space="preserve">&amp;Amount:</source>
<context-group purpose="location"><context context-type="linenumber">37</context></context-group>
</trans-unit>
- <trans-unit id="_msg632">
+ <trans-unit id="_msg652">
<source xml:space="preserve">&amp;Label:</source>
<context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg633">
+ <trans-unit id="_msg653">
<source xml:space="preserve">&amp;Message:</source>
<context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg634">
+ <trans-unit id="_msg654">
<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="_msg635">
+ <trans-unit id="_msg655">
<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="_msg636">
+ <trans-unit id="_msg656">
<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="_msg637">
+ <trans-unit id="_msg657">
<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="_msg638">
+ <trans-unit id="_msg658">
<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="_msg639">
+ <trans-unit id="_msg659">
<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="_msg640">
+ <trans-unit id="_msg660">
<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="_msg641">
+ <trans-unit id="_msg661">
<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="_msg642">
+ <trans-unit id="_msg662">
<source xml:space="preserve">Clear</source>
<context-group purpose="location"><context context-type="linenumber">137</context></context-group>
</trans-unit>
- <trans-unit id="_msg643">
+ <trans-unit id="_msg663">
<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="_msg644">
+ <trans-unit id="_msg664">
<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="_msg645">
+ <trans-unit id="_msg665">
<source xml:space="preserve">Show</source>
<context-group purpose="location"><context context-type="linenumber">301</context></context-group>
</trans-unit>
- <trans-unit id="_msg646">
+ <trans-unit id="_msg666">
<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="_msg647">
+ <trans-unit id="_msg667">
<source xml:space="preserve">Remove</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
@@ -3010,63 +3101,63 @@ 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="_msg648">
+ <trans-unit id="_msg668">
<source xml:space="preserve">Copy &amp;URI</source>
<context-group purpose="location"><context context-type="linenumber">46</context></context-group>
</trans-unit>
- <trans-unit id="_msg649">
+ <trans-unit id="_msg669">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">47</context></context-group>
</trans-unit>
- <trans-unit id="_msg650">
+ <trans-unit id="_msg670">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">48</context></context-group>
</trans-unit>
- <trans-unit id="_msg651">
+ <trans-unit id="_msg671">
<source xml:space="preserve">Copy &amp;message</source>
<context-group purpose="location"><context context-type="linenumber">49</context></context-group>
</trans-unit>
- <trans-unit id="_msg652">
+ <trans-unit id="_msg672">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg653">
+ <trans-unit id="_msg673">
<source xml:space="preserve">Base58 (Legacy)</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg654">
+ <trans-unit id="_msg674">
<source xml:space="preserve">Not recommended due to higher fees and less protection against typos.</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg655">
+ <trans-unit id="_msg675">
<source xml:space="preserve">Base58 (P2SH-SegWit)</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
</trans-unit>
- <trans-unit id="_msg656">
+ <trans-unit id="_msg676">
<source xml:space="preserve">Generates an address compatible with older wallets.</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
</trans-unit>
- <trans-unit id="_msg657">
+ <trans-unit id="_msg677">
<source xml:space="preserve">Bech32 (SegWit)</source>
<context-group purpose="location"><context context-type="linenumber">98</context></context-group>
</trans-unit>
- <trans-unit id="_msg658">
+ <trans-unit id="_msg678">
<source xml:space="preserve">Generates a native segwit address (BIP-173). Some old wallets don&apos;t support it.</source>
<context-group purpose="location"><context context-type="linenumber">98</context></context-group>
</trans-unit>
- <trans-unit id="_msg659">
+ <trans-unit id="_msg679">
<source xml:space="preserve">Bech32m (Taproot)</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg660">
+ <trans-unit id="_msg680">
<source xml:space="preserve">Bech32m (BIP-350) is an upgrade to Bech32, wallet support is still limited.</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg661">
+ <trans-unit id="_msg681">
<source xml:space="preserve">Could not unlock wallet.</source>
<context-group purpose="location"><context context-type="linenumber">175</context></context-group>
</trans-unit>
- <trans-unit id="_msg662">
+ <trans-unit id="_msg682">
<source xml:space="preserve">Could not generate new %1 address</source>
<context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
@@ -3074,51 +3165,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="_msg663">
+ <trans-unit id="_msg683">
<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="_msg664">
+ <trans-unit id="_msg684">
<source xml:space="preserve">Address:</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg665">
+ <trans-unit id="_msg685">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">119</context></context-group>
</trans-unit>
- <trans-unit id="_msg666">
+ <trans-unit id="_msg686">
<source xml:space="preserve">Label:</source>
<context-group purpose="location"><context context-type="linenumber">148</context></context-group>
</trans-unit>
- <trans-unit id="_msg667">
+ <trans-unit id="_msg687">
<source xml:space="preserve">Message:</source>
<context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg668">
+ <trans-unit id="_msg688">
<source xml:space="preserve">Wallet:</source>
<context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg669">
+ <trans-unit id="_msg689">
<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="_msg670">
+ <trans-unit id="_msg690">
<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="_msg671">
+ <trans-unit id="_msg691">
<source xml:space="preserve">&amp;Verify</source>
<context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg672">
+ <trans-unit id="_msg692">
<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="_msg673">
+ <trans-unit id="_msg693">
<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="_msg674">
+ <trans-unit id="_msg694">
<source xml:space="preserve">Payment information</source>
<context-group purpose="location"><context context-type="linenumber">39</context></context-group>
</trans-unit>
@@ -3126,7 +3217,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="_msg675">
+ <trans-unit id="_msg695">
<source xml:space="preserve">Request payment to %1</source>
<context-group purpose="location"><context context-type="linenumber">48</context></context-group>
</trans-unit>
@@ -3134,31 +3225,31 @@ For more information on using this console, type %6.
</body></file>
<file original="../recentrequeststablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="RecentRequestsTableModel">
- <trans-unit id="_msg676">
+ <trans-unit id="_msg696">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg677">
+ <trans-unit id="_msg697">
<source xml:space="preserve">Label</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg678">
+ <trans-unit id="_msg698">
<source xml:space="preserve">Message</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg679">
+ <trans-unit id="_msg699">
<source xml:space="preserve">(no label)</source>
<context-group purpose="location"><context context-type="linenumber">70</context></context-group>
</trans-unit>
- <trans-unit id="_msg680">
+ <trans-unit id="_msg700">
<source xml:space="preserve">(no message)</source>
<context-group purpose="location"><context context-type="linenumber">79</context></context-group>
</trans-unit>
- <trans-unit id="_msg681">
+ <trans-unit id="_msg701">
<source xml:space="preserve">(no amount requested)</source>
<context-group purpose="location"><context context-type="linenumber">87</context></context-group>
</trans-unit>
- <trans-unit id="_msg682">
+ <trans-unit id="_msg702">
<source xml:space="preserve">Requested</source>
<context-group purpose="location"><context context-type="linenumber">130</context></context-group>
</trans-unit>
@@ -3166,150 +3257,150 @@ For more information on using this console, type %6.
</body></file>
<file original="../forms/sendcoinsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendCoinsDialog">
- <trans-unit id="_msg683">
+ <trans-unit id="_msg703">
<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">762</context></context-group>
</trans-unit>
- <trans-unit id="_msg684">
+ <trans-unit id="_msg704">
<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="_msg685">
+ <trans-unit id="_msg705">
<source xml:space="preserve">automatically selected</source>
<context-group purpose="location"><context context-type="linenumber">120</context></context-group>
</trans-unit>
- <trans-unit id="_msg686">
+ <trans-unit id="_msg706">
<source xml:space="preserve">Insufficient funds!</source>
<context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
- <trans-unit id="_msg687">
+ <trans-unit id="_msg707">
<source xml:space="preserve">Quantity:</source>
<context-group purpose="location"><context context-type="linenumber">231</context></context-group>
</trans-unit>
- <trans-unit id="_msg688">
+ <trans-unit id="_msg708">
<source xml:space="preserve">Bytes:</source>
<context-group purpose="location"><context context-type="linenumber">266</context></context-group>
</trans-unit>
- <trans-unit id="_msg689">
+ <trans-unit id="_msg709">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">314</context></context-group>
</trans-unit>
- <trans-unit id="_msg690">
+ <trans-unit id="_msg710">
<source xml:space="preserve">Fee:</source>
<context-group purpose="location"><context context-type="linenumber">365</context></context-group>
</trans-unit>
- <trans-unit id="_msg691">
+ <trans-unit id="_msg711">
<source xml:space="preserve">After Fee:</source>
<context-group purpose="location"><context context-type="linenumber">419</context></context-group>
</trans-unit>
- <trans-unit id="_msg692">
+ <trans-unit id="_msg712">
<source xml:space="preserve">Change:</source>
<context-group purpose="location"><context context-type="linenumber">451</context></context-group>
</trans-unit>
- <trans-unit id="_msg693">
+ <trans-unit id="_msg713">
<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">495</context></context-group>
</trans-unit>
- <trans-unit id="_msg694">
+ <trans-unit id="_msg714">
<source xml:space="preserve">Custom change address</source>
<context-group purpose="location"><context context-type="linenumber">498</context></context-group>
</trans-unit>
- <trans-unit id="_msg695">
+ <trans-unit id="_msg715">
<source xml:space="preserve">Transaction Fee:</source>
<context-group purpose="location"><context context-type="linenumber">704</context></context-group>
</trans-unit>
- <trans-unit id="_msg696">
+ <trans-unit id="_msg716">
<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">742</context></context-group>
</trans-unit>
- <trans-unit id="_msg697">
+ <trans-unit id="_msg717">
<source xml:space="preserve">Warning: Fee estimation is currently not possible.</source>
<context-group purpose="location"><context context-type="linenumber">751</context></context-group>
</trans-unit>
- <trans-unit id="_msg698">
+ <trans-unit id="_msg718">
<source xml:space="preserve">per kilobyte</source>
<context-group purpose="location"><context context-type="linenumber">833</context></context-group>
</trans-unit>
- <trans-unit id="_msg699">
+ <trans-unit id="_msg719">
<source xml:space="preserve">Hide</source>
<context-group purpose="location"><context context-type="linenumber">780</context></context-group>
</trans-unit>
- <trans-unit id="_msg700">
+ <trans-unit id="_msg720">
<source xml:space="preserve">Recommended:</source>
<context-group purpose="location"><context context-type="linenumber">892</context></context-group>
</trans-unit>
- <trans-unit id="_msg701">
+ <trans-unit id="_msg721">
<source xml:space="preserve">Custom:</source>
<context-group purpose="location"><context context-type="linenumber">922</context></context-group>
</trans-unit>
- <trans-unit id="_msg702">
+ <trans-unit id="_msg722">
<source xml:space="preserve">Send to multiple recipients at once</source>
<context-group purpose="location"><context context-type="linenumber">1137</context></context-group>
</trans-unit>
- <trans-unit id="_msg703">
+ <trans-unit id="_msg723">
<source xml:space="preserve">Add &amp;Recipient</source>
<context-group purpose="location"><context context-type="linenumber">1140</context></context-group>
</trans-unit>
- <trans-unit id="_msg704">
+ <trans-unit id="_msg724">
<source xml:space="preserve">Clear all fields of the form.</source>
<context-group purpose="location"><context context-type="linenumber">1120</context></context-group>
</trans-unit>
- <trans-unit id="_msg705">
+ <trans-unit id="_msg725">
<source xml:space="preserve">Inputs…</source>
<context-group purpose="location"><context context-type="linenumber">110</context></context-group>
</trans-unit>
- <trans-unit id="_msg706">
+ <trans-unit id="_msg726">
<source xml:space="preserve">Choose…</source>
<context-group purpose="location"><context context-type="linenumber">718</context></context-group>
</trans-unit>
- <trans-unit id="_msg707">
+ <trans-unit id="_msg727">
<source xml:space="preserve">Hide transaction fee settings</source>
<context-group purpose="location"><context context-type="linenumber">777</context></context-group>
</trans-unit>
- <trans-unit id="_msg708">
+ <trans-unit id="_msg728">
<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">828</context></context-group>
</trans-unit>
- <trans-unit id="_msg709">
+ <trans-unit id="_msg729">
<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">863</context></context-group>
</trans-unit>
- <trans-unit id="_msg710">
+ <trans-unit id="_msg730">
<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">866</context></context-group>
</trans-unit>
- <trans-unit id="_msg711">
+ <trans-unit id="_msg731">
<source xml:space="preserve">(Smart fee not initialized yet. This usually takes a few blocks…)</source>
<context-group purpose="location"><context context-type="linenumber">971</context></context-group>
</trans-unit>
- <trans-unit id="_msg712">
+ <trans-unit id="_msg732">
<source xml:space="preserve">Confirmation time target:</source>
<context-group purpose="location"><context context-type="linenumber">997</context></context-group>
</trans-unit>
- <trans-unit id="_msg713">
+ <trans-unit id="_msg733">
<source xml:space="preserve">Enable Replace-By-Fee</source>
<context-group purpose="location"><context context-type="linenumber">1055</context></context-group>
</trans-unit>
- <trans-unit id="_msg714">
+ <trans-unit id="_msg734">
<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">1058</context></context-group>
</trans-unit>
- <trans-unit id="_msg715">
+ <trans-unit id="_msg735">
<source xml:space="preserve">Clear &amp;All</source>
<context-group purpose="location"><context context-type="linenumber">1123</context></context-group>
</trans-unit>
- <trans-unit id="_msg716">
+ <trans-unit id="_msg736">
<source xml:space="preserve">Balance:</source>
<context-group purpose="location"><context context-type="linenumber">1178</context></context-group>
</trans-unit>
- <trans-unit id="_msg717">
+ <trans-unit id="_msg737">
<source xml:space="preserve">Confirm the send action</source>
<context-group purpose="location"><context context-type="linenumber">1094</context></context-group>
</trans-unit>
- <trans-unit id="_msg718">
+ <trans-unit id="_msg738">
<source xml:space="preserve">S&amp;end</source>
<context-group purpose="location"><context context-type="linenumber">1097</context></context-group>
</trans-unit>
@@ -3317,231 +3408,231 @@ 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="_msg719">
+ <trans-unit id="_msg739">
<source xml:space="preserve">Copy quantity</source>
<context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg720">
+ <trans-unit id="_msg740">
<source xml:space="preserve">Copy amount</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg721">
+ <trans-unit id="_msg741">
<source xml:space="preserve">Copy fee</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
</trans-unit>
- <trans-unit id="_msg722">
+ <trans-unit id="_msg742">
<source xml:space="preserve">Copy after fee</source>
<context-group purpose="location"><context context-type="linenumber">98</context></context-group>
</trans-unit>
- <trans-unit id="_msg723">
+ <trans-unit id="_msg743">
<source xml:space="preserve">Copy bytes</source>
<context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg724">
+ <trans-unit id="_msg744">
<source xml:space="preserve">Copy change</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg725">
+ <trans-unit id="_msg745">
<source xml:space="preserve">%1 (%2 blocks)</source>
<context-group purpose="location"><context context-type="linenumber">172</context></context-group>
</trans-unit>
- <trans-unit id="_msg726">
+ <trans-unit id="_msg746">
<source xml:space="preserve">Sign on device</source>
<context-group purpose="location"><context context-type="linenumber">202</context></context-group>
<note annotates="source" from="developer">&quot;device&quot; usually means a hardware wallet.</note>
</trans-unit>
- <trans-unit id="_msg727">
+ <trans-unit id="_msg747">
<source xml:space="preserve">Connect your hardware wallet first.</source>
<context-group purpose="location"><context context-type="linenumber">205</context></context-group>
</trans-unit>
- <trans-unit id="_msg728">
+ <trans-unit id="_msg748">
<source xml:space="preserve">Set external signer script path in Options -&gt; Wallet</source>
<context-group purpose="location"><context context-type="linenumber">209</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="_msg729">
+ <trans-unit id="_msg749">
<source xml:space="preserve">Cr&amp;eate Unsigned</source>
<context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg730">
+ <trans-unit id="_msg750">
<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">213</context></context-group>
</trans-unit>
- <trans-unit id="_msg731">
+ <trans-unit id="_msg751">
<source xml:space="preserve"> from wallet &apos;%1&apos;</source>
<context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
- <trans-unit id="_msg732">
+ <trans-unit id="_msg752">
<source xml:space="preserve">%1 to &apos;%2&apos;</source>
<context-group purpose="location"><context context-type="linenumber">316</context></context-group>
</trans-unit>
- <trans-unit id="_msg733">
+ <trans-unit id="_msg753">
<source xml:space="preserve">%1 to %2</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg734">
+ <trans-unit id="_msg754">
<source xml:space="preserve">To review recipient list click &quot;Show Details…&quot;</source>
<context-group purpose="location"><context context-type="linenumber">388</context></context-group>
</trans-unit>
- <trans-unit id="_msg735">
+ <trans-unit id="_msg755">
<source xml:space="preserve">Sign failed</source>
<context-group purpose="location"><context context-type="linenumber">450</context></context-group>
</trans-unit>
- <trans-unit id="_msg736">
+ <trans-unit id="_msg756">
<source xml:space="preserve">External signer not found</source>
<context-group purpose="location"><context context-type="linenumber">455</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="_msg737">
+ <trans-unit id="_msg757">
<source xml:space="preserve">External signer failure</source>
<context-group purpose="location"><context context-type="linenumber">461</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="_msg738">
+ <trans-unit id="_msg758">
<source xml:space="preserve">Save Transaction Data</source>
<context-group purpose="location"><context context-type="linenumber">425</context></context-group>
</trans-unit>
- <trans-unit id="_msg739">
+ <trans-unit id="_msg759">
<source xml:space="preserve">Partially Signed Transaction (Binary)</source>
<context-group purpose="location"><context context-type="linenumber">427</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="_msg740">
+ <trans-unit id="_msg760">
<source xml:space="preserve">PSBT saved</source>
<context-group purpose="location"><context context-type="linenumber">435</context></context-group>
<note annotates="source" from="developer">Popup message when a PSBT has been saved to a file</note>
</trans-unit>
- <trans-unit id="_msg741">
+ <trans-unit id="_msg761">
<source xml:space="preserve">External balance:</source>
<context-group purpose="location"><context context-type="linenumber">708</context></context-group>
</trans-unit>
- <trans-unit id="_msg742">
+ <trans-unit id="_msg762">
<source xml:space="preserve">or</source>
<context-group purpose="location"><context context-type="linenumber">384</context></context-group>
</trans-unit>
- <trans-unit id="_msg743">
+ <trans-unit id="_msg763">
<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">366</context></context-group>
</trans-unit>
- <trans-unit id="_msg744">
+ <trans-unit id="_msg764">
<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">335</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="_msg745">
+ <trans-unit id="_msg765">
<source xml:space="preserve">Do you want to create this transaction?</source>
<context-group purpose="location"><context context-type="linenumber">329</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="_msg746">
+ <trans-unit id="_msg766">
<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">340</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="_msg747">
+ <trans-unit id="_msg767">
<source xml:space="preserve">Please, review your transaction.</source>
<context-group purpose="location"><context context-type="linenumber">343</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="_msg748">
+ <trans-unit id="_msg768">
<source xml:space="preserve">Transaction fee</source>
<context-group purpose="location"><context context-type="linenumber">351</context></context-group>
</trans-unit>
- <trans-unit id="_msg749">
+ <trans-unit id="_msg769">
<source xml:space="preserve">%1 kvB</source>
<context-group purpose="location"><context context-type="linenumber">356</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">PSBT transaction creation</context></context-group>
<note annotates="source" from="developer">When reviewing a newly created PSBT (via Send flow), the transaction fee is shown, with &quot;virtual size&quot; of the transaction displayed for context</note>
</trans-unit>
- <trans-unit id="_msg750">
+ <trans-unit id="_msg770">
<source xml:space="preserve">Not signalling Replace-By-Fee, BIP-125.</source>
<context-group purpose="location"><context context-type="linenumber">368</context></context-group>
</trans-unit>
- <trans-unit id="_msg751">
+ <trans-unit id="_msg771">
<source xml:space="preserve">Total Amount</source>
<context-group purpose="location"><context context-type="linenumber">381</context></context-group>
</trans-unit>
- <trans-unit id="_msg752">
+ <trans-unit id="_msg772">
<source xml:space="preserve">Unsigned Transaction</source>
<context-group purpose="location"><context context-type="linenumber">405</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">PSBT copied</context></context-group>
<note annotates="source" from="developer">Caption of &quot;PSBT has been copied&quot; messagebox</note>
</trans-unit>
- <trans-unit id="_msg753">
+ <trans-unit id="_msg773">
<source xml:space="preserve">The PSBT has been copied to the clipboard. You can also save it.</source>
<context-group purpose="location"><context context-type="linenumber">406</context></context-group>
</trans-unit>
- <trans-unit id="_msg754">
+ <trans-unit id="_msg774">
<source xml:space="preserve">PSBT saved to disk</source>
<context-group purpose="location"><context context-type="linenumber">435</context></context-group>
</trans-unit>
- <trans-unit id="_msg755">
+ <trans-unit id="_msg775">
<source xml:space="preserve">Confirm send coins</source>
<context-group purpose="location"><context context-type="linenumber">484</context></context-group>
</trans-unit>
- <trans-unit id="_msg756">
+ <trans-unit id="_msg776">
<source xml:space="preserve">Watch-only balance:</source>
<context-group purpose="location"><context context-type="linenumber">711</context></context-group>
</trans-unit>
- <trans-unit id="_msg757">
+ <trans-unit id="_msg777">
<source xml:space="preserve">The recipient address is not valid. Please recheck.</source>
<context-group purpose="location"><context context-type="linenumber">735</context></context-group>
</trans-unit>
- <trans-unit id="_msg758">
+ <trans-unit id="_msg778">
<source xml:space="preserve">The amount to pay must be larger than 0.</source>
<context-group purpose="location"><context context-type="linenumber">738</context></context-group>
</trans-unit>
- <trans-unit id="_msg759">
+ <trans-unit id="_msg779">
<source xml:space="preserve">The amount exceeds your balance.</source>
<context-group purpose="location"><context context-type="linenumber">741</context></context-group>
</trans-unit>
- <trans-unit id="_msg760">
+ <trans-unit id="_msg780">
<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">744</context></context-group>
</trans-unit>
- <trans-unit id="_msg761">
+ <trans-unit id="_msg781">
<source xml:space="preserve">Duplicate address found: addresses should only be used once each.</source>
<context-group purpose="location"><context context-type="linenumber">747</context></context-group>
</trans-unit>
- <trans-unit id="_msg762">
+ <trans-unit id="_msg782">
<source xml:space="preserve">Transaction creation failed!</source>
<context-group purpose="location"><context context-type="linenumber">750</context></context-group>
</trans-unit>
- <trans-unit id="_msg763">
+ <trans-unit id="_msg783">
<source xml:space="preserve">A fee higher than %1 is considered an absurdly high fee.</source>
<context-group purpose="location"><context context-type="linenumber">754</context></context-group>
</trans-unit>
- <trans-unit id="_msg764">
+ <trans-unit id="_msg784">
<source xml:space="preserve">%1/kvB</source>
<context-group purpose="location"><context context-type="linenumber">833</context></context-group>
<context-group purpose="location"><context context-type="linenumber">868</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">882</context></context-group>
- <trans-unit id="_msg765[0]">
+ <trans-unit id="_msg785[0]">
<source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source>
</trans-unit>
- <trans-unit id="_msg765[1]">
+ <trans-unit id="_msg785[1]">
<source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source>
</trans-unit>
</group>
- <trans-unit id="_msg766">
+ <trans-unit id="_msg786">
<source xml:space="preserve">Warning: Invalid Bitcoin address</source>
<context-group purpose="location"><context context-type="linenumber">977</context></context-group>
</trans-unit>
- <trans-unit id="_msg767">
+ <trans-unit id="_msg787">
<source xml:space="preserve">Warning: Unknown change address</source>
<context-group purpose="location"><context context-type="linenumber">982</context></context-group>
</trans-unit>
- <trans-unit id="_msg768">
+ <trans-unit id="_msg788">
<source xml:space="preserve">Confirm custom change address</source>
<context-group purpose="location"><context context-type="linenumber">985</context></context-group>
</trans-unit>
- <trans-unit id="_msg769">
+ <trans-unit id="_msg789">
<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">985</context></context-group>
</trans-unit>
- <trans-unit id="_msg770">
+ <trans-unit id="_msg790">
<source xml:space="preserve">(no label)</source>
<context-group purpose="location"><context context-type="linenumber">1006</context></context-group>
</trans-unit>
@@ -3549,68 +3640,68 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../forms/sendcoinsentry.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendCoinsEntry">
- <trans-unit id="_msg771">
+ <trans-unit id="_msg791">
<source xml:space="preserve">A&amp;mount:</source>
<context-group purpose="location"><context context-type="linenumber">151</context></context-group>
</trans-unit>
- <trans-unit id="_msg772">
+ <trans-unit id="_msg792">
<source xml:space="preserve">Pay &amp;To:</source>
<context-group purpose="location"><context context-type="linenumber">35</context></context-group>
</trans-unit>
- <trans-unit id="_msg773">
+ <trans-unit id="_msg793">
<source xml:space="preserve">&amp;Label:</source>
<context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
- <trans-unit id="_msg774">
+ <trans-unit id="_msg794">
<source xml:space="preserve">Choose previously used address</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg775">
+ <trans-unit id="_msg795">
<source xml:space="preserve">The Bitcoin address to send the payment to</source>
<context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg776">
+ <trans-unit id="_msg796">
<source xml:space="preserve">Alt+A</source>
<context-group purpose="location"><context context-type="linenumber">76</context></context-group>
</trans-unit>
- <trans-unit id="_msg777">
+ <trans-unit id="_msg797">
<source xml:space="preserve">Paste address from clipboard</source>
<context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg778">
+ <trans-unit id="_msg798">
<source xml:space="preserve">Alt+P</source>
<context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg779">
+ <trans-unit id="_msg799">
<source xml:space="preserve">Remove this entry</source>
<context-group purpose="location"><context context-type="linenumber">106</context></context-group>
</trans-unit>
- <trans-unit id="_msg780">
+ <trans-unit id="_msg800">
<source xml:space="preserve">The amount to send in the selected unit</source>
<context-group purpose="location"><context context-type="linenumber">166</context></context-group>
</trans-unit>
- <trans-unit id="_msg781">
+ <trans-unit id="_msg801">
<source xml:space="preserve">The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
<context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg782">
+ <trans-unit id="_msg802">
<source xml:space="preserve">S&amp;ubtract fee from amount</source>
<context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg783">
+ <trans-unit id="_msg803">
<source xml:space="preserve">Use available balance</source>
<context-group purpose="location"><context context-type="linenumber">183</context></context-group>
</trans-unit>
- <trans-unit id="_msg784">
+ <trans-unit id="_msg804">
<source xml:space="preserve">Message:</source>
<context-group purpose="location"><context context-type="linenumber">192</context></context-group>
</trans-unit>
- <trans-unit id="_msg785">
+ <trans-unit id="_msg805">
<source xml:space="preserve">Enter a label for this address to add it to the list of used addresses</source>
<context-group purpose="location"><context context-type="linenumber">141</context></context-group>
<context-group purpose="location"><context context-type="linenumber">144</context></context-group>
</trans-unit>
- <trans-unit id="_msg786">
+ <trans-unit id="_msg806">
<source xml:space="preserve">A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
@@ -3618,11 +3709,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../sendcoinsdialog.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendConfirmationDialog">
- <trans-unit id="_msg787">
+ <trans-unit id="_msg807">
<source xml:space="preserve">Send</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg788">
+ <trans-unit id="_msg808">
<source xml:space="preserve">Create Unsigned</source>
<context-group purpose="location"><context context-type="linenumber">148</context></context-group>
</trans-unit>
@@ -3630,105 +3721,105 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../forms/signverifymessagedialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SignVerifyMessageDialog">
- <trans-unit id="_msg789">
+ <trans-unit id="_msg809">
<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="_msg790">
+ <trans-unit id="_msg810">
<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="_msg791">
+ <trans-unit id="_msg811">
<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="_msg792">
+ <trans-unit id="_msg812">
<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="_msg793">
+ <trans-unit id="_msg813">
<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="_msg794">
+ <trans-unit id="_msg814">
<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="_msg795">
+ <trans-unit id="_msg815">
<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="_msg796">
+ <trans-unit id="_msg816">
<source xml:space="preserve">Alt+P</source>
<context-group purpose="location"><context context-type="linenumber">88</context></context-group>
</trans-unit>
- <trans-unit id="_msg797">
+ <trans-unit id="_msg817">
<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="_msg798">
+ <trans-unit id="_msg818">
<source xml:space="preserve">Signature</source>
<context-group purpose="location"><context context-type="linenumber">110</context></context-group>
</trans-unit>
- <trans-unit id="_msg799">
+ <trans-unit id="_msg819">
<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="_msg800">
+ <trans-unit id="_msg820">
<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="_msg801">
+ <trans-unit id="_msg821">
<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="_msg802">
+ <trans-unit id="_msg822">
<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="_msg803">
+ <trans-unit id="_msg823">
<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="_msg804">
+ <trans-unit id="_msg824">
<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="_msg805">
+ <trans-unit id="_msg825">
<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="_msg806">
+ <trans-unit id="_msg826">
<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="_msg807">
+ <trans-unit id="_msg827">
<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="_msg808">
+ <trans-unit id="_msg828">
<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="_msg809">
+ <trans-unit id="_msg829">
<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="_msg810">
+ <trans-unit id="_msg830">
<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="_msg811">
+ <trans-unit id="_msg831">
<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="_msg812">
+ <trans-unit id="_msg832">
<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>
@@ -3736,61 +3827,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="_msg813">
+ <trans-unit id="_msg833">
<source xml:space="preserve">The entered address is invalid.</source>
<context-group purpose="location"><context context-type="linenumber">119</context></context-group>
<context-group purpose="location"><context context-type="linenumber">218</context></context-group>
</trans-unit>
- <trans-unit id="_msg814">
+ <trans-unit id="_msg834">
<source xml:space="preserve">Please check the address and try again.</source>
<context-group purpose="location"><context context-type="linenumber">119</context></context-group>
<context-group purpose="location"><context context-type="linenumber">126</context></context-group>
<context-group purpose="location"><context context-type="linenumber">219</context></context-group>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg815">
+ <trans-unit id="_msg835">
<source xml:space="preserve">The entered address does not refer to a key.</source>
<context-group purpose="location"><context context-type="linenumber">126</context></context-group>
<context-group purpose="location"><context context-type="linenumber">225</context></context-group>
</trans-unit>
- <trans-unit id="_msg816">
+ <trans-unit id="_msg836">
<source xml:space="preserve">Wallet unlock was cancelled.</source>
<context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg817">
+ <trans-unit id="_msg837">
<source xml:space="preserve">No error</source>
<context-group purpose="location"><context context-type="linenumber">145</context></context-group>
</trans-unit>
- <trans-unit id="_msg818">
+ <trans-unit id="_msg838">
<source xml:space="preserve">Private key for the entered address is not available.</source>
<context-group purpose="location"><context context-type="linenumber">148</context></context-group>
</trans-unit>
- <trans-unit id="_msg819">
+ <trans-unit id="_msg839">
<source xml:space="preserve">Message signing failed.</source>
<context-group purpose="location"><context context-type="linenumber">151</context></context-group>
</trans-unit>
- <trans-unit id="_msg820">
+ <trans-unit id="_msg840">
<source xml:space="preserve">Message signed.</source>
<context-group purpose="location"><context context-type="linenumber">163</context></context-group>
</trans-unit>
- <trans-unit id="_msg821">
+ <trans-unit id="_msg841">
<source xml:space="preserve">The signature could not be decoded.</source>
<context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg822">
+ <trans-unit id="_msg842">
<source xml:space="preserve">Please check the signature and try again.</source>
<context-group purpose="location"><context context-type="linenumber">233</context></context-group>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg823">
+ <trans-unit id="_msg843">
<source xml:space="preserve">The signature did not match the message digest.</source>
<context-group purpose="location"><context context-type="linenumber">239</context></context-group>
</trans-unit>
- <trans-unit id="_msg824">
+ <trans-unit id="_msg844">
<source xml:space="preserve">Message verification failed.</source>
<context-group purpose="location"><context context-type="linenumber">245</context></context-group>
</trans-unit>
- <trans-unit id="_msg825">
+ <trans-unit id="_msg845">
<source xml:space="preserve">Message verified.</source>
<context-group purpose="location"><context context-type="linenumber">213</context></context-group>
</trans-unit>
@@ -3798,11 +3889,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="_msg826">
+ <trans-unit id="_msg846">
<source xml:space="preserve">(press q to shutdown and continue later)</source>
<context-group purpose="location"><context context-type="linenumber">177</context></context-group>
</trans-unit>
- <trans-unit id="_msg827">
+ <trans-unit id="_msg847">
<source xml:space="preserve">press q to shutdown</source>
<context-group purpose="location"><context context-type="linenumber">178</context></context-group>
</trans-unit>
@@ -3810,7 +3901,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="_msg828">
+ <trans-unit id="_msg848">
<source xml:space="preserve">kB/s</source>
<context-group purpose="location"><context context-type="linenumber">74</context></context-group>
</trans-unit>
@@ -3818,84 +3909,84 @@ 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="_msg829">
+ <trans-unit id="_msg849">
<source xml:space="preserve">conflicted with a transaction with %1 confirmations</source>
<context-group purpose="location"><context context-type="linenumber">44</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="_msg830">
+ <trans-unit id="_msg850">
<source xml:space="preserve">0/unconfirmed, in memory pool</source>
<context-group purpose="location"><context context-type="linenumber">51</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="_msg831">
+ <trans-unit id="_msg851">
<source xml:space="preserve">0/unconfirmed, not in memory pool</source>
<context-group purpose="location"><context context-type="linenumber">56</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="_msg832">
+ <trans-unit id="_msg852">
<source xml:space="preserve">abandoned</source>
<context-group purpose="location"><context context-type="linenumber">62</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="_msg833">
+ <trans-unit id="_msg853">
<source xml:space="preserve">%1/unconfirmed</source>
<context-group purpose="location"><context context-type="linenumber">70</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="_msg834">
+ <trans-unit id="_msg854">
<source xml:space="preserve">%1 confirmations</source>
<context-group purpose="location"><context context-type="linenumber">75</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="_msg835">
+ <trans-unit id="_msg855">
<source xml:space="preserve">Status</source>
<context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
- <trans-unit id="_msg836">
+ <trans-unit id="_msg856">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
- <trans-unit id="_msg837">
+ <trans-unit id="_msg857">
<source xml:space="preserve">Source</source>
<context-group purpose="location"><context context-type="linenumber">135</context></context-group>
</trans-unit>
- <trans-unit id="_msg838">
+ <trans-unit id="_msg858">
<source xml:space="preserve">Generated</source>
<context-group purpose="location"><context context-type="linenumber">135</context></context-group>
</trans-unit>
- <trans-unit id="_msg839">
+ <trans-unit id="_msg859">
<source xml:space="preserve">From</source>
<context-group purpose="location"><context context-type="linenumber">140</context></context-group>
<context-group purpose="location"><context context-type="linenumber">154</context></context-group>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg840">
+ <trans-unit id="_msg860">
<source xml:space="preserve">unknown</source>
<context-group purpose="location"><context context-type="linenumber">154</context></context-group>
</trans-unit>
- <trans-unit id="_msg841">
+ <trans-unit id="_msg861">
<source xml:space="preserve">To</source>
<context-group purpose="location"><context context-type="linenumber">155</context></context-group>
<context-group purpose="location"><context context-type="linenumber">175</context></context-group>
<context-group purpose="location"><context context-type="linenumber">245</context></context-group>
</trans-unit>
- <trans-unit id="_msg842">
+ <trans-unit id="_msg862">
<source xml:space="preserve">own address</source>
<context-group purpose="location"><context context-type="linenumber">157</context></context-group>
<context-group purpose="location"><context context-type="linenumber">252</context></context-group>
</trans-unit>
- <trans-unit id="_msg843">
+ <trans-unit id="_msg863">
<source xml:space="preserve">watch-only</source>
<context-group purpose="location"><context context-type="linenumber">157</context></context-group>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
<context-group purpose="location"><context context-type="linenumber">254</context></context-group>
</trans-unit>
- <trans-unit id="_msg844">
+ <trans-unit id="_msg864">
<source xml:space="preserve">label</source>
<context-group purpose="location"><context context-type="linenumber">159</context></context-group>
</trans-unit>
- <trans-unit id="_msg845">
+ <trans-unit id="_msg865">
<source xml:space="preserve">Credit</source>
<context-group purpose="location"><context context-type="linenumber">195</context></context-group>
<context-group purpose="location"><context context-type="linenumber">207</context></context-group>
@@ -3905,98 +3996,98 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">197</context></context-group>
- <trans-unit id="_msg846[0]">
+ <trans-unit id="_msg866[0]">
<source xml:space="preserve">matures in %n more block(s)</source>
</trans-unit>
- <trans-unit id="_msg846[1]">
+ <trans-unit id="_msg866[1]">
<source xml:space="preserve">matures in %n more block(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg847">
+ <trans-unit id="_msg867">
<source xml:space="preserve">not accepted</source>
<context-group purpose="location"><context context-type="linenumber">199</context></context-group>
</trans-unit>
- <trans-unit id="_msg848">
+ <trans-unit id="_msg868">
<source xml:space="preserve">Debit</source>
<context-group purpose="location"><context context-type="linenumber">259</context></context-group>
<context-group purpose="location"><context context-type="linenumber">285</context></context-group>
<context-group purpose="location"><context context-type="linenumber">348</context></context-group>
</trans-unit>
- <trans-unit id="_msg849">
+ <trans-unit id="_msg869">
<source xml:space="preserve">Total debit</source>
<context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg850">
+ <trans-unit id="_msg870">
<source xml:space="preserve">Total credit</source>
<context-group purpose="location"><context context-type="linenumber">270</context></context-group>
</trans-unit>
- <trans-unit id="_msg851">
+ <trans-unit id="_msg871">
<source xml:space="preserve">Transaction fee</source>
<context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
- <trans-unit id="_msg852">
+ <trans-unit id="_msg872">
<source xml:space="preserve">Net amount</source>
<context-group purpose="location"><context context-type="linenumber">297</context></context-group>
</trans-unit>
- <trans-unit id="_msg853">
+ <trans-unit id="_msg873">
<source xml:space="preserve">Message</source>
<context-group purpose="location"><context context-type="linenumber">303</context></context-group>
<context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
- <trans-unit id="_msg854">
+ <trans-unit id="_msg874">
<source xml:space="preserve">Comment</source>
<context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
- <trans-unit id="_msg855">
+ <trans-unit id="_msg875">
<source xml:space="preserve">Transaction ID</source>
<context-group purpose="location"><context context-type="linenumber">307</context></context-group>
</trans-unit>
- <trans-unit id="_msg856">
+ <trans-unit id="_msg876">
<source xml:space="preserve">Transaction total size</source>
<context-group purpose="location"><context context-type="linenumber">308</context></context-group>
</trans-unit>
- <trans-unit id="_msg857">
+ <trans-unit id="_msg877">
<source xml:space="preserve">Transaction virtual size</source>
<context-group purpose="location"><context context-type="linenumber">309</context></context-group>
</trans-unit>
- <trans-unit id="_msg858">
+ <trans-unit id="_msg878">
<source xml:space="preserve">Output index</source>
<context-group purpose="location"><context context-type="linenumber">310</context></context-group>
</trans-unit>
- <trans-unit id="_msg859">
+ <trans-unit id="_msg879">
<source xml:space="preserve"> (Certificate was not verified)</source>
<context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg860">
+ <trans-unit id="_msg880">
<source xml:space="preserve">Merchant</source>
<context-group purpose="location"><context context-type="linenumber">329</context></context-group>
</trans-unit>
- <trans-unit id="_msg861">
+ <trans-unit id="_msg881">
<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">337</context></context-group>
</trans-unit>
- <trans-unit id="_msg862">
+ <trans-unit id="_msg882">
<source xml:space="preserve">Debug information</source>
<context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
- <trans-unit id="_msg863">
+ <trans-unit id="_msg883">
<source xml:space="preserve">Transaction</source>
<context-group purpose="location"><context context-type="linenumber">353</context></context-group>
</trans-unit>
- <trans-unit id="_msg864">
+ <trans-unit id="_msg884">
<source xml:space="preserve">Inputs</source>
<context-group purpose="location"><context context-type="linenumber">356</context></context-group>
</trans-unit>
- <trans-unit id="_msg865">
+ <trans-unit id="_msg885">
<source xml:space="preserve">Amount</source>
<context-group purpose="location"><context context-type="linenumber">377</context></context-group>
</trans-unit>
- <trans-unit id="_msg866">
+ <trans-unit id="_msg886">
<source xml:space="preserve">true</source>
<context-group purpose="location"><context context-type="linenumber">378</context></context-group>
<context-group purpose="location"><context context-type="linenumber">379</context></context-group>
</trans-unit>
- <trans-unit id="_msg867">
+ <trans-unit id="_msg887">
<source xml:space="preserve">false</source>
<context-group purpose="location"><context context-type="linenumber">378</context></context-group>
<context-group purpose="location"><context context-type="linenumber">379</context></context-group>
@@ -4005,7 +4096,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../forms/transactiondescdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionDescDialog">
- <trans-unit id="_msg868">
+ <trans-unit id="_msg888">
<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>
@@ -4013,7 +4104,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="_msg869">
+ <trans-unit id="_msg889">
<source xml:space="preserve">Details for %1</source>
<context-group purpose="location"><context context-type="linenumber">18</context></context-group>
</trans-unit>
@@ -4021,306 +4112,298 @@ 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="_msg870">
+ <trans-unit id="_msg890">
<source xml:space="preserve">Date</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
</trans-unit>
- <trans-unit id="_msg871">
+ <trans-unit id="_msg891">
<source xml:space="preserve">Type</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
</trans-unit>
- <trans-unit id="_msg872">
+ <trans-unit id="_msg892">
<source xml:space="preserve">Label</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
</trans-unit>
- <trans-unit id="_msg873">
+ <trans-unit id="_msg893">
<source xml:space="preserve">Unconfirmed</source>
- <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
</trans-unit>
- <trans-unit id="_msg874">
+ <trans-unit id="_msg894">
<source xml:space="preserve">Abandoned</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="_msg875">
+ <trans-unit id="_msg895">
<source xml:space="preserve">Confirming (%1 of %2 recommended confirmations)</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="_msg876">
+ <trans-unit id="_msg896">
<source xml:space="preserve">Confirmed (%1 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="_msg877">
+ <trans-unit id="_msg897">
<source xml:space="preserve">Conflicted</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="_msg878">
+ <trans-unit id="_msg898">
<source xml:space="preserve">Immature (%1 confirmations, will be available after %2)</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="_msg879">
+ <trans-unit id="_msg899">
<source xml:space="preserve">Generated but not accepted</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="_msg880">
+ <trans-unit id="_msg900">
<source xml:space="preserve">Received with</source>
- <context-group purpose="location"><context context-type="linenumber">374</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg881">
+ <trans-unit id="_msg901">
<source xml:space="preserve">Received from</source>
- <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
</trans-unit>
- <trans-unit id="_msg882">
+ <trans-unit id="_msg902">
<source xml:space="preserve">Sent to</source>
- <context-group purpose="location"><context context-type="linenumber">379</context></context-group>
- </trans-unit>
- <trans-unit id="_msg883">
- <source xml:space="preserve">Payment to yourself</source>
- <context-group purpose="location"><context context-type="linenumber">381</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">380</context></context-group>
</trans-unit>
- <trans-unit id="_msg884">
+ <trans-unit id="_msg903">
<source xml:space="preserve">Mined</source>
- <context-group purpose="location"><context context-type="linenumber">383</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">382</context></context-group>
</trans-unit>
- <trans-unit id="_msg885">
+ <trans-unit id="_msg904">
<source xml:space="preserve">watch-only</source>
- <context-group purpose="location"><context context-type="linenumber">411</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">410</context></context-group>
</trans-unit>
- <trans-unit id="_msg886">
+ <trans-unit id="_msg905">
<source xml:space="preserve">(n/a)</source>
- <context-group purpose="location"><context context-type="linenumber">427</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">424</context></context-group>
</trans-unit>
- <trans-unit id="_msg887">
+ <trans-unit id="_msg906">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">634</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">629</context></context-group>
</trans-unit>
- <trans-unit id="_msg888">
+ <trans-unit id="_msg907">
<source xml:space="preserve">Transaction status. Hover over this field to show number of confirmations.</source>
- <context-group purpose="location"><context context-type="linenumber">673</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">668</context></context-group>
</trans-unit>
- <trans-unit id="_msg889">
+ <trans-unit id="_msg908">
<source xml:space="preserve">Date and time that the transaction was received.</source>
- <context-group purpose="location"><context context-type="linenumber">675</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">670</context></context-group>
</trans-unit>
- <trans-unit id="_msg890">
+ <trans-unit id="_msg909">
<source xml:space="preserve">Type of transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">677</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">672</context></context-group>
</trans-unit>
- <trans-unit id="_msg891">
+ <trans-unit id="_msg910">
<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">679</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">674</context></context-group>
</trans-unit>
- <trans-unit id="_msg892">
+ <trans-unit id="_msg911">
<source xml:space="preserve">User-defined intent/purpose of the transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">681</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">676</context></context-group>
</trans-unit>
- <trans-unit id="_msg893">
+ <trans-unit id="_msg912">
<source xml:space="preserve">Amount removed from or added to balance.</source>
- <context-group purpose="location"><context context-type="linenumber">683</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">678</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="_msg894">
+ <trans-unit id="_msg913">
<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="_msg895">
+ <trans-unit id="_msg914">
<source xml:space="preserve">Today</source>
<context-group purpose="location"><context context-type="linenumber">74</context></context-group>
</trans-unit>
- <trans-unit id="_msg896">
+ <trans-unit id="_msg915">
<source xml:space="preserve">This week</source>
<context-group purpose="location"><context context-type="linenumber">75</context></context-group>
</trans-unit>
- <trans-unit id="_msg897">
+ <trans-unit id="_msg916">
<source xml:space="preserve">This month</source>
<context-group purpose="location"><context context-type="linenumber">76</context></context-group>
</trans-unit>
- <trans-unit id="_msg898">
+ <trans-unit id="_msg917">
<source xml:space="preserve">Last month</source>
<context-group purpose="location"><context context-type="linenumber">77</context></context-group>
</trans-unit>
- <trans-unit id="_msg899">
+ <trans-unit id="_msg918">
<source xml:space="preserve">This year</source>
<context-group purpose="location"><context context-type="linenumber">78</context></context-group>
</trans-unit>
- <trans-unit id="_msg900">
+ <trans-unit id="_msg919">
<source xml:space="preserve">Received with</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg901">
+ <trans-unit id="_msg920">
<source xml:space="preserve">Sent to</source>
<context-group purpose="location"><context context-type="linenumber">92</context></context-group>
</trans-unit>
- <trans-unit id="_msg902">
- <source xml:space="preserve">To yourself</source>
- <context-group purpose="location"><context context-type="linenumber">94</context></context-group>
- </trans-unit>
- <trans-unit id="_msg903">
+ <trans-unit id="_msg921">
<source xml:space="preserve">Mined</source>
- <context-group purpose="location"><context context-type="linenumber">95</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">94</context></context-group>
</trans-unit>
- <trans-unit id="_msg904">
+ <trans-unit id="_msg922">
<source xml:space="preserve">Other</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg905">
+ <trans-unit id="_msg923">
<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>
+ <context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg906">
+ <trans-unit id="_msg924">
<source xml:space="preserve">Min amount</source>
- <context-group purpose="location"><context context-type="linenumber">105</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">104</context></context-group>
</trans-unit>
- <trans-unit id="_msg907">
+ <trans-unit id="_msg925">
<source xml:space="preserve">Range…</source>
<context-group purpose="location"><context context-type="linenumber">79</context></context-group>
</trans-unit>
- <trans-unit id="_msg908">
+ <trans-unit id="_msg926">
<source xml:space="preserve">&amp;Copy address</source>
- <context-group purpose="location"><context context-type="linenumber">169</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
</trans-unit>
- <trans-unit id="_msg909">
+ <trans-unit id="_msg927">
<source xml:space="preserve">Copy &amp;label</source>
- <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">169</context></context-group>
</trans-unit>
- <trans-unit id="_msg910">
+ <trans-unit id="_msg928">
<source xml:space="preserve">Copy &amp;amount</source>
- <context-group purpose="location"><context context-type="linenumber">171</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg911">
+ <trans-unit id="_msg929">
<source xml:space="preserve">Copy transaction &amp;ID</source>
- <context-group purpose="location"><context context-type="linenumber">172</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">171</context></context-group>
</trans-unit>
- <trans-unit id="_msg912">
+ <trans-unit id="_msg930">
<source xml:space="preserve">Copy &amp;raw transaction</source>
- <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">172</context></context-group>
</trans-unit>
- <trans-unit id="_msg913">
+ <trans-unit id="_msg931">
<source xml:space="preserve">Copy full transaction &amp;details</source>
- <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg914">
+ <trans-unit id="_msg932">
<source xml:space="preserve">&amp;Show transaction details</source>
- <context-group purpose="location"><context context-type="linenumber">175</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
</trans-unit>
- <trans-unit id="_msg915">
+ <trans-unit id="_msg933">
<source xml:space="preserve">Increase transaction &amp;fee</source>
- <context-group purpose="location"><context context-type="linenumber">177</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg916">
+ <trans-unit id="_msg934">
<source xml:space="preserve">A&amp;bandon transaction</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">179</context></context-group>
</trans-unit>
- <trans-unit id="_msg917">
+ <trans-unit id="_msg935">
<source xml:space="preserve">&amp;Edit address label</source>
- <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg918">
+ <trans-unit id="_msg936">
<source xml:space="preserve">Show in %1</source>
- <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">239</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="_msg919">
+ <trans-unit id="_msg937">
<source xml:space="preserve">Export Transaction History</source>
- <context-group purpose="location"><context context-type="linenumber">359</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
</trans-unit>
- <trans-unit id="_msg920">
+ <trans-unit id="_msg938">
<source xml:space="preserve">Comma separated file</source>
- <context-group purpose="location"><context context-type="linenumber">362</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">361</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="_msg921">
+ <trans-unit id="_msg939">
<source xml:space="preserve">Confirmed</source>
- <context-group purpose="location"><context context-type="linenumber">371</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">370</context></context-group>
</trans-unit>
- <trans-unit id="_msg922">
+ <trans-unit id="_msg940">
<source xml:space="preserve">Watch-only</source>
- <context-group purpose="location"><context context-type="linenumber">373</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">372</context></context-group>
</trans-unit>
- <trans-unit id="_msg923">
+ <trans-unit id="_msg941">
<source xml:space="preserve">Date</source>
- <context-group purpose="location"><context context-type="linenumber">374</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">373</context></context-group>
</trans-unit>
- <trans-unit id="_msg924">
+ <trans-unit id="_msg942">
<source xml:space="preserve">Type</source>
- <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">374</context></context-group>
</trans-unit>
- <trans-unit id="_msg925">
+ <trans-unit id="_msg943">
<source xml:space="preserve">Label</source>
- <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg926">
+ <trans-unit id="_msg944">
<source xml:space="preserve">Address</source>
- <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
</trans-unit>
- <trans-unit id="_msg927">
+ <trans-unit id="_msg945">
<source xml:space="preserve">ID</source>
- <context-group purpose="location"><context context-type="linenumber">379</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
</trans-unit>
- <trans-unit id="_msg928">
+ <trans-unit id="_msg946">
<source xml:space="preserve">Exporting Failed</source>
- <context-group purpose="location"><context context-type="linenumber">382</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">381</context></context-group>
</trans-unit>
- <trans-unit id="_msg929">
+ <trans-unit id="_msg947">
<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>
+ <context-group purpose="location"><context context-type="linenumber">381</context></context-group>
</trans-unit>
- <trans-unit id="_msg930">
+ <trans-unit id="_msg948">
<source xml:space="preserve">Exporting Successful</source>
- <context-group purpose="location"><context context-type="linenumber">386</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">385</context></context-group>
</trans-unit>
- <trans-unit id="_msg931">
+ <trans-unit id="_msg949">
<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>
+ <context-group purpose="location"><context context-type="linenumber">385</context></context-group>
</trans-unit>
- <trans-unit id="_msg932">
+ <trans-unit id="_msg950">
<source xml:space="preserve">Range:</source>
- <context-group purpose="location"><context context-type="linenumber">556</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">555</context></context-group>
</trans-unit>
- <trans-unit id="_msg933">
+ <trans-unit id="_msg951">
<source xml:space="preserve">to</source>
- <context-group purpose="location"><context context-type="linenumber">564</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">563</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletframe.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletFrame">
- <trans-unit id="_msg934">
+ <trans-unit id="_msg952">
<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="_msg935">
+ <trans-unit id="_msg953">
<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="_msg936">
+ <trans-unit id="_msg954">
<source xml:space="preserve">Error</source>
<context-group purpose="location"><context context-type="linenumber">201</context></context-group>
<context-group purpose="location"><context context-type="linenumber">211</context></context-group>
<context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
- <trans-unit id="_msg937">
+ <trans-unit id="_msg955">
<source xml:space="preserve">Unable to decode PSBT from clipboard (invalid base64)</source>
<context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg938">
+ <trans-unit id="_msg956">
<source xml:space="preserve">Load Transaction Data</source>
<context-group purpose="location"><context context-type="linenumber">207</context></context-group>
</trans-unit>
- <trans-unit id="_msg939">
+ <trans-unit id="_msg957">
<source xml:space="preserve">Partially Signed Transaction (*.psbt)</source>
<context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg940">
+ <trans-unit id="_msg958">
<source xml:space="preserve">PSBT file must be smaller than 100 MiB</source>
<context-group purpose="location"><context context-type="linenumber">211</context></context-group>
</trans-unit>
- <trans-unit id="_msg941">
+ <trans-unit id="_msg959">
<source xml:space="preserve">Unable to decode PSBT</source>
<context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
@@ -4328,73 +4411,73 @@ Go to File &gt; Open Wallet to load a wallet.
</body></file>
<file original="../walletmodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletModel">
- <trans-unit id="_msg942">
+ <trans-unit id="_msg960">
<source xml:space="preserve">Send Coins</source>
<context-group purpose="location"><context context-type="linenumber">228</context></context-group>
<context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg943">
+ <trans-unit id="_msg961">
<source xml:space="preserve">Fee bump error</source>
<context-group purpose="location"><context context-type="linenumber">488</context></context-group>
<context-group purpose="location"><context context-type="linenumber">543</context></context-group>
<context-group purpose="location"><context context-type="linenumber">558</context></context-group>
<context-group purpose="location"><context context-type="linenumber">563</context></context-group>
</trans-unit>
- <trans-unit id="_msg944">
+ <trans-unit id="_msg962">
<source xml:space="preserve">Increasing transaction fee failed</source>
<context-group purpose="location"><context context-type="linenumber">488</context></context-group>
</trans-unit>
- <trans-unit id="_msg945">
+ <trans-unit id="_msg963">
<source xml:space="preserve">Do you want to increase the fee?</source>
<context-group purpose="location"><context context-type="linenumber">495</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="_msg946">
+ <trans-unit id="_msg964">
<source xml:space="preserve">Current fee:</source>
<context-group purpose="location"><context context-type="linenumber">499</context></context-group>
</trans-unit>
- <trans-unit id="_msg947">
+ <trans-unit id="_msg965">
<source xml:space="preserve">Increase:</source>
<context-group purpose="location"><context context-type="linenumber">503</context></context-group>
</trans-unit>
- <trans-unit id="_msg948">
+ <trans-unit id="_msg966">
<source xml:space="preserve">New fee:</source>
<context-group purpose="location"><context context-type="linenumber">507</context></context-group>
</trans-unit>
- <trans-unit id="_msg949">
+ <trans-unit id="_msg967">
<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">515</context></context-group>
</trans-unit>
- <trans-unit id="_msg950">
+ <trans-unit id="_msg968">
<source xml:space="preserve">Confirm fee bump</source>
<context-group purpose="location"><context context-type="linenumber">520</context></context-group>
</trans-unit>
- <trans-unit id="_msg951">
+ <trans-unit id="_msg969">
<source xml:space="preserve">Can&apos;t draft transaction.</source>
<context-group purpose="location"><context context-type="linenumber">543</context></context-group>
</trans-unit>
- <trans-unit id="_msg952">
+ <trans-unit id="_msg970">
<source xml:space="preserve">PSBT copied</source>
<context-group purpose="location"><context context-type="linenumber">550</context></context-group>
</trans-unit>
- <trans-unit id="_msg953">
+ <trans-unit id="_msg971">
<source xml:space="preserve">Copied to clipboard</source>
<context-group purpose="location"><context context-type="linenumber">550</context></context-group>
<context-group><context context-type="x-gettext-msgctxt">Fee-bump PSBT saved</context></context-group>
</trans-unit>
- <trans-unit id="_msg954">
+ <trans-unit id="_msg972">
<source xml:space="preserve">Can&apos;t sign transaction.</source>
<context-group purpose="location"><context context-type="linenumber">558</context></context-group>
</trans-unit>
- <trans-unit id="_msg955">
+ <trans-unit id="_msg973">
<source xml:space="preserve">Could not commit transaction</source>
<context-group purpose="location"><context context-type="linenumber">563</context></context-group>
</trans-unit>
- <trans-unit id="_msg956">
+ <trans-unit id="_msg974">
<source xml:space="preserve">Can&apos;t display address</source>
<context-group purpose="location"><context context-type="linenumber">577</context></context-group>
</trans-unit>
- <trans-unit id="_msg957">
+ <trans-unit id="_msg975">
<source xml:space="preserve">default wallet</source>
<context-group purpose="location"><context context-type="linenumber">595</context></context-group>
</trans-unit>
@@ -4402,40 +4485,40 @@ Go to File &gt; Open Wallet to load a wallet.
</body></file>
<file original="../walletview.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletView">
- <trans-unit id="_msg958">
+ <trans-unit id="_msg976">
<source xml:space="preserve">&amp;Export</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg959">
+ <trans-unit id="_msg977">
<source xml:space="preserve">Export the data in the current tab to a file</source>
<context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg960">
+ <trans-unit id="_msg978">
<source xml:space="preserve">Backup Wallet</source>
<context-group purpose="location"><context context-type="linenumber">214</context></context-group>
</trans-unit>
- <trans-unit id="_msg961">
+ <trans-unit id="_msg979">
<source xml:space="preserve">Wallet Data</source>
<context-group purpose="location"><context context-type="linenumber">216</context></context-group>
<note annotates="source" from="developer">Name of the wallet data file format.</note>
</trans-unit>
- <trans-unit id="_msg962">
+ <trans-unit id="_msg980">
<source xml:space="preserve">Backup Failed</source>
<context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg963">
+ <trans-unit id="_msg981">
<source xml:space="preserve">There was an error trying to save the wallet data to %1.</source>
<context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg964">
+ <trans-unit id="_msg982">
<source xml:space="preserve">Backup Successful</source>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg965">
+ <trans-unit id="_msg983">
<source xml:space="preserve">The wallet data was successfully saved to %1.</source>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg966">
+ <trans-unit id="_msg984">
<source xml:space="preserve">Cancel</source>
<context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
@@ -4443,874 +4526,870 @@ Go to File &gt; Open Wallet to load a wallet.
</body></file>
<file original="../bitcoinstrings.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="bitcoin-core">
- <trans-unit id="_msg967">
+ <trans-unit id="_msg985">
<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="_msg968">
+ <trans-unit id="_msg986">
<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="_msg969">
+ <trans-unit id="_msg987">
<source xml:space="preserve">%s failed to validate the -assumeutxo snapshot state. This indicates a hardware problem, or a bug in the software, or a bad software modification that allowed an invalid snapshot to be loaded. As a result of this, the node will shut down and stop using any state that was built on the snapshot, resetting the chain height from %d to %d. On the next restart, the node will resume syncing from %d without using any snapshot data. Please report this incident to %s, including how you obtained the snapshot. The invalid snapshot chainstate will be left on disk in case it is helpful in diagnosing the issue that caused this error.</source>
<context-group purpose="location"><context context-type="linenumber">16</context></context-group>
</trans-unit>
- <trans-unit id="_msg970">
+ <trans-unit id="_msg988">
<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 peer will connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
<context-group purpose="location"><context context-type="linenumber">28</context></context-group>
</trans-unit>
- <trans-unit id="_msg971">
+ <trans-unit id="_msg989">
<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">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg972">
+ <trans-unit id="_msg990">
<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">35</context></context-group>
</trans-unit>
- <trans-unit id="_msg973">
+ <trans-unit id="_msg991">
<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">40</context></context-group>
</trans-unit>
- <trans-unit id="_msg974">
+ <trans-unit id="_msg992">
<source xml:space="preserve">Disk space for %s may not accommodate the block files. Approximately %u GB of data will be stored in this directory.</source>
<context-group purpose="location"><context context-type="linenumber">44</context></context-group>
</trans-unit>
- <trans-unit id="_msg975">
+ <trans-unit id="_msg993">
<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">47</context></context-group>
</trans-unit>
- <trans-unit id="_msg976">
+ <trans-unit id="_msg994">
<source xml:space="preserve">Error loading wallet. Wallet requires blocks to be downloaded, and software does not currently support loading wallets while blocks are being downloaded out of order when using assumeutxo snapshots. Wallet should be able to load successfully after node sync reaches height %s</source>
<context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg977">
+ <trans-unit id="_msg995">
<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">61</context></context-group>
</trans-unit>
- <trans-unit id="_msg978">
+ <trans-unit id="_msg996">
<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">67</context></context-group>
</trans-unit>
- <trans-unit id="_msg979">
+ <trans-unit id="_msg997">
<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">69</context></context-group>
</trans-unit>
- <trans-unit id="_msg980">
+ <trans-unit id="_msg998">
<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">71</context></context-group>
</trans-unit>
- <trans-unit id="_msg981">
+ <trans-unit id="_msg999">
<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">77</context></context-group>
</trans-unit>
- <trans-unit id="_msg982">
+ <trans-unit id="_msg1000">
<source xml:space="preserve">Error: Unable to produce descriptors for this legacy wallet. Make sure to provide the wallet&apos;s passphrase if it is encrypted.</source>
<context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg983">
+ <trans-unit id="_msg1001">
<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">92</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg984">
+ <trans-unit id="_msg1002">
<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">101</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">104</context></context-group>
</trans-unit>
- <trans-unit id="_msg985">
+ <trans-unit id="_msg1003">
<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">105</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
</trans-unit>
- <trans-unit id="_msg986">
+ <trans-unit id="_msg1004">
<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">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">111</context></context-group>
</trans-unit>
- <trans-unit id="_msg987">
+ <trans-unit id="_msg1005">
<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">111</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">114</context></context-group>
</trans-unit>
- <trans-unit id="_msg988">
+ <trans-unit id="_msg1006">
<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">113</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">116</context></context-group>
</trans-unit>
- <trans-unit id="_msg989">
+ <trans-unit id="_msg1007">
<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">129</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
</trans-unit>
- <trans-unit id="_msg990">
+ <trans-unit id="_msg1008">
<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">132</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">135</context></context-group>
</trans-unit>
- <trans-unit id="_msg991">
+ <trans-unit id="_msg1009">
<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">135</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
</trans-unit>
- <trans-unit id="_msg992">
+ <trans-unit id="_msg1010">
<source xml:space="preserve">Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
- <context-group purpose="location"><context context-type="linenumber">137</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">140</context></context-group>
</trans-unit>
- <trans-unit id="_msg993">
+ <trans-unit id="_msg1011">
<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">140</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
- <trans-unit id="_msg994">
+ <trans-unit id="_msg1012">
<source xml:space="preserve">Rename of &apos;%s&apos; -&gt; &apos;%s&apos; failed. You should resolve this by manually moving or deleting the invalid snapshot directory %s, otherwise you will encounter the same error again on the next startup.</source>
- <context-group purpose="location"><context context-type="linenumber">143</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg995">
+ <trans-unit id="_msg1013">
<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">147</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">150</context></context-group>
</trans-unit>
- <trans-unit id="_msg996">
+ <trans-unit id="_msg1014">
<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">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg997">
- <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">158</context></context-group>
- </trans-unit>
- <trans-unit id="_msg998">
+ <trans-unit id="_msg1015">
<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">169</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">165</context></context-group>
</trans-unit>
- <trans-unit id="_msg999">
+ <trans-unit id="_msg1016">
<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">171</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">167</context></context-group>
</trans-unit>
- <trans-unit id="_msg1000">
+ <trans-unit id="_msg1017">
<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">175</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">171</context></context-group>
</trans-unit>
- <trans-unit id="_msg1001">
+ <trans-unit id="_msg1018">
<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">178</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
</trans-unit>
- <trans-unit id="_msg1002">
+ <trans-unit id="_msg1019">
<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">181</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">177</context></context-group>
</trans-unit>
- <trans-unit id="_msg1003">
+ <trans-unit id="_msg1020">
<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">184</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg1004">
+ <trans-unit id="_msg1021">
<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">186</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">182</context></context-group>
</trans-unit>
- <trans-unit id="_msg1005">
+ <trans-unit id="_msg1022">
<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">195</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">191</context></context-group>
</trans-unit>
- <trans-unit id="_msg1006">
+ <trans-unit id="_msg1023">
<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">205</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg1007">
+ <trans-unit id="_msg1024">
<source xml:space="preserve">Unsupported category-specific logging level %1$s=%2$s. Expected %1$s=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %3$s. Valid loglevels: %4$s.</source>
- <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
</trans-unit>
- <trans-unit id="_msg1008">
+ <trans-unit id="_msg1025">
<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">216</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg1009">
+ <trans-unit id="_msg1026">
<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">219</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
</trans-unit>
- <trans-unit id="_msg1010">
+ <trans-unit id="_msg1027">
<source xml:space="preserve">Wallet loaded successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future. Legacy wallets can be migrated to a descriptor wallet with migratewallet.</source>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
</trans-unit>
- <trans-unit id="_msg1011">
+ <trans-unit id="_msg1028">
<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">228</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
</trans-unit>
- <trans-unit id="_msg1012">
+ <trans-unit id="_msg1029">
<source xml:space="preserve">Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <context-group purpose="location"><context context-type="linenumber">231</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">227</context></context-group>
</trans-unit>
- <trans-unit id="_msg1013">
+ <trans-unit id="_msg1030">
<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">233</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
- <trans-unit id="_msg1014">
+ <trans-unit id="_msg1031">
<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">236</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg1015">
+ <trans-unit id="_msg1032">
<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">239</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">235</context></context-group>
</trans-unit>
- <trans-unit id="_msg1016">
+ <trans-unit id="_msg1033">
<source xml:space="preserve">%s is set very high!</source>
- <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
</trans-unit>
- <trans-unit id="_msg1017">
+ <trans-unit id="_msg1034">
<source xml:space="preserve">-maxmempool must be at least %d MB</source>
- <context-group purpose="location"><context context-type="linenumber">249</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">245</context></context-group>
</trans-unit>
- <trans-unit id="_msg1018">
+ <trans-unit id="_msg1035">
<source xml:space="preserve">A fatal internal error occurred, see debug.log for details</source>
- <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
</trans-unit>
- <trans-unit id="_msg1019">
+ <trans-unit id="_msg1036">
<source xml:space="preserve">Cannot resolve -%s address: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">252</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
</trans-unit>
- <trans-unit id="_msg1020">
+ <trans-unit id="_msg1037">
<source xml:space="preserve">Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
- <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">249</context></context-group>
</trans-unit>
- <trans-unit id="_msg1021">
+ <trans-unit id="_msg1038">
<source xml:space="preserve">Cannot set -peerblockfilters without -blockfilterindex.</source>
- <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg1022">
+ <trans-unit id="_msg1039">
<source xml:space="preserve">Cannot write to data directory &apos;%s&apos;; check permissions.</source>
- <context-group purpose="location"><context context-type="linenumber">255</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1023">
- <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">150</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
</trans-unit>
- <trans-unit id="_msg1024">
+ <trans-unit id="_msg1040">
<source xml:space="preserve">%s is set very high! Fees this large could be paid on a single transaction.</source>
<context-group purpose="location"><context context-type="linenumber">26</context></context-group>
</trans-unit>
- <trans-unit id="_msg1025">
+ <trans-unit id="_msg1041">
<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">37</context></context-group>
</trans-unit>
- <trans-unit id="_msg1026">
+ <trans-unit id="_msg1042">
<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">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg1027">
+ <trans-unit id="_msg1043">
<source xml:space="preserve">Error reading %s! All keys read correctly, but transaction data or address metadata may be missing or incorrect.</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
</trans-unit>
- <trans-unit id="_msg1028">
+ <trans-unit id="_msg1044">
<source xml:space="preserve">Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
<context-group purpose="location"><context context-type="linenumber">64</context></context-group>
</trans-unit>
- <trans-unit id="_msg1029">
+ <trans-unit id="_msg1045">
<source xml:space="preserve">Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
<context-group purpose="location"><context context-type="linenumber">74</context></context-group>
</trans-unit>
- <trans-unit id="_msg1030">
+ <trans-unit id="_msg1046">
<source xml:space="preserve">Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
<context-group purpose="location"><context context-type="linenumber">80</context></context-group>
</trans-unit>
- <trans-unit id="_msg1031">
- <source xml:space="preserve">Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <trans-unit id="_msg1047">
+ <source xml:space="preserve">Failed to calculate bump fees, because unconfirmed UTXOs depend on enormous cluster of unconfirmed transactions.</source>
<context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg1032">
- <source xml:space="preserve">Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s.</source>
+ <trans-unit id="_msg1048">
+ <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">89</context></context-group>
</trans-unit>
- <trans-unit id="_msg1033">
+ <trans-unit id="_msg1049">
+ <source xml:space="preserve">Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s.</source>
+ <context-group purpose="location"><context context-type="linenumber">92</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1050">
<source xml:space="preserve">Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
- <context-group purpose="location"><context context-type="linenumber">95</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">98</context></context-group>
</trans-unit>
- <trans-unit id="_msg1034">
+ <trans-unit id="_msg1051">
<source xml:space="preserve">Invalid amount for %s=&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">98</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">101</context></context-group>
</trans-unit>
- <trans-unit id="_msg1035">
+ <trans-unit id="_msg1052">
<source xml:space="preserve">Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided</source>
- <context-group purpose="location"><context context-type="linenumber">116</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">119</context></context-group>
</trans-unit>
- <trans-unit id="_msg1036">
+ <trans-unit id="_msg1053">
<source xml:space="preserve">Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
- <context-group purpose="location"><context context-type="linenumber">119</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">122</context></context-group>
</trans-unit>
- <trans-unit id="_msg1037">
+ <trans-unit id="_msg1054">
<source xml:space="preserve">Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is not provided: none of -proxy, -onion or -listenonion is given</source>
- <context-group purpose="location"><context context-type="linenumber">122</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
- <trans-unit id="_msg1038">
+ <trans-unit id="_msg1055">
<source xml:space="preserve">Outbound connections restricted to i2p (-onlynet=i2p) but -i2psam is not provided</source>
- <context-group purpose="location"><context context-type="linenumber">126</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">129</context></context-group>
</trans-unit>
- <trans-unit id="_msg1039">
+ <trans-unit id="_msg1056">
<source xml:space="preserve">The inputs size exceeds the maximum weight. Please try sending a smaller amount or manually consolidating your wallet&apos;s UTXOs</source>
- <context-group purpose="location"><context context-type="linenumber">162</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">158</context></context-group>
</trans-unit>
- <trans-unit id="_msg1040">
+ <trans-unit id="_msg1057">
<source xml:space="preserve">The preselected coins total amount does not cover the transaction target. Please allow other inputs to be automatically selected or include more coins manually</source>
- <context-group purpose="location"><context context-type="linenumber">165</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">161</context></context-group>
</trans-unit>
- <trans-unit id="_msg1041">
+ <trans-unit id="_msg1058">
<source xml:space="preserve">Transaction requires one destination of non-0 value, a non-0 feerate, or a pre-selected input</source>
- <context-group purpose="location"><context context-type="linenumber">189</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
</trans-unit>
- <trans-unit id="_msg1042">
+ <trans-unit id="_msg1059">
<source xml:space="preserve">UTXO snapshot failed to validate. Restart to resume normal initial block download, or try loading a different snapshot.</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">188</context></context-group>
</trans-unit>
- <trans-unit id="_msg1043">
+ <trans-unit id="_msg1060">
<source xml:space="preserve">Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool</source>
- <context-group purpose="location"><context context-type="linenumber">198</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg1044">
+ <trans-unit id="_msg1061">
<source xml:space="preserve">Unexpected legacy entry in descriptor wallet found. Loading wallet %s
The wallet might have been tampered with or created with malicious intent.
</source>
- <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
</trans-unit>
- <trans-unit id="_msg1045">
+ <trans-unit id="_msg1062">
<source xml:space="preserve">Unrecognized descriptor found. Loading wallet %s
The wallet might had been created on a newer version.
Please try running the latest software version.
</source>
- <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
</trans-unit>
- <trans-unit id="_msg1046">
+ <trans-unit id="_msg1063">
<source xml:space="preserve">
Unable to cleanup failed migration</source>
- <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">238</context></context-group>
</trans-unit>
- <trans-unit id="_msg1047">
+ <trans-unit id="_msg1064">
<source xml:space="preserve">
Unable to restore backup of wallet.</source>
- <context-group purpose="location"><context context-type="linenumber">245</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg1048">
+ <trans-unit id="_msg1065">
<source xml:space="preserve">Block verification was interrupted</source>
- <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
</trans-unit>
- <trans-unit id="_msg1049">
+ <trans-unit id="_msg1066">
<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">256</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">252</context></context-group>
</trans-unit>
- <trans-unit id="_msg1050">
+ <trans-unit id="_msg1067">
<source xml:space="preserve">Copyright (C) %i-%i</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
</trans-unit>
- <trans-unit id="_msg1051">
+ <trans-unit id="_msg1068">
<source xml:space="preserve">Corrupted block database detected</source>
- <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
</trans-unit>
- <trans-unit id="_msg1052">
+ <trans-unit id="_msg1069">
<source xml:space="preserve">Could not find asmap file %s</source>
- <context-group purpose="location"><context context-type="linenumber">259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">255</context></context-group>
</trans-unit>
- <trans-unit id="_msg1053">
+ <trans-unit id="_msg1070">
<source xml:space="preserve">Could not parse asmap file %s</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">256</context></context-group>
</trans-unit>
- <trans-unit id="_msg1054">
+ <trans-unit id="_msg1071">
<source xml:space="preserve">Disk space is too low!</source>
- <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
</trans-unit>
- <trans-unit id="_msg1055">
+ <trans-unit id="_msg1072">
<source xml:space="preserve">Do you want to rebuild the block database now?</source>
- <context-group purpose="location"><context context-type="linenumber">262</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
</trans-unit>
- <trans-unit id="_msg1056">
+ <trans-unit id="_msg1073">
<source xml:space="preserve">Done loading</source>
- <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">259</context></context-group>
</trans-unit>
- <trans-unit id="_msg1057">
+ <trans-unit id="_msg1074">
<source xml:space="preserve">Dump file %s does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg1058">
+ <trans-unit id="_msg1075">
<source xml:space="preserve">Error creating %s</source>
- <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg1059">
+ <trans-unit id="_msg1076">
<source xml:space="preserve">Error initializing block database</source>
- <context-group purpose="location"><context context-type="linenumber">266</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">262</context></context-group>
</trans-unit>
- <trans-unit id="_msg1060">
+ <trans-unit id="_msg1077">
<source xml:space="preserve">Error initializing wallet database environment %s!</source>
- <context-group purpose="location"><context context-type="linenumber">267</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
- <trans-unit id="_msg1061">
+ <trans-unit id="_msg1078">
<source xml:space="preserve">Error loading %s</source>
- <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
</trans-unit>
- <trans-unit id="_msg1062">
+ <trans-unit id="_msg1079">
<source xml:space="preserve">Error loading %s: Private keys can only be disabled during creation</source>
- <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
</trans-unit>
- <trans-unit id="_msg1063">
+ <trans-unit id="_msg1080">
<source xml:space="preserve">Error loading %s: Wallet corrupted</source>
- <context-group purpose="location"><context context-type="linenumber">270</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">266</context></context-group>
</trans-unit>
- <trans-unit id="_msg1064">
+ <trans-unit id="_msg1081">
<source xml:space="preserve">Error loading %s: Wallet requires newer version of %s</source>
- <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
- <trans-unit id="_msg1065">
+ <trans-unit id="_msg1082">
<source xml:space="preserve">Error loading block database</source>
- <context-group purpose="location"><context context-type="linenumber">272</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
- <trans-unit id="_msg1066">
+ <trans-unit id="_msg1083">
<source xml:space="preserve">Error opening block database</source>
- <context-group purpose="location"><context context-type="linenumber">273</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg1067">
+ <trans-unit id="_msg1084">
<source xml:space="preserve">Error reading configuration file: %s</source>
- <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">270</context></context-group>
</trans-unit>
- <trans-unit id="_msg1068">
+ <trans-unit id="_msg1085">
<source xml:space="preserve">Error reading from database, shutting down.</source>
- <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
</trans-unit>
- <trans-unit id="_msg1069">
+ <trans-unit id="_msg1086">
<source xml:space="preserve">Error reading next record from wallet database</source>
- <context-group purpose="location"><context context-type="linenumber">276</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">272</context></context-group>
</trans-unit>
- <trans-unit id="_msg1070">
+ <trans-unit id="_msg1087">
<source xml:space="preserve">Error: Cannot extract destination from the generated scriptpubkey</source>
- <context-group purpose="location"><context context-type="linenumber">277</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg1071">
+ <trans-unit id="_msg1088">
<source xml:space="preserve">Error: Could not add watchonly tx to watchonly wallet</source>
- <context-group purpose="location"><context context-type="linenumber">278</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
- <trans-unit id="_msg1072">
+ <trans-unit id="_msg1089">
<source xml:space="preserve">Error: Could not delete watchonly transactions</source>
- <context-group purpose="location"><context context-type="linenumber">279</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
- <trans-unit id="_msg1073">
+ <trans-unit id="_msg1090">
<source xml:space="preserve">Error: Couldn&apos;t create cursor into database</source>
- <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">276</context></context-group>
</trans-unit>
- <trans-unit id="_msg1074">
+ <trans-unit id="_msg1091">
<source xml:space="preserve">Error: Disk space is low for %s</source>
- <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">277</context></context-group>
</trans-unit>
- <trans-unit id="_msg1075">
+ <trans-unit id="_msg1092">
<source xml:space="preserve">Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
- <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">278</context></context-group>
</trans-unit>
- <trans-unit id="_msg1076">
+ <trans-unit id="_msg1093">
<source xml:space="preserve">Error: Failed to create new watchonly wallet</source>
- <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg1077">
+ <trans-unit id="_msg1094">
<source xml:space="preserve">Error: Got key that was not hex: %s</source>
- <context-group purpose="location"><context context-type="linenumber">284</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
- <trans-unit id="_msg1078">
+ <trans-unit id="_msg1095">
<source xml:space="preserve">Error: Got value that was not hex: %s</source>
- <context-group purpose="location"><context context-type="linenumber">285</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
</trans-unit>
- <trans-unit id="_msg1079">
+ <trans-unit id="_msg1096">
<source xml:space="preserve">Error: Keypool ran out, please call keypoolrefill first</source>
- <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
</trans-unit>
- <trans-unit id="_msg1080">
+ <trans-unit id="_msg1097">
<source xml:space="preserve">Error: Missing checksum</source>
- <context-group purpose="location"><context context-type="linenumber">287</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
</trans-unit>
- <trans-unit id="_msg1081">
+ <trans-unit id="_msg1098">
<source xml:space="preserve">Error: No %s addresses available.</source>
- <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg1082">
+ <trans-unit id="_msg1099">
<source xml:space="preserve">Error: Not all watchonly txs could be deleted</source>
- <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">285</context></context-group>
</trans-unit>
- <trans-unit id="_msg1083">
+ <trans-unit id="_msg1100">
<source xml:space="preserve">Error: This wallet already uses SQLite</source>
- <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
</trans-unit>
- <trans-unit id="_msg1084">
+ <trans-unit id="_msg1101">
<source xml:space="preserve">Error: This wallet is already a descriptor wallet</source>
- <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">287</context></context-group>
</trans-unit>
- <trans-unit id="_msg1085">
+ <trans-unit id="_msg1102">
<source xml:space="preserve">Error: Unable to begin reading all records in the database</source>
- <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
</trans-unit>
- <trans-unit id="_msg1086">
+ <trans-unit id="_msg1103">
<source xml:space="preserve">Error: Unable to make a backup of your wallet</source>
- <context-group purpose="location"><context context-type="linenumber">293</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
</trans-unit>
- <trans-unit id="_msg1087">
+ <trans-unit id="_msg1104">
<source xml:space="preserve">Error: Unable to parse version %u as a uint32_t</source>
- <context-group purpose="location"><context context-type="linenumber">294</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
</trans-unit>
- <trans-unit id="_msg1088">
+ <trans-unit id="_msg1105">
<source xml:space="preserve">Error: Unable to read all records in the database</source>
- <context-group purpose="location"><context context-type="linenumber">295</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
</trans-unit>
- <trans-unit id="_msg1089">
+ <trans-unit id="_msg1106">
<source xml:space="preserve">Error: Unable to remove watchonly address book data</source>
- <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
</trans-unit>
- <trans-unit id="_msg1090">
+ <trans-unit id="_msg1107">
<source xml:space="preserve">Error: Unable to write record to new wallet</source>
- <context-group purpose="location"><context context-type="linenumber">297</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">293</context></context-group>
</trans-unit>
- <trans-unit id="_msg1091">
+ <trans-unit id="_msg1108">
<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">298</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
- <trans-unit id="_msg1092">
+ <trans-unit id="_msg1109">
<source xml:space="preserve">Failed to rescan the wallet during initialization</source>
- <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">295</context></context-group>
</trans-unit>
- <trans-unit id="_msg1093">
+ <trans-unit id="_msg1110">
<source xml:space="preserve">Failed to start indexes, shutting down..</source>
- <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
- <trans-unit id="_msg1094">
+ <trans-unit id="_msg1111">
<source xml:space="preserve">Failed to verify database</source>
- <context-group purpose="location"><context context-type="linenumber">301</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">297</context></context-group>
</trans-unit>
- <trans-unit id="_msg1095">
+ <trans-unit id="_msg1112">
<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">302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">298</context></context-group>
</trans-unit>
- <trans-unit id="_msg1096">
+ <trans-unit id="_msg1113">
<source xml:space="preserve">Ignoring duplicate -wallet %s.</source>
- <context-group purpose="location"><context context-type="linenumber">303</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
</trans-unit>
- <trans-unit id="_msg1097">
+ <trans-unit id="_msg1114">
<source xml:space="preserve">Importing…</source>
- <context-group purpose="location"><context context-type="linenumber">304</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
</trans-unit>
- <trans-unit id="_msg1098">
+ <trans-unit id="_msg1115">
<source xml:space="preserve">Incorrect or no genesis block found. Wrong datadir for network?</source>
- <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">301</context></context-group>
</trans-unit>
- <trans-unit id="_msg1099">
+ <trans-unit id="_msg1116">
<source xml:space="preserve">Initialization sanity check failed. %s is shutting down.</source>
- <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
</trans-unit>
- <trans-unit id="_msg1100">
+ <trans-unit id="_msg1117">
<source xml:space="preserve">Input not found or already spent</source>
- <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">303</context></context-group>
</trans-unit>
- <trans-unit id="_msg1101">
+ <trans-unit id="_msg1118">
<source xml:space="preserve">Insufficient dbcache for block verification</source>
- <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">304</context></context-group>
</trans-unit>
- <trans-unit id="_msg1102">
+ <trans-unit id="_msg1119">
<source xml:space="preserve">Insufficient funds</source>
- <context-group purpose="location"><context context-type="linenumber">309</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
- <trans-unit id="_msg1103">
+ <trans-unit id="_msg1120">
<source xml:space="preserve">Invalid -i2psam address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
- <trans-unit id="_msg1104">
+ <trans-unit id="_msg1121">
<source xml:space="preserve">Invalid -onion address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
</trans-unit>
- <trans-unit id="_msg1105">
+ <trans-unit id="_msg1122">
<source xml:space="preserve">Invalid -proxy address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">312</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
</trans-unit>
- <trans-unit id="_msg1106">
+ <trans-unit id="_msg1123">
<source xml:space="preserve">Invalid P2P permission: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">309</context></context-group>
</trans-unit>
- <trans-unit id="_msg1107">
+ <trans-unit id="_msg1124">
<source xml:space="preserve">Invalid amount for %s=&lt;amount&gt;: &apos;%s&apos; (must be at least %s)</source>
- <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
</trans-unit>
- <trans-unit id="_msg1108">
+ <trans-unit id="_msg1125">
<source xml:space="preserve">Invalid amount for %s=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
</trans-unit>
- <trans-unit id="_msg1109">
+ <trans-unit id="_msg1126">
<source xml:space="preserve">Invalid amount for -%s=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">312</context></context-group>
</trans-unit>
- <trans-unit id="_msg1110">
+ <trans-unit id="_msg1127">
<source xml:space="preserve">Invalid netmask specified in -whitelist: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
</trans-unit>
- <trans-unit id="_msg1111">
+ <trans-unit id="_msg1128">
<source xml:space="preserve">Invalid port specified in %s: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
</trans-unit>
- <trans-unit id="_msg1112">
+ <trans-unit id="_msg1129">
<source xml:space="preserve">Invalid pre-selected input %s</source>
- <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
- <trans-unit id="_msg1113">
+ <trans-unit id="_msg1130">
<source xml:space="preserve">Listening for incoming connections failed (listen returned error %s)</source>
- <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
</trans-unit>
- <trans-unit id="_msg1114">
+ <trans-unit id="_msg1131">
<source xml:space="preserve">Loading P2P addresses…</source>
- <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
</trans-unit>
- <trans-unit id="_msg1115">
+ <trans-unit id="_msg1132">
<source xml:space="preserve">Loading banlist…</source>
- <context-group purpose="location"><context context-type="linenumber">322</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
</trans-unit>
- <trans-unit id="_msg1116">
+ <trans-unit id="_msg1133">
<source xml:space="preserve">Loading block index…</source>
- <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
</trans-unit>
- <trans-unit id="_msg1117">
+ <trans-unit id="_msg1134">
<source xml:space="preserve">Loading wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
</trans-unit>
- <trans-unit id="_msg1118">
+ <trans-unit id="_msg1135">
<source xml:space="preserve">Missing amount</source>
- <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg1119">
+ <trans-unit id="_msg1136">
<source xml:space="preserve">Missing solving data for estimating transaction size</source>
- <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">322</context></context-group>
</trans-unit>
- <trans-unit id="_msg1120">
+ <trans-unit id="_msg1137">
<source xml:space="preserve">Need to specify a port with -whitebind: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
- <trans-unit id="_msg1121">
+ <trans-unit id="_msg1138">
<source xml:space="preserve">No addresses available</source>
- <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
- <trans-unit id="_msg1122">
+ <trans-unit id="_msg1139">
<source xml:space="preserve">Not enough file descriptors available.</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg1123">
+ <trans-unit id="_msg1140">
<source xml:space="preserve">Not found pre-selected input %s</source>
- <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg1124">
+ <trans-unit id="_msg1141">
<source xml:space="preserve">Not solvable pre-selected input %s</source>
- <context-group purpose="location"><context context-type="linenumber">331</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
</trans-unit>
- <trans-unit id="_msg1125">
+ <trans-unit id="_msg1142">
<source xml:space="preserve">Prune cannot be configured with a negative value.</source>
- <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
</trans-unit>
- <trans-unit id="_msg1126">
+ <trans-unit id="_msg1143">
<source xml:space="preserve">Prune mode is incompatible with -txindex.</source>
- <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
</trans-unit>
- <trans-unit id="_msg1127">
+ <trans-unit id="_msg1144">
<source xml:space="preserve">Pruning blockstore…</source>
- <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
</trans-unit>
- <trans-unit id="_msg1128">
+ <trans-unit id="_msg1145">
<source xml:space="preserve">Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">331</context></context-group>
</trans-unit>
- <trans-unit id="_msg1129">
+ <trans-unit id="_msg1146">
<source xml:space="preserve">Replaying blocks…</source>
- <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
- <trans-unit id="_msg1130">
+ <trans-unit id="_msg1147">
<source xml:space="preserve">Rescanning…</source>
- <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
- <trans-unit id="_msg1131">
+ <trans-unit id="_msg1148">
<source xml:space="preserve">SQLiteDatabase: Failed to execute statement to verify database: %s</source>
- <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
- <trans-unit id="_msg1132">
+ <trans-unit id="_msg1149">
<source xml:space="preserve">SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
- <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg1133">
+ <trans-unit id="_msg1150">
<source xml:space="preserve">SQLiteDatabase: Failed to read database verification error: %s</source>
- <context-group purpose="location"><context context-type="linenumber">340</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
</trans-unit>
- <trans-unit id="_msg1134">
+ <trans-unit id="_msg1151">
<source xml:space="preserve">SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
- <context-group purpose="location"><context context-type="linenumber">341</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
</trans-unit>
- <trans-unit id="_msg1135">
+ <trans-unit id="_msg1152">
<source xml:space="preserve">Section [%s] is not recognized.</source>
- <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
</trans-unit>
- <trans-unit id="_msg1136">
+ <trans-unit id="_msg1153">
<source xml:space="preserve">Signing transaction failed</source>
- <context-group purpose="location"><context context-type="linenumber">345</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">341</context></context-group>
</trans-unit>
- <trans-unit id="_msg1137">
+ <trans-unit id="_msg1154">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; does not exist</source>
- <context-group purpose="location"><context context-type="linenumber">346</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
</trans-unit>
- <trans-unit id="_msg1138">
+ <trans-unit id="_msg1155">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; is a relative path</source>
- <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">343</context></context-group>
</trans-unit>
- <trans-unit id="_msg1139">
+ <trans-unit id="_msg1156">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; is not a directory</source>
- <context-group purpose="location"><context context-type="linenumber">348</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg1140">
+ <trans-unit id="_msg1157">
<source xml:space="preserve">Specified blocks directory &quot;%s&quot; does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">349</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
- <trans-unit id="_msg1141">
+ <trans-unit id="_msg1158">
<source xml:space="preserve">Specified data directory &quot;%s&quot; does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">346</context></context-group>
</trans-unit>
- <trans-unit id="_msg1142">
+ <trans-unit id="_msg1159">
<source xml:space="preserve">Starting network threads…</source>
- <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
</trans-unit>
- <trans-unit id="_msg1143">
+ <trans-unit id="_msg1160">
<source xml:space="preserve">The source code is available from %s.</source>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">348</context></context-group>
</trans-unit>
- <trans-unit id="_msg1144">
+ <trans-unit id="_msg1161">
<source xml:space="preserve">The specified config file %s does not exist</source>
- <context-group purpose="location"><context context-type="linenumber">353</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">349</context></context-group>
</trans-unit>
- <trans-unit id="_msg1145">
+ <trans-unit id="_msg1162">
<source xml:space="preserve">The transaction amount is too small to pay the fee</source>
- <context-group purpose="location"><context context-type="linenumber">354</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
</trans-unit>
- <trans-unit id="_msg1146">
+ <trans-unit id="_msg1163">
<source xml:space="preserve">The wallet will avoid paying less than the minimum relay fee.</source>
- <context-group purpose="location"><context context-type="linenumber">355</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
</trans-unit>
- <trans-unit id="_msg1147">
+ <trans-unit id="_msg1164">
<source xml:space="preserve">This is experimental software.</source>
- <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
</trans-unit>
- <trans-unit id="_msg1148">
+ <trans-unit id="_msg1165">
<source xml:space="preserve">This is the minimum transaction fee you pay on every transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">357</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">353</context></context-group>
</trans-unit>
- <trans-unit id="_msg1149">
+ <trans-unit id="_msg1166">
<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">358</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">354</context></context-group>
</trans-unit>
- <trans-unit id="_msg1150">
+ <trans-unit id="_msg1167">
<source xml:space="preserve">Transaction amount too small</source>
- <context-group purpose="location"><context context-type="linenumber">359</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">355</context></context-group>
</trans-unit>
- <trans-unit id="_msg1151">
+ <trans-unit id="_msg1168">
<source xml:space="preserve">Transaction amounts must not be negative</source>
- <context-group purpose="location"><context context-type="linenumber">360</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
</trans-unit>
- <trans-unit id="_msg1152">
+ <trans-unit id="_msg1169">
<source xml:space="preserve">Transaction change output index out of range</source>
- <context-group purpose="location"><context context-type="linenumber">361</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">357</context></context-group>
</trans-unit>
- <trans-unit id="_msg1153">
+ <trans-unit id="_msg1170">
<source xml:space="preserve">Transaction has too long of a mempool chain</source>
- <context-group purpose="location"><context context-type="linenumber">362</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
</trans-unit>
- <trans-unit id="_msg1154">
+ <trans-unit id="_msg1171">
<source xml:space="preserve">Transaction must have at least one recipient</source>
- <context-group purpose="location"><context context-type="linenumber">363</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">359</context></context-group>
</trans-unit>
- <trans-unit id="_msg1155">
+ <trans-unit id="_msg1172">
<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">364</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">360</context></context-group>
</trans-unit>
- <trans-unit id="_msg1156">
+ <trans-unit id="_msg1173">
<source xml:space="preserve">Transaction too large</source>
- <context-group purpose="location"><context context-type="linenumber">365</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">361</context></context-group>
</trans-unit>
- <trans-unit id="_msg1157">
+ <trans-unit id="_msg1174">
<source xml:space="preserve">Unable to allocate memory for -maxsigcachesize: &apos;%s&apos; MiB</source>
- <context-group purpose="location"><context context-type="linenumber">366</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">362</context></context-group>
</trans-unit>
- <trans-unit id="_msg1158">
+ <trans-unit id="_msg1175">
<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">367</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">363</context></context-group>
</trans-unit>
- <trans-unit id="_msg1159">
+ <trans-unit id="_msg1176">
<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">368</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">364</context></context-group>
</trans-unit>
- <trans-unit id="_msg1160">
+ <trans-unit id="_msg1177">
<source xml:space="preserve">Unable to create the PID file &apos;%s&apos;: %s</source>
- <context-group purpose="location"><context context-type="linenumber">369</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">365</context></context-group>
</trans-unit>
- <trans-unit id="_msg1161">
+ <trans-unit id="_msg1178">
<source xml:space="preserve">Unable to find UTXO for external input</source>
- <context-group purpose="location"><context context-type="linenumber">370</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">366</context></context-group>
</trans-unit>
- <trans-unit id="_msg1162">
+ <trans-unit id="_msg1179">
<source xml:space="preserve">Unable to generate initial keys</source>
- <context-group purpose="location"><context context-type="linenumber">371</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">367</context></context-group>
</trans-unit>
- <trans-unit id="_msg1163">
+ <trans-unit id="_msg1180">
<source xml:space="preserve">Unable to generate keys</source>
- <context-group purpose="location"><context context-type="linenumber">372</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">368</context></context-group>
</trans-unit>
- <trans-unit id="_msg1164">
+ <trans-unit id="_msg1181">
<source xml:space="preserve">Unable to open %s for writing</source>
- <context-group purpose="location"><context context-type="linenumber">373</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">369</context></context-group>
</trans-unit>
- <trans-unit id="_msg1165">
+ <trans-unit id="_msg1182">
<source xml:space="preserve">Unable to parse -maxuploadtarget: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">374</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">370</context></context-group>
</trans-unit>
- <trans-unit id="_msg1166">
+ <trans-unit id="_msg1183">
<source xml:space="preserve">Unable to start HTTP server. See debug log for details.</source>
- <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">371</context></context-group>
</trans-unit>
- <trans-unit id="_msg1167">
+ <trans-unit id="_msg1184">
<source xml:space="preserve">Unable to unload the wallet before migrating</source>
- <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">372</context></context-group>
</trans-unit>
- <trans-unit id="_msg1168">
+ <trans-unit id="_msg1185">
<source xml:space="preserve">Unknown -blockfilterindex value %s.</source>
- <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">373</context></context-group>
</trans-unit>
- <trans-unit id="_msg1169">
+ <trans-unit id="_msg1186">
<source xml:space="preserve">Unknown address type &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">374</context></context-group>
</trans-unit>
- <trans-unit id="_msg1170">
+ <trans-unit id="_msg1187">
<source xml:space="preserve">Unknown change type &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">379</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg1171">
+ <trans-unit id="_msg1188">
<source xml:space="preserve">Unknown network specified in -onlynet: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">380</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
</trans-unit>
- <trans-unit id="_msg1172">
+ <trans-unit id="_msg1189">
<source xml:space="preserve">Unknown new rules activated (versionbit %i)</source>
- <context-group purpose="location"><context context-type="linenumber">381</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
</trans-unit>
- <trans-unit id="_msg1173">
+ <trans-unit id="_msg1190">
<source xml:space="preserve">Unsupported global logging level %s=%s. Valid values: %s.</source>
- <context-group purpose="location"><context context-type="linenumber">382</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
</trans-unit>
- <trans-unit id="_msg1174">
+ <trans-unit id="_msg1191">
<source xml:space="preserve">acceptstalefeeestimates is not supported on %s chain.</source>
- <context-group purpose="location"><context context-type="linenumber">388</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">384</context></context-group>
</trans-unit>
- <trans-unit id="_msg1175">
+ <trans-unit id="_msg1192">
<source xml:space="preserve">Unsupported logging category %s=%s.</source>
- <context-group purpose="location"><context context-type="linenumber">383</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">379</context></context-group>
</trans-unit>
- <trans-unit id="_msg1176">
+ <trans-unit id="_msg1193">
<source xml:space="preserve">User Agent comment (%s) contains unsafe characters.</source>
- <context-group purpose="location"><context context-type="linenumber">384</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">380</context></context-group>
</trans-unit>
- <trans-unit id="_msg1177">
+ <trans-unit id="_msg1194">
<source xml:space="preserve">Verifying blocks…</source>
- <context-group purpose="location"><context context-type="linenumber">385</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">381</context></context-group>
</trans-unit>
- <trans-unit id="_msg1178">
+ <trans-unit id="_msg1195">
<source xml:space="preserve">Verifying wallet(s)…</source>
- <context-group purpose="location"><context context-type="linenumber">386</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">382</context></context-group>
</trans-unit>
- <trans-unit id="_msg1179">
+ <trans-unit id="_msg1196">
<source xml:space="preserve">Wallet needed to be rewritten: restart %s to complete</source>
- <context-group purpose="location"><context context-type="linenumber">387</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">383</context></context-group>
</trans-unit>
- <trans-unit id="_msg1180">
+ <trans-unit id="_msg1197">
<source xml:space="preserve">Settings file could not be read</source>
- <context-group purpose="location"><context context-type="linenumber">343</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
- <trans-unit id="_msg1181">
+ <trans-unit id="_msg1198">
<source xml:space="preserve">Settings file could not be written</source>
- <context-group purpose="location"><context context-type="linenumber">344</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">340</context></context-group>
</trans-unit>
</group>
</body></file>
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 998a4e5cbe..ceaa3ac46b 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -169,7 +169,7 @@ public:
bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const WalletModel* wallet_model)
{
std::vector< std::vector<std::string> > stack;
- stack.push_back(std::vector<std::string>());
+ stack.emplace_back();
enum CmdParseState
{
@@ -197,7 +197,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
}
// Make sure stack is not empty before adding something
if (stack.empty()) {
- stack.push_back(std::vector<std::string>());
+ stack.emplace_back();
}
stack.back().push_back(strArg);
};
@@ -206,7 +206,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
if (nDepthInsideSensitive) {
if (!--nDepthInsideSensitive) {
assert(filter_begin_pos);
- filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos));
+ filter_ranges.emplace_back(filter_begin_pos, chpos);
filter_begin_pos = 0;
}
}
@@ -306,7 +306,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
if (nDepthInsideSensitive) {
++nDepthInsideSensitive;
}
- stack.push_back(std::vector<std::string>());
+ stack.emplace_back();
}
// don't allow commands after executed commands on baselevel
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index ca2fa2d672..b1ef489cc3 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -250,15 +250,14 @@ void CreateWalletActivity::createWallet()
std::string name = m_create_wallet_dialog->walletName().toStdString();
uint64_t flags = 0;
+ // Enable descriptors by default.
+ flags |= WALLET_FLAG_DESCRIPTORS;
if (m_create_wallet_dialog->isDisablePrivateKeysChecked()) {
flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
}
if (m_create_wallet_dialog->isMakeBlankWalletChecked()) {
flags |= WALLET_FLAG_BLANK_WALLET;
}
- if (m_create_wallet_dialog->isDescriptorWalletChecked()) {
- flags |= WALLET_FLAG_DESCRIPTORS;
- }
if (m_create_wallet_dialog->isExternalSignerChecked()) {
flags |= WALLET_FLAG_EXTERNAL_SIGNER;
}
diff --git a/src/rest.cpp b/src/rest.cpp
index ba149c1a9e..e094039366 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -798,7 +798,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
return RESTERR(req, HTTP_BAD_REQUEST, "Parse error");
txid.SetHex(strTxid);
- vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput));
+ vOutPoints.emplace_back(txid, (uint32_t)nOutput);
}
if (vOutPoints.size() > 0)
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 0f4941b40c..6d2b84cb6c 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1455,7 +1455,7 @@ static RPCHelpMan getchaintips()
} else if (block->nStatus & BLOCK_FAILED_MASK) {
// This block or one of its ancestors is invalid.
status = "invalid";
- } else if (!block->HaveTxsDownloaded()) {
+ } else if (!block->HaveNumChainTxs()) {
// This block cannot be connected because full block data for it or one of its parents is missing.
status = "headers-only";
} else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
@@ -1930,7 +1930,7 @@ static RPCHelpMan getblockstats()
// New feerate uses satoshis per virtual byte instead of per serialized byte
CAmount feerate = weight ? (txfee * WITNESS_SCALE_FACTOR) / weight : 0;
if (do_feerate_percentiles) {
- feerate_array.emplace_back(std::make_pair(feerate, weight));
+ feerate_array.emplace_back(feerate, weight);
}
maxfeerate = std::max(maxfeerate, feerate);
minfeerate = std::min(minfeerate, feerate);
@@ -2667,7 +2667,7 @@ UniValue CreateUTXOSnapshot(
tip->nHeight, tip->GetBlockHash().ToString(),
fs::PathToString(path), fs::PathToString(temppath)));
- SnapshotMetadata metadata{tip->GetBlockHash(), maybe_stats->coins_count, tip->nChainTx};
+ SnapshotMetadata metadata{tip->GetBlockHash(), maybe_stats->coins_count};
afile << metadata;
@@ -2694,9 +2694,7 @@ UniValue CreateUTXOSnapshot(
result.pushKV("base_height", tip->nHeight);
result.pushKV("path", path.u8string());
result.pushKV("txoutset_hash", maybe_stats->hashSerialized.ToString());
- // Cast required because univalue doesn't have serialization specified for
- // `unsigned int`, nChainTx's type.
- result.pushKV("nchaintx", uint64_t{tip->nChainTx});
+ result.pushKV("nchaintx", tip->nChainTx);
return result;
}
@@ -2707,7 +2705,7 @@ static RPCHelpMan loadtxoutset()
"Load the serialized UTXO set from disk.\n"
"Once this snapshot is loaded, its contents will be "
"deserialized into a second chainstate data structure, which is then used to sync to "
- "the network's tip under a security model very much like `assumevalid`. "
+ "the network's tip. "
"Meanwhile, the original chainstate will complete the initial block download process in "
"the background, eventually validating up to the block that the snapshot is based upon.\n\n"
@@ -2739,6 +2737,7 @@ static RPCHelpMan loadtxoutset()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureAnyNodeContext(request.context);
+ ChainstateManager& chainman = EnsureChainman(node);
fs::path path{AbsPathForConfigVal(EnsureArgsman(node), fs::u8path(request.params[0].get_str()))};
FILE* file{fsbridge::fopen(path, "rb")};
@@ -2753,14 +2752,16 @@ static RPCHelpMan loadtxoutset()
afile >> metadata;
uint256 base_blockhash = metadata.m_base_blockhash;
+ if (!chainman.GetParams().AssumeutxoForBlockhash(base_blockhash).has_value()) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to load UTXO snapshot, "
+ "assumeutxo block hash in snapshot metadata not recognized (%s)", base_blockhash.ToString()));
+ }
int max_secs_to_wait_for_headers = 60 * 10;
CBlockIndex* snapshot_start_block = nullptr;
LogPrintf("[snapshot] waiting to see blockheader %s in headers chain before snapshot activation\n",
base_blockhash.ToString());
- ChainstateManager& chainman = *node.chainman;
-
while (max_secs_to_wait_for_headers > 0) {
snapshot_start_block = WITH_LOCK(::cs_main,
return chainman.m_blockman.LookupBlockIndex(base_blockhash));
@@ -2807,6 +2808,7 @@ const std::vector<RPCResult> RPCHelpForChainstate{
{RPCResult::Type::STR_HEX, "snapshot_blockhash", /*optional=*/true, "the base block of the snapshot this chainstate is based on, if any"},
{RPCResult::Type::NUM, "coins_db_cache_bytes", "size of the coinsdb cache"},
{RPCResult::Type::NUM, "coins_tip_cache_bytes", "size of the coinstip cache"},
+ {RPCResult::Type::BOOL, "validated", "whether the chainstate is fully validated. True if all blocks in the chainstate were validated, false if the chain is based on a snapshot and the snapshot has not yet been validated."},
};
static RPCHelpMan getchainstates()
@@ -2818,8 +2820,7 @@ return RPCHelpMan{
RPCResult{
RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::NUM, "headers", "the number of headers seen so far"},
- {RPCResult::Type::OBJ, "normal", /*optional=*/true, "fully validated chainstate containing blocks this node has validated starting from the genesis block", RPCHelpForChainstate},
- {RPCResult::Type::OBJ, "snapshot", /*optional=*/true, "only present if an assumeutxo snapshot is loaded. Partially validated chainstate containing blocks this node has validated starting from the snapshot. After the snapshot is validated (when the 'normal' chainstate advances far enough to validate it), this chainstate will replace and become the 'normal' chainstate.", RPCHelpForChainstate},
+ {RPCResult::Type::ARR, "chainstates", "list of the chainstates ordered by work, with the most-work (active) chainstate last", {{RPCResult::Type::OBJ, "", "", RPCHelpForChainstate},}},
}
},
RPCExamples{
@@ -2831,10 +2832,9 @@ return RPCHelpMan{
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
- NodeContext& node = EnsureAnyNodeContext(request.context);
- ChainstateManager& chainman = *node.chainman;
+ ChainstateManager& chainman = EnsureAnyChainman(request.context);
- auto make_chain_data = [&](const Chainstate& cs) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ auto make_chain_data = [&](const Chainstate& cs, bool validated) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
UniValue data(UniValue::VOBJ);
if (!cs.m_chain.Tip()) {
@@ -2852,20 +2852,18 @@ return RPCHelpMan{
if (cs.m_from_snapshot_blockhash) {
data.pushKV("snapshot_blockhash", cs.m_from_snapshot_blockhash->ToString());
}
+ data.pushKV("validated", validated);
return data;
};
- if (chainman.GetAll().size() > 1) {
- for (Chainstate* chainstate : chainman.GetAll()) {
- obj.pushKV(
- chainstate->m_from_snapshot_blockhash ? "snapshot" : "normal",
- make_chain_data(*chainstate));
- }
- } else {
- obj.pushKV("normal", make_chain_data(chainman.ActiveChainstate()));
- }
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
+ const auto& chainstates = chainman.GetAll();
+ UniValue obj_chainstates{UniValue::VARR};
+ for (Chainstate* cs : chainstates) {
+ obj_chainstates.push_back(make_chain_data(*cs, !cs->m_from_snapshot_blockhash || chainstates.size() == 1));
+ }
+ obj.pushKV("chainstates", std::move(obj_chainstates));
return obj;
}
};
diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
index 705608bd47..136969eb87 100644
--- a/src/rpc/mempool.cpp
+++ b/src/rpc/mempool.cpp
@@ -819,11 +819,11 @@ static RPCHelpMan savemempool()
static RPCHelpMan submitpackage()
{
return RPCHelpMan{"submitpackage",
- "Submit a package of raw transactions (serialized, hex-encoded) to local node (-regtest only).\n"
+ "Submit a package of raw transactions (serialized, hex-encoded) to local node.\n"
+ "The package must consist of a child with its parents, and none of the parents may depend on one another.\n"
"The package will be validated according to consensus and mempool policy rules. If all transactions pass, they will be accepted to mempool.\n"
"This RPC is experimental and the interface may be unstable. Refer to doc/policy/packages.md for documentation on package policies.\n"
- "Warning: until package relay is in use, successful submission does not mean the transaction will propagate to other nodes on the network.\n"
- "Currently, each transaction is broadcasted individually after submission, which means they must meet other nodes' feerate requirements alone.\n"
+ "Warning: successful submission does not mean the transactions will propagate throughout the network.\n"
,
{
{"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.",
@@ -862,9 +862,6 @@ static RPCHelpMan submitpackage()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- if (Params().GetChainType() != ChainType::REGTEST) {
- throw std::runtime_error("submitpackage is for regression testing (-regtest mode) only");
- }
const UniValue raw_transactions = request.params[0].get_array();
if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
@@ -881,6 +878,9 @@ static RPCHelpMan submitpackage()
}
txns.emplace_back(MakeTransactionRef(std::move(mtx)));
}
+ if (!IsChildWithParentsTree(txns)) {
+ throw JSONRPCTransactionError(TransactionError::INVALID_PACKAGE, "package topology disallowed. not child-with-parents or parents depend on each other.");
+ }
NodeContext& node = EnsureAnyNodeContext(request.context);
CTxMemPool& mempool = EnsureMemPool(node);
@@ -983,7 +983,7 @@ void RegisterMempoolRPCCommands(CRPCTable& t)
{"blockchain", &getrawmempool},
{"blockchain", &importmempool},
{"blockchain", &savemempool},
- {"hidden", &submitpackage},
+ {"rawtransactions", &submitpackage},
};
for (const auto& c : commands) {
t.appendCommand(c.name, &c);
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index ec0eab52d1..63788c3a03 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -949,10 +949,7 @@ static RPCHelpMan addpeeraddress()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- NodeContext& node = EnsureAnyNodeContext(request.context);
- if (!node.addrman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
- }
+ AddrMan& addrman = EnsureAnyAddrman(request.context);
const std::string& addr_string{request.params[0].get_str()};
const auto port{request.params[1].getInt<uint16_t>()};
@@ -968,11 +965,11 @@ static RPCHelpMan addpeeraddress()
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)) {
+ if (addrman.Add({address}, address)) {
success = true;
if (tried) {
// Attempt to move the address to the tried addresses table.
- node.addrman->Good(address);
+ addrman.Good(address);
}
}
}
@@ -1033,50 +1030,40 @@ static RPCHelpMan sendmsgtopeer()
static RPCHelpMan getaddrmaninfo()
{
- return RPCHelpMan{"getaddrmaninfo",
- "\nProvides information about the node's address manager by returning the number of "
- "addresses in the `new` and `tried` tables and their sum for all networks.\n"
- "This RPC is for testing only.\n",
- {},
- RPCResult{
- RPCResult::Type::OBJ_DYN, "", "json object with network type as keys",
- {
- {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ")",
- {
- {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."},
- {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."},
- {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"},
- }},
- }
- },
- RPCExamples{
- HelpExampleCli("getaddrmaninfo", "")
- + HelpExampleRpc("getaddrmaninfo", "")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
- {
- NodeContext& node = EnsureAnyNodeContext(request.context);
- if (!node.addrman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
- }
-
- UniValue ret(UniValue::VOBJ);
- for (int n = 0; n < NET_MAX; ++n) {
- enum Network network = static_cast<enum Network>(n);
- if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
- UniValue obj(UniValue::VOBJ);
- obj.pushKV("new", node.addrman->Size(network, true));
- obj.pushKV("tried", node.addrman->Size(network, false));
- obj.pushKV("total", node.addrman->Size(network));
- ret.pushKV(GetNetworkName(network), obj);
- }
- UniValue obj(UniValue::VOBJ);
- obj.pushKV("new", node.addrman->Size(std::nullopt, true));
- obj.pushKV("tried", node.addrman->Size(std::nullopt, false));
- obj.pushKV("total", node.addrman->Size());
- ret.pushKV("all_networks", obj);
- return ret;
- },
+ return RPCHelpMan{
+ "getaddrmaninfo",
+ "\nProvides information about the node's address manager by returning the number of "
+ "addresses in the `new` and `tried` tables and their sum for all networks.\n",
+ {},
+ RPCResult{
+ RPCResult::Type::OBJ_DYN, "", "json object with network type as keys", {
+ {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ", all_networks)", {
+ {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."},
+ {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."},
+ {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"},
+ }},
+ }},
+ RPCExamples{HelpExampleCli("getaddrmaninfo", "") + HelpExampleRpc("getaddrmaninfo", "")},
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
+ AddrMan& addrman = EnsureAnyAddrman(request.context);
+
+ UniValue ret(UniValue::VOBJ);
+ for (int n = 0; n < NET_MAX; ++n) {
+ enum Network network = static_cast<enum Network>(n);
+ if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("new", addrman.Size(network, true));
+ obj.pushKV("tried", addrman.Size(network, false));
+ obj.pushKV("total", addrman.Size(network));
+ ret.pushKV(GetNetworkName(network), obj);
+ }
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("new", addrman.Size(std::nullopt, true));
+ obj.pushKV("tried", addrman.Size(std::nullopt, false));
+ obj.pushKV("total", addrman.Size());
+ ret.pushKV("all_networks", obj);
+ return ret;
+ },
};
}
@@ -1135,14 +1122,11 @@ static RPCHelpMan getrawaddrman()
+ HelpExampleRpc("getrawaddrman", "")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
- NodeContext& node = EnsureAnyNodeContext(request.context);
- if (!node.addrman) {
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
- }
+ AddrMan& addrman = EnsureAnyAddrman(request.context);
UniValue ret(UniValue::VOBJ);
- ret.pushKV("new", AddrmanTableToJSON(node.addrman->GetEntries(false)));
- ret.pushKV("tried", AddrmanTableToJSON(node.addrman->GetEntries(true)));
+ ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false)));
+ ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true)));
return ret;
},
};
@@ -1164,10 +1148,10 @@ void RegisterNetRPCCommands(CRPCTable& t)
{"network", &clearbanned},
{"network", &setnetworkactive},
{"network", &getnodeaddresses},
+ {"network", &getaddrmaninfo},
{"hidden", &addconnection},
{"hidden", &addpeeraddress},
{"hidden", &sendmsgtopeer},
- {"hidden", &getaddrmaninfo},
{"hidden", &getrawaddrman},
};
for (const auto& c : commands) {
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 31ca126862..16705b3ce2 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1581,10 +1581,10 @@ static RPCHelpMan createpsbt()
PartiallySignedTransaction psbtx;
psbtx.tx = rawTx;
for (unsigned int i = 0; i < rawTx.vin.size(); ++i) {
- psbtx.inputs.push_back(PSBTInput());
+ psbtx.inputs.emplace_back();
}
for (unsigned int i = 0; i < rawTx.vout.size(); ++i) {
- psbtx.outputs.push_back(PSBTOutput());
+ psbtx.outputs.emplace_back();
}
// Serialize the PSBT
@@ -1648,10 +1648,10 @@ static RPCHelpMan converttopsbt()
PartiallySignedTransaction psbtx;
psbtx.tx = tx;
for (unsigned int i = 0; i < tx.vin.size(); ++i) {
- psbtx.inputs.push_back(PSBTInput());
+ psbtx.inputs.emplace_back();
}
for (unsigned int i = 0; i < tx.vout.size(); ++i) {
- psbtx.outputs.push_back(PSBTOutput());
+ psbtx.outputs.emplace_back();
}
// Serialize the PSBT
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index daf751111f..d3c5a19326 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -88,7 +88,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest&
vCommands.reserve(mapCommands.size());
for (const auto& entry : mapCommands)
- vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front()));
+ vCommands.emplace_back(entry.second.front()->category + entry.first, entry.second.front());
sort(vCommands.begin(), vCommands.end());
JSONRPCRequest jreq = helpreq;
diff --git a/src/rpc/server_util.cpp b/src/rpc/server_util.cpp
index 1d4afb3758..efd4a43c28 100644
--- a/src/rpc/server_util.cpp
+++ b/src/rpc/server_util.cpp
@@ -108,3 +108,16 @@ PeerManager& EnsurePeerman(const NodeContext& node)
}
return *node.peerman;
}
+
+AddrMan& EnsureAddrman(const NodeContext& node)
+{
+ if (!node.addrman) {
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
+ }
+ return *node.addrman;
+}
+
+AddrMan& EnsureAnyAddrman(const std::any& context)
+{
+ return EnsureAddrman(EnsureAnyNodeContext(context));
+}
diff --git a/src/rpc/server_util.h b/src/rpc/server_util.h
index 9af9572431..a4a53166b4 100644
--- a/src/rpc/server_util.h
+++ b/src/rpc/server_util.h
@@ -7,6 +7,7 @@
#include <any>
+class AddrMan;
class ArgsManager;
class CBlockPolicyEstimator;
class CConnman;
@@ -31,5 +32,7 @@ CBlockPolicyEstimator& EnsureFeeEstimator(const node::NodeContext& node);
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context);
CConnman& EnsureConnman(const node::NodeContext& node);
PeerManager& EnsurePeerman(const node::NodeContext& node);
+AddrMan& EnsureAddrman(const node::NodeContext& node);
+AddrMan& EnsureAnyAddrman(const std::any& context);
#endif // BITCOIN_RPC_SERVER_UTIL_H
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index 4fab481b39..71005cfb6e 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -72,14 +72,34 @@ static bool verify_flags(unsigned int flags)
static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CAmount amount,
const unsigned char *txTo , unsigned int txToLen,
+ const UTXO *spentOutputs, unsigned int spentOutputsLen,
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
{
if (!verify_flags(flags)) {
return set_error(err, bitcoinconsensus_ERR_INVALID_FLAGS);
}
+
+ if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT && spentOutputs == nullptr) {
+ return set_error(err, bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+ }
+
try {
TxInputStream stream(PROTOCOL_VERSION, txTo, txToLen);
CTransaction tx(deserialize, stream);
+
+ std::vector<CTxOut> spent_outputs;
+ if (spentOutputs != nullptr) {
+ if (spentOutputsLen != tx.vin.size()) {
+ return set_error(err, bitcoinconsensus_ERR_SPENT_OUTPUTS_MISMATCH);
+ }
+ for (size_t i = 0; i < spentOutputsLen; i++) {
+ CScript spk = CScript(spentOutputs[i].scriptPubKey, spentOutputs[i].scriptPubKey + spentOutputs[i].scriptPubKeySize);
+ const CAmount& value = spentOutputs[i].value;
+ CTxOut tx_out = CTxOut(value, spk);
+ spent_outputs.push_back(tx_out);
+ }
+ }
+
if (nIn >= tx.vin.size())
return set_error(err, bitcoinconsensus_ERR_TX_INDEX);
if (GetSerializeSize(tx, PROTOCOL_VERSION) != txToLen)
@@ -89,18 +109,34 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
set_error(err, bitcoinconsensus_ERR_OK);
PrecomputedTransactionData txdata(tx);
+
+ if (spentOutputs != nullptr && flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT) {
+ txdata.Init(tx, std::move(spent_outputs));
+ }
+
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata, MissingDataBehavior::FAIL), nullptr);
} catch (const std::exception&) {
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
}
}
+int bitcoinconsensus_verify_script_with_spent_outputs(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
+ const unsigned char *txTo , unsigned int txToLen,
+ const UTXO *spentOutputs, unsigned int spentOutputsLen,
+ unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
+{
+ CAmount am(amount);
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
+}
+
int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
{
CAmount am(amount);
- return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
+ UTXO *spentOutputs = nullptr;
+ unsigned int spentOutputsLen = 0;
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
}
@@ -113,7 +149,9 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i
}
CAmount am(0);
- return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
+ UTXO *spentOutputs = nullptr;
+ unsigned int spentOutputsLen = 0;
+ return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
}
unsigned int bitcoinconsensus_version()
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index f2f2ff8686..a202b5ba06 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -31,7 +31,7 @@
extern "C" {
#endif
-#define BITCOINCONSENSUS_API_VER 1
+#define BITCOINCONSENSUS_API_VER 2
typedef enum bitcoinconsensus_error_t
{
@@ -41,6 +41,8 @@ typedef enum bitcoinconsensus_error_t
bitcoinconsensus_ERR_TX_DESERIALIZE,
bitcoinconsensus_ERR_AMOUNT_REQUIRED,
bitcoinconsensus_ERR_INVALID_FLAGS,
+ bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED,
+ bitcoinconsensus_ERR_SPENT_OUTPUTS_MISMATCH
} bitcoinconsensus_error;
/** Script verification flags */
@@ -53,11 +55,19 @@ enum
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), // enable CHECKSEQUENCEVERIFY (BIP112)
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141)
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT = (1U << 17), // enable TAPROOT (BIPs 341 & 342)
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL = bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH | bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG |
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NULLDUMMY | bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY |
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY | bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY | bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS |
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT
};
+typedef struct {
+ const unsigned char *scriptPubKey;
+ unsigned int scriptPubKeySize;
+ int64_t value;
+} UTXO;
+
/// Returns 1 if the input nIn of the serialized transaction pointed to by
/// txTo correctly spends the scriptPubKey pointed to by scriptPubKey under
/// the additional constraints specified by flags.
@@ -70,6 +80,11 @@ EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
+EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_spent_outputs(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
+ const unsigned char *txTo , unsigned int txToLen,
+ const UTXO *spentOutputs, unsigned int spentOutputsLen,
+ unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
+
EXPORT_SYMBOL unsigned int bitcoinconsensus_version();
#ifdef __cplusplus
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 2f3f2c7a1d..7e62d75583 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -1114,16 +1114,33 @@ public:
class ScriptMaker {
//! Keys contained in the Miniscript (the evaluation of DescriptorImpl::m_pubkey_args).
const std::vector<CPubKey>& m_keys;
+ //! The script context we're operating within (Tapscript or P2WSH).
+ const miniscript::MiniscriptContext m_script_ctx;
+
+ //! Get the ripemd160(sha256()) hash of this key.
+ //! Any key that is valid in a descriptor serializes as 32 bytes within a Tapscript context. So we
+ //! must not hash the sign-bit byte in this case.
+ uint160 GetHash160(uint32_t key) const {
+ if (miniscript::IsTapscript(m_script_ctx)) {
+ return Hash160(XOnlyPubKey{m_keys[key]});
+ }
+ return m_keys[key].GetID();
+ }
public:
- ScriptMaker(const std::vector<CPubKey>& keys LIFETIMEBOUND) : m_keys(keys) {}
+ ScriptMaker(const std::vector<CPubKey>& keys LIFETIMEBOUND, const miniscript::MiniscriptContext script_ctx) : m_keys(keys), m_script_ctx{script_ctx} {}
std::vector<unsigned char> ToPKBytes(uint32_t key) const {
- return {m_keys[key].begin(), m_keys[key].end()};
+ // In Tapscript keys always serialize as x-only, whether an x-only key was used in the descriptor or not.
+ if (!miniscript::IsTapscript(m_script_ctx)) {
+ return {m_keys[key].begin(), m_keys[key].end()};
+ }
+ const XOnlyPubKey xonly_pubkey{m_keys[key]};
+ return {xonly_pubkey.begin(), xonly_pubkey.end()};
}
std::vector<unsigned char> ToPKHBytes(uint32_t key) const {
- auto id = m_keys[key].GetID();
+ auto id = GetHash160(key);
return {id.begin(), id.end()};
}
};
@@ -1164,8 +1181,15 @@ protected:
std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts,
FlatSigningProvider& provider) const override
{
- for (const auto& key : keys) provider.pubkeys.emplace(key.GetID(), key);
- return Vector(m_node->ToScript(ScriptMaker(keys)));
+ const auto script_ctx{m_node->GetMsCtx()};
+ for (const auto& key : keys) {
+ if (miniscript::IsTapscript(script_ctx)) {
+ provider.pubkeys.emplace(Hash160(XOnlyPubKey{key}), key);
+ } else {
+ provider.pubkeys.emplace(key.GetID(), key);
+ }
+ }
+ return Vector(m_node->ToScript(ScriptMaker(keys, script_ctx)));
}
public:
@@ -1290,6 +1314,10 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const S
if (IsHex(str)) {
std::vector<unsigned char> data = ParseHex(str);
CPubKey pubkey(data);
+ if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
+ error = "Hybrid public keys are not allowed";
+ return nullptr;
+ }
if (pubkey.IsFullyValid()) {
if (permit_uncompressed || pubkey.IsCompressed()) {
return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, false);
@@ -1385,8 +1413,16 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<c
return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider), apostrophe);
}
-std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
+std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext ctx, const SigningProvider& provider)
{
+ // Key cannot be hybrid
+ if (!pubkey.IsValidNonHybrid()) {
+ return nullptr;
+ }
+ // Uncompressed is only allowed in TOP and P2SH contexts
+ if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.IsCompressed()) {
+ return nullptr;
+ }
std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, false);
KeyOriginInfo info;
if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
@@ -1397,9 +1433,7 @@ std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptCo
std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(const XOnlyPubKey& xkey, ParseScriptContext ctx, const SigningProvider& provider)
{
- unsigned char full_key[CPubKey::COMPRESSED_SIZE] = {0x02};
- std::copy(xkey.begin(), xkey.end(), full_key + 1);
- CPubKey pubkey(full_key);
+ CPubKey pubkey{xkey.GetEvenCorrespondingCPubKey()};
std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, true);
KeyOriginInfo info;
if (provider.GetKeyOriginByXOnly(xkey, info)) {
@@ -1422,18 +1456,32 @@ struct KeyParser {
mutable std::vector<std::unique_ptr<PubkeyProvider>> m_keys;
//! Used to detect key parsing errors within a Miniscript.
mutable std::string m_key_parsing_error;
+ //! The script context we're operating within (Tapscript or P2WSH).
+ const miniscript::MiniscriptContext m_script_ctx;
+ //! The number of keys that were parsed before starting to parse this Miniscript descriptor.
+ uint32_t m_offset;
- KeyParser(FlatSigningProvider* out LIFETIMEBOUND, const SigningProvider* in LIFETIMEBOUND) : m_out(out), m_in(in) {}
+ KeyParser(FlatSigningProvider* out LIFETIMEBOUND, const SigningProvider* in LIFETIMEBOUND,
+ miniscript::MiniscriptContext ctx, uint32_t offset = 0)
+ : m_out(out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
bool KeyCompare(const Key& a, const Key& b) const {
return *m_keys.at(a) < *m_keys.at(b);
}
+ ParseScriptContext ParseContext() const {
+ switch (m_script_ctx) {
+ case miniscript::MiniscriptContext::P2WSH: return ParseScriptContext::P2WSH;
+ case miniscript::MiniscriptContext::TAPSCRIPT: return ParseScriptContext::P2TR;
+ }
+ assert(false);
+ }
+
template<typename I> std::optional<Key> FromString(I begin, I end) const
{
assert(m_out);
Key key = m_keys.size();
- auto pk = ParsePubkey(key, {&*begin, &*end}, ParseScriptContext::P2WSH, *m_out, m_key_parsing_error);
+ auto pk = ParsePubkey(m_offset + key, {&*begin, &*end}, ParseContext(), *m_out, m_key_parsing_error);
if (!pk) return {};
m_keys.push_back(std::move(pk));
return key;
@@ -1447,11 +1495,20 @@ struct KeyParser {
template<typename I> std::optional<Key> FromPKBytes(I begin, I end) const
{
assert(m_in);
- CPubKey pubkey(begin, end);
- if (pubkey.IsValid()) {
- Key key = m_keys.size();
- m_keys.push_back(InferPubkey(pubkey, ParseScriptContext::P2WSH, *m_in));
- return key;
+ Key key = m_keys.size();
+ if (miniscript::IsTapscript(m_script_ctx) && end - begin == 32) {
+ XOnlyPubKey pubkey;
+ std::copy(begin, end, pubkey.begin());
+ if (auto pubkey_provider = InferPubkey(pubkey.GetEvenCorrespondingCPubKey(), ParseContext(), *m_in)) {
+ m_keys.push_back(std::move(pubkey_provider));
+ return key;
+ }
+ } else if (!miniscript::IsTapscript(m_script_ctx)) {
+ CPubKey pubkey(begin, end);
+ if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) {
+ m_keys.push_back(std::move(pubkey_provider));
+ return key;
+ }
}
return {};
}
@@ -1465,12 +1522,18 @@ struct KeyParser {
CKeyID keyid(hash);
CPubKey pubkey;
if (m_in->GetPubKey(keyid, pubkey)) {
- Key key = m_keys.size();
- m_keys.push_back(InferPubkey(pubkey, ParseScriptContext::P2WSH, *m_in));
- return key;
+ if (auto pubkey_provider = InferPubkey(pubkey, ParseContext(), *m_in)) {
+ Key key = m_keys.size();
+ m_keys.push_back(std::move(pubkey_provider));
+ return key;
+ }
}
return {};
}
+
+ miniscript::MiniscriptContext MsContext() const {
+ return m_script_ctx;
+ }
};
/** Parse a script in a particular context. */
@@ -1496,8 +1559,9 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
}
++key_exp_index;
return std::make_unique<PKHDescriptor>(std::move(pubkey));
- } else if (Func("pkh", expr)) {
- error = "Can only have pkh at top level, in sh(), or in wsh()";
+ } else if (ctx != ParseScriptContext::P2TR && Func("pkh", expr)) {
+ // Under Taproot, always the Miniscript parser deal with it.
+ error = "Can only have pkh at top level, in sh(), wsh(), or in tr()";
return nullptr;
}
if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
@@ -1710,11 +1774,12 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
}
// Process miniscript expressions.
{
- KeyParser parser(&out, nullptr);
+ const auto script_ctx{ctx == ParseScriptContext::P2WSH ? miniscript::MiniscriptContext::P2WSH : miniscript::MiniscriptContext::TAPSCRIPT};
+ KeyParser parser(/*out = */&out, /* in = */nullptr, /* ctx = */script_ctx, key_exp_index);
auto node = miniscript::FromString(std::string(expr.begin(), expr.end()), parser);
if (node) {
- if (ctx != ParseScriptContext::P2WSH) {
- error = "Miniscript expressions can only be used in wsh";
+ if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
+ error = "Miniscript expressions can only be used in wsh or tr.";
return nullptr;
}
if (parser.m_key_parsing_error != "") {
@@ -1749,6 +1814,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
// A signature check is required for a miniscript to be sane. Therefore no sane miniscript
// may have an empty list of public keys.
CHECK_NONFATAL(!parser.m_keys.empty());
+ key_exp_index += parser.m_keys.size();
return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(node));
}
}
@@ -1795,8 +1861,8 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
if (txntype == TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
CPubKey pubkey(data[0]);
- if (pubkey.IsValid()) {
- return std::make_unique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
+ if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
+ return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
}
}
if (txntype == TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
@@ -1804,7 +1870,9 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
CKeyID keyid(hash);
CPubKey pubkey;
if (provider.GetPubKey(keyid, pubkey)) {
- return std::make_unique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
+ if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
+ return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
+ }
}
}
if (txntype == TxoutType::WITNESS_V0_KEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) {
@@ -1812,16 +1880,24 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
CKeyID keyid(hash);
CPubKey pubkey;
if (provider.GetPubKey(keyid, pubkey)) {
- return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
+ if (auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
+ return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
+ }
}
}
if (txntype == TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
+ bool ok = true;
std::vector<std::unique_ptr<PubkeyProvider>> providers;
for (size_t i = 1; i + 1 < data.size(); ++i) {
CPubKey pubkey(data[i]);
- providers.push_back(InferPubkey(pubkey, ctx, provider));
+ if (auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
+ providers.push_back(std::move(pubkey_provider));
+ } else {
+ ok = false;
+ break;
+ }
}
- return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
+ if (ok) return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
}
if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
uint160 hash(data[0]);
@@ -1882,8 +1958,9 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
}
}
- if (ctx == ParseScriptContext::P2WSH) {
- KeyParser parser(nullptr, &provider);
+ if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
+ const auto script_ctx{ctx == ParseScriptContext::P2WSH ? miniscript::MiniscriptContext::P2WSH : miniscript::MiniscriptContext::TAPSCRIPT};
+ KeyParser parser(/* out = */nullptr, /* in = */&provider, /* ctx = */script_ctx);
auto node = miniscript::FromScript(script, parser);
if (node && node->IsSane()) {
return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(node));
diff --git a/src/script/miniscript.cpp b/src/script/miniscript.cpp
index 19556a9775..344a81bdf0 100644
--- a/src/script/miniscript.cpp
+++ b/src/script/miniscript.cpp
@@ -6,6 +6,7 @@
#include <vector>
#include <script/script.h>
#include <script/miniscript.h>
+#include <serialize.h>
#include <assert.h>
@@ -32,7 +33,8 @@ Type SanitizeType(Type e) {
return e;
}
-Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Type>& sub_types, uint32_t k, size_t data_size, size_t n_subs, size_t n_keys) {
+Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Type>& sub_types, uint32_t k,
+ size_t data_size, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx) {
// Sanity check on data
if (fragment == Fragment::SHA256 || fragment == Fragment::HASH256) {
assert(data_size == 32);
@@ -44,7 +46,7 @@ Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Ty
// Sanity check on k
if (fragment == Fragment::OLDER || fragment == Fragment::AFTER) {
assert(k >= 1 && k < 0x80000000UL);
- } else if (fragment == Fragment::MULTI) {
+ } else if (fragment == Fragment::MULTI || fragment == Fragment::MULTI_A) {
assert(k >= 1 && k <= n_keys);
} else if (fragment == Fragment::THRESH) {
assert(k >= 1 && k <= n_subs);
@@ -68,7 +70,11 @@ Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Ty
if (fragment == Fragment::PK_K || fragment == Fragment::PK_H) {
assert(n_keys == 1);
} else if (fragment == Fragment::MULTI) {
- assert(n_keys >= 1 && n_keys <= 20);
+ assert(n_keys >= 1 && n_keys <= MAX_PUBKEYS_PER_MULTISIG);
+ assert(!IsTapscript(ms_ctx));
+ } else if (fragment == Fragment::MULTI_A) {
+ assert(n_keys >= 1 && n_keys <= MAX_PUBKEYS_PER_MULTI_A);
+ assert(IsTapscript(ms_ctx));
} else {
assert(n_keys == 0);
}
@@ -113,7 +119,8 @@ Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Ty
"e"_mst.If(x << "f"_mst) | // e=f_x
(x & "ghijk"_mst) | // g=g_x, h=h_x, i=i_x, j=j_x, k=k_x
(x & "ms"_mst) | // m=m_x, s=s_x
- // NOTE: 'd:' is not 'u' under P2WSH as MINIMALIF is only a policy rule there.
+ // NOTE: 'd:' is 'u' under Tapscript but not P2WSH as MINIMALIF is only a policy rule there.
+ "u"_mst.If(IsTapscript(ms_ctx)) |
"ndx"_mst; // n, d, x
case Fragment::WRAP_V: return
"V"_mst.If(x << "B"_mst) | // V=B_x
@@ -210,7 +217,12 @@ Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Ty
((x << "h"_mst) && (y << "g"_mst)) ||
((x << "i"_mst) && (y << "j"_mst)) ||
((x << "j"_mst) && (y << "i"_mst)))); // k=k_x*k_y*k_z* !(g_x*h_y + h_x*g_y + i_x*j_y + j_x*i_y)
- case Fragment::MULTI: return "Bnudemsk"_mst;
+ case Fragment::MULTI: {
+ return "Bnudemsk"_mst;
+ }
+ case Fragment::MULTI_A: {
+ return "Budemsk"_mst;
+ }
case Fragment::THRESH: {
bool all_e = true;
bool all_m = true;
@@ -246,11 +258,12 @@ Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Ty
assert(false);
}
-size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys) {
+size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs,
+ size_t n_keys, MiniscriptContext ms_ctx) {
switch (fragment) {
case Fragment::JUST_1:
case Fragment::JUST_0: return 1;
- case Fragment::PK_K: return 34;
+ case Fragment::PK_K: return IsTapscript(ms_ctx) ? 33 : 34;
case Fragment::PK_H: return 3 + 21;
case Fragment::OLDER:
case Fragment::AFTER: return 1 + BuildScript(k).size();
@@ -259,6 +272,7 @@ size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_
case Fragment::HASH160:
case Fragment::RIPEMD160: return 4 + 2 + 21;
case Fragment::MULTI: return 1 + BuildScript(n_keys).size() + BuildScript(k).size() + 34 * n_keys;
+ case Fragment::MULTI_A: return (1 + 32 + 1) * n_keys + BuildScript(k).size() + 1;
case Fragment::AND_V: return subsize;
case Fragment::WRAP_V: return subsize + (sub0typ << "x"_mst);
case Fragment::WRAP_S:
@@ -372,9 +386,13 @@ std::optional<std::vector<Opcode>> DecomposeScript(const CScript& script)
// Decompose OP_EQUALVERIFY into OP_EQUAL OP_VERIFY
out.emplace_back(OP_EQUAL, std::vector<unsigned char>());
opcode = OP_VERIFY;
+ } else if (opcode == OP_NUMEQUALVERIFY) {
+ // Decompose OP_NUMEQUALVERIFY into OP_NUMEQUAL OP_VERIFY
+ out.emplace_back(OP_NUMEQUAL, std::vector<unsigned char>());
+ opcode = OP_VERIFY;
} else if (IsPushdataOp(opcode)) {
if (!CheckMinimalPush(push_data, opcode)) return {};
- } else if (it != itend && (opcode == OP_CHECKSIG || opcode == OP_CHECKMULTISIG || opcode == OP_EQUAL) && (*it == OP_VERIFY)) {
+ } else if (it != itend && (opcode == OP_CHECKSIG || opcode == OP_CHECKMULTISIG || opcode == OP_EQUAL || opcode == OP_NUMEQUAL) && (*it == OP_VERIFY)) {
// Rule out non minimal VERIFY sequences
return {};
}
diff --git a/src/script/miniscript.h b/src/script/miniscript.h
index 4c6bd0bb1d..76b952350b 100644
--- a/src/script/miniscript.h
+++ b/src/script/miniscript.h
@@ -20,6 +20,7 @@
#include <primitives/transaction.h>
#include <script/script.h>
#include <span.h>
+#include <util/check.h>
#include <util/spanparsing.h>
#include <util/strencodings.h>
#include <util/string.h>
@@ -44,8 +45,8 @@ namespace miniscript {
* - When satisfied, pushes nothing.
* - Cannot be dissatisfied.
* - This can be obtained by adding an OP_VERIFY to a B, modifying the last opcode
- * of a B to its -VERIFY version (only for OP_CHECKSIG, OP_CHECKSIGVERIFY
- * and OP_EQUAL), or by combining a V fragment under some conditions.
+ * of a B to its -VERIFY version (only for OP_CHECKSIG, OP_CHECKSIGVERIFY,
+ * OP_NUMEQUAL and OP_EQUAL), or by combining a V fragment under some conditions.
* - For example vc:pk_k(key) = <key> OP_CHECKSIGVERIFY
* - "K" Key:
* - Takes its inputs from the top of the stack.
@@ -216,7 +217,8 @@ enum class Fragment {
OR_I, //!< OP_IF [X] OP_ELSE [Y] OP_ENDIF
ANDOR, //!< [X] OP_NOTIF [Z] OP_ELSE [Y] OP_ENDIF
THRESH, //!< [X1] ([Xn] OP_ADD)* [k] OP_EQUAL
- MULTI, //!< [k] [key_n]* [n] OP_CHECKMULTISIG
+ MULTI, //!< [k] [key_n]* [n] OP_CHECKMULTISIG (only available within P2WSH context)
+ MULTI_A, //!< [key_0] OP_CHECKSIG ([key_n] OP_CHECKSIGADD)* [k] OP_NUMEQUAL (only within Tapscript ctx)
// AND_N(X,Y) is represented as ANDOR(X,Y,0)
// WRAP_T(X) is represented as AND_V(X,1)
// WRAP_L(X) is represented as OR_I(0,X)
@@ -229,13 +231,56 @@ enum class Availability {
MAYBE,
};
+enum class MiniscriptContext {
+ P2WSH,
+ TAPSCRIPT,
+};
+
+/** Whether the context Tapscript, ensuring the only other possibility is P2WSH. */
+constexpr bool IsTapscript(MiniscriptContext ms_ctx)
+{
+ switch (ms_ctx) {
+ case MiniscriptContext::P2WSH: return false;
+ case MiniscriptContext::TAPSCRIPT: return true;
+ }
+ assert(false);
+}
+
namespace internal {
+//! The maximum size of a witness item for a Miniscript under Tapscript context. (A BIP340 signature with a sighash type byte.)
+static constexpr uint32_t MAX_TAPMINISCRIPT_STACK_ELEM_SIZE{65};
+
+//! nVersion + nLockTime
+constexpr uint32_t TX_OVERHEAD{4 + 4};
+//! prevout + nSequence + scriptSig
+constexpr uint32_t TXIN_BYTES_NO_WITNESS{36 + 4 + 1};
+//! nValue + script len + OP_0 + pushdata 32.
+constexpr uint32_t P2WSH_TXOUT_BYTES{8 + 1 + 1 + 33};
+//! Data other than the witness in a transaction. Overhead + vin count + one vin + vout count + one vout + segwit marker
+constexpr uint32_t TX_BODY_LEEWAY_WEIGHT{(TX_OVERHEAD + GetSizeOfCompactSize(1) + TXIN_BYTES_NO_WITNESS + GetSizeOfCompactSize(1) + P2WSH_TXOUT_BYTES) * WITNESS_SCALE_FACTOR + 2};
+//! Maximum possible stack size to spend a Taproot output (excluding the script itself).
+constexpr uint32_t MAX_TAPSCRIPT_SAT_SIZE{GetSizeOfCompactSize(MAX_STACK_SIZE) + (GetSizeOfCompactSize(MAX_TAPMINISCRIPT_STACK_ELEM_SIZE) + MAX_TAPMINISCRIPT_STACK_ELEM_SIZE) * MAX_STACK_SIZE + GetSizeOfCompactSize(TAPROOT_CONTROL_MAX_SIZE) + TAPROOT_CONTROL_MAX_SIZE};
+/** The maximum size of a script depending on the context. */
+constexpr uint32_t MaxScriptSize(MiniscriptContext ms_ctx)
+{
+ if (IsTapscript(ms_ctx)) {
+ // Leaf scripts under Tapscript are not explicitly limited in size. They are only implicitly
+ // bounded by the maximum standard size of a spending transaction. Let the maximum script
+ // size conservatively be small enough such that even a maximum sized witness and a reasonably
+ // sized spending transaction can spend an output paying to this script without running into
+ // the maximum standard tx size limit.
+ constexpr auto max_size{MAX_STANDARD_TX_WEIGHT - TX_BODY_LEEWAY_WEIGHT - MAX_TAPSCRIPT_SAT_SIZE};
+ return max_size - GetSizeOfCompactSize(max_size);
+ }
+ return MAX_STANDARD_P2WSH_SCRIPT_SIZE;
+}
+
//! Helper function for Node::CalcType.
-Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Type>& sub_types, uint32_t k, size_t data_size, size_t n_subs, size_t n_keys);
+Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector<Type>& sub_types, uint32_t k, size_t data_size, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx);
//! Helper function for Node::CalcScriptLen.
-size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys);
+size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx);
//! A helper sanitizer/checker for the output of CalcType.
Type SanitizeType(Type x);
@@ -328,13 +373,112 @@ struct Ops {
Ops(uint32_t in_count, MaxInt<uint32_t> in_sat, MaxInt<uint32_t> in_dsat) : count(in_count), sat(in_sat), dsat(in_dsat) {};
};
+/** A data structure to help the calculation of stack size limits.
+ *
+ * Conceptually, every SatInfo object corresponds to a (possibly empty) set of script execution
+ * traces (sequences of opcodes).
+ * - SatInfo{} corresponds to the empty set.
+ * - SatInfo{n, e} corresponds to a single trace whose net effect is removing n elements from the
+ * stack (may be negative for a net increase), and reaches a maximum of e stack elements more
+ * than it ends with.
+ * - operator| is the union operation: (a | b) corresponds to the union of the traces in a and the
+ * traces in b.
+ * - operator+ is the concatenation operator: (a + b) corresponds to the set of traces formed by
+ * concatenating any trace in a with any trace in b.
+ *
+ * Its fields are:
+ * - valid is true if the set is non-empty.
+ * - netdiff (if valid) is the largest difference between stack size at the beginning and at the
+ * end of the script across all traces in the set.
+ * - exec (if valid) is the largest difference between stack size anywhere during execution and at
+ * the end of the script, across all traces in the set (note that this is not necessarily due
+ * to the same trace as the one that resulted in the value for netdiff).
+ *
+ * This allows us to build up stack size limits for any script efficiently, by starting from the
+ * individual opcodes miniscripts correspond to, using concatenation to construct scripts, and
+ * using the union operation to choose between execution branches. Since any top-level script
+ * satisfaction ends with a single stack element, we know that for a full script:
+ * - netdiff+1 is the maximal initial stack size (relevant for P2WSH stack limits).
+ * - exec+1 is the maximal stack size reached during execution (relevant for P2TR stack limits).
+ *
+ * Mathematically, SatInfo forms a semiring:
+ * - operator| is the semiring addition operator, with identity SatInfo{}, and which is commutative
+ * and associative.
+ * - operator+ is the semiring multiplication operator, with identity SatInfo{0}, and which is
+ * associative.
+ * - operator+ is distributive over operator|, so (a + (b | c)) = (a+b | a+c). This means we do not
+ * need to actually materialize all possible full execution traces over the whole script (which
+ * may be exponential in the length of the script); instead we can use the union operation at the
+ * individual subexpression level, and concatenate the result with subexpressions before and
+ * after it.
+ * - It is not a commutative semiring, because a+b can differ from b+a. For example, "OP_1 OP_DROP"
+ * has exec=1, while "OP_DROP OP_1" has exec=0.
+ */
+struct SatInfo {
+ //! Whether a canonical satisfaction/dissatisfaction is possible at all.
+ const bool valid;
+ //! How much higher the stack size at start of execution can be compared to at the end.
+ const int32_t netdiff;
+ //! Mow much higher the stack size can be during execution compared to at the end.
+ const int32_t exec;
+
+ /** Empty script set. */
+ constexpr SatInfo() noexcept : valid(false), netdiff(0), exec(0) {}
+
+ /** Script set with a single script in it, with specified netdiff and exec. */
+ constexpr SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept :
+ valid{true}, netdiff{in_netdiff}, exec{in_exec} {}
+
+ /** Script set union. */
+ constexpr friend SatInfo operator|(const SatInfo& a, const SatInfo& b) noexcept
+ {
+ // Union with an empty set is itself.
+ if (!a.valid) return b;
+ if (!b.valid) return a;
+ // Otherwise the netdiff and exec of the union is the maximum of the individual values.
+ return {std::max(a.netdiff, b.netdiff), std::max(a.exec, b.exec)};
+ }
+
+ /** Script set concatenation. */
+ constexpr friend SatInfo operator+(const SatInfo& a, const SatInfo& b) noexcept
+ {
+ // Concatenation with an empty set yields an empty set.
+ if (!a.valid || !b.valid) return {};
+ // Otherwise, the maximum stack size difference for the combined scripts is the sum of the
+ // netdiffs, and the maximum stack size difference anywhere is either b.exec (if the
+ // maximum occurred in b) or b.netdiff+a.exec (if the maximum occurred in a).
+ return {a.netdiff + b.netdiff, std::max(b.exec, b.netdiff + a.exec)};
+ }
+
+ /** The empty script. */
+ static constexpr SatInfo Empty() noexcept { return {0, 0}; }
+ /** A script consisting of a single push opcode. */
+ static constexpr SatInfo Push() noexcept { return {-1, 0}; }
+ /** A script consisting of a single hash opcode. */
+ static constexpr SatInfo Hash() noexcept { return {0, 0}; }
+ /** A script consisting of just a repurposed nop (OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY). */
+ static constexpr SatInfo Nop() noexcept { return {0, 0}; }
+ /** A script consisting of just OP_IF or OP_NOTIF. Note that OP_ELSE and OP_ENDIF have no stack effect. */
+ static constexpr SatInfo If() noexcept { return {1, 1}; }
+ /** A script consisting of just a binary operator (OP_BOOLAND, OP_BOOLOR, OP_ADD). */
+ static constexpr SatInfo BinaryOp() noexcept { return {1, 1}; }
+
+ // Scripts for specific individual opcodes.
+ static constexpr SatInfo OP_DUP() noexcept { return {-1, 0}; }
+ static constexpr SatInfo OP_IFDUP(bool nonzero) noexcept { return {nonzero ? -1 : 0, 0}; }
+ static constexpr SatInfo OP_EQUALVERIFY() noexcept { return {2, 2}; }
+ static constexpr SatInfo OP_EQUAL() noexcept { return {1, 1}; }
+ static constexpr SatInfo OP_SIZE() noexcept { return {-1, 0}; }
+ static constexpr SatInfo OP_CHECKSIG() noexcept { return {1, 1}; }
+ static constexpr SatInfo OP_0NOTEQUAL() noexcept { return {0, 0}; }
+ static constexpr SatInfo OP_VERIFY() noexcept { return {1, 1}; }
+};
+
struct StackSize {
- //! Maximum stack size to satisfy;
- MaxInt<uint32_t> sat;
- //! Maximum stack size to dissatisfy;
- MaxInt<uint32_t> dsat;
+ const SatInfo sat, dsat;
- StackSize(MaxInt<uint32_t> in_sat, MaxInt<uint32_t> in_dsat) : sat(in_sat), dsat(in_dsat) {};
+ constexpr StackSize(SatInfo in_sat, SatInfo in_dsat) noexcept : sat(in_sat), dsat(in_dsat) {};
+ constexpr StackSize(SatInfo in_both) noexcept : sat(in_both), dsat(in_both) {};
};
struct WitnessSize {
@@ -362,7 +506,22 @@ struct Node {
//! The data bytes in this expression (only for HASH160/HASH256/SHA256/RIPEMD10).
const std::vector<unsigned char> data;
//! Subexpressions (for WRAP_*/AND_*/OR_*/ANDOR/THRESH)
- const std::vector<NodeRef<Key>> subs;
+ mutable std::vector<NodeRef<Key>> subs;
+ //! The Script context for this node. Either P2WSH or Tapscript.
+ const MiniscriptContext m_script_ctx;
+
+ /* Destroy the shared pointers iteratively to avoid a stack-overflow due to recursive calls
+ * to the subs' destructors. */
+ ~Node() {
+ while (!subs.empty()) {
+ auto node = std::move(subs.back());
+ subs.pop_back();
+ while (!node->subs.empty()) {
+ subs.push_back(std::move(node->subs.back()));
+ node->subs.pop_back();
+ }
+ }
+ }
private:
//! Cached ops counts.
@@ -390,7 +549,7 @@ private:
subsize += sub->ScriptSize();
}
Type sub0type = subs.size() > 0 ? subs[0]->GetType() : ""_mst;
- return internal::ComputeScriptLen(fragment, sub0type, subsize, k, subs.size(), keys.size());
+ return internal::ComputeScriptLen(fragment, sub0type, subsize, k, subs.size(), keys.size(), m_script_ctx);
}
/* Apply a recursive algorithm to a Miniscript tree, without actual recursive calls.
@@ -557,7 +716,7 @@ private:
Type y = subs.size() > 1 ? subs[1]->GetType() : ""_mst;
Type z = subs.size() > 2 ? subs[2]->GetType() : ""_mst;
- return SanitizeType(ComputeType(fragment, x, y, z, sub_types, k, data.size(), subs.size(), keys.size()));
+ return SanitizeType(ComputeType(fragment, x, y, z, sub_types, k, data.size(), subs.size(), keys.size(), m_script_ctx));
}
public:
@@ -578,7 +737,8 @@ public:
};
// The upward function computes for a node, given its followed-by-OP_VERIFY status
// and the CScripts of its child nodes, the CScript of the node.
- auto upfn = [&ctx](bool verify, const Node& node, Span<CScript> subs) -> CScript {
+ const bool is_tapscript{IsTapscript(m_script_ctx)};
+ auto upfn = [&ctx, is_tapscript](bool verify, const Node& node, Span<CScript> subs) -> CScript {
switch (node.fragment) {
case Fragment::PK_K: return BuildScript(ctx.ToPKBytes(node.keys[0]));
case Fragment::PK_H: return BuildScript(OP_DUP, OP_HASH160, ctx.ToPKHBytes(node.keys[0]), OP_EQUALVERIFY);
@@ -611,12 +771,21 @@ public:
case Fragment::OR_I: return BuildScript(OP_IF, subs[0], OP_ELSE, subs[1], OP_ENDIF);
case Fragment::ANDOR: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[2], OP_ELSE, subs[1], OP_ENDIF);
case Fragment::MULTI: {
+ CHECK_NONFATAL(!is_tapscript);
CScript script = BuildScript(node.k);
for (const auto& key : node.keys) {
script = BuildScript(std::move(script), ctx.ToPKBytes(key));
}
return BuildScript(std::move(script), node.keys.size(), verify ? OP_CHECKMULTISIGVERIFY : OP_CHECKMULTISIG);
}
+ case Fragment::MULTI_A: {
+ CHECK_NONFATAL(is_tapscript);
+ CScript script = BuildScript(ctx.ToPKBytes(*node.keys.begin()), OP_CHECKSIG);
+ for (auto it = node.keys.begin() + 1; it != node.keys.end(); ++it) {
+ script = BuildScript(std::move(script), ctx.ToPKBytes(*it), OP_CHECKSIGADD);
+ }
+ return BuildScript(std::move(script), node.k, verify ? OP_NUMEQUALVERIFY : OP_NUMEQUAL);
+ }
case Fragment::THRESH: {
CScript script = std::move(subs[0]);
for (size_t i = 1; i < subs.size(); ++i) {
@@ -646,7 +815,8 @@ public:
};
// The upward function computes for a node, given whether its parent is a wrapper,
// and the string representations of its child nodes, the string representation of the node.
- auto upfn = [&ctx](bool wrapped, const Node& node, Span<std::string> subs) -> std::optional<std::string> {
+ const bool is_tapscript{IsTapscript(m_script_ctx)};
+ auto upfn = [&ctx, is_tapscript](bool wrapped, const Node& node, Span<std::string> subs) -> std::optional<std::string> {
std::string ret = wrapped ? ":" : "";
switch (node.fragment) {
@@ -710,6 +880,7 @@ public:
if (node.subs[2]->fragment == Fragment::JUST_0) return std::move(ret) + "and_n(" + std::move(subs[0]) + "," + std::move(subs[1]) + ")";
return std::move(ret) + "andor(" + std::move(subs[0]) + "," + std::move(subs[1]) + "," + std::move(subs[2]) + ")";
case Fragment::MULTI: {
+ CHECK_NONFATAL(!is_tapscript);
auto str = std::move(ret) + "multi(" + ::ToString(node.k);
for (const auto& key : node.keys) {
auto key_str = ctx.ToString(key);
@@ -718,6 +889,16 @@ public:
}
return std::move(str) + ")";
}
+ case Fragment::MULTI_A: {
+ CHECK_NONFATAL(is_tapscript);
+ auto str = std::move(ret) + "multi_a(" + ::ToString(node.k);
+ for (const auto& key : node.keys) {
+ auto key_str = ctx.ToString(key);
+ if (!key_str) return {};
+ str += "," + std::move(*key_str);
+ }
+ return std::move(str) + ")";
+ }
case Fragment::THRESH: {
auto str = std::move(ret) + "thresh(" + ::ToString(node.k);
for (auto& sub : subs) {
@@ -783,6 +964,7 @@ private:
return {count, sat, dsat};
}
case Fragment::MULTI: return {1, (uint32_t)keys.size(), (uint32_t)keys.size()};
+ case Fragment::MULTI_A: return {(uint32_t)keys.size() + 1, 0, 0};
case Fragment::WRAP_S:
case Fragment::WRAP_C:
case Fragment::WRAP_N: return {1 + subs[0]->ops.count, subs[0]->ops.sat, subs[0]->ops.dsat};
@@ -808,63 +990,130 @@ private:
}
internal::StackSize CalcStackSize() const {
+ using namespace internal;
switch (fragment) {
- case Fragment::JUST_0: return {{}, 0};
- case Fragment::JUST_1:
+ case Fragment::JUST_0: return {{}, SatInfo::Push()};
+ case Fragment::JUST_1: return {SatInfo::Push(), {}};
case Fragment::OLDER:
- case Fragment::AFTER: return {0, {}};
- case Fragment::PK_K: return {1, 1};
- case Fragment::PK_H: return {2, 2};
+ case Fragment::AFTER: return {SatInfo::Push() + SatInfo::Nop(), {}};
+ case Fragment::PK_K: return {SatInfo::Push()};
+ case Fragment::PK_H: return {SatInfo::OP_DUP() + SatInfo::Hash() + SatInfo::Push() + SatInfo::OP_EQUALVERIFY()};
case Fragment::SHA256:
case Fragment::RIPEMD160:
case Fragment::HASH256:
- case Fragment::HASH160: return {1, {}};
+ case Fragment::HASH160: return {
+ SatInfo::OP_SIZE() + SatInfo::Push() + SatInfo::OP_EQUALVERIFY() + SatInfo::Hash() + SatInfo::Push() + SatInfo::OP_EQUAL(),
+ {}
+ };
case Fragment::ANDOR: {
- const auto sat{(subs[0]->ss.sat + subs[1]->ss.sat) | (subs[0]->ss.dsat + subs[2]->ss.sat)};
- const auto dsat{subs[0]->ss.dsat + subs[2]->ss.dsat};
- return {sat, dsat};
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ const auto& z{subs[2]->ss};
+ return {
+ (x.sat + SatInfo::If() + y.sat) | (x.dsat + SatInfo::If() + z.sat),
+ x.dsat + SatInfo::If() + z.dsat
+ };
+ }
+ case Fragment::AND_V: {
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ return {x.sat + y.sat, {}};
+ }
+ case Fragment::AND_B: {
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ return {x.sat + y.sat + SatInfo::BinaryOp(), x.dsat + y.dsat + SatInfo::BinaryOp()};
}
- case Fragment::AND_V: return {subs[0]->ss.sat + subs[1]->ss.sat, {}};
- case Fragment::AND_B: return {subs[0]->ss.sat + subs[1]->ss.sat, subs[0]->ss.dsat + subs[1]->ss.dsat};
case Fragment::OR_B: {
- const auto sat{(subs[0]->ss.dsat + subs[1]->ss.sat) | (subs[0]->ss.sat + subs[1]->ss.dsat)};
- const auto dsat{subs[0]->ss.dsat + subs[1]->ss.dsat};
- return {sat, dsat};
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ return {
+ ((x.sat + y.dsat) | (x.dsat + y.sat)) + SatInfo::BinaryOp(),
+ x.dsat + y.dsat + SatInfo::BinaryOp()
+ };
}
- case Fragment::OR_C: return {subs[0]->ss.sat | (subs[0]->ss.dsat + subs[1]->ss.sat), {}};
- case Fragment::OR_D: return {subs[0]->ss.sat | (subs[0]->ss.dsat + subs[1]->ss.sat), subs[0]->ss.dsat + subs[1]->ss.dsat};
- case Fragment::OR_I: return {(subs[0]->ss.sat + 1) | (subs[1]->ss.sat + 1), (subs[0]->ss.dsat + 1) | (subs[1]->ss.dsat + 1)};
- case Fragment::MULTI: return {k + 1, k + 1};
+ case Fragment::OR_C: {
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ return {(x.sat + SatInfo::If()) | (x.dsat + SatInfo::If() + y.sat), {}};
+ }
+ case Fragment::OR_D: {
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ return {
+ (x.sat + SatInfo::OP_IFDUP(true) + SatInfo::If()) | (x.dsat + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.sat),
+ x.dsat + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.dsat
+ };
+ }
+ case Fragment::OR_I: {
+ const auto& x{subs[0]->ss};
+ const auto& y{subs[1]->ss};
+ return {SatInfo::If() + (x.sat | y.sat), SatInfo::If() + (x.dsat | y.dsat)};
+ }
+ // multi(k, key1, key2, ..., key_n) starts off with k+1 stack elements (a 0, plus k
+ // signatures), then reaches n+k+3 stack elements after pushing the n keys, plus k and
+ // n itself, and ends with 1 stack element (success or failure). Thus, it net removes
+ // k elements (from k+1 to 1), while reaching k+n+2 more than it ends with.
+ case Fragment::MULTI: return {SatInfo(k, k + keys.size() + 2)};
+ // multi_a(k, key1, key2, ..., key_n) starts off with n stack elements (the
+ // signatures), reaches 1 more (after the first key push), and ends with 1. Thus it net
+ // removes n-1 elements (from n to 1) while reaching n more than it ends with.
+ case Fragment::MULTI_A: return {SatInfo(keys.size() - 1, keys.size())};
case Fragment::WRAP_A:
case Fragment::WRAP_N:
- case Fragment::WRAP_S:
- case Fragment::WRAP_C: return subs[0]->ss;
- case Fragment::WRAP_D: return {1 + subs[0]->ss.sat, 1};
- case Fragment::WRAP_V: return {subs[0]->ss.sat, {}};
- case Fragment::WRAP_J: return {subs[0]->ss.sat, 1};
+ case Fragment::WRAP_S: return subs[0]->ss;
+ case Fragment::WRAP_C: return {
+ subs[0]->ss.sat + SatInfo::OP_CHECKSIG(),
+ subs[0]->ss.dsat + SatInfo::OP_CHECKSIG()
+ };
+ case Fragment::WRAP_D: return {
+ SatInfo::OP_DUP() + SatInfo::If() + subs[0]->ss.sat,
+ SatInfo::OP_DUP() + SatInfo::If()
+ };
+ case Fragment::WRAP_V: return {subs[0]->ss.sat + SatInfo::OP_VERIFY(), {}};
+ case Fragment::WRAP_J: return {
+ SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() + subs[0]->ss.sat,
+ SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If()
+ };
case Fragment::THRESH: {
- auto sats = Vector(internal::MaxInt<uint32_t>(0));
- for (const auto& sub : subs) {
- auto next_sats = Vector(sats[0] + sub->ss.dsat);
- for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub->ss.dsat) | (sats[j - 1] + sub->ss.sat));
- next_sats.push_back(sats[sats.size() - 1] + sub->ss.sat);
+ // sats[j] is the SatInfo corresponding to all traces reaching j satisfactions.
+ auto sats = Vector(SatInfo::Empty());
+ for (size_t i = 0; i < subs.size(); ++i) {
+ // Loop over the subexpressions, processing them one by one. After adding
+ // element i we need to add OP_ADD (if i>0).
+ auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty();
+ // Construct a variable that will become the next sats, starting with index 0.
+ auto next_sats = Vector(sats[0] + subs[i]->ss.dsat + add);
+ // Then loop to construct next_sats[1..i].
+ for (size_t j = 1; j < sats.size(); ++j) {
+ next_sats.push_back(((sats[j] + subs[i]->ss.dsat) | (sats[j - 1] + subs[i]->ss.sat)) + add);
+ }
+ // Finally construct next_sats[i+1].
+ next_sats.push_back(sats[sats.size() - 1] + subs[i]->ss.sat + add);
+ // Switch over.
sats = std::move(next_sats);
}
- assert(k <= sats.size());
- return {sats[k], sats[0]};
+ // To satisfy thresh we need k satisfactions; to dissatisfy we need 0. In both
+ // cases a push of k and an OP_EQUAL follow.
+ return {
+ sats[k] + SatInfo::Push() + SatInfo::OP_EQUAL(),
+ sats[0] + SatInfo::Push() + SatInfo::OP_EQUAL()
+ };
}
}
assert(false);
}
internal::WitnessSize CalcWitnessSize() const {
+ const uint32_t sig_size = IsTapscript(m_script_ctx) ? 1 + 65 : 1 + 72;
+ const uint32_t pubkey_size = IsTapscript(m_script_ctx) ? 1 + 32 : 1 + 33;
switch (fragment) {
case Fragment::JUST_0: return {{}, 0};
case Fragment::JUST_1:
case Fragment::OLDER:
case Fragment::AFTER: return {0, {}};
- case Fragment::PK_K: return {1 + 72, 1};
- case Fragment::PK_H: return {1 + 72 + 1 + 33, 1 + 1 + 33};
+ case Fragment::PK_K: return {sig_size, 1};
+ case Fragment::PK_H: return {sig_size + pubkey_size, 1 + pubkey_size};
case Fragment::SHA256:
case Fragment::RIPEMD160:
case Fragment::HASH256:
@@ -884,7 +1133,8 @@ private:
case Fragment::OR_C: return {subs[0]->ws.sat | (subs[0]->ws.dsat + subs[1]->ws.sat), {}};
case Fragment::OR_D: return {subs[0]->ws.sat | (subs[0]->ws.dsat + subs[1]->ws.sat), subs[0]->ws.dsat + subs[1]->ws.dsat};
case Fragment::OR_I: return {(subs[0]->ws.sat + 1 + 1) | (subs[1]->ws.sat + 1), (subs[0]->ws.dsat + 1 + 1) | (subs[1]->ws.dsat + 1)};
- case Fragment::MULTI: return {k * (1 + 72) + 1, k + 1};
+ case Fragment::MULTI: return {k * sig_size + 1, k + 1};
+ case Fragment::MULTI_A: return {k * sig_size + static_cast<uint32_t>(keys.size()) - k, static_cast<uint32_t>(keys.size())};
case Fragment::WRAP_A:
case Fragment::WRAP_N:
case Fragment::WRAP_S:
@@ -925,6 +1175,34 @@ private:
Availability avail = ctx.Sign(node.keys[0], sig);
return {ZERO + InputStack(key), (InputStack(std::move(sig)).SetWithSig() + InputStack(key)).SetAvailable(avail)};
}
+ case Fragment::MULTI_A: {
+ // sats[j] represents the best stack containing j valid signatures (out of the first i keys).
+ // In the loop below, these stacks are built up using a dynamic programming approach.
+ std::vector<InputStack> sats = Vector(EMPTY);
+ for (size_t i = 0; i < node.keys.size(); ++i) {
+ // Get the signature for the i'th key in reverse order (the signature for the first key needs to
+ // be at the top of the stack, contrary to CHECKMULTISIG's satisfaction).
+ std::vector<unsigned char> sig;
+ Availability avail = ctx.Sign(node.keys[node.keys.size() - 1 - i], sig);
+ // Compute signature stack for just this key.
+ auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);
+ // Compute the next sats vector: next_sats[0] is a copy of sats[0] (no signatures). All further
+ // next_sats[j] are equal to either the existing sats[j] + ZERO, or sats[j-1] plus a signature
+ // for the current (i'th) key. The very last element needs all signatures filled.
+ std::vector<InputStack> next_sats;
+ next_sats.push_back(sats[0] + ZERO);
+ for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + ZERO) | (std::move(sats[j - 1]) + sat));
+ next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));
+ // Switch over.
+ sats = std::move(next_sats);
+ }
+ // The dissatisfaction consists of as many empty vectors as there are keys, which is the same as
+ // satisfying 0 keys.
+ auto& nsat{sats[0]};
+ assert(node.k != 0);
+ assert(node.k <= sats.size());
+ return {std::move(nsat), std::move(sats[node.k])};
+ }
case Fragment::MULTI: {
// sats[j] represents the best stack containing j valid signatures (out of the first i keys).
// In the loop below, these stacks are built up using a dynamic programming approach.
@@ -1205,19 +1483,36 @@ public:
//! Check the ops limit of this script against the consensus limit.
bool CheckOpsLimit() const {
+ if (IsTapscript(m_script_ctx)) return true;
if (const auto ops = GetOps()) return *ops <= MAX_OPS_PER_SCRIPT;
return true;
}
- /** Return the maximum number of stack elements needed to satisfy this script non-malleably.
- * This does not account for the P2WSH script push. */
+ /** Whether this node is of type B, K or W. (That is, anything but V.) */
+ bool IsBKW() const {
+ return !((GetType() & "BKW"_mst) == ""_mst);
+ }
+
+ /** Return the maximum number of stack elements needed to satisfy this script non-malleably. */
std::optional<uint32_t> GetStackSize() const {
if (!ss.sat.valid) return {};
- return ss.sat.value;
+ return ss.sat.netdiff + static_cast<int32_t>(IsBKW());
+ }
+
+ //! Return the maximum size of the stack during execution of this script.
+ std::optional<uint32_t> GetExecStackSize() const {
+ if (!ss.sat.valid) return {};
+ return ss.sat.exec + static_cast<int32_t>(IsBKW());
}
//! Check the maximum stack size for this script against the policy limit.
bool CheckStackSize() const {
+ // Since in Tapscript there is no standardness limit on the script and witness sizes, we may run
+ // into the maximum stack size while executing the script. Make sure it doesn't happen.
+ if (IsTapscript(m_script_ctx)) {
+ if (const auto exec_ss = GetExecStackSize()) return exec_ss <= MAX_STACK_SIZE;
+ return true;
+ }
if (const auto ss = GetStackSize()) return *ss <= MAX_STANDARD_P2WSH_STACK_ITEMS;
return true;
}
@@ -1235,6 +1530,9 @@ public:
//! Return the expression type.
Type GetType() const { return typ; }
+ //! Return the script context for this node.
+ MiniscriptContext GetMsCtx() const { return m_script_ctx; }
+
//! Find an insane subnode which has no insane children. Nullptr if there is none.
const Node* FindInsaneSub() const {
return TreeEval<const Node*>([](const Node& node, Span<const Node*> subs) -> const Node* {
@@ -1259,6 +1557,7 @@ public:
case Fragment::PK_K:
case Fragment::PK_H:
case Fragment::MULTI:
+ case Fragment::MULTI_A:
case Fragment::AFTER:
case Fragment::OLDER:
case Fragment::HASH256:
@@ -1286,7 +1585,10 @@ public:
}
//! Check whether this node is valid at all.
- bool IsValid() const { return !(GetType() == ""_mst) && ScriptSize() <= MAX_STANDARD_P2WSH_SCRIPT_SIZE; }
+ bool IsValid() const {
+ if (GetType() == ""_mst) return false;
+ return ScriptSize() <= internal::MaxScriptSize(m_script_ctx);
+ }
//! Check whether this node is valid as a script on its own.
bool IsValidTopLevel() const { return IsValid() && GetType() << "B"_mst; }
@@ -1328,20 +1630,32 @@ public:
bool operator==(const Node<Key>& arg) const { return Compare(*this, arg) == 0; }
// Constructors with various argument combinations, which bypass the duplicate key check.
- Node(internal::NoDupCheck, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) : fragment(nt), k(val), data(std::move(arg)), subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
- Node(internal::NoDupCheck, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) : fragment(nt), k(val), data(std::move(arg)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
- Node(internal::NoDupCheck, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0) : fragment(nt), k(val), keys(std::move(key)), subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
- Node(internal::NoDupCheck, Fragment nt, std::vector<Key> key, uint32_t val = 0) : fragment(nt), k(val), keys(std::move(key)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
- Node(internal::NoDupCheck, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) : fragment(nt), k(val), subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
- Node(internal::NoDupCheck, Fragment nt, uint32_t val = 0) : fragment(nt), k(val), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0)
+ : fragment(nt), k(val), data(std::move(arg)), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0)
+ : fragment(nt), k(val), data(std::move(arg)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0)
+ : fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0)
+ : fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0)
+ : fragment(nt), k(val), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, uint32_t val = 0)
+ : fragment(nt), k(val), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
// Constructors with various argument combinations, which do perform the duplicate key check.
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) : Node(internal::NoDupCheck{}, nt, std::move(sub), std::move(arg), val) { DuplicateKeyCheck(ctx); }
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) : Node(internal::NoDupCheck{}, nt, std::move(arg), val) { DuplicateKeyCheck(ctx);}
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0) : Node(internal::NoDupCheck{}, nt, std::move(sub), std::move(key), val) { DuplicateKeyCheck(ctx); }
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0) : Node(internal::NoDupCheck{}, nt, std::move(key), val) { DuplicateKeyCheck(ctx); }
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) : Node(internal::NoDupCheck{}, nt, std::move(sub), val) { DuplicateKeyCheck(ctx); }
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, uint32_t val = 0) : Node(internal::NoDupCheck{}, nt, val) { DuplicateKeyCheck(ctx); }
+ template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0)
+ : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(arg), val) { DuplicateKeyCheck(ctx); }
+ template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0)
+ : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(arg), val) { DuplicateKeyCheck(ctx);}
+ template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0)
+ : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(key), val) { DuplicateKeyCheck(ctx); }
+ template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0)
+ : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(key), val) { DuplicateKeyCheck(ctx); }
+ template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0)
+ : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), val) { DuplicateKeyCheck(ctx); }
+ template <typename Ctx> Node(const Ctx& ctx, Fragment nt, uint32_t val = 0)
+ : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, val) { DuplicateKeyCheck(ctx); }
};
namespace internal {
@@ -1429,14 +1743,14 @@ std::optional<std::pair<std::vector<unsigned char>, int>> ParseHexStrEnd(Span<co
/** BuildBack pops the last two elements off `constructed` and wraps them in the specified Fragment */
template<typename Key>
-void BuildBack(Fragment nt, std::vector<NodeRef<Key>>& constructed, const bool reverse = false)
+void BuildBack(const MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>>& constructed, const bool reverse = false)
{
NodeRef<Key> child = std::move(constructed.back());
constructed.pop_back();
if (reverse) {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, nt, Vector(std::move(child), std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, script_ctx, nt, Vector(std::move(child), std::move(constructed.back())));
} else {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, nt, Vector(std::move(constructed.back()), std::move(child)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, script_ctx, nt, Vector(std::move(constructed.back()), std::move(child)));
}
}
@@ -1461,6 +1775,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
// (instead transforming another opcode into its VERIFY form). However, the v: wrapper has
// to be interleaved with other fragments to be valid, so this is not a concern.
size_t script_size{1};
+ size_t max_size{internal::MaxScriptSize(ctx.MsContext())};
// The two integers are used to hold state for thresh()
std::vector<std::tuple<ParseContext, int64_t, int64_t>> to_parse;
@@ -1468,8 +1783,43 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
+ // Parses a multi() or multi_a() from its string representation. Returns false on parsing error.
+ const auto parse_multi_exp = [&](Span<const char>& in, const bool is_multi_a) -> bool {
+ const auto max_keys{is_multi_a ? MAX_PUBKEYS_PER_MULTI_A : MAX_PUBKEYS_PER_MULTISIG};
+ const auto required_ctx{is_multi_a ? MiniscriptContext::TAPSCRIPT : MiniscriptContext::P2WSH};
+ if (ctx.MsContext() != required_ctx) return false;
+ // Get threshold
+ int next_comma = FindNextChar(in, ',');
+ if (next_comma < 1) return false;
+ int64_t k;
+ if (!ParseInt64(std::string(in.begin(), in.begin() + next_comma), &k)) return false;
+ in = in.subspan(next_comma + 1);
+ // Get keys. It is compatible for both compressed and x-only keys.
+ std::vector<Key> keys;
+ while (next_comma != -1) {
+ next_comma = FindNextChar(in, ',');
+ int key_length = (next_comma == -1) ? FindNextChar(in, ')') : next_comma;
+ if (key_length < 1) return false;
+ auto key = ctx.FromString(in.begin(), in.begin() + key_length);
+ if (!key) return false;
+ keys.push_back(std::move(*key));
+ in = in.subspan(key_length + 1);
+ }
+ if (keys.size() < 1 || keys.size() > max_keys) return false;
+ if (k < 1 || k > (int64_t)keys.size()) return false;
+ if (is_multi_a) {
+ // (push + xonly-key + CHECKSIG[ADD]) * n + k + OP_NUMEQUAL(VERIFY), minus one.
+ script_size += (1 + 32 + 1) * keys.size() + BuildScript(k).size();
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI_A, std::move(keys), k));
+ } else {
+ script_size += 2 + (keys.size() > 16) + (k > 16) + 34 * keys.size();
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI, std::move(keys), k));
+ }
+ return true;
+ };
+
while (!to_parse.empty()) {
- if (script_size > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
+ if (script_size > max_size) return {};
// Get the current context we are decoding within
auto [cur_context, n, k] = to_parse.back();
@@ -1488,7 +1838,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
// If there is no colon, this loop won't execute
bool last_was_v{false};
for (size_t j = 0; colon_index && j < *colon_index; ++j) {
- if (script_size > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
+ if (script_size > max_size) return {};
if (in[j] == 'a') {
script_size += 2;
to_parse.emplace_back(ParseContext::ALT, -1, -1);
@@ -1521,7 +1871,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
} else if (in[j] == 'l') {
// The l: wrapper is equivalent to or_i(0,X)
script_size += 4;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0));
to_parse.emplace_back(ParseContext::OR_I, -1, -1);
} else {
return {};
@@ -1534,63 +1884,63 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
}
case ParseContext::EXPR: {
if (Const("0", in)) {
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0));
} else if (Const("1", in)) {
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_1));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1));
} else if (Const("pk(", in)) {
auto res = ParseKeyEnd<Key, Ctx>(in, ctx);
if (!res) return {};
auto& [key, key_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_K, Vector(std::move(key))))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(key))))));
in = in.subspan(key_size + 1);
- script_size += 34;
+ script_size += IsTapscript(ctx.MsContext()) ? 33 : 34;
} else if (Const("pkh(", in)) {
auto res = ParseKeyEnd<Key>(in, ctx);
if (!res) return {};
auto& [key, key_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_H, Vector(std::move(key))))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(key))))));
in = in.subspan(key_size + 1);
script_size += 24;
} else if (Const("pk_k(", in)) {
auto res = ParseKeyEnd<Key>(in, ctx);
if (!res) return {};
auto& [key, key_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_K, Vector(std::move(key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(key))));
in = in.subspan(key_size + 1);
- script_size += 33;
+ script_size += IsTapscript(ctx.MsContext()) ? 32 : 33;
} else if (Const("pk_h(", in)) {
auto res = ParseKeyEnd<Key>(in, ctx);
if (!res) return {};
auto& [key, key_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_H, Vector(std::move(key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(key))));
in = in.subspan(key_size + 1);
script_size += 23;
} else if (Const("sha256(", in)) {
auto res = ParseHexStrEnd(in, 32, ctx);
if (!res) return {};
auto& [hash, hash_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::SHA256, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::SHA256, std::move(hash)));
in = in.subspan(hash_size + 1);
script_size += 38;
} else if (Const("ripemd160(", in)) {
auto res = ParseHexStrEnd(in, 20, ctx);
if (!res) return {};
auto& [hash, hash_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::RIPEMD160, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, std::move(hash)));
in = in.subspan(hash_size + 1);
script_size += 26;
} else if (Const("hash256(", in)) {
auto res = ParseHexStrEnd(in, 32, ctx);
if (!res) return {};
auto& [hash, hash_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::HASH256, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, std::move(hash)));
in = in.subspan(hash_size + 1);
script_size += 38;
} else if (Const("hash160(", in)) {
auto res = ParseHexStrEnd(in, 20, ctx);
if (!res) return {};
auto& [hash, hash_size] = *res;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::HASH160, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, std::move(hash)));
in = in.subspan(hash_size + 1);
script_size += 26;
} else if (Const("after(", in)) {
@@ -1599,7 +1949,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
int64_t num;
if (!ParseInt64(std::string(in.begin(), in.begin() + arg_size), &num)) return {};
if (num < 1 || num >= 0x80000000L) return {};
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::AFTER, num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, num));
in = in.subspan(arg_size + 1);
script_size += 1 + (num > 16) + (num > 0x7f) + (num > 0x7fff) + (num > 0x7fffff);
} else if (Const("older(", in)) {
@@ -1608,30 +1958,13 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
int64_t num;
if (!ParseInt64(std::string(in.begin(), in.begin() + arg_size), &num)) return {};
if (num < 1 || num >= 0x80000000L) return {};
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::OLDER, num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, num));
in = in.subspan(arg_size + 1);
script_size += 1 + (num > 16) + (num > 0x7f) + (num > 0x7fff) + (num > 0x7fffff);
} else if (Const("multi(", in)) {
- // Get threshold
- int next_comma = FindNextChar(in, ',');
- if (next_comma < 1) return {};
- if (!ParseInt64(std::string(in.begin(), in.begin() + next_comma), &k)) return {};
- in = in.subspan(next_comma + 1);
- // Get keys
- std::vector<Key> keys;
- while (next_comma != -1) {
- next_comma = FindNextChar(in, ',');
- int key_length = (next_comma == -1) ? FindNextChar(in, ')') : next_comma;
- if (key_length < 1) return {};
- auto key = ctx.FromString(in.begin(), in.begin() + key_length);
- if (!key) return {};
- keys.push_back(std::move(*key));
- in = in.subspan(key_length + 1);
- }
- if (keys.size() < 1 || keys.size() > 20) return {};
- if (k < 1 || k > (int64_t)keys.size()) return {};
- script_size += 2 + (keys.size() > 16) + (k > 16) + 34 * keys.size();
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::MULTI, std::move(keys), k));
+ if (!parse_multi_exp(in, /* is_multi_a = */false)) return {};
+ } else if (Const("multi_a(", in)) {
+ if (!parse_multi_exp(in, /* is_multi_a = */true)) return {};
} else if (Const("thresh(", in)) {
int next_comma = FindNextChar(in, ',');
if (next_comma < 1) return {};
@@ -1684,70 +2017,70 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
break;
}
case ParseContext::ALT: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_A, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_A, Vector(std::move(constructed.back())));
break;
}
case ParseContext::SWAP: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_S, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_S, Vector(std::move(constructed.back())));
break;
}
case ParseContext::CHECK: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(std::move(constructed.back())));
break;
}
case ParseContext::DUP_IF: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_D, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_D, Vector(std::move(constructed.back())));
break;
}
case ParseContext::NON_ZERO: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_J, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_J, Vector(std::move(constructed.back())));
break;
}
case ParseContext::ZERO_NOTEQUAL: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_N, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_N, Vector(std::move(constructed.back())));
break;
}
case ParseContext::VERIFY: {
script_size += (constructed.back()->GetType() << "x"_mst);
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_V, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_V, Vector(std::move(constructed.back())));
break;
}
case ParseContext::WRAP_U: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::OR_I, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OR_I, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0)));
break;
}
case ParseContext::WRAP_T: {
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::AND_V, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_1)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AND_V, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1)));
break;
}
case ParseContext::AND_B: {
- BuildBack(Fragment::AND_B, constructed);
+ BuildBack(ctx.MsContext(), Fragment::AND_B, constructed);
break;
}
case ParseContext::AND_N: {
auto mid = std::move(constructed.back());
constructed.pop_back();
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), MakeNodeRef<Key>(ctx, Fragment::JUST_0)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0)));
break;
}
case ParseContext::AND_V: {
- BuildBack(Fragment::AND_V, constructed);
+ BuildBack(ctx.MsContext(), Fragment::AND_V, constructed);
break;
}
case ParseContext::OR_B: {
- BuildBack(Fragment::OR_B, constructed);
+ BuildBack(ctx.MsContext(), Fragment::OR_B, constructed);
break;
}
case ParseContext::OR_C: {
- BuildBack(Fragment::OR_C, constructed);
+ BuildBack(ctx.MsContext(), Fragment::OR_C, constructed);
break;
}
case ParseContext::OR_D: {
- BuildBack(Fragment::OR_D, constructed);
+ BuildBack(ctx.MsContext(), Fragment::OR_D, constructed);
break;
}
case ParseContext::OR_I: {
- BuildBack(Fragment::OR_I, constructed);
+ BuildBack(ctx.MsContext(), Fragment::OR_I, constructed);
break;
}
case ParseContext::ANDOR: {
@@ -1755,7 +2088,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
constructed.pop_back();
auto mid = std::move(constructed.back());
constructed.pop_back();
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), std::move(right)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), std::move(right)));
break;
}
case ParseContext::THRESH: {
@@ -1775,7 +2108,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
constructed.pop_back();
}
std::reverse(subs.begin(), subs.end());
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::THRESH, std::move(subs), k));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::THRESH, std::move(subs), k));
} else {
return {};
}
@@ -1808,8 +2141,8 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
* Construct a vector with one element per opcode in the script, in reverse order.
* Each element is a pair consisting of the opcode, as well as the data pushed by
* the opcode (including OP_n), if any. OP_CHECKSIGVERIFY, OP_CHECKMULTISIGVERIFY,
- * and OP_EQUALVERIFY are decomposed into OP_CHECKSIG, OP_CHECKMULTISIG, OP_EQUAL
- * respectively, plus OP_VERIFY.
+ * OP_NUMEQUALVERIFY and OP_EQUALVERIFY are decomposed into OP_CHECKSIG, OP_CHECKMULTISIG,
+ * OP_EQUAL and OP_NUMEQUAL respectively, plus OP_VERIFY.
*/
std::optional<std::vector<Opcode>> DecomposeScript(const CScript& script);
@@ -1911,27 +2244,27 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
// Constants
if (in[0].first == OP_1) {
++in;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_1));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1));
break;
}
if (in[0].first == OP_0) {
++in;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0));
break;
}
// Public keys
- if (in[0].second.size() == 33) {
+ if (in[0].second.size() == 33 || in[0].second.size() == 32) {
auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end());
if (!key) return {};
++in;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_K, Vector(std::move(*key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(*key))));
break;
}
if (last - in >= 5 && in[0].first == OP_VERIFY && in[1].first == OP_EQUAL && in[3].first == OP_HASH160 && in[4].first == OP_DUP && in[2].second.size() == 20) {
auto key = ctx.FromPKHBytes(in[2].second.begin(), in[2].second.end());
if (!key) return {};
in += 5;
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_H, Vector(std::move(*key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(*key))));
break;
}
// Time locks
@@ -1939,37 +2272,38 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
if (last - in >= 2 && in[0].first == OP_CHECKSEQUENCEVERIFY && (num = ParseScriptNumber(in[1]))) {
in += 2;
if (*num < 1 || *num > 0x7FFFFFFFL) return {};
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::OLDER, *num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num));
break;
}
if (last - in >= 2 && in[0].first == OP_CHECKLOCKTIMEVERIFY && (num = ParseScriptNumber(in[1]))) {
in += 2;
if (num < 1 || num > 0x7FFFFFFFL) return {};
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::AFTER, *num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, *num));
break;
}
// Hashes
if (last - in >= 7 && in[0].first == OP_EQUAL && in[3].first == OP_VERIFY && in[4].first == OP_EQUAL && (num = ParseScriptNumber(in[5])) && num == 32 && in[6].first == OP_SIZE) {
if (in[2].first == OP_SHA256 && in[1].second.size() == 32) {
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::SHA256, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::SHA256, in[1].second));
in += 7;
break;
} else if (in[2].first == OP_RIPEMD160 && in[1].second.size() == 20) {
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::RIPEMD160, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, in[1].second));
in += 7;
break;
} else if (in[2].first == OP_HASH256 && in[1].second.size() == 32) {
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::HASH256, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, in[1].second));
in += 7;
break;
} else if (in[2].first == OP_HASH160 && in[1].second.size() == 20) {
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::HASH160, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, in[1].second));
in += 7;
break;
}
}
// Multi
if (last - in >= 3 && in[0].first == OP_CHECKMULTISIG) {
+ if (IsTapscript(ctx.MsContext())) return {};
std::vector<Key> keys;
const auto n = ParseScriptNumber(in[1]);
if (!n || last - in < 3 + *n) return {};
@@ -1984,7 +2318,37 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
if (!k || *k < 1 || *k > *n) return {};
in += 3 + *n;
std::reverse(keys.begin(), keys.end());
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::MULTI, std::move(keys), *k));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI, std::move(keys), *k));
+ break;
+ }
+ // Tapscript's equivalent of multi
+ if (last - in >= 4 && in[0].first == OP_NUMEQUAL) {
+ if (!IsTapscript(ctx.MsContext())) return {};
+ // The necessary threshold of signatures.
+ const auto k = ParseScriptNumber(in[1]);
+ if (!k) return {};
+ if (*k < 1 || *k > MAX_PUBKEYS_PER_MULTI_A) return {};
+ if (last - in < 2 + *k * 2) return {};
+ std::vector<Key> keys;
+ keys.reserve(*k);
+ // Walk through the expected (pubkey, CHECKSIG[ADD]) pairs.
+ for (int pos = 2;; pos += 2) {
+ if (last - in < pos + 2) return {};
+ // Make sure it's indeed an x-only pubkey and a CHECKSIG[ADD], then parse the key.
+ if (in[pos].first != OP_CHECKSIGADD && in[pos].first != OP_CHECKSIG) return {};
+ if (in[pos + 1].second.size() != 32) return {};
+ auto key = ctx.FromPKBytes(in[pos + 1].second.begin(), in[pos + 1].second.end());
+ if (!key) return {};
+ keys.push_back(std::move(*key));
+ // Make sure early we don't parse an arbitrary large expression.
+ if (keys.size() > MAX_PUBKEYS_PER_MULTI_A) return {};
+ // OP_CHECKSIG means it was the last one to parse.
+ if (in[pos].first == OP_CHECKSIG) break;
+ }
+ if (keys.size() < (size_t)*k) return {};
+ in += 2 + keys.size() * 2;
+ std::reverse(keys.begin(), keys.end());
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI_A, std::move(keys), *k));
break;
}
/** In the following wrappers, we only need to push SINGLE_BKV_EXPR rather
@@ -2079,63 +2443,63 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
case DecodeContext::SWAP: {
if (in >= last || in[0].first != OP_SWAP || constructed.empty()) return {};
++in;
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_S, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_S, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::ALT: {
if (in >= last || in[0].first != OP_TOALTSTACK || constructed.empty()) return {};
++in;
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_A, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_A, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::CHECK: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_C, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::DUP_IF: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_D, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_D, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::VERIFY: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_V, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_V, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::NON_ZERO: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_J, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_J, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::ZERO_NOTEQUAL: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_N, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::WRAP_N, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::AND_V: {
if (constructed.size() < 2) return {};
- BuildBack(Fragment::AND_V, constructed, /*reverse=*/true);
+ BuildBack(ctx.MsContext(), Fragment::AND_V, constructed, /*reverse=*/true);
break;
}
case DecodeContext::AND_B: {
if (constructed.size() < 2) return {};
- BuildBack(Fragment::AND_B, constructed, /*reverse=*/true);
+ BuildBack(ctx.MsContext(), Fragment::AND_B, constructed, /*reverse=*/true);
break;
}
case DecodeContext::OR_B: {
if (constructed.size() < 2) return {};
- BuildBack(Fragment::OR_B, constructed, /*reverse=*/true);
+ BuildBack(ctx.MsContext(), Fragment::OR_B, constructed, /*reverse=*/true);
break;
}
case DecodeContext::OR_C: {
if (constructed.size() < 2) return {};
- BuildBack(Fragment::OR_C, constructed, /*reverse=*/true);
+ BuildBack(ctx.MsContext(), Fragment::OR_C, constructed, /*reverse=*/true);
break;
}
case DecodeContext::OR_D: {
if (constructed.size() < 2) return {};
- BuildBack(Fragment::OR_D, constructed, /*reverse=*/true);
+ BuildBack(ctx.MsContext(), Fragment::OR_D, constructed, /*reverse=*/true);
break;
}
case DecodeContext::ANDOR: {
@@ -2145,7 +2509,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
NodeRef<Key> right = std::move(constructed.back());
constructed.pop_back();
NodeRef<Key> mid = std::move(constructed.back());
- constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::ANDOR, Vector(std::move(left), std::move(mid), std::move(right)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::ANDOR, Vector(std::move(left), std::move(mid), std::move(right)));
break;
}
case DecodeContext::THRESH_W: {
@@ -2169,7 +2533,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
constructed.pop_back();
subs.push_back(std::move(sub));
}
- constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::THRESH, std::move(subs), k));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::THRESH, std::move(subs), k));
break;
}
case DecodeContext::ENDIF: {
@@ -2219,7 +2583,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
if (in >= last) return {};
if (in[0].first == OP_IF) {
++in;
- BuildBack(Fragment::OR_I, constructed, /*reverse=*/true);
+ BuildBack(ctx.MsContext(), Fragment::OR_I, constructed, /*reverse=*/true);
} else if (in[0].first == OP_NOTIF) {
++in;
to_parse.emplace_back(DecodeContext::ANDOR, -1, -1);
@@ -2252,7 +2616,7 @@ template<typename Ctx>
inline NodeRef<typename Ctx::Key> FromScript(const CScript& script, const Ctx& ctx) {
using namespace internal;
// A too large Script is necessarily invalid, don't bother parsing it.
- if (script.size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
+ if (script.size() > MaxScriptSize(ctx.MsContext())) return {};
auto decomposed = DecomposeScript(script);
if (!decomposed) return {};
auto it = decomposed->begin();
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 92b7ad50b5..251a8420f7 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -114,12 +114,17 @@ static bool GetPubKey(const SigningProvider& provider, const SignatureData& sigd
pubkey = it->second.first;
return true;
}
- // Look for pubkey in pubkey list
+ // Look for pubkey in pubkey lists
const auto& pk_it = sigdata.misc_pubkeys.find(address);
if (pk_it != sigdata.misc_pubkeys.end()) {
pubkey = pk_it->second.first;
return true;
}
+ const auto& tap_pk_it = sigdata.tap_pubkeys.find(address);
+ if (tap_pk_it != sigdata.tap_pubkeys.end()) {
+ pubkey = tap_pk_it->second.GetEvenCorrespondingCPubKey();
+ return true;
+ }
// Query the underlying provider
return provider.GetPubKey(address, pubkey);
}
@@ -171,49 +176,158 @@ static bool CreateTaprootScriptSig(const BaseSignatureCreator& creator, Signatur
return false;
}
-static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatureCreator& creator, SignatureData& sigdata, int leaf_version, Span<const unsigned char> script_bytes, std::vector<valtype>& result)
+template<typename M, typename K, typename V>
+miniscript::Availability MsLookupHelper(const M& map, const K& key, V& value)
{
- // Only BIP342 tapscript signing is supported for now.
- if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false;
- SigVersion sigversion = SigVersion::TAPSCRIPT;
+ auto it = map.find(key);
+ if (it != map.end()) {
+ value = it->second;
+ return miniscript::Availability::YES;
+ }
+ return miniscript::Availability::NO;
+}
- uint256 leaf_hash = ComputeTapleafHash(leaf_version, script_bytes);
- CScript script = CScript(script_bytes.begin(), script_bytes.end());
+/**
+ * Context for solving a Miniscript.
+ * If enough material (access to keys, hash preimages, ..) is given, produces a valid satisfaction.
+ */
+template<typename Pk>
+struct Satisfier {
+ using Key = Pk;
- // <xonly pubkey> OP_CHECKSIG
- if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {
- XOnlyPubKey pubkey{Span{script}.subspan(1, 32)};
- std::vector<unsigned char> sig;
- if (CreateTaprootScriptSig(creator, sigdata, provider, sig, pubkey, leaf_hash, sigversion)) {
- result = Vector(std::move(sig));
- return true;
- }
- return false;
+ const SigningProvider& m_provider;
+ SignatureData& m_sig_data;
+ const BaseSignatureCreator& m_creator;
+ const CScript& m_witness_script;
+ //! The context of the script we are satisfying (either P2WSH or Tapscript).
+ const miniscript::MiniscriptContext m_script_ctx;
+
+ explicit Satisfier(const SigningProvider& provider LIFETIMEBOUND, SignatureData& sig_data LIFETIMEBOUND,
+ const BaseSignatureCreator& creator LIFETIMEBOUND,
+ const CScript& witscript LIFETIMEBOUND,
+ miniscript::MiniscriptContext script_ctx) : m_provider(provider),
+ m_sig_data(sig_data),
+ m_creator(creator),
+ m_witness_script(witscript),
+ m_script_ctx(script_ctx) {}
+
+ static bool KeyCompare(const Key& a, const Key& b) {
+ return a < b;
}
- // multi_a scripts (<key> OP_CHECKSIG <key> OP_CHECKSIGADD <key> OP_CHECKSIGADD <k> OP_NUMEQUAL)
- if (auto match = MatchMultiA(script)) {
- std::vector<std::vector<unsigned char>> sigs;
- int good_sigs = 0;
- for (size_t i = 0; i < match->second.size(); ++i) {
- XOnlyPubKey pubkey{*(match->second.rbegin() + i)};
- std::vector<unsigned char> sig;
- bool good_sig = CreateTaprootScriptSig(creator, sigdata, provider, sig, pubkey, leaf_hash, sigversion);
- if (good_sig && good_sigs < match->first) {
- ++good_sigs;
- sigs.push_back(std::move(sig));
- } else {
- sigs.emplace_back();
- }
+ //! Get a CPubKey from a key hash. Note the key hash may be of an xonly pubkey.
+ template<typename I>
+ std::optional<CPubKey> CPubFromPKHBytes(I first, I last) const {
+ assert(last - first == 20);
+ CPubKey pubkey;
+ CKeyID key_id;
+ std::copy(first, last, key_id.begin());
+ if (GetPubKey(m_provider, m_sig_data, key_id, pubkey)) return pubkey;
+ m_sig_data.missing_pubkeys.push_back(key_id);
+ return {};
+ }
+
+ //! Conversion to raw public key.
+ std::vector<unsigned char> ToPKBytes(const Key& key) const { return {key.begin(), key.end()}; }
+
+ //! Time lock satisfactions.
+ bool CheckAfter(uint32_t value) const { return m_creator.Checker().CheckLockTime(CScriptNum(value)); }
+ bool CheckOlder(uint32_t value) const { return m_creator.Checker().CheckSequence(CScriptNum(value)); }
+
+ //! Hash preimage satisfactions.
+ miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
+ return MsLookupHelper(m_sig_data.sha256_preimages, hash, preimage);
+ }
+ miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
+ return MsLookupHelper(m_sig_data.ripemd160_preimages, hash, preimage);
+ }
+ miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
+ return MsLookupHelper(m_sig_data.hash256_preimages, hash, preimage);
+ }
+ miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
+ return MsLookupHelper(m_sig_data.hash160_preimages, hash, preimage);
+ }
+
+ miniscript::MiniscriptContext MsContext() const {
+ return m_script_ctx;
+ }
+};
+
+/** Miniscript satisfier specific to P2WSH context. */
+struct WshSatisfier: Satisfier<CPubKey> {
+ explicit WshSatisfier(const SigningProvider& provider LIFETIMEBOUND, SignatureData& sig_data LIFETIMEBOUND,
+ const BaseSignatureCreator& creator LIFETIMEBOUND, const CScript& witscript LIFETIMEBOUND)
+ : Satisfier(provider, sig_data, creator, witscript, miniscript::MiniscriptContext::P2WSH) {}
+
+ //! Conversion from a raw compressed public key.
+ template <typename I>
+ std::optional<CPubKey> FromPKBytes(I first, I last) const {
+ CPubKey pubkey{first, last};
+ if (pubkey.IsValid()) return pubkey;
+ return {};
+ }
+
+ //! Conversion from a raw compressed public key hash.
+ template<typename I>
+ std::optional<CPubKey> FromPKHBytes(I first, I last) const {
+ return Satisfier::CPubFromPKHBytes(first, last);
+ }
+
+ //! Satisfy an ECDSA signature check.
+ miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
+ if (CreateSig(m_creator, m_sig_data, m_provider, sig, key, m_witness_script, SigVersion::WITNESS_V0)) {
+ return miniscript::Availability::YES;
}
- if (good_sigs == match->first) {
- result = std::move(sigs);
- return true;
+ return miniscript::Availability::NO;
+ }
+};
+
+/** Miniscript satisfier specific to Tapscript context. */
+struct TapSatisfier: Satisfier<XOnlyPubKey> {
+ const uint256& m_leaf_hash;
+
+ explicit TapSatisfier(const SigningProvider& provider LIFETIMEBOUND, SignatureData& sig_data LIFETIMEBOUND,
+ const BaseSignatureCreator& creator LIFETIMEBOUND, const CScript& script LIFETIMEBOUND,
+ const uint256& leaf_hash LIFETIMEBOUND)
+ : Satisfier(provider, sig_data, creator, script, miniscript::MiniscriptContext::TAPSCRIPT),
+ m_leaf_hash(leaf_hash) {}
+
+ //! Conversion from a raw xonly public key.
+ template <typename I>
+ std::optional<XOnlyPubKey> FromPKBytes(I first, I last) const {
+ CHECK_NONFATAL(last - first == 32);
+ XOnlyPubKey pubkey;
+ std::copy(first, last, pubkey.begin());
+ return pubkey;
+ }
+
+ //! Conversion from a raw xonly public key hash.
+ template<typename I>
+ std::optional<XOnlyPubKey> FromPKHBytes(I first, I last) const {
+ if (auto pubkey = Satisfier::CPubFromPKHBytes(first, last)) return XOnlyPubKey{*pubkey};
+ return {};
+ }
+
+ //! Satisfy a BIP340 signature check.
+ miniscript::Availability Sign(const XOnlyPubKey& key, std::vector<unsigned char>& sig) const {
+ if (CreateTaprootScriptSig(m_creator, m_sig_data, m_provider, sig, key, m_leaf_hash, SigVersion::TAPSCRIPT)) {
+ return miniscript::Availability::YES;
}
- return false;
+ return miniscript::Availability::NO;
}
+};
- return false;
+static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatureCreator& creator, SignatureData& sigdata, int leaf_version, Span<const unsigned char> script_bytes, std::vector<valtype>& result)
+{
+ // Only BIP342 tapscript signing is supported for now.
+ if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false;
+
+ uint256 leaf_hash = ComputeTapleafHash(leaf_version, script_bytes);
+ CScript script = CScript(script_bytes.begin(), script_bytes.end());
+
+ TapSatisfier ms_satisfier{provider, sigdata, creator, script, leaf_hash};
+ const auto ms = miniscript::FromScript(script, ms_satisfier);
+ return ms && ms->Satisfy(ms_satisfier, result) == miniscript::Availability::YES;
}
static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCreator& creator, const WitnessV1Taproot& output, SignatureData& sigdata, std::vector<valtype>& result)
@@ -319,7 +433,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TxoutType::SCRIPTHASH: {
uint160 h160{vSolutions[0]};
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
- ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
+ ret.emplace_back(scriptRet.begin(), scriptRet.end());
return true;
}
// Could not find redeemScript, add to missing
@@ -328,7 +442,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
}
case TxoutType::MULTISIG: {
size_t required = vSolutions.front()[0];
- ret.push_back(valtype()); // workaround CHECKMULTISIG bug
+ ret.emplace_back(); // workaround CHECKMULTISIG bug
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
CPubKey pubkey = CPubKey(vSolutions[i]);
// We need to always call CreateSig in order to fill sigdata with all
@@ -342,7 +456,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
}
bool ok = ret.size() == required + 1;
for (size_t i = 0; i + ret.size() < required + 1; ++i) {
- ret.push_back(valtype());
+ ret.emplace_back();
}
return ok;
}
@@ -352,7 +466,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TxoutType::WITNESS_V0_SCRIPTHASH:
if (GetCScript(provider, sigdata, CScriptID{RIPEMD160(vSolutions[0])}, scriptRet)) {
- ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
+ ret.emplace_back(scriptRet.begin(), scriptRet.end());
return true;
}
// Could not find witnessScript, add to missing
@@ -382,92 +496,6 @@ static CScript PushAll(const std::vector<valtype>& values)
return result;
}
-template<typename M, typename K, typename V>
-miniscript::Availability MsLookupHelper(const M& map, const K& key, V& value)
-{
- auto it = map.find(key);
- if (it != map.end()) {
- value = it->second;
- return miniscript::Availability::YES;
- }
- return miniscript::Availability::NO;
-}
-
-/**
- * Context for solving a Miniscript.
- * If enough material (access to keys, hash preimages, ..) is given, produces a valid satisfaction.
- */
-struct Satisfier {
- typedef CPubKey Key;
-
- const SigningProvider& m_provider;
- SignatureData& m_sig_data;
- const BaseSignatureCreator& m_creator;
- const CScript& m_witness_script;
-
- explicit Satisfier(const SigningProvider& provider LIFETIMEBOUND, SignatureData& sig_data LIFETIMEBOUND,
- const BaseSignatureCreator& creator LIFETIMEBOUND,
- const CScript& witscript LIFETIMEBOUND) : m_provider(provider),
- m_sig_data(sig_data),
- m_creator(creator),
- m_witness_script(witscript) {}
-
- static bool KeyCompare(const Key& a, const Key& b) {
- return a < b;
- }
-
- //! Conversion from a raw public key.
- template <typename I>
- std::optional<Key> FromPKBytes(I first, I last) const
- {
- Key pubkey{first, last};
- if (pubkey.IsValid()) return pubkey;
- return {};
- }
-
- //! Conversion from a raw public key hash.
- template<typename I>
- std::optional<Key> FromPKHBytes(I first, I last) const {
- assert(last - first == 20);
- Key pubkey;
- CKeyID key_id;
- std::copy(first, last, key_id.begin());
- if (GetPubKey(m_provider, m_sig_data, key_id, pubkey)) return pubkey;
- m_sig_data.missing_pubkeys.push_back(key_id);
- return {};
- }
-
- //! Conversion to raw public key.
- std::vector<unsigned char> ToPKBytes(const CPubKey& key) const { return {key.begin(), key.end()}; }
-
- //! Satisfy a signature check.
- miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
- if (CreateSig(m_creator, m_sig_data, m_provider, sig, key, m_witness_script, SigVersion::WITNESS_V0)) {
- return miniscript::Availability::YES;
- }
- return miniscript::Availability::NO;
- }
-
- //! Time lock satisfactions.
- bool CheckAfter(uint32_t value) const { return m_creator.Checker().CheckLockTime(CScriptNum(value)); }
- bool CheckOlder(uint32_t value) const { return m_creator.Checker().CheckSequence(CScriptNum(value)); }
-
-
- //! Hash preimage satisfactions.
- miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
- return MsLookupHelper(m_sig_data.sha256_preimages, hash, preimage);
- }
- miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
- return MsLookupHelper(m_sig_data.ripemd160_preimages, hash, preimage);
- }
- miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
- return MsLookupHelper(m_sig_data.hash256_preimages, hash, preimage);
- }
- miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
- return MsLookupHelper(m_sig_data.hash160_preimages, hash, preimage);
- }
-};
-
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
{
if (sigdata.complete) return true;
@@ -512,11 +540,11 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
// isn't fully solved. For instance the CHECKMULTISIG satisfaction in SignStep() pushes partial signatures
// and the extractor relies on this behaviour to combine witnesses.
if (!solved && result.empty()) {
- Satisfier ms_satisfier{provider, sigdata, creator, witnessscript};
+ WshSatisfier ms_satisfier{provider, sigdata, creator, witnessscript};
const auto ms = miniscript::FromScript(witnessscript, ms_satisfier);
solved = ms && ms->Satisfy(ms_satisfier, result) == miniscript::Availability::YES;
}
- result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
+ result.emplace_back(witnessscript.begin(), witnessscript.end());
sigdata.scriptWitness.stack = result;
sigdata.witness = true;
@@ -533,7 +561,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
if (!sigdata.witness) sigdata.scriptWitness.stack.clear();
if (P2SH) {
- result.push_back(std::vector<unsigned char>(subscript.begin(), subscript.end()));
+ result.emplace_back(subscript.begin(), subscript.end());
}
sigdata.scriptSig = PushAll(result);
diff --git a/src/script/sign.h b/src/script/sign.h
index 4d7dade44e..ace2ba7856 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -79,6 +79,7 @@ struct SignatureData {
std::vector<unsigned char> taproot_key_path_sig; /// Schnorr signature for key path spending
std::map<std::pair<XOnlyPubKey, uint256>, std::vector<unsigned char>> taproot_script_sigs; ///< (Partial) schnorr signatures, indexed by XOnlyPubKey and leaf_hash.
std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> taproot_misc_pubkeys; ///< Miscellaneous Taproot pubkeys involved in this input along with their leaf script hashes and key origin data. Also includes the Taproot internal key (may have no leaf script hashes).
+ std::map<CKeyID, XOnlyPubKey> tap_pubkeys; ///< Misc Taproot pubkeys involved in this input, by hash. (Equivalent of misc_pubkeys but for Taproot.)
std::vector<CKeyID> missing_pubkeys; ///< KeyIDs of pubkeys which could not be found
std::vector<CKeyID> missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found
uint160 missing_redeem_script; ///< ScriptID of the missing redeemScript (if any)
diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp
index 168b3030cc..ff02ab5a12 100644
--- a/src/script/signingprovider.cpp
+++ b/src/script/signingprovider.cpp
@@ -368,6 +368,8 @@ TaprootBuilder& TaprootBuilder::Add(int depth, Span<const unsigned char> script,
/* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
NodeInfo node;
node.hash = ComputeTapleafHash(leaf_version, script);
+ // due to bug in clang-tidy-17:
+ // NOLINTNEXTLINE(modernize-use-emplace)
if (track) node.leaves.emplace_back(LeafInfo{std::vector<unsigned char>(script.begin(), script.end()), leaf_version, {}});
/* Insert into the branch. */
Insert(std::move(node), depth);
@@ -569,7 +571,7 @@ std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> TaprootBui
assert(leaf.merkle_branch.size() <= TAPROOT_CONTROL_MAX_NODE_COUNT);
uint8_t depth = (uint8_t)leaf.merkle_branch.size();
uint8_t leaf_ver = (uint8_t)leaf.leaf_version;
- tuples.push_back(std::make_tuple(depth, leaf_ver, leaf.script));
+ tuples.emplace_back(depth, leaf_ver, leaf.script);
}
}
return tuples;
diff --git a/src/serialize.h b/src/serialize.h
index e53ff9fa4c..8b15178ec0 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -316,7 +316,7 @@ template <typename Stream> inline void Unserialize(Stream& s, bool& a) { uint8_t
* size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
* size > UINT_MAX -- 9 bytes (255 + 8 bytes)
*/
-inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
+constexpr inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
{
if (nSize < 253) return sizeof(unsigned char);
else if (nSize <= std::numeric_limits<uint16_t>::max()) return sizeof(unsigned char) + sizeof(uint16_t);
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index b01ba81c5f..bfefc3ff97 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -98,8 +98,8 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
// Test: reset addrman and test AddrMan::Add multiple addresses works as expected
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
std::vector<CAddress> vAddr;
- vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
- vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
+ vAddr.emplace_back(ResolveService("250.1.1.3", 8333), NODE_NONE);
+ vAddr.emplace_back(ResolveService("250.1.1.4", 8333), NODE_NONE);
BOOST_CHECK(addrman->Add(vAddr, source));
BOOST_CHECK(addrman->Size() >= 1);
}
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index fe3d8995e9..cbbec94e00 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -29,7 +29,7 @@ struct TestVector {
explicit TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}
TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
- vDerive.push_back(TestDerivation());
+ vDerive.emplace_back();
TestDerivation &der = vDerive.back();
der.pub = pub;
der.prv = prv;
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index 3a30ef453e..f4f4e39f40 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -384,6 +384,54 @@ void Check(const std::string& prv, const std::string& pub, const std::string& no
}
}
+void CheckInferDescriptor(const std::string& script_hex, const std::string& expected_desc, const std::vector<std::string>& hex_scripts, const std::vector<std::pair<std::string, std::string>>& origin_pubkeys)
+{
+ std::vector<unsigned char> script_bytes{ParseHex(script_hex)};
+ const CScript& script{script_bytes.begin(), script_bytes.end()};
+
+ FlatSigningProvider provider;
+ for (const std::string& prov_script_hex : hex_scripts) {
+ std::vector<unsigned char> prov_script_bytes{ParseHex(prov_script_hex)};
+ const CScript& prov_script{prov_script_bytes.begin(), prov_script_bytes.end()};
+ provider.scripts.emplace(CScriptID(prov_script), prov_script);
+ }
+ for (const auto& [pubkey_hex, origin_str] : origin_pubkeys) {
+ CPubKey origin_pubkey{ParseHex(pubkey_hex)};
+ provider.pubkeys.emplace(origin_pubkey.GetID(), origin_pubkey);
+
+ if (!origin_str.empty()) {
+ using namespace spanparsing;
+ KeyOriginInfo info;
+ Span<const char> origin_sp{origin_str};
+ std::vector<Span<const char>> origin_split = Split(origin_sp, "/");
+ std::string fpr_str(origin_split[0].begin(), origin_split[0].end());
+ auto fpr_bytes = ParseHex(fpr_str);
+ std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
+ for (size_t i = 1; i < origin_split.size(); ++i) {
+ Span<const char> elem = origin_split[i];
+ bool hardened = false;
+ if (elem.size() > 0) {
+ const char last = elem[elem.size() - 1];
+ if (last == '\'' || last == 'h') {
+ elem = elem.first(elem.size() - 1);
+ hardened = true;
+ }
+ }
+ uint32_t p;
+ assert(ParseUInt32(std::string(elem.begin(), elem.end()), &p));
+ info.path.push_back(p | (((uint32_t)hardened) << 31));
+ }
+
+ provider.origins.emplace(origin_pubkey.GetID(), std::make_pair(origin_pubkey, info));
+ }
+ }
+
+ std::string checksum{GetDescriptorChecksum(expected_desc)};
+
+ std::unique_ptr<Descriptor> desc = InferDescriptor(script, provider);
+ BOOST_CHECK_EQUAL(desc->ToString(), expected_desc + "#" + checksum);
+}
+
}
BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
@@ -409,6 +457,11 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "pk(): Uncompressed keys are not allowed"); // No uncompressed keys in witness
CheckUnparsable("sh(wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "sh(wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "wpkh(): Uncompressed keys are not allowed"); // No uncompressed keys in witness
+ // Equivalent single-key hybrid is not allowed
+ CheckUnparsable("", "combo(07a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(): Hybrid public keys are not allowed");
+ CheckUnparsable("", "pk(0623542d61708e3fc48ba78fbe8fcc983ba94a520bc33f82b8e45e51dbc47af2726bcf181925eee1bdd868b109314f3ea92a6fc23d6b66057d3acfba04d6b08b58)", "pk(): Hybrid public keys are not allowed");
+ CheckUnparsable("", "pkh(07a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(): Hybrid public keys are not allowed");
+
// Some unconventional single-key constructions
Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}}, OutputType::LEGACY);
Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}}, OutputType::LEGACY);
@@ -533,11 +586,15 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Invalid checksum
CheckUnparsable("wsh(and_v(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))#abcdef12", "wsh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))#abcdef12", "Provided checksum 'abcdef12' does not match computed checksum 'tyzp6a7p'");
- // Only p2wsh context is valid
- CheckUnparsable("sh(and_v(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "sh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "Miniscript expressions can only be used in wsh");
+ // Only p2wsh or tr contexts are valid
+ CheckUnparsable("sh(and_v(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "sh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "Miniscript expressions can only be used in wsh or tr.");
CheckUnparsable("tr(and_v(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "tr(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "tr(): key 'and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10))' is not valid");
- CheckUnparsable("raw(and_v(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "sh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "Miniscript expressions can only be used in wsh");
+ CheckUnparsable("raw(and_v(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "sh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "Miniscript expressions can only be used in wsh or tr.");
CheckUnparsable("", "tr(034D2224bbbbbbbbbbcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb40,{{{{{{{{{{{{{{{{{{{{{{multi(1,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/967808'/9,xprvA1RpRA33e1JQ7ifknakTFNpgXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/968/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/58/2/5/8/5/2/8/5/8/3/4/5/58/55/2/5/58/58/2/5/5/5/8/5/2/8/5/85/2/8/2/5/8/5/2/5/58/58/2/5/58/58/588/2/58/2/8/5/8/5/4/5/585/2/5/58/58/2/5/5/58/588/2/58/2/5/8/5/2/8/2/5/8/5/5/58/588/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/58/58/2/0/8/5/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/58/58/588/2/58/2/5/8/5/8/24/5/58/52/5/8/5/2/8/24/5/58/588/246/8/5/2/8/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/58/2/5/8/5/2/8/5/8/5/4/5/58/55/58/2/5/8/55/2/5/8/58/555/58/2/5/8/4//2/5/58/5w/2/5/8/5/2/4/5/58/5558'/2/5/58/58/2/5/5/58/588/2/58/2/5/8/5/2/8/2/5/8/5/5/8/58/2/5/58/58/2/5/8/9/588/2/58/2/5/8/5/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/5/58/588/2/58/2/5/8/5/2/82/5/8/5/5/58/52/6/8/5/2/8/{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}{{{{{{{{{DDD2/5/8/5/2/5/58/58/2/5/58/58/588/2/58/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8588/246/8/5/2DLDDDDDDDbbD3DDDD/8/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/58/2/5/8/5/2/8/5/8/3/4/5/58/55/2/5/58/58/2/5/5/5/8/5/2/8/5/85/2/8/2/5/8D)/5/2/5/58/58/2/5/58/58/58/588/2/58/2/5/8/5/25/58/58/2/5/58/58/2/5/8/9/588/2/58/2/6780,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFW/8/5/2/5/58678008')", "'multi(1,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/967808'/9,xprvA1RpRA33e1JQ7ifknakTFNpgXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/968/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/58/2/5/8/5/2/8/5/8/3/4/5/58/55/2/5/58/58/2/5/5/5/8/5/2/8/5/85/2/8/2/5/8/5/2/5/58/58/2/5/58/58/588/2/58/2/8/5/8/5/4/5/585/2/5/58/58/2/5/5/58/588/2/58/2/5/8/5/2/8/2/5/8/5/5/58/588/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/58/58/2/0/8/5/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/58/58/588/2/58/2/5/8/5/8/24/5/58/52/5/8/5/2/8/24/5/58/588/246/8/5/2/8/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/58/2/5/8/5/2/8/5/8/5/4/5/58/55/58/2/5/8/55/2/5/8/58/555/58/2/5/8/4//2/5/58/5w/2/5/8/5/2/4/5/58/5558'/2/5/58/58/2/5/5/58/588/2/58/2/5/8/5/2/8/2/5/8/5/5/8/58/2/5/58/58/2/5/8/9/588/2/58/2/5/8/5/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8/5/2/5/58/58/2/5/5/58/588/2/58/2/5/8/5/2/82/5/8/5/5/58/52/6/8/5/2/8/{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}{{{{{{{{{DDD2/5/8/5/2/5/58/58/2/5/58/58/588/2/58/2/8/5/8/5/4/5/58/588/2/6/8/5/2/8/2/5/8588/246/8/5/2DLDDDDDDDbbD3DDDD/8/2/5/8/5/2/5/58/58/2/5/5/5/58/588/2/6/8/5/2/8/2/5/8/2/58/2/5/8/5/2/8/5/8/3/4/5/58/55/2/5/58/58/2/5/5/5/8/5/2/8/5/85/2/8/2/5/8D)/5/2/5/58/58/2/5/58/58/58/588/2/58/2/5/8/5/25/58/58/2/5/58/58/2/5/8/9/588/2/58/2/6780,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFW/8/5/2/5/58678008'' is not a valid descriptor function");
+ // No uncompressed keys allowed
+ CheckUnparsable("", "wsh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(049228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4))),after(10)))", "A function is needed within P2WSH");
+ // No hybrid keys allowed
+ CheckUnparsable("", "wsh(and_v(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(069228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4))),after(10)))", "A function is needed within P2WSH");
// Insane at top level
CheckUnparsable("wsh(and_b(vc:andor(pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "wsh(and_b(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "and_b(vc:andor(pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)) is invalid");
// Invalid sub
@@ -573,6 +630,31 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Same for hash256
Check("wsh(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)))", "wsh(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))", "wsh(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))", SIGNABLE_FAILS, {{"0020cf62bf97baf977aec69cbc290c372899f913337a9093e8f066ab59b8657a365c"}}, OutputType::BECH32, /*op_desc_id=*/uint256S("8412ba3ac20ba3a30f81442d10d32e0468fa52814960d04e959bf84a9b813b88"), {{}}, /*spender_nlocktime=*/0, /*spender_nsequence=*/CTxIn::SEQUENCE_FINAL, {});
Check("wsh(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)))", "wsh(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))", "wsh(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))", SIGNABLE, {{"0020cf62bf97baf977aec69cbc290c372899f913337a9093e8f066ab59b8657a365c"}}, OutputType::BECH32, /*op_desc_id=*/uint256S("8412ba3ac20ba3a30f81442d10d32e0468fa52814960d04e959bf84a9b813b88"), {{}}, /*spender_nlocktime=*/0, /*spender_nsequence=*/CTxIn::SEQUENCE_FINAL, {{ParseHex("ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588"), ParseHex("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")}});
+ // Can have a Miniscript expression under tr() if it's alone.
+ Check("tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,thresh(2,pk(L1NKM8dVA1h52mwDrmk1YreTWkAZZTu2vmKLpmLEbFRqGQYjHeEV),s:pk(Kz3iCBy3HNGP5CZWDsAMmnCMFNwqdDohudVN9fvkrN7tAkzKNtM7),adv:older(42)))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,thresh(2,pk(30a6069f344fb784a2b4c99540a91ee727c91e3a25ef6aae867d9c65b5f23529),s:pk(9918d400c1b8c3c478340a40117ced4054b6b58f48cdb3c89b836bdfee1f5766),adv:older(42)))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,thresh(2,pk(30a6069f344fb784a2b4c99540a91ee727c91e3a25ef6aae867d9c65b5f23529),s:pk(9918d400c1b8c3c478340a40117ced4054b6b58f48cdb3c89b836bdfee1f5766),adv:older(42)))", MISSING_PRIVKEYS | XONLY_KEYS | SIGNABLE, {{"512033982eebe204dc66508e4b19cfc31b5ffc6e1bfcbf6e5597dfc2521a52270795"}}, OutputType::BECH32M);
+ // Can have a pkh() expression alone as tr() script path (because pkh() is valid Miniscript).
+ Check("tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pkh(L1NKM8dVA1h52mwDrmk1YreTWkAZZTu2vmKLpmLEbFRqGQYjHeEV))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pkh(30a6069f344fb784a2b4c99540a91ee727c91e3a25ef6aae867d9c65b5f23529))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pkh(30a6069f344fb784a2b4c99540a91ee727c91e3a25ef6aae867d9c65b5f23529))", MISSING_PRIVKEYS | XONLY_KEYS | SIGNABLE, {{"51201e9875f690f5847404e4c5951e2f029887df0525691ee11a682afd37b608aad4"}}, OutputType::BECH32M);
+ // Can have a Miniscript expression under tr() if it's part of a tree.
+ Check("tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{{pkh(KykUPmR5967F4URzMUeCv9kNMU9CNRWycrPmx3ZvfkWoQLabbimL),pk(L3Enys1jFgTq4E24b8Uom1kAz6cNkz3Z82XZpBKCE2ztErq9fqvJ)},thresh(1,pk(L1NKM8dVA1h52mwDrmk1YreTWkAZZTu2vmKLpmLEbFRqGQYjHeEV),s:pk(Kz3iCBy3HNGP5CZWDsAMmnCMFNwqdDohudVN9fvkrN7tAkzKNtM7))})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{{pkh(1c9bc926084382e76da33b5a52d17b1fa153c072aae5fb5228ecc2ccf89d79d5),pk(0dd6b52b192ab195558d22dd8437a9ec4519ee5ded496c0d55bc9b1a8b0e8c2b)},thresh(1,pk(30a6069f344fb784a2b4c99540a91ee727c91e3a25ef6aae867d9c65b5f23529),s:pk(9918d400c1b8c3c478340a40117ced4054b6b58f48cdb3c89b836bdfee1f5766))})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{{pkh(1c9bc926084382e76da33b5a52d17b1fa153c072aae5fb5228ecc2ccf89d79d5),pk(0dd6b52b192ab195558d22dd8437a9ec4519ee5ded496c0d55bc9b1a8b0e8c2b)},thresh(1,pk(30a6069f344fb784a2b4c99540a91ee727c91e3a25ef6aae867d9c65b5f23529),s:pk(9918d400c1b8c3c478340a40117ced4054b6b58f48cdb3c89b836bdfee1f5766))})", MISSING_PRIVKEYS | XONLY_KEYS, {{"5120d8ea39b29de2b550b68bd2ada8b075c888c2b2df3290c7a35856482747848934"}}, OutputType::BECH32M);
+ // Can have two Miniscripts in a Taproot with mixed private and public keys, and mixed ranged extended keys and raw keys.
+ Check("tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(v:pk(xpub6AGbgdKcAGeUWaGNKH2o3sRvjtvJCGZ1NwrHqMJDwD4bN1QuwPQSsdeAYkPZGPt2FTAyu6nWGsC3fN2nsBELrLPcRNuwwr5k1X7yW5WV4aX/*),pk(02daf6e3477fc3906a1997820ed2940c8f5fa0942946d0368f981b001fdd85afcb)),and_v(v:pk(xprv9wCN7tTqN5ATsmBGEijuNeUgQjma9tv3GmdWLmbYiuArPsAMj6tD1uASiBfm47kdoi7bDBAVxUZNLM2MkeouPK5menDTyCNZtExQrKhVu7C/*),pk(03272c0c1ae2c07528283b91ca57b45d2cc84e7960e1f17f58815372285f35e99a))})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(v:pk(xpub6AGbgdKcAGeUWaGNKH2o3sRvjtvJCGZ1NwrHqMJDwD4bN1QuwPQSsdeAYkPZGPt2FTAyu6nWGsC3fN2nsBELrLPcRNuwwr5k1X7yW5WV4aX/*),pk(02daf6e3477fc3906a1997820ed2940c8f5fa0942946d0368f981b001fdd85afcb)),and_v(v:pk(xpub6ABiXPzjCSim6FFjLkGujnRQxmc4ZMdtdzZ79A1AHEhqGfVWGeCTZhUvZTSf1mNnGUtyNqgfE9eWaYdYReDKbPYqgqi9LLVZSmWnLQRx477/*),pk(03272c0c1ae2c07528283b91ca57b45d2cc84e7960e1f17f58815372285f35e99a))})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(v:pk(xpub6AGbgdKcAGeUWaGNKH2o3sRvjtvJCGZ1NwrHqMJDwD4bN1QuwPQSsdeAYkPZGPt2FTAyu6nWGsC3fN2nsBELrLPcRNuwwr5k1X7yW5WV4aX/*),pk(02daf6e3477fc3906a1997820ed2940c8f5fa0942946d0368f981b001fdd85afcb)),and_v(v:pk(xpub6ABiXPzjCSim6FFjLkGujnRQxmc4ZMdtdzZ79A1AHEhqGfVWGeCTZhUvZTSf1mNnGUtyNqgfE9eWaYdYReDKbPYqgqi9LLVZSmWnLQRx477/*),pk(03272c0c1ae2c07528283b91ca57b45d2cc84e7960e1f17f58815372285f35e99a))})", MISSING_PRIVKEYS | XONLY_KEYS | RANGE | MIXED_PUBKEYS, {{"5120793185cd1a9a0bb710fa57df3845ac4ddf7df63b74beadce2573cbb0b508b3a4"}}, OutputType::BECH32M, /*op_desc_id=*/{}, {{}, {0}});
+ // Can sign for a Miniscript expression containing a hash challenge inside a Taproot tree. (Fails without the
+ // preimages and the sequence, passes with.)
+ Check("tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),v:pk(KykUPmR5967F4URzMUeCv9kNMU9CNRWycrPmx3ZvfkWoQLabbimL)),older(42)),multi_a(2,adf586a32ad4b0674a86022b000348b681b4c97a811f67eefe4a6e066e55080c,KztMyyi1pXUtuZfJSB7JzVdmJMAz7wfGVFoSRUR5CVZxXxULXuGR)})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),v:pk(1c9bc926084382e76da33b5a52d17b1fa153c072aae5fb5228ecc2ccf89d79d5)),older(42)),multi_a(2,adf586a32ad4b0674a86022b000348b681b4c97a811f67eefe4a6e066e55080c,14fa4ad085cdee1e2fc73d491b36a96c192382b1d9a21108eb3533f630364f9f)})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),v:pk(1c9bc926084382e76da33b5a52d17b1fa153c072aae5fb5228ecc2ccf89d79d5)),older(42)),multi_a(2,adf586a32ad4b0674a86022b000348b681b4c97a811f67eefe4a6e066e55080c,14fa4ad085cdee1e2fc73d491b36a96c192382b1d9a21108eb3533f630364f9f)})", MISSING_PRIVKEYS | XONLY_KEYS | SIGNABLE | SIGNABLE_FAILS, {{"51209a3d79db56fbe3ba4d905d827b62e1ed31cd6df1198b8c759d589c0f4efc27bd"}}, OutputType::BECH32M);
+ Check("tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),v:pk(KykUPmR5967F4URzMUeCv9kNMU9CNRWycrPmx3ZvfkWoQLabbimL)),older(42)),multi_a(2,adf586a32ad4b0674a86022b000348b681b4c97a811f67eefe4a6e066e55080c,KztMyyi1pXUtuZfJSB7JzVdmJMAz7wfGVFoSRUR5CVZxXxULXuGR)})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),v:pk(1c9bc926084382e76da33b5a52d17b1fa153c072aae5fb5228ecc2ccf89d79d5)),older(42)),multi_a(2,adf586a32ad4b0674a86022b000348b681b4c97a811f67eefe4a6e066e55080c,14fa4ad085cdee1e2fc73d491b36a96c192382b1d9a21108eb3533f630364f9f)})", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{and_v(and_v(v:hash256(ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588),v:pk(1c9bc926084382e76da33b5a52d17b1fa153c072aae5fb5228ecc2ccf89d79d5)),older(42)),multi_a(2,adf586a32ad4b0674a86022b000348b681b4c97a811f67eefe4a6e066e55080c,14fa4ad085cdee1e2fc73d491b36a96c192382b1d9a21108eb3533f630364f9f)})", MISSING_PRIVKEYS | XONLY_KEYS | SIGNABLE, {{"51209a3d79db56fbe3ba4d905d827b62e1ed31cd6df1198b8c759d589c0f4efc27bd"}}, OutputType::BECH32M, /*op_desc_id=*/{}, {{}}, /*spender_nlocktime=*/0, /*spender_nsequence=*/42, /*preimages=*/{{ParseHex("ae253ca2a54debcac7ecf414f6734f48c56421a08bb59182ff9f39a6fffdb588"), ParseHex("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")}});
+
+ // Basic sh(pkh()) with key origin
+ CheckInferDescriptor("a9141a31ad23bf49c247dd531a623c2ef57da3c400c587", "sh(pkh([deadbeef/0h/0h/0]03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", {"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}, {{"03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd", "deadbeef/0h/0h/0"}});
+ // p2pk script with hybrid key must infer as raw()
+ CheckInferDescriptor("41069228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4ac", "raw(41069228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4ac)", {}, {{"069228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4", ""}});
+ // p2pkh script with hybrid key must infer as addr()
+ CheckInferDescriptor("76a91445ff7c2327866472639d507334a9a00119dfd32688ac", "addr(17P7ge56F2QcdHxxRBa2NyzmejFggPwBJ9)", {}, {{"069228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4", ""}});
+ // p2wpkh script with uncompressed key must infer as addr()
+ CheckInferDescriptor("001422e363a523947a110d9a9eb114820de183aca313", "addr(bc1qyt3k8ffrj3apzrv6n6c3fqsduxp6egcnk2r66j)", {}, {{"049228de6902abb4f541791f6d7f925b10e2078ccb1298856e5ea5cc5fd667f930eac37a00cc07f9a91ef3c2d17bf7a17db04552ff90ac312a5b8b4caca6c97aa4", ""}});
+ // Infer pkh() from p2pkh with uncompressed key
+ CheckInferDescriptor("76a914a31725c74421fadc50d35520ab8751ed120af80588ac", "pkh(04c56fe4a92d401bcbf1b3dfbe4ac3dac5602ca155a3681497f02c1b9a733b92d704e2da6ec4162e4846af9236ef4171069ac8b7f8234a8405b6cadd96f34f5a31)", {}, {{"04c56fe4a92d401bcbf1b3dfbe4ac3dac5602ca155a3681497f02c1b9a733b92d704e2da6ec4162e4846af9236ef4171069ac8b7f8234a8405b6cadd96f34f5a31", ""}});
+ // Infer pk() from p2pk with uncompressed key
+ CheckInferDescriptor("4104032540df1d3c7070a8ab3a9cdd304dfc7fd1e6541369c53c4c3310b2537d91059afc8b8e7673eb812a32978dabb78c40f2e423f7757dca61d11838c7aeeb5220ac", "pk(04032540df1d3c7070a8ab3a9cdd304dfc7fd1e6541369c53c4c3310b2537d91059afc8b8e7673eb812a32978dabb78c40f2e423f7757dca61d11838c7aeeb5220)", {}, {{"04032540df1d3c7070a8ab3a9cdd304dfc7fd1e6541369c53c4c3310b2537d91059afc8b8e7673eb812a32978dabb78c40f2e423f7757dca61d11838c7aeeb5220", ""}});
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
index 49b9898228..0363f317b6 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -29,7 +29,7 @@ FUZZ_TARGET(chain)
(void)disk_block_index->GetBlockTimeMax();
(void)disk_block_index->GetMedianTimePast();
(void)disk_block_index->GetUndoPos();
- (void)disk_block_index->HaveTxsDownloaded();
+ (void)disk_block_index->HaveNumChainTxs();
(void)disk_block_index->IsValid();
}
diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp
index deb0ed65ca..38a8c6798e 100644
--- a/src/test/fuzz/fees.cpp
+++ b/src/test/fuzz/fees.cpp
@@ -17,7 +17,8 @@ FUZZ_TARGET(fees)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)};
- FeeFilterRounder fee_filter_rounder{minimal_incremental_fee};
+ FastRandomContext rng{/*fDeterministic=*/true};
+ FeeFilterRounder fee_filter_rounder{minimal_incremental_fee, rng};
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider);
const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee);
diff --git a/src/test/fuzz/mini_miner.cpp b/src/test/fuzz/mini_miner.cpp
index e17e2bad60..2f53943c31 100644
--- a/src/test/fuzz/mini_miner.cpp
+++ b/src/test/fuzz/mini_miner.cpp
@@ -25,7 +25,7 @@ void initialize_miner()
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
g_setup = testing_setup.get();
for (uint32_t i = 0; i < uint32_t{100}; ++i) {
- g_available_coins.push_back(COutPoint{uint256::ZERO, i});
+ g_available_coins.emplace_back(uint256::ZERO, i);
}
}
@@ -45,11 +45,11 @@ FUZZ_TARGET(mini_miner, .init = initialize_miner)
const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 50);
for (size_t n{0}; n < num_inputs; ++n) {
auto prevout = available_coins.front();
- mtx.vin.push_back(CTxIn(prevout, CScript()));
+ mtx.vin.emplace_back(prevout, CScript());
available_coins.pop_front();
}
for (uint32_t n{0}; n < num_outputs; ++n) {
- mtx.vout.push_back(CTxOut(100, P2WSH_OP_TRUE));
+ mtx.vout.emplace_back(100, P2WSH_OP_TRUE);
}
CTransactionRef tx = MakeTransactionRef(mtx);
TestMemPoolEntryHelper entry;
@@ -60,14 +60,14 @@ FUZZ_TARGET(mini_miner, .init = initialize_miner)
// All outputs are available to spend
for (uint32_t n{0}; n < num_outputs; ++n) {
if (fuzzed_data_provider.ConsumeBool()) {
- available_coins.push_back(COutPoint{tx->GetHash(), n});
+ available_coins.emplace_back(tx->GetHash(), n);
}
}
if (fuzzed_data_provider.ConsumeBool() && !tx->vout.empty()) {
// Add outpoint from this tx (may or not be spent by a later tx)
- outpoints.push_back(COutPoint{tx->GetHash(),
- (uint32_t)fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, tx->vout.size())});
+ outpoints.emplace_back(tx->GetHash(),
+ (uint32_t)fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, tx->vout.size()));
} else {
// Add some random outpoint (will be interpreted as confirmed or not yet submitted
// to mempool).
@@ -123,11 +123,11 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(2, 5);
for (size_t n{0}; n < num_inputs; ++n) {
auto prevout = available_coins.at(0);
- mtx.vin.push_back(CTxIn(prevout, CScript()));
+ mtx.vin.emplace_back(prevout, CScript());
available_coins.pop_front();
}
for (uint32_t n{0}; n < num_outputs; ++n) {
- mtx.vout.push_back(CTxOut(100, P2WSH_OP_TRUE));
+ mtx.vout.emplace_back(100, P2WSH_OP_TRUE);
}
CTransactionRef tx = MakeTransactionRef(mtx);
@@ -136,9 +136,9 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
// MiniMiner interprets spent coins as to-be-replaced and excludes them.
for (uint32_t n{0}; n < num_outputs - 1; ++n) {
if (fuzzed_data_provider.ConsumeBool()) {
- available_coins.push_front(COutPoint{tx->GetHash(), n});
+ available_coins.emplace_front(tx->GetHash(), n);
} else {
- available_coins.push_back(COutPoint{tx->GetHash(), n});
+ available_coins.emplace_back(tx->GetHash(), n);
}
}
diff --git a/src/test/fuzz/miniscript.cpp b/src/test/fuzz/miniscript.cpp
index 0246507da1..8c73edfa9d 100644
--- a/src/test/fuzz/miniscript.cpp
+++ b/src/test/fuzz/miniscript.cpp
@@ -7,6 +7,7 @@
#include <key.h>
#include <script/miniscript.h>
#include <script/script.h>
+#include <script/signingprovider.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
@@ -14,6 +15,13 @@
namespace {
+using Fragment = miniscript::Fragment;
+using NodeRef = miniscript::NodeRef<CPubKey>;
+using Node = miniscript::Node<CPubKey>;
+using Type = miniscript::Type;
+using MsCtx = miniscript::MiniscriptContext;
+using miniscript::operator"" _mst;
+
//! Some pre-computed data for more efficient string roundtrips and to simulate challenges.
struct TestData {
typedef CPubKey Key;
@@ -23,6 +31,7 @@ struct TestData {
std::map<Key, int> dummy_key_idx_map;
std::map<CKeyID, Key> dummy_keys_map;
std::map<Key, std::pair<std::vector<unsigned char>, bool>> dummy_sigs;
+ std::map<XOnlyPubKey, std::pair<std::vector<unsigned char>, bool>> schnorr_sigs;
// Precomputed hashes of each kind.
std::vector<std::vector<unsigned char>> sha256;
@@ -37,6 +46,11 @@ struct TestData {
//! Set the precomputed data.
void Init() {
unsigned char keydata[32] = {1};
+ // All our signatures sign (and are required to sign) this constant message.
+ auto const MESSAGE_HASH{uint256S("f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065")};
+ // We don't pass additional randomness when creating a schnorr signature.
+ auto const EMPTY_AUX{uint256S("")};
+
for (size_t i = 0; i < 256; i++) {
keydata[31] = i;
CKey privkey;
@@ -46,11 +60,18 @@ struct TestData {
dummy_keys.push_back(pubkey);
dummy_key_idx_map.emplace(pubkey, i);
dummy_keys_map.insert({pubkey.GetID(), pubkey});
+ XOnlyPubKey xonly_pubkey{pubkey};
+ dummy_key_idx_map.emplace(xonly_pubkey, i);
+ uint160 xonly_hash{Hash160(xonly_pubkey)};
+ dummy_keys_map.emplace(xonly_hash, pubkey);
- std::vector<unsigned char> sig;
- privkey.Sign(uint256S(""), sig);
+ std::vector<unsigned char> sig, schnorr_sig(64);
+ privkey.Sign(MESSAGE_HASH, sig);
sig.push_back(1); // SIGHASH_ALL
dummy_sigs.insert({pubkey, {sig, i & 1}});
+ assert(privkey.SignSchnorr(MESSAGE_HASH, schnorr_sig, nullptr, EMPTY_AUX));
+ schnorr_sig.push_back(1); // Maximally-sized signature has sighash byte
+ schnorr_sigs.emplace(XOnlyPubKey{pubkey}, std::make_pair(std::move(schnorr_sig), i & 1));
std::vector<unsigned char> hash;
hash.resize(32);
@@ -70,6 +91,19 @@ struct TestData {
if (i & 1) hash160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
}
}
+
+ //! Get the (Schnorr or ECDSA, depending on context) signature for this pubkey.
+ const std::pair<std::vector<unsigned char>, bool>* GetSig(const MsCtx script_ctx, const Key& key) const {
+ if (!miniscript::IsTapscript(script_ctx)) {
+ const auto it = dummy_sigs.find(key);
+ if (it == dummy_sigs.end()) return nullptr;
+ return &it->second;
+ } else {
+ const auto it = schnorr_sigs.find(XOnlyPubKey{key});
+ if (it == schnorr_sigs.end()) return nullptr;
+ return &it->second;
+ }
+ }
} TEST_DATA;
/**
@@ -80,6 +114,10 @@ struct TestData {
struct ParserContext {
typedef CPubKey Key;
+ const MsCtx script_ctx;
+
+ constexpr ParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
+
bool KeyCompare(const Key& a, const Key& b) const {
return a < b;
}
@@ -92,14 +130,20 @@ struct ParserContext {
return HexStr(Span{&idx, 1});
}
- std::vector<unsigned char> ToPKBytes(const Key& key) const
- {
- return {key.begin(), key.end()};
+ std::vector<unsigned char> ToPKBytes(const Key& key) const {
+ if (!miniscript::IsTapscript(script_ctx)) {
+ return {key.begin(), key.end()};
+ }
+ const XOnlyPubKey xonly_pubkey{key};
+ return {xonly_pubkey.begin(), xonly_pubkey.end()};
}
- std::vector<unsigned char> ToPKHBytes(const Key& key) const
- {
- const auto h = Hash160(key);
+ std::vector<unsigned char> ToPKHBytes(const Key& key) const {
+ if (!miniscript::IsTapscript(script_ctx)) {
+ const auto h = Hash160(key);
+ return {h.begin(), h.end()};
+ }
+ const auto h = Hash160(XOnlyPubKey{key});
return {h.begin(), h.end()};
}
@@ -113,10 +157,15 @@ struct ParserContext {
template<typename I>
std::optional<Key> FromPKBytes(I first, I last) const {
- CPubKey key;
- key.Set(first, last);
- if (!key.IsValid()) return {};
- return key;
+ if (!miniscript::IsTapscript(script_ctx)) {
+ Key key{first, last};
+ if (key.IsValid()) return key;
+ return {};
+ }
+ if (last - first != 32) return {};
+ XOnlyPubKey xonly_pubkey;
+ std::copy(first, last, xonly_pubkey.begin());
+ return xonly_pubkey.GetEvenCorrespondingCPubKey();
}
template<typename I>
@@ -128,10 +177,18 @@ struct ParserContext {
if (it == TEST_DATA.dummy_keys_map.end()) return {};
return it->second;
}
-} PARSER_CTX;
+
+ MsCtx MsContext() const {
+ return script_ctx;
+ }
+};
//! Context that implements naive conversion from/to script only, for roundtrip testing.
struct ScriptParserContext {
+ const MsCtx script_ctx;
+
+ constexpr ScriptParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
+
//! For Script roundtrip we never need the key from a key hash.
struct Key {
bool is_hash;
@@ -172,10 +229,17 @@ struct ScriptParserContext {
key.is_hash = true;
return key;
}
-} SCRIPT_PARSER_CONTEXT;
+
+ MsCtx MsContext() const {
+ return script_ctx;
+ }
+};
//! Context to produce a satisfaction for a Miniscript node using the pre-computed data.
-struct SatisfierContext: ParserContext {
+struct SatisfierContext : ParserContext {
+
+ constexpr SatisfierContext(MsCtx ctx) noexcept : ParserContext(ctx) {}
+
// Timelock challenges satisfaction. Make the value (deterministically) vary to explore different
// paths.
bool CheckAfter(uint32_t value) const { return value % 2; }
@@ -183,15 +247,11 @@ struct SatisfierContext: ParserContext {
// Signature challenges fulfilled with a dummy signature, if it was one of our dummy keys.
miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
- const auto it = TEST_DATA.dummy_sigs.find(key);
- if (it == TEST_DATA.dummy_sigs.end()) return miniscript::Availability::NO;
- if (it->second.second) {
- // Key is "available"
- sig = it->second.first;
- return miniscript::Availability::YES;
- } else {
- return miniscript::Availability::NO;
+ bool sig_available{false};
+ if (auto res = TEST_DATA.GetSig(script_ctx, key)) {
+ std::tie(sig, sig_available) = *res;
}
+ return sig_available ? miniscript::Availability::YES : miniscript::Availability::NO;
}
//! Lookup generalization for all the hash satisfactions below
@@ -215,12 +275,10 @@ struct SatisfierContext: ParserContext {
miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const {
return LookupHash(hash, preimage, TEST_DATA.hash160_preimages);
}
-} SATISFIER_CTX;
+};
//! Context to check a satisfaction against the pre-computed data.
-struct CheckerContext: BaseSignatureChecker {
- TestData *test_data;
-
+const struct CheckerContext: BaseSignatureChecker {
// Signature checker methods. Checks the right dummy signature is used.
bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& vchPubKey,
const CScript& scriptCode, SigVersion sigversion) const override
@@ -230,12 +288,19 @@ struct CheckerContext: BaseSignatureChecker {
if (it == TEST_DATA.dummy_sigs.end()) return false;
return it->second.first == sig;
}
+ bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion,
+ ScriptExecutionData&, ScriptError*) const override {
+ XOnlyPubKey pk{pubkey};
+ auto it = TEST_DATA.schnorr_sigs.find(pk);
+ if (it == TEST_DATA.schnorr_sigs.end()) return false;
+ return it->second.first == sig;
+ }
bool CheckLockTime(const CScriptNum& nLockTime) const override { return nLockTime.GetInt64() & 1; }
bool CheckSequence(const CScriptNum& nSequence) const override { return nSequence.GetInt64() & 1; }
} CHECKER_CTX;
//! Context to check for duplicates when instancing a Node.
-struct KeyComparator {
+const struct KeyComparator {
bool KeyCompare(const CPubKey& a, const CPubKey& b) const {
return a < b;
}
@@ -244,11 +309,8 @@ struct KeyComparator {
// A dummy scriptsig to pass to VerifyScript (we always use Segwit v0).
const CScript DUMMY_SCRIPTSIG;
-using Fragment = miniscript::Fragment;
-using NodeRef = miniscript::NodeRef<CPubKey>;
-using Node = miniscript::Node<CPubKey>;
-using Type = miniscript::Type;
-using miniscript::operator"" _mst;
+//! Public key to be used as internal key for dummy Taproot spends.
+const std::vector<unsigned char> NUMS_PK{ParseHex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
//! Construct a miniscript node as a shared_ptr.
template<typename... Args> NodeRef MakeNodeRef(Args&&... args) {
@@ -321,9 +383,10 @@ std::optional<uint32_t> ConsumeTimeLock(FuzzedDataProvider& provider) {
* - For pk_k(), pk_h(), and all hashes, the next byte defines the index of the value in the test data.
* - For multi(), the next 2 bytes define respectively the threshold and the number of keys. Then as many
* bytes as the number of keys define the index of each key in the test data.
+ * - For multi_a(), same as for multi() but the threshold and the keys count are encoded on two bytes.
* - For thresh(), the next byte defines the threshold value and the following one the number of subs.
*/
-std::optional<NodeInfo> ConsumeNodeStable(FuzzedDataProvider& provider, Type type_needed) {
+std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx, FuzzedDataProvider& provider, Type type_needed) {
bool allow_B = (type_needed == ""_mst) || (type_needed << "B"_mst);
bool allow_K = (type_needed == ""_mst) || (type_needed << "K"_mst);
bool allow_V = (type_needed == ""_mst) || (type_needed << "V"_mst);
@@ -367,7 +430,7 @@ std::optional<NodeInfo> ConsumeNodeStable(FuzzedDataProvider& provider, Type typ
if (!allow_B) return {};
return {{Fragment::HASH160, ConsumeHash160(provider)}};
case 10: {
- if (!allow_B) return {};
+ if (!allow_B || IsTapscript(script_ctx)) return {};
const auto k = provider.ConsumeIntegral<uint8_t>();
const auto n_keys = provider.ConsumeIntegral<uint8_t>();
if (n_keys > 20 || k == 0 || k > n_keys) return {};
@@ -428,6 +491,15 @@ std::optional<NodeInfo> ConsumeNodeStable(FuzzedDataProvider& provider, Type typ
case 26:
if (!allow_B) return {};
return {{{"B"_mst}, Fragment::WRAP_N}};
+ case 27: {
+ if (!allow_B || !IsTapscript(script_ctx)) return {};
+ const auto k = provider.ConsumeIntegral<uint16_t>();
+ const auto n_keys = provider.ConsumeIntegral<uint16_t>();
+ if (n_keys > 999 || k == 0 || k > n_keys) return {};
+ std::vector<CPubKey> keys{n_keys};
+ for (auto& key: keys) key = ConsumePubKey(provider);
+ return {{Fragment::MULTI_A, k, std::move(keys)}};
+ }
default:
break;
}
@@ -444,10 +516,16 @@ std::optional<NodeInfo> ConsumeNodeStable(FuzzedDataProvider& provider, Type typ
struct SmartInfo
{
using recipe = std::pair<Fragment, std::vector<Type>>;
- std::map<Type, std::vector<recipe>> table;
+ std::map<Type, std::vector<recipe>> wsh_table, tap_table;
void Init()
{
+ Init(wsh_table, MsCtx::P2WSH);
+ Init(tap_table, MsCtx::TAPSCRIPT);
+ }
+
+ void Init(std::map<Type, std::vector<recipe>>& table, MsCtx script_ctx)
+ {
/* Construct a set of interesting type requirements to reason with (sections of BKVWzondu). */
std::vector<Type> types;
for (int base = 0; base < 4; ++base) { /* select from B,K,V,W */
@@ -495,7 +573,7 @@ struct SmartInfo
std::sort(types.begin(), types.end());
// Iterate over all possible fragments.
- for (int fragidx = 0; fragidx <= int(Fragment::MULTI); ++fragidx) {
+ for (int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {
int sub_count = 0; //!< The minimum number of child nodes this recipe has.
int sub_range = 1; //!< The maximum number of child nodes for this recipe is sub_count+sub_range-1.
size_t data_size = 0;
@@ -503,6 +581,12 @@ struct SmartInfo
uint32_t k = 0;
Fragment frag{fragidx};
+ // Only produce recipes valid in the given context.
+ if ((!miniscript::IsTapscript(script_ctx) && frag == Fragment::MULTI_A)
+ || (miniscript::IsTapscript(script_ctx) && frag == Fragment::MULTI)) {
+ continue;
+ }
+
// Based on the fragment, determine #subs/data/k/keys to pass to ComputeType. */
switch (frag) {
case Fragment::PK_K:
@@ -510,6 +594,7 @@ struct SmartInfo
n_keys = 1;
break;
case Fragment::MULTI:
+ case Fragment::MULTI_A:
n_keys = 1;
k = 1;
break;
@@ -568,7 +653,7 @@ struct SmartInfo
if (subs > 0) subt.push_back(x);
if (subs > 1) subt.push_back(y);
if (subs > 2) subt.push_back(z);
- Type res = miniscript::internal::ComputeType(frag, x, y, z, subt, k, data_size, subs, n_keys);
+ Type res = miniscript::internal::ComputeType(frag, x, y, z, subt, k, data_size, subs, n_keys, script_ctx);
// Continue if the result is not a valid node.
if ((res << "K"_mst) + (res << "V"_mst) + (res << "B"_mst) + (res << "W"_mst) != 1) continue;
@@ -685,10 +770,11 @@ struct SmartInfo
* (as improvements to the tables or changes to the typing rules could invalidate
* everything).
*/
-std::optional<NodeInfo> ConsumeNodeSmart(FuzzedDataProvider& provider, Type type_needed) {
+std::optional<NodeInfo> ConsumeNodeSmart(MsCtx script_ctx, FuzzedDataProvider& provider, Type type_needed) {
/** Table entry for the requested type. */
- auto recipes_it = SMARTINFO.table.find(type_needed);
- assert(recipes_it != SMARTINFO.table.end());
+ const auto& table{IsTapscript(script_ctx) ? SMARTINFO.tap_table : SMARTINFO.wsh_table};
+ auto recipes_it = table.find(type_needed);
+ assert(recipes_it != table.end());
/** Pick one recipe from the available ones for that type. */
const auto& [frag, subt] = PickValue(provider, recipes_it->second);
@@ -704,6 +790,13 @@ std::optional<NodeInfo> ConsumeNodeSmart(FuzzedDataProvider& provider, Type type
for (auto& key: keys) key = ConsumePubKey(provider);
return {{frag, k, std::move(keys)}};
}
+ case Fragment::MULTI_A: {
+ const auto n_keys = provider.ConsumeIntegralInRange<uint16_t>(1, 999);
+ const auto k = provider.ConsumeIntegralInRange<uint16_t>(1, n_keys);
+ std::vector<CPubKey> keys{n_keys};
+ for (auto& key: keys) key = ConsumePubKey(provider);
+ return {{frag, k, std::move(keys)}};
+ }
case Fragment::OLDER:
case Fragment::AFTER:
return {{frag, provider.ConsumeIntegralInRange<uint32_t>(1, 0x7FFFFFF)}};
@@ -760,7 +853,7 @@ std::optional<NodeInfo> ConsumeNodeSmart(FuzzedDataProvider& provider, Type type
* a NodeRef whose Type() matches the type fed to ConsumeNode.
*/
template<typename F>
-NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
+NodeRef GenNode(MsCtx script_ctx, F ConsumeNode, Type root_type, bool strict_valid = false) {
/** A stack of miniscript Nodes being built up. */
std::vector<NodeRef> stack;
/** The queue of instructions. */
@@ -781,7 +874,8 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
// Update predicted resource limits. Since every leaf Miniscript node is at least one
// byte long, we move one byte from each child to their parent. A similar technique is
// used in the miniscript::internal::Parse function to prevent runaway string parsing.
- scriptsize += miniscript::internal::ComputeScriptLen(node_info->fragment, ""_mst, node_info->subtypes.size(), node_info->k, node_info->subtypes.size(), node_info->keys.size()) - 1;
+ scriptsize += miniscript::internal::ComputeScriptLen(node_info->fragment, ""_mst, node_info->subtypes.size(), node_info->k, node_info->subtypes.size(),
+ node_info->keys.size(), script_ctx) - 1;
if (scriptsize > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
switch (node_info->fragment) {
case Fragment::JUST_0:
@@ -826,6 +920,9 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
case Fragment::MULTI:
ops += 1;
break;
+ case Fragment::MULTI_A:
+ ops += node_info->keys.size() + 1;
+ break;
case Fragment::WRAP_A:
ops += 2;
break;
@@ -874,11 +971,11 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
// Construct new NodeRef.
NodeRef node;
if (info.keys.empty()) {
- node = MakeNodeRef(info.fragment, std::move(sub), std::move(info.hash), info.k);
+ node = MakeNodeRef(script_ctx, info.fragment, std::move(sub), std::move(info.hash), info.k);
} else {
assert(sub.empty());
assert(info.hash.empty());
- node = MakeNodeRef(info.fragment, std::move(info.keys), info.k);
+ node = MakeNodeRef(script_ctx, info.fragment, std::move(info.keys), info.k);
}
// Verify acceptability.
if (!node || (node->GetType() & "KVWB"_mst) == ""_mst) {
@@ -894,8 +991,10 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
ops += 1;
scriptsize += 1;
}
- if (ops > MAX_OPS_PER_SCRIPT) return {};
- if (scriptsize > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
+ if (!miniscript::IsTapscript(script_ctx) && ops > MAX_OPS_PER_SCRIPT) return {};
+ if (scriptsize > miniscript::internal::MaxScriptSize(script_ctx)) {
+ return {};
+ }
// Move it to the stack.
stack.push_back(std::move(node));
todo.pop_back();
@@ -908,44 +1007,67 @@ NodeRef GenNode(F ConsumeNode, Type root_type, bool strict_valid = false) {
return std::move(stack[0]);
}
+//! The spk for this script under the given context. If it's a Taproot output also record the spend data.
+CScript ScriptPubKey(MsCtx ctx, const CScript& script, TaprootBuilder& builder)
+{
+ if (!miniscript::IsTapscript(ctx)) return CScript() << OP_0 << WitnessV0ScriptHash(script);
+
+ // For Taproot outputs we always use a tree with a single script and a dummy internal key.
+ builder.Add(0, script, TAPROOT_LEAF_TAPSCRIPT);
+ builder.Finalize(XOnlyPubKey{NUMS_PK});
+ return GetScriptForDestination(builder.GetOutput());
+}
+
+//! Fill the witness with the data additional to the script satisfaction.
+void SatisfactionToWitness(MsCtx ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
+ // For P2WSH, it's only the witness script.
+ witness.stack.emplace_back(script.begin(), script.end());
+ if (!miniscript::IsTapscript(ctx)) return;
+ // For Tapscript we also need the control block.
+ witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
+}
+
/** Perform various applicable tests on a miniscript Node. */
-void TestNode(const NodeRef& node, FuzzedDataProvider& provider)
+void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& provider)
{
if (!node) return;
// Check that it roundtrips to text representation
- std::optional<std::string> str{node->ToString(PARSER_CTX)};
+ const ParserContext parser_ctx{script_ctx};
+ std::optional<std::string> str{node->ToString(parser_ctx)};
assert(str);
- auto parsed = miniscript::FromString(*str, PARSER_CTX);
+ auto parsed = miniscript::FromString(*str, parser_ctx);
assert(parsed);
assert(*parsed == *node);
// Check consistency between script size estimation and real size.
- auto script = node->ToScript(PARSER_CTX);
+ auto script = node->ToScript(parser_ctx);
assert(node->ScriptSize() == script.size());
// Check consistency of "x" property with the script (type K is excluded, because it can end
// with a push of a key, which could match these opcodes).
if (!(node->GetType() << "K"_mst)) {
bool ends_in_verify = !(node->GetType() << "x"_mst);
- assert(ends_in_verify == (script.back() == OP_CHECKSIG || script.back() == OP_CHECKMULTISIG || script.back() == OP_EQUAL));
+ assert(ends_in_verify == (script.back() == OP_CHECKSIG || script.back() == OP_CHECKMULTISIG || script.back() == OP_EQUAL || script.back() == OP_NUMEQUAL));
}
// The rest of the checks only apply when testing a valid top-level script.
if (!node->IsValidTopLevel()) return;
// Check roundtrip to script
- auto decoded = miniscript::FromScript(script, PARSER_CTX);
+ auto decoded = miniscript::FromScript(script, parser_ctx);
assert(decoded);
// Note we can't use *decoded == *node because the miniscript representation may differ, so we check that:
// - The script corresponding to that decoded form matches exactly
// - The type matches exactly
- assert(decoded->ToScript(PARSER_CTX) == script);
+ assert(decoded->ToScript(parser_ctx) == script);
assert(decoded->GetType() == node->GetType());
- const auto node_ops{node->GetOps()};
- if (provider.ConsumeBool() && node_ops && *node_ops < MAX_OPS_PER_SCRIPT && node->ScriptSize() < MAX_STANDARD_P2WSH_SCRIPT_SIZE) {
- // Optionally pad the script with OP_NOPs to max op the ops limit of the constructed script.
+ // Optionally pad the script or the witness in order to increase the sensitivity of the tests of
+ // the resources limits logic.
+ CScriptWitness witness_mal, witness_nonmal;
+ if (provider.ConsumeBool()) {
+ // Under P2WSH, optionally pad the script with OP_NOPs to max op the ops limit of the constructed script.
// This makes the script obviously not actually miniscript-compatible anymore, but the
// signatures constructed in this test don't commit to the script anyway, so the same
// miniscript satisfier will work. This increases the sensitivity of the test to the ops
@@ -954,31 +1076,57 @@ void TestNode(const NodeRef& node, FuzzedDataProvider& provider)
// maximal.
// Do not pad more than what would cause MAX_STANDARD_P2WSH_SCRIPT_SIZE to be reached, however,
// as that also invalidates scripts.
- int add = std::min<int>(
- MAX_OPS_PER_SCRIPT - *node_ops,
- MAX_STANDARD_P2WSH_SCRIPT_SIZE - node->ScriptSize());
- for (int i = 0; i < add; ++i) script.push_back(OP_NOP);
+ const auto node_ops{node->GetOps()};
+ if (!IsTapscript(script_ctx) && node_ops && *node_ops < MAX_OPS_PER_SCRIPT
+ && node->ScriptSize() < MAX_STANDARD_P2WSH_SCRIPT_SIZE) {
+ int add = std::min<int>(
+ MAX_OPS_PER_SCRIPT - *node_ops,
+ MAX_STANDARD_P2WSH_SCRIPT_SIZE - node->ScriptSize());
+ for (int i = 0; i < add; ++i) script.push_back(OP_NOP);
+ }
+
+ // Under Tapscript, optionally pad the stack up to the limit minus the calculated maximum execution stack
+ // size to assert a Miniscript would never add more elements to the stack during execution than anticipated.
+ const auto node_exec_ss{node->GetExecStackSize()};
+ if (miniscript::IsTapscript(script_ctx) && node_exec_ss && *node_exec_ss < MAX_STACK_SIZE) {
+ unsigned add{(unsigned)MAX_STACK_SIZE - *node_exec_ss};
+ witness_mal.stack.resize(add);
+ witness_nonmal.stack.resize(add);
+ script.reserve(add);
+ for (unsigned i = 0; i < add; ++i) script.push_back(OP_NIP);
+ }
}
+ const SatisfierContext satisfier_ctx{script_ctx};
+
+ // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
+ TaprootBuilder builder;
+ const CScript script_pubkey{ScriptPubKey(script_ctx, script, builder)};
+
// Run malleable satisfaction algorithm.
- const CScript script_pubkey = CScript() << OP_0 << WitnessV0ScriptHash(script);
- CScriptWitness witness_mal;
- const bool mal_success = node->Satisfy(SATISFIER_CTX, witness_mal.stack, false) == miniscript::Availability::YES;
- witness_mal.stack.push_back(std::vector<unsigned char>(script.begin(), script.end()));
+ std::vector<std::vector<unsigned char>> stack_mal;
+ const bool mal_success = node->Satisfy(satisfier_ctx, stack_mal, false) == miniscript::Availability::YES;
// Run non-malleable satisfaction algorithm.
- CScriptWitness witness_nonmal;
- const bool nonmal_success = node->Satisfy(SATISFIER_CTX, witness_nonmal.stack, true) == miniscript::Availability::YES;
- witness_nonmal.stack.push_back(std::vector<unsigned char>(script.begin(), script.end()));
+ std::vector<std::vector<unsigned char>> stack_nonmal;
+ const bool nonmal_success = node->Satisfy(satisfier_ctx, stack_nonmal, true) == miniscript::Availability::YES;
if (nonmal_success) {
- // Non-malleable satisfactions are bounded by GetStackSize().
- assert(witness_nonmal.stack.size() <= *node->GetStackSize() + 1);
+ // Non-malleable satisfactions are bounded by the satisfaction size plus:
+ // - For P2WSH spends, the witness script
+ // - For Tapscript spends, both the witness script and the control block
+ const size_t max_stack_size{*node->GetStackSize() + 1 + miniscript::IsTapscript(script_ctx)};
+ assert(stack_nonmal.size() <= max_stack_size);
// If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
assert(mal_success);
- assert(witness_nonmal.stack == witness_mal.stack);
+ assert(stack_nonmal == stack_mal);
+ // Compute witness size (excluding script push, control block, and witness count encoding).
+ const size_t wit_size = GetSerializeSize(stack_nonmal, PROTOCOL_VERSION) - GetSizeOfCompactSize(stack_nonmal.size());
+ assert(wit_size <= *node->GetWitnessSize());
// Test non-malleable satisfaction.
+ witness_nonmal.stack.insert(witness_nonmal.stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
+ SatisfactionToWitness(script_ctx, witness_nonmal, script, builder);
ScriptError serror;
bool res = VerifyScript(DUMMY_SCRIPTSIG, script_pubkey, &witness_nonmal, STANDARD_SCRIPT_VERIFY_FLAGS, CHECKER_CTX, &serror);
// Non-malleable satisfactions are guaranteed to be valid if ValidSatisfactions().
@@ -992,6 +1140,8 @@ void TestNode(const NodeRef& node, FuzzedDataProvider& provider)
if (mal_success && (!nonmal_success || witness_mal.stack != witness_nonmal.stack)) {
// Test malleable satisfaction only if it's different from the non-malleable one.
+ witness_mal.stack.insert(witness_mal.stack.end(), std::make_move_iterator(stack_mal.begin()), std::make_move_iterator(stack_mal.end()));
+ SatisfactionToWitness(script_ctx, witness_mal, script, builder);
ScriptError serror;
bool res = VerifyScript(DUMMY_SCRIPTSIG, script_pubkey, &witness_mal, STANDARD_SCRIPT_VERIFY_FLAGS, CHECKER_CTX, &serror);
// Malleable satisfactions are not guaranteed to be valid under any conditions, but they can only
@@ -1008,21 +1158,20 @@ void TestNode(const NodeRef& node, FuzzedDataProvider& provider)
// algorithm succeeds. Given that under IsSane() both satisfactions
// are identical, this implies that for such nodes, the non-malleable
// satisfaction will also match the expected policy.
- bool satisfiable = node->IsSatisfiable([](const Node& node) -> bool {
+ const auto is_key_satisfiable = [script_ctx](const CPubKey& pubkey) -> bool {
+ auto sig_ptr{TEST_DATA.GetSig(script_ctx, pubkey)};
+ return sig_ptr != nullptr && sig_ptr->second;
+ };
+ bool satisfiable = node->IsSatisfiable([&](const Node& node) -> bool {
switch (node.fragment) {
case Fragment::PK_K:
- case Fragment::PK_H: {
- auto it = TEST_DATA.dummy_sigs.find(node.keys[0]);
- assert(it != TEST_DATA.dummy_sigs.end());
- return it->second.second;
- }
- case Fragment::MULTI: {
- size_t sats = 0;
- for (const auto& key : node.keys) {
- auto it = TEST_DATA.dummy_sigs.find(key);
- assert(it != TEST_DATA.dummy_sigs.end());
- sats += it->second.second;
- }
+ case Fragment::PK_H:
+ return is_key_satisfiable(node.keys[0]);
+ case Fragment::MULTI:
+ case Fragment::MULTI_A: {
+ size_t sats = std::count_if(node.keys.begin(), node.keys.end(), [&](const auto& key) {
+ return size_t(is_key_satisfiable(key));
+ });
return sats >= node.k;
}
case Fragment::OLDER:
@@ -1061,10 +1210,13 @@ void FuzzInitSmart()
/** Fuzz target that runs TestNode on nodes generated using ConsumeNodeStable. */
FUZZ_TARGET(miniscript_stable, .init = FuzzInit)
{
- FuzzedDataProvider provider(buffer.data(), buffer.size());
- TestNode(GenNode([&](Type needed_type) {
- return ConsumeNodeStable(provider, needed_type);
- }, ""_mst), provider);
+ // Run it under both P2WSH and Tapscript contexts.
+ for (const auto script_ctx: {MsCtx::P2WSH, MsCtx::TAPSCRIPT}) {
+ FuzzedDataProvider provider(buffer.data(), buffer.size());
+ TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
+ return ConsumeNodeStable(script_ctx, provider, needed_type);
+ }, ""_mst), provider);
+ }
}
/** Fuzz target that runs TestNode on nodes generated using ConsumeNodeSmart. */
@@ -1074,22 +1226,25 @@ FUZZ_TARGET(miniscript_smart, .init = FuzzInitSmart)
static constexpr std::array<Type, 4> BASE_TYPES{"B"_mst, "V"_mst, "K"_mst, "W"_mst};
FuzzedDataProvider provider(buffer.data(), buffer.size());
- TestNode(GenNode([&](Type needed_type) {
- return ConsumeNodeSmart(provider, needed_type);
+ const auto script_ctx{(MsCtx)provider.ConsumeBool()};
+ TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
+ return ConsumeNodeSmart(script_ctx, provider, needed_type);
}, PickValue(provider, BASE_TYPES), true), provider);
}
/* Fuzz tests that test parsing from a string, and roundtripping via string. */
FUZZ_TARGET(miniscript_string, .init = FuzzInit)
{
+ if (buffer.empty()) return;
FuzzedDataProvider provider(buffer.data(), buffer.size());
- auto str = provider.ConsumeRemainingBytesAsString();
- auto parsed = miniscript::FromString(str, PARSER_CTX);
+ auto str = provider.ConsumeBytesAsString(provider.remaining_bytes() - 1);
+ const ParserContext parser_ctx{(MsCtx)provider.ConsumeBool()};
+ auto parsed = miniscript::FromString(str, parser_ctx);
if (!parsed) return;
- const auto str2 = parsed->ToString(PARSER_CTX);
+ const auto str2 = parsed->ToString(parser_ctx);
assert(str2);
- auto parsed2 = miniscript::FromString(*str2, PARSER_CTX);
+ auto parsed2 = miniscript::FromString(*str2, parser_ctx);
assert(parsed2);
assert(*parsed == *parsed2);
}
@@ -1101,8 +1256,9 @@ FUZZ_TARGET(miniscript_script)
const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
if (!script) return;
- const auto ms = miniscript::FromScript(*script, SCRIPT_PARSER_CONTEXT);
+ const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.ConsumeBool()};
+ const auto ms = miniscript::FromScript(*script, script_parser_ctx);
if (!ms) return;
- assert(ms->ToScript(SCRIPT_PARSER_CONTEXT) == *script);
+ assert(ms->ToScript(script_parser_ctx) == *script);
}
diff --git a/src/test/fuzz/script_bitcoin_consensus.cpp b/src/test/fuzz/script_bitcoin_consensus.cpp
index fcd66b234e..846389863d 100644
--- a/src/test/fuzz/script_bitcoin_consensus.cpp
+++ b/src/test/fuzz/script_bitcoin_consensus.cpp
@@ -28,4 +28,23 @@ FUZZ_TARGET(script_bitcoin_consensus)
}
(void)bitcoinconsensus_verify_script(random_bytes_1.data(), random_bytes_1.size(), random_bytes_2.data(), random_bytes_2.size(), n_in, flags, err_p);
(void)bitcoinconsensus_verify_script_with_amount(random_bytes_1.data(), random_bytes_1.size(), money, random_bytes_2.data(), random_bytes_2.size(), n_in, flags, err_p);
+
+ std::vector<UTXO> spent_outputs;
+ std::vector<std::vector<unsigned char>> spent_spks;
+ if (n_in <= 24386) {
+ spent_outputs.reserve(n_in);
+ spent_spks.reserve(n_in);
+ for (size_t i = 0; i < n_in; ++i) {
+ spent_spks.push_back(ConsumeRandomLengthByteVector(fuzzed_data_provider));
+ const CAmount value{ConsumeMoney(fuzzed_data_provider)};
+ const auto spk_size{static_cast<unsigned>(spent_spks.back().size())};
+ spent_outputs.push_back({.scriptPubKey = spent_spks.back().data(), .scriptPubKeySize = spk_size, .value = value});
+ }
+ }
+
+ const auto spent_outs_size{static_cast<unsigned>(spent_outputs.size())};
+
+ (void)bitcoinconsensus_verify_script_with_spent_outputs(
+ random_bytes_1.data(), random_bytes_1.size(), money, random_bytes_2.data(), random_bytes_2.size(),
+ spent_outputs.data(), spent_outs_size, n_in, flags, err_p);
}
diff --git a/src/test/headers_sync_chainwork_tests.cpp b/src/test/headers_sync_chainwork_tests.cpp
index 41241ebee2..b710ad1801 100644
--- a/src/test/headers_sync_chainwork_tests.cpp
+++ b/src/test/headers_sync_chainwork_tests.cpp
@@ -40,7 +40,7 @@ void HeadersGeneratorSetup::GenerateHeaders(std::vector<CBlockHeader>& headers,
uint256 prev_hash = starting_hash;
while (headers.size() < count) {
- headers.push_back(CBlockHeader());
+ headers.emplace_back();
CBlockHeader& next_header = headers.back();;
next_header.nVersion = nVersion;
next_header.hashPrevBlock = prev_hash;
diff --git a/src/test/miniscript_tests.cpp b/src/test/miniscript_tests.cpp
index b69317c4d9..996c379962 100644
--- a/src/test/miniscript_tests.cpp
+++ b/src/test/miniscript_tests.cpp
@@ -20,6 +20,7 @@
#include <script/interpreter.h>
#include <script/miniscript.h>
#include <script/script_error.h>
+#include <script/signingprovider.h>
namespace {
@@ -30,7 +31,9 @@ struct TestData {
//! A map from the public keys to their CKeyIDs (faster than hashing every time).
std::map<CPubKey, CKeyID> pkhashes;
std::map<CKeyID, CPubKey> pkmap;
+ std::map<XOnlyPubKey, CKeyID> xonly_pkhashes;
std::map<CPubKey, std::vector<unsigned char>> signatures;
+ std::map<XOnlyPubKey, std::vector<unsigned char>> schnorr_signatures;
// Various precomputed hashes
std::vector<std::vector<unsigned char>> sha256;
@@ -46,6 +49,9 @@ struct TestData {
{
// All our signatures sign (and are required to sign) this constant message.
auto const MESSAGE_HASH = uint256S("f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065");
+ // We don't pass additional randomness when creating a schnorr signature.
+ auto const EMPTY_AUX{uint256S("")};
+
// We generate 255 public keys and 255 hashes of each type.
for (int i = 1; i <= 255; ++i) {
// This 32-byte array functions as both private key data and hash preimage (31 zero bytes plus any nonzero byte).
@@ -60,12 +66,19 @@ struct TestData {
pubkeys.push_back(pubkey);
pkhashes.emplace(pubkey, keyid);
pkmap.emplace(keyid, pubkey);
+ XOnlyPubKey xonly_pubkey{pubkey};
+ uint160 xonly_hash{Hash160(xonly_pubkey)};
+ xonly_pkhashes.emplace(xonly_pubkey, xonly_hash);
+ pkmap.emplace(xonly_hash, pubkey);
// Compute ECDSA signatures on MESSAGE_HASH with the private keys.
- std::vector<unsigned char> sig;
+ std::vector<unsigned char> sig, schnorr_sig(64);
BOOST_CHECK(key.Sign(MESSAGE_HASH, sig));
sig.push_back(1); // sighash byte
signatures.emplace(pubkey, sig);
+ BOOST_CHECK(key.SignSchnorr(MESSAGE_HASH, schnorr_sig, nullptr, EMPTY_AUX));
+ schnorr_sig.push_back(1); // Maximally sized Schnorr sigs have a sighash byte.
+ schnorr_signatures.emplace(XOnlyPubKey{pubkey}, schnorr_sig);
// Compute various hashes
std::vector<unsigned char> hash;
@@ -114,19 +127,32 @@ typedef std::pair<ChallengeType, uint32_t> Challenge;
struct KeyConverter {
typedef CPubKey Key;
+ const miniscript::MiniscriptContext m_script_ctx;
+
+ constexpr KeyConverter(miniscript::MiniscriptContext ctx) noexcept : m_script_ctx{ctx} {}
+
bool KeyCompare(const Key& a, const Key& b) const {
return a < b;
}
//! Convert a public key to bytes.
- std::vector<unsigned char> ToPKBytes(const CPubKey& key) const { return {key.begin(), key.end()}; }
+ std::vector<unsigned char> ToPKBytes(const CPubKey& key) const {
+ if (!miniscript::IsTapscript(m_script_ctx)) {
+ return {key.begin(), key.end()};
+ }
+ const XOnlyPubKey xonly_pubkey{key};
+ return {xonly_pubkey.begin(), xonly_pubkey.end()};
+ }
//! Convert a public key to its Hash160 bytes (precomputed).
- std::vector<unsigned char> ToPKHBytes(const CPubKey& key) const
- {
- auto it = g_testdata->pkhashes.find(key);
- assert(it != g_testdata->pkhashes.end());
- return {it->second.begin(), it->second.end()};
+ std::vector<unsigned char> ToPKHBytes(const CPubKey& key) const {
+ if (!miniscript::IsTapscript(m_script_ctx)) {
+ auto hash = g_testdata->pkhashes.at(key);
+ return {hash.begin(), hash.end()};
+ }
+ const XOnlyPubKey xonly_key{key};
+ auto hash = g_testdata->xonly_pkhashes.at(xonly_key);
+ return {hash.begin(), hash.end()};
}
//! Parse a public key from a range of hex characters.
@@ -140,9 +166,15 @@ struct KeyConverter {
template<typename I>
std::optional<Key> FromPKBytes(I first, I last) const {
- Key key{first, last};
- if (key.IsValid()) return key;
- return {};
+ if (!miniscript::IsTapscript(m_script_ctx)) {
+ Key key{first, last};
+ if (key.IsValid()) return key;
+ return {};
+ }
+ if (last - first != 32) return {};
+ XOnlyPubKey xonly_pubkey;
+ std::copy(first, last, xonly_pubkey.begin());
+ return xonly_pubkey.GetEvenCorrespondingCPubKey();
}
template<typename I>
@@ -150,18 +182,23 @@ struct KeyConverter {
assert(last - first == 20);
CKeyID keyid;
std::copy(first, last, keyid.begin());
- auto it = g_testdata->pkmap.find(keyid);
- assert(it != g_testdata->pkmap.end());
- return it->second;
+ return g_testdata->pkmap.at(keyid);
}
std::optional<std::string> ToString(const Key& key) const {
return HexStr(ToPKBytes(key));
}
+
+ miniscript::MiniscriptContext MsContext() const {
+ return m_script_ctx;
+ }
};
/** A class that encapsulates all signing/hash revealing operations. */
struct Satisfier : public KeyConverter {
+
+ Satisfier(miniscript::MiniscriptContext ctx) noexcept : KeyConverter{ctx} {}
+
//! Which keys/timelocks/hash preimages are available.
std::set<Challenge> supported;
@@ -178,9 +215,15 @@ struct Satisfier : public KeyConverter {
//! Produce a signature for the given key.
miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
if (supported.count(Challenge(ChallengeType::PK, ChallengeNumber(key)))) {
- auto it = g_testdata->signatures.find(key);
- if (it == g_testdata->signatures.end()) return miniscript::Availability::NO;
- sig = it->second;
+ if (!miniscript::IsTapscript(m_script_ctx)) {
+ auto it = g_testdata->signatures.find(key);
+ if (it == g_testdata->signatures.end()) return miniscript::Availability::NO;
+ sig = it->second;
+ } else {
+ auto it = g_testdata->schnorr_signatures.find(XOnlyPubKey{key});
+ if (it == g_testdata->schnorr_signatures.end()) return miniscript::Availability::NO;
+ sig = it->second;
+ }
return miniscript::Availability::YES;
}
return miniscript::Availability::NO;
@@ -226,6 +269,14 @@ public:
return sig == it->second;
}
+ bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion,
+ ScriptExecutionData&, ScriptError*) const override {
+ XOnlyPubKey pk{pubkey};
+ auto it = g_testdata->schnorr_signatures.find(pk);
+ if (it == g_testdata->schnorr_signatures.end()) return false;
+ return sig == it->second;
+ }
+
bool CheckLockTime(const CScriptNum& locktime) const override {
// Delegate to Satisfier.
return ctx.CheckAfter(locktime.GetInt64());
@@ -237,8 +288,8 @@ public:
}
};
-//! Singleton instance of KeyConverter.
-const KeyConverter CONVERTER{};
+//! Public key to be used as internal key for dummy Taproot spends.
+const std::vector<unsigned char> NUMS_PK{ParseHex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
using Fragment = miniscript::Fragment;
using NodeRef = miniscript::NodeRef<CPubKey>;
@@ -271,37 +322,66 @@ std::set<Challenge> FindChallenges(const NodeRef& ref) {
return chal;
}
+//! The spk for this script under the given context. If it's a Taproot output also record the spend data.
+CScript ScriptPubKey(miniscript::MiniscriptContext ctx, const CScript& script, TaprootBuilder& builder)
+{
+ if (!miniscript::IsTapscript(ctx)) return CScript() << OP_0 << WitnessV0ScriptHash(script);
+
+ // For Taproot outputs we always use a tree with a single script and a dummy internal key.
+ builder.Add(0, script, TAPROOT_LEAF_TAPSCRIPT);
+ builder.Finalize(XOnlyPubKey{NUMS_PK});
+ return GetScriptForDestination(builder.GetOutput());
+}
+
+//! Fill the witness with the data additional to the script satisfaction.
+void SatisfactionToWitness(miniscript::MiniscriptContext ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
+ // For P2WSH, it's only the witness script.
+ witness.stack.emplace_back(script.begin(), script.end());
+ if (!miniscript::IsTapscript(ctx)) return;
+ // For Tapscript we also need the control block.
+ witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
+}
+
/** Run random satisfaction tests. */
-void TestSatisfy(const std::string& testcase, const NodeRef& node) {
- auto script = node->ToScript(CONVERTER);
+void TestSatisfy(const KeyConverter& converter, const std::string& testcase, const NodeRef& node) {
+ auto script = node->ToScript(converter);
auto challenges = FindChallenges(node); // Find all challenges in the generated miniscript.
std::vector<Challenge> challist(challenges.begin(), challenges.end());
for (int iter = 0; iter < 3; ++iter) {
Shuffle(challist.begin(), challist.end(), g_insecure_rand_ctx);
- Satisfier satisfier;
+ Satisfier satisfier(converter.MsContext());
TestSignatureChecker checker(satisfier);
bool prev_mal_success = false, prev_nonmal_success = false;
// Go over all challenges involved in this miniscript in random order.
for (int add = -1; add < (int)challist.size(); ++add) {
if (add >= 0) satisfier.supported.insert(challist[add]); // The first iteration does not add anything
+ // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
+ TaprootBuilder builder;
+ const CScript script_pubkey{ScriptPubKey(converter.MsContext(), script, builder)};
+
// Run malleable satisfaction algorithm.
- const CScript script_pubkey = CScript() << OP_0 << WitnessV0ScriptHash(script);
CScriptWitness witness_mal;
const bool mal_success = node->Satisfy(satisfier, witness_mal.stack, false) == miniscript::Availability::YES;
- witness_mal.stack.push_back(std::vector<unsigned char>(script.begin(), script.end()));
+ SatisfactionToWitness(converter.MsContext(), witness_mal, script, builder);
// Run non-malleable satisfaction algorithm.
CScriptWitness witness_nonmal;
const bool nonmal_success = node->Satisfy(satisfier, witness_nonmal.stack, true) == miniscript::Availability::YES;
- witness_nonmal.stack.push_back(std::vector<unsigned char>(script.begin(), script.end()));
+ // Compute witness size (excluding script push, control block, and witness count encoding).
+ const size_t wit_size = GetSerializeSize(witness_nonmal.stack, PROTOCOL_VERSION) - GetSizeOfCompactSize(witness_nonmal.stack.size());
+ SatisfactionToWitness(converter.MsContext(), witness_nonmal, script, builder);
if (nonmal_success) {
- // Non-malleable satisfactions are bounded by GetStackSize().
- BOOST_CHECK(witness_nonmal.stack.size() <= *node->GetStackSize() + 1);
+ // Non-malleable satisfactions are bounded by the satisfaction size plus:
+ // - For P2WSH spends, the witness script
+ // - For Tapscript spends, both the witness script and the control block
+ const size_t max_stack_size{*node->GetStackSize() + 1 + miniscript::IsTapscript(converter.MsContext())};
+ BOOST_CHECK(witness_nonmal.stack.size() <= max_stack_size);
// If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
BOOST_CHECK(mal_success);
BOOST_CHECK(witness_nonmal.stack == witness_mal.stack);
+ assert(wit_size <= *node->GetWitnessSize());
// Test non-malleable satisfaction.
ScriptError serror;
@@ -351,37 +431,66 @@ void TestSatisfy(const std::string& testcase, const NodeRef& node) {
}
enum TestMode : int {
+ //! Invalid under any context
TESTMODE_INVALID = 0,
+ //! Valid under any context unless overridden
TESTMODE_VALID = 1,
TESTMODE_NONMAL = 2,
TESTMODE_NEEDSIG = 4,
- TESTMODE_TIMELOCKMIX = 8
+ TESTMODE_TIMELOCKMIX = 8,
+ //! Invalid only under P2WSH context
+ TESTMODE_P2WSH_INVALID = 16,
+ //! Invalid only under Tapscript context
+ TESTMODE_TAPSCRIPT_INVALID = 32,
};
-void Test(const std::string& ms, const std::string& hexscript, int mode, int opslimit = -1, int stacklimit = -1, std::optional<uint32_t> max_wit_size = std::nullopt)
+void Test(const std::string& ms, const std::string& hexscript, int mode, const KeyConverter& converter,
+ int opslimit = -1, int stacklimit = -1, std::optional<uint32_t> max_wit_size = std::nullopt,
+ std::optional<uint32_t> stack_exec = {})
{
- auto node = miniscript::FromString(ms, CONVERTER);
- if (mode == TESTMODE_INVALID) {
+ auto node = miniscript::FromString(ms, converter);
+ const bool is_tapscript{miniscript::IsTapscript(converter.MsContext())};
+ if (mode == TESTMODE_INVALID || ((mode & TESTMODE_P2WSH_INVALID) && !is_tapscript) || ((mode & TESTMODE_TAPSCRIPT_INVALID) && is_tapscript)) {
BOOST_CHECK_MESSAGE(!node || !node->IsValid(), "Unexpectedly valid: " + ms);
} else {
BOOST_CHECK_MESSAGE(node, "Unparseable: " + ms);
BOOST_CHECK_MESSAGE(node->IsValid(), "Invalid: " + ms);
BOOST_CHECK_MESSAGE(node->IsValidTopLevel(), "Invalid top level: " + ms);
- auto computed_script = node->ToScript(CONVERTER);
+ auto computed_script = node->ToScript(converter);
BOOST_CHECK_MESSAGE(node->ScriptSize() == computed_script.size(), "Script size mismatch: " + ms);
if (hexscript != "?") BOOST_CHECK_MESSAGE(HexStr(computed_script) == hexscript, "Script mismatch: " + ms + " (" + HexStr(computed_script) + " vs " + hexscript + ")");
BOOST_CHECK_MESSAGE(node->IsNonMalleable() == !!(mode & TESTMODE_NONMAL), "Malleability mismatch: " + ms);
BOOST_CHECK_MESSAGE(node->NeedsSignature() == !!(mode & TESTMODE_NEEDSIG), "Signature necessity mismatch: " + ms);
BOOST_CHECK_MESSAGE((node->GetType() << "k"_mst) == !(mode & TESTMODE_TIMELOCKMIX), "Timelock mix mismatch: " + ms);
- auto inferred_miniscript = miniscript::FromScript(computed_script, CONVERTER);
+ auto inferred_miniscript = miniscript::FromScript(computed_script, converter);
BOOST_CHECK_MESSAGE(inferred_miniscript, "Cannot infer miniscript from script: " + ms);
- BOOST_CHECK_MESSAGE(inferred_miniscript->ToScript(CONVERTER) == computed_script, "Roundtrip failure: miniscript->script != miniscript->script->miniscript->script: " + ms);
+ BOOST_CHECK_MESSAGE(inferred_miniscript->ToScript(converter) == computed_script, "Roundtrip failure: miniscript->script != miniscript->script->miniscript->script: " + ms);
if (opslimit != -1) BOOST_CHECK_MESSAGE((int)*node->GetOps() == opslimit, "Ops limit mismatch: " << ms << " (" << *node->GetOps() << " vs " << opslimit << ")");
if (stacklimit != -1) BOOST_CHECK_MESSAGE((int)*node->GetStackSize() == stacklimit, "Stack limit mismatch: " << ms << " (" << *node->GetStackSize() << " vs " << stacklimit << ")");
if (max_wit_size) BOOST_CHECK_MESSAGE(*node->GetWitnessSize() == *max_wit_size, "Witness size limit mismatch: " << ms << " (" << *node->GetWitnessSize() << " vs " << *max_wit_size << ")");
- TestSatisfy(ms, node);
+ if (stack_exec) BOOST_CHECK_MESSAGE(*node->GetExecStackSize() == *stack_exec, "Stack execution limit mismatch: " << ms << " (" << *node->GetExecStackSize() << " vs " << *stack_exec << ")");
+ TestSatisfy(converter, ms, node);
}
}
+
+void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode,
+ int opslimit, int stacklimit, std::optional<uint32_t> max_wit_size,
+ std::optional<uint32_t> max_tap_wit_size,
+ std::optional<uint32_t> stack_exec)
+{
+ KeyConverter wsh_converter(miniscript::MiniscriptContext::P2WSH);
+ Test(ms, hexscript, mode, wsh_converter, opslimit, stacklimit, max_wit_size, stack_exec);
+ KeyConverter tap_converter(miniscript::MiniscriptContext::TAPSCRIPT);
+ Test(ms, hextapscript == "=" ? hexscript : hextapscript, mode, tap_converter, opslimit, stacklimit, max_tap_wit_size, stack_exec);
+}
+
+void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode)
+{
+ Test(ms, hexscript, hextapscript, mode,
+ /*opslimit=*/-1, /*stacklimit=*/-1,
+ /*max_wit_size=*/std::nullopt, /*max_tap_wit_size=*/std::nullopt, /*stack_exec=*/std::nullopt);
+}
+
} // namespace
BOOST_FIXTURE_TEST_SUITE(miniscript_tests, BasicTestingSetup)
@@ -391,114 +500,169 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
g_testdata.reset(new TestData());
// Validity rules
- Test("l:older(1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(1): valid
- Test("l:older(0)", "?", TESTMODE_INVALID); // older(0): k must be at least 1
- Test("l:older(2147483647)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(2147483647): valid
- Test("l:older(2147483648)", "?", TESTMODE_INVALID); // older(2147483648): k must be below 2^31
- Test("u:after(1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(1): valid
- Test("u:after(0)", "?", TESTMODE_INVALID); // after(0): k must be at least 1
- Test("u:after(2147483647)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(2147483647): valid
- Test("u:after(2147483648)", "?", TESTMODE_INVALID); // after(2147483648): k must be below 2^31
- Test("andor(0,1,1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,B,B): valid
- Test("andor(a:0,1,1)", "?", TESTMODE_INVALID); // andor(Wdu,B,B): X must be B
- Test("andor(0,a:1,a:1)", "?", TESTMODE_INVALID); // andor(Bdu,W,W): Y and Z must be B/V/K
- Test("andor(1,1,1)", "?", TESTMODE_INVALID); // andor(Bu,B,B): X must be d
- Test("andor(n:or_i(0,after(1)),1,1)", "?", TESTMODE_VALID); // andor(Bdu,B,B): valid
- Test("andor(or_i(0,after(1)),1,1)", "?", TESTMODE_INVALID); // andor(Bd,B,B): X must be u
- Test("c:andor(0,pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // andor(Bdu,K,K): valid
- Test("t:andor(0,v:1,v:1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,V,V): valid
- Test("and_v(v:1,1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,B): valid
- Test("t:and_v(v:1,v:1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,V): valid
- Test("c:and_v(v:1,pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // and_v(V,K): valid
- Test("and_v(1,1)", "?", TESTMODE_INVALID); // and_v(B,B): X must be V
- Test("and_v(pk_k(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),1)", "?", TESTMODE_INVALID); // and_v(K,B): X must be V
- Test("and_v(v:1,a:1)", "?", TESTMODE_INVALID); // and_v(K,W): Y must be B/V/K
- Test("and_b(1,a:1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_b(B,W): valid
- Test("and_b(1,1)", "?", TESTMODE_INVALID); // and_b(B,B): Y must W
- Test("and_b(v:1,a:1)", "?", TESTMODE_INVALID); // and_b(V,W): X must be B
- Test("and_b(a:1,a:1)", "?", TESTMODE_INVALID); // and_b(W,W): X must be B
- Test("and_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:1)", "?", TESTMODE_INVALID); // and_b(K,W): X must be B
- Test("or_b(0,a:0)", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_b(Bd,Wd): valid
- Test("or_b(1,a:0)", "?", TESTMODE_INVALID); // or_b(B,Wd): X must be d
- Test("or_b(0,a:1)", "?", TESTMODE_INVALID); // or_b(Bd,W): Y must be d
- Test("or_b(0,0)", "?", TESTMODE_INVALID); // or_b(Bd,Bd): Y must W
- Test("or_b(v:0,a:0)", "?", TESTMODE_INVALID); // or_b(V,Wd): X must be B
- Test("or_b(a:0,a:0)", "?", TESTMODE_INVALID); // or_b(Wd,Wd): X must be B
- Test("or_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:0)", "?", TESTMODE_INVALID); // or_b(Kd,Wd): X must be B
- Test("t:or_c(0,v:1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_c(Bdu,V): valid
- Test("t:or_c(a:0,v:1)", "?", TESTMODE_INVALID); // or_c(Wdu,V): X must be B
- Test("t:or_c(1,v:1)", "?", TESTMODE_INVALID); // or_c(Bu,V): X must be d
- Test("t:or_c(n:or_i(0,after(1)),v:1)", "?", TESTMODE_VALID); // or_c(Bdu,V): valid
- Test("t:or_c(or_i(0,after(1)),v:1)", "?", TESTMODE_INVALID); // or_c(Bd,V): X must be u
- Test("t:or_c(0,1)", "?", TESTMODE_INVALID); // or_c(Bdu,B): Y must be V
- Test("or_d(0,1)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_d(Bdu,B): valid
- Test("or_d(a:0,1)", "?", TESTMODE_INVALID); // or_d(Wdu,B): X must be B
- Test("or_d(1,1)", "?", TESTMODE_INVALID); // or_d(Bu,B): X must be d
- Test("or_d(n:or_i(0,after(1)),1)", "?", TESTMODE_VALID); // or_d(Bdu,B): valid
- Test("or_d(or_i(0,after(1)),1)", "?", TESTMODE_INVALID); // or_d(Bd,B): X must be u
- Test("or_d(0,v:1)", "?", TESTMODE_INVALID); // or_d(Bdu,V): Y must be B
- Test("or_i(1,1)", "?", TESTMODE_VALID); // or_i(B,B): valid
- Test("t:or_i(v:1,v:1)", "?", TESTMODE_VALID); // or_i(V,V): valid
- Test("c:or_i(pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_i(K,K): valid
- Test("or_i(a:1,a:1)", "?", TESTMODE_INVALID); // or_i(W,W): X and Y must be B/V/K
- Test("or_b(l:after(100),al:after(1000000000))", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
- Test("and_b(after(100),a:after(1000000000))", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
- Test("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_k
- Test("pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "76a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_h
-
+ Test("l:older(1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(1): valid
+ Test("l:older(0)", "?", "?", TESTMODE_INVALID); // older(0): k must be at least 1
+ Test("l:older(2147483647)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(2147483647): valid
+ Test("l:older(2147483648)", "?", "?", TESTMODE_INVALID); // older(2147483648): k must be below 2^31
+ Test("u:after(1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(1): valid
+ Test("u:after(0)", "?", "?", TESTMODE_INVALID); // after(0): k must be at least 1
+ Test("u:after(2147483647)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(2147483647): valid
+ Test("u:after(2147483648)", "?", "?", TESTMODE_INVALID); // after(2147483648): k must be below 2^31
+ Test("andor(0,1,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,B,B): valid
+ Test("andor(a:0,1,1)", "?", "?", TESTMODE_INVALID); // andor(Wdu,B,B): X must be B
+ Test("andor(0,a:1,a:1)", "?", "?", TESTMODE_INVALID); // andor(Bdu,W,W): Y and Z must be B/V/K
+ Test("andor(1,1,1)", "?", "?", TESTMODE_INVALID); // andor(Bu,B,B): X must be d
+ Test("andor(n:or_i(0,after(1)),1,1)", "?", "?", TESTMODE_VALID); // andor(Bdu,B,B): valid
+ Test("andor(or_i(0,after(1)),1,1)", "?", "?", TESTMODE_INVALID); // andor(Bd,B,B): X must be u
+ Test("c:andor(0,pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // andor(Bdu,K,K): valid
+ Test("t:andor(0,v:1,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,V,V): valid
+ Test("and_v(v:1,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,B): valid
+ Test("t:and_v(v:1,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,V): valid
+ Test("c:and_v(v:1,pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // and_v(V,K): valid
+ Test("and_v(1,1)", "?", "?", TESTMODE_INVALID); // and_v(B,B): X must be V
+ Test("and_v(pk_k(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),1)", "?", "?", TESTMODE_INVALID); // and_v(K,B): X must be V
+ Test("and_v(v:1,a:1)", "?", "?", TESTMODE_INVALID); // and_v(K,W): Y must be B/V/K
+ Test("and_b(1,a:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_b(B,W): valid
+ Test("and_b(1,1)", "?", "?", TESTMODE_INVALID); // and_b(B,B): Y must W
+ Test("and_b(v:1,a:1)", "?", "?", TESTMODE_INVALID); // and_b(V,W): X must be B
+ Test("and_b(a:1,a:1)", "?", "?", TESTMODE_INVALID); // and_b(W,W): X must be B
+ Test("and_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:1)", "?", "?", TESTMODE_INVALID); // and_b(K,W): X must be B
+ Test("or_b(0,a:0)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_b(Bd,Wd): valid
+ Test("or_b(1,a:0)", "?", "?", TESTMODE_INVALID); // or_b(B,Wd): X must be d
+ Test("or_b(0,a:1)", "?", "?", TESTMODE_INVALID); // or_b(Bd,W): Y must be d
+ Test("or_b(0,0)", "?", "?", TESTMODE_INVALID); // or_b(Bd,Bd): Y must W
+ Test("or_b(v:0,a:0)", "?", "?", TESTMODE_INVALID); // or_b(V,Wd): X must be B
+ Test("or_b(a:0,a:0)", "?", "?", TESTMODE_INVALID); // or_b(Wd,Wd): X must be B
+ Test("or_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:0)", "?", "?", TESTMODE_INVALID); // or_b(Kd,Wd): X must be B
+ Test("t:or_c(0,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_c(Bdu,V): valid
+ Test("t:or_c(a:0,v:1)", "?", "?", TESTMODE_INVALID); // or_c(Wdu,V): X must be B
+ Test("t:or_c(1,v:1)", "?", "?", TESTMODE_INVALID); // or_c(Bu,V): X must be d
+ Test("t:or_c(n:or_i(0,after(1)),v:1)", "?", "?", TESTMODE_VALID); // or_c(Bdu,V): valid
+ Test("t:or_c(or_i(0,after(1)),v:1)", "?", "?", TESTMODE_INVALID); // or_c(Bd,V): X must be u
+ Test("t:or_c(0,1)", "?", "?", TESTMODE_INVALID); // or_c(Bdu,B): Y must be V
+ Test("or_d(0,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_d(Bdu,B): valid
+ Test("or_d(a:0,1)", "?", "?", TESTMODE_INVALID); // or_d(Wdu,B): X must be B
+ Test("or_d(1,1)", "?", "?", TESTMODE_INVALID); // or_d(Bu,B): X must be d
+ Test("or_d(n:or_i(0,after(1)),1)", "?", "?", TESTMODE_VALID); // or_d(Bdu,B): valid
+ Test("or_d(or_i(0,after(1)),1)", "?", "?", TESTMODE_INVALID); // or_d(Bd,B): X must be u
+ Test("or_d(0,v:1)", "?", "?", TESTMODE_INVALID); // or_d(Bdu,V): Y must be B
+ Test("or_i(1,1)", "?", "?", TESTMODE_VALID); // or_i(B,B): valid
+ Test("t:or_i(v:1,v:1)", "?", "?", TESTMODE_VALID); // or_i(V,V): valid
+ Test("c:or_i(pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_i(K,K): valid
+ Test("or_i(a:1,a:1)", "?", "?", TESTMODE_INVALID); // or_i(W,W): X and Y must be B/V/K
+ Test("or_b(l:after(100),al:after(1000000000))", "?", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
+ Test("and_b(after(100),a:after(1000000000))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
+ Test("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_k
+ Test("pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "76a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac", "76a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_h
// Randomly generated test set that covers the majority of type and node type combinations
- Test("lltvln:after(1231488000)", "6300676300676300670400046749b1926869516868", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 3);
- Test("uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "6363829263522103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a21025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc52af0400046749b168670068670068", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 14, 5, 2 + 2 + 1 + 2 * 73);
- Test("or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16))", "63522103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee872921024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae926700686b63006760b2686c9b", TESTMODE_VALID, 14, 5, 2 + 1 + 2 * 73 + 2);
- Test("j:and_v(vdv:after(1567547623),older(2016))", "829263766304e7e06e5db169686902e007b268", TESTMODE_VALID | TESTMODE_NONMAL, 11, 1, 2);
- Test("t:and_v(vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5))", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 2 + 33 + 33);
- Test("t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2))", "532102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975562102e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1353ae6482012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2886703010040b2696851", TESTMODE_VALID | TESTMODE_NONMAL, 13, 5, 1 + 3 * 73);
- Test("or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000)))", "512102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f951ae73645321022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a0121032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f2103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a53ae7c630320a107b16700689b68", TESTMODE_VALID | TESTMODE_NONMAL, 15, 7, 2 + 1 + 3 * 73 + 1);
- Test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", TESTMODE_VALID, 16, 1, 33);
- Test("and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68))", "63522102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52103774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb52af67522103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a21025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc52af6882012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c6887", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 11, 5, 2 + 1 + 2 * 73 + 33);
- Test("j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898)))", "82926352210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae7c6351b26703e2e440b2689a68", TESTMODE_VALID | TESTMODE_NEEDSIG, 14, 4, 1 + 2 * 73 + 2);
- Test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", TESTMODE_VALID, 12, 1, 33);
- Test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", TESTMODE_VALID, 16, 2, 33 + 33);
- Test("and_b(hash256(32ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac),a:and_b(hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),a:older(1)))", "82012088aa2032ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac876b82012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876b51b26c9a6c9a", TESTMODE_VALID | TESTMODE_NONMAL, 15, 2, 33 + 33);
- Test("thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", "522103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c721036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0052ae6b5121036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0051ae6c936b21022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ac6c935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 13, 6, 1 + 2 * 73 + 1 + 73 + 1);
- Test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", TESTMODE_VALID, 14, 2, 33 + 2);
- Test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", TESTMODE_VALID, 15, 2, 1 + 33);
- Test("c:and_v(or_c(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764512102c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db51af682103acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeac", TESTMODE_VALID | TESTMODE_NEEDSIG, 8, 2, 33 + 73);
- Test("c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(1b0f3c404d12075c68c938f9f60ebea4f74941a0)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "5221036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a002102352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d552ae6482012088a6141b0f3c404d12075c68c938f9f60ebea4f74941a088682103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 10, 5, 1 + 2 * 73 + 73);
- Test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", TESTMODE_VALID, 14, 2, 33 + 33);
- Test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", TESTMODE_VALID, 20, 2, 33 + 33);
- Test("or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946))", "630320a107b1692102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", TESTMODE_VALID | TESTMODE_NONMAL, 10, 2, 2 + 73);
- Test("thresh(2,c:pk_h(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),a:hash160(dd69735817e0e3f6f826a9238dc2e291184f0131))", "76a9145dedfbf9ea599dd4e3ca6a80b333c472fd0b3f6988ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", TESTMODE_VALID, 18, 4, 1 + 34 + 33 + 33);
- Test("and_n(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),uc:and_v(v:older(144),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce)))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b2692103fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", TESTMODE_VALID | TESTMODE_NEEDSIG, 13, 3, 33 + 2 + 73);
- Test("and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))", "2103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TIMELOCKMIX, 12, 2, 73 + 1);
- Test("c:or_i(and_v(v:older(16),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)),pk_h(026a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4))", "6360b26976a9149fc5dbe5efdce10374a4dd4053c93af540211718886776a9142fbd32c8dd59ee7c17e66cb6ebea7e9846c3040f8868ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 12, 3, 2 + 34 + 73);
- Test("or_d(c:pk_h(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623)))", "76a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac736421024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", TESTMODE_VALID | TESTMODE_NONMAL, 13, 3, 1 + 34 + 73);
- Test("c:andor(ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),and_v(v:hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),pk_h(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a)))", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914dd100be7d9aea5721158ebde6d6a1fd8fff93bb1886776a9149fc5dbe5efdce10374a4dd4053c93af5402117188868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 18, 3, 33 + 34 + 73);
- Test("c:andor(u:ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)))", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a9149652d86bedf43ad264362e6e6eba6eb764508127886776a914751e76e8199196d454941c45d1b3a323f1433bd688686776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 23, 4, 2 + 33 + 34 + 73);
- Test("c:or_i(andor(c:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),pk_k(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", "6376a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac6476a91406afd46bcdfd22ef94ac122aa11f241244a37ecc886776a9149652d86bedf43ad264362e6e6eba6eb7645081278868672102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 17, 5, 2 + 34 + 73 + 34 + 73);
- Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", TESTMODE_VALID, 18, 3, 73 + 2 + 2);
- Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX, 22, 4, 73 + 73 + 2 + 2);
+ Test("lltvln:after(1231488000)", "6300676300676300670400046749b1926869516868", "=", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 3, 3, 3);
+ Test("uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "6363829263522103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a21025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc52af0400046749b168670068670068", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 2 + 1 + 2 * 73, 0, 7);
+ Test("or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16))", "63522103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee872921024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae926700686b63006760b2686c9b", "?", TESTMODE_VALID | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 1 + 2 * 73 + 2, 0, 8);
+ Test("j:and_v(vdv:after(1567547623),older(2016))", "829263766304e7e06e5db169686902e007b268", "=", TESTMODE_VALID | TESTMODE_NONMAL, 11, 1, 2, 2, 2);
+ Test("t:and_v(vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5))", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 2 + 33 + 33, 2 + 33 + 33, 4);
+ Test("t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2))", "532102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975562102e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1353ae6482012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2886703010040b2696851", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 13, 5, 1 + 3 * 73, 0, 10);
+ Test("or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000)))", "512102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f951ae73645321022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a0121032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f2103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a53ae7c630320a107b16700689b68", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 15, 7, 2 + 1 + 3 * 73 + 1, 0, 10);
+ Test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", TESTMODE_VALID, 16, 1, 33, 33, 3);
+ Test("and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68))", "63522102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52103774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb52af67522103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a21025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc52af6882012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c6887", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 11, 5, 2 + 1 + 2 * 73 + 33, 0, 8);
+ Test("j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898)))", "82926352210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae7c6351b26703e2e440b2689a68", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 4, 1 + 2 * 73 + 2, 0, 8);
+ Test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", "=", TESTMODE_VALID, 12, 1, 33, 33, 4);
+ Test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", "=", TESTMODE_VALID, 16, 2, 33 + 33, 33 + 33, 4);
+ Test("and_b(hash256(32ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac),a:and_b(hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),a:older(1)))", "82012088aa2032ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac876b82012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876b51b26c9a6c9a", "=", TESTMODE_VALID | TESTMODE_NONMAL, 15, 2, 33 + 33, 33 + 33, 4);
+ Test("thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", "522103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c721036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0052ae6b5121036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0051ae6c936b21022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ac6c935287", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 13, 6, 1 + 2 * 73 + 1 + 73 + 1, 0, 10);
+ Test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", "=", TESTMODE_VALID, 14, 2, 33 + 2, 33 + 2, 4);
+ Test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", "=", TESTMODE_VALID, 15, 2, 1 + 33, 1 + 33, 3);
+ Test("c:and_v(or_c(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764512102c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db51af682103acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeac", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 8, 2, 33 + 73, 0, 4);
+ Test("c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(1b0f3c404d12075c68c938f9f60ebea4f74941a0)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "5221036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a002102352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d552ae6482012088a6141b0f3c404d12075c68c938f9f60ebea4f74941a088682103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 10, 5, 1 + 2 * 73 + 73, 0, 9);
+ Test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", "=", TESTMODE_VALID, 14, 2, 33 + 33, 33 + 33, 4);
+ Test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", "=", TESTMODE_VALID, 20, 2, 33 + 33, 33 + 33, 4);
+ Test("or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946))", "630320a107b1692102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", "630320a107b16920c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", TESTMODE_VALID | TESTMODE_NONMAL, 10, 2, 2 + 73, 2 + 66, 3);
+ Test("thresh(2,c:pk_h(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),a:hash160(dd69735817e0e3f6f826a9238dc2e291184f0131))", "76a9145dedfbf9ea599dd4e3ca6a80b333c472fd0b3f6988ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", "76a9141a7ac36cfa8431ab2395d701b0050045ae4a37d188ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", TESTMODE_VALID, 18, 4, 1 + 34 + 33 + 33, 1 + 33 + 33 + 33, 6);
+ Test("and_n(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),uc:and_v(v:older(144),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce)))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b2692103fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b26920fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", TESTMODE_VALID | TESTMODE_NEEDSIG, 13, 3, 33 + 2 + 73, 33 + 2 + 66, 5);
+ Test("and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))", "2103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", "20daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TIMELOCKMIX, 12, 2, 73 + 1, 66 + 1, 3);
+ Test("c:or_i(and_v(v:older(16),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)),pk_h(026a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4))", "6360b26976a9149fc5dbe5efdce10374a4dd4053c93af540211718886776a9142fbd32c8dd59ee7c17e66cb6ebea7e9846c3040f8868ac", "6360b26976a9144d4421361c3289bdad06441ffaee8be8e786f1ad886776a91460d4a7bcbd08f58e58bd208d1069837d7adb16ae8868ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 12, 3, 2 + 34 + 73, 2 + 33 + 66, 4);
+ Test("or_d(c:pk_h(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623)))", "76a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac736421024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", "76a91421ab1a140d0d305b8ff62bdb887d9fef82c9899e88ac7364204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", TESTMODE_VALID | TESTMODE_NONMAL, 13, 3, 1 + 34 + 73, 1 + 33 + 66, 5);
+ Test("c:andor(ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),and_v(v:hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),pk_h(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a)))", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914dd100be7d9aea5721158ebde6d6a1fd8fff93bb1886776a9149fc5dbe5efdce10374a4dd4053c93af5402117188868ac", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914a63d1e4d2ed109246c600ec8c19cce546b65b1cc886776a9144d4421361c3289bdad06441ffaee8be8e786f1ad8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 18, 3, 33 + 34 + 73, 33 + 33 + 66, 5);
+ Test("c:andor(u:ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)))", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a9149652d86bedf43ad264362e6e6eba6eb764508127886776a914751e76e8199196d454941c45d1b3a323f1433bd688686776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a914ceedcb44b38bdbcb614d872223964fd3dca8a434886776a914f678d9b79045452c8c64e9309d0f0046056e26c588686776a914a2a75e1819afa208f6c89ae0da43021116dfcb0c8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 23, 4, 2 + 33 + 34 + 73, 2 + 33 + 33 + 66, 5);
+ Test("c:or_i(andor(c:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),pk_k(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", "6376a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac6476a91406afd46bcdfd22ef94ac122aa11f241244a37ecc886776a9149652d86bedf43ad264362e6e6eba6eb7645081278868672102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", "6376a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac6476a9149b652a14674a506079f574d20ca7daef6f9a66bb886776a914ceedcb44b38bdbcb614d872223964fd3dca8a43488686720d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 17, 5, 2 + 34 + 73 + 34 + 73, 2 + 33 + 66 + 33 + 66, 6);
+ Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", TESTMODE_VALID, 18, 3, 73 + 2 + 2, 66 + 2 + 2, 4);
+ Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX, 22, 4, 73 + 73 + 2 + 2, 66 + 66 + 2 + 2, 5);
+
+ // Additional Tapscript-related tests
+ // Edge cases when parsing multi_a from script:
+ // - no pubkey at all
+ // - no pubkey before a CHECKSIGADD
+ // - no pubkey before the CHECKSIG
+ constexpr KeyConverter tap_converter{miniscript::MiniscriptContext::TAPSCRIPT};
+ constexpr KeyConverter wsh_converter{miniscript::MiniscriptContext::P2WSH};
+ const auto no_pubkey{ParseHex("ac519c")};
+ BOOST_CHECK(miniscript::FromScript({no_pubkey.begin(), no_pubkey.end()}, tap_converter) == nullptr);
+ const auto incomplete_multi_a{ParseHex("ba20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
+ BOOST_CHECK(miniscript::FromScript({incomplete_multi_a.begin(), incomplete_multi_a.end()}, tap_converter) == nullptr);
+ const auto incomplete_multi_a_2{ParseHex("ac2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
+ BOOST_CHECK(miniscript::FromScript({incomplete_multi_a_2.begin(), incomplete_multi_a_2.end()}, tap_converter) == nullptr);
+ // Can use multi_a under Tapscript but not P2WSH.
+ Test("and_v(v:multi_a(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "?", "20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aac205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba529d0400046749b1", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4, 2, {}, {}, 3);
+ // Can use more than 20 keys in a multi_a.
+ std::string ms_str_multi_a{"multi_a(1,"};
+ for (size_t i = 0; i < 21; ++i) {
+ ms_str_multi_a += HexStr(g_testdata->pubkeys[i]);
+ if (i < 20) ms_str_multi_a += ",";
+ }
+ ms_str_multi_a += ")";
+ Test(ms_str_multi_a, "?", "2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba20f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ba20e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13ba202f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4ba20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ba205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcba202f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ba20acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeba20a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ba20774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cbba20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aba20f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8ba20499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4ba20d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080eba20e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0aba20defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34ba205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba202b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6cba204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ba20352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5ba519c", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 22, 21, {}, {}, 22);
+ // Since 'd:' is 'u' we can use it directly inside a thresh. But we can't under P2WSH.
+ Test("thresh(2,dv:older(42),s:pk(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "7663012ab269687c205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcac937c20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 12, 3, {}, {}, 4);
+ // We can have a script that has more than 201 ops (n = 99), that needs a stack size > 100 (n = 110), or has a
+ // script that is larger than 3600 bytes (n = 200). All that can't be under P2WSH.
+ for (const auto pk_count: {99, 110, 200}) {
+ std::string ms_str_large;
+ for (auto i = 0; i < pk_count - 1; ++i) {
+ ms_str_large += "and_b(pk(" + HexStr(g_testdata->pubkeys[i]) + "),a:";
+ }
+ ms_str_large += "pk(" + HexStr(g_testdata->pubkeys[pk_count - 1]) + ")";
+ ms_str_large.insert(ms_str_large.end(), pk_count - 1, ')');
+ Test(ms_str_large, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, pk_count + (pk_count - 1) * 3, pk_count, {}, {}, pk_count + 1);
+ }
+ // We can have a script that reaches a stack size of 1000 during execution.
+ std::string ms_stack_limit;
+ auto count{998};
+ for (auto i = 0; i < count; ++i) {
+ ms_stack_limit += "and_b(older(1),a:";
+ }
+ ms_stack_limit += "pk(" + HexStr(g_testdata->pubkeys[0]) + ")";
+ ms_stack_limit.insert(ms_stack_limit.end(), count, ')');
+ const auto ms_stack_ok{miniscript::FromString(ms_stack_limit, tap_converter)};
+ BOOST_CHECK(ms_stack_ok && ms_stack_ok->CheckStackSize());
+ Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
+ // But one more element on the stack during execution will make it fail. And we'd detect that.
+ count++;
+ ms_stack_limit = "and_b(older(1),a:" + ms_stack_limit + ")";
+ const auto ms_stack_nok{miniscript::FromString(ms_stack_limit, tap_converter)};
+ BOOST_CHECK(ms_stack_nok && !ms_stack_nok->CheckStackSize());
+ Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
// Misc unit tests
// A Script with a non minimal push is invalid
std::vector<unsigned char> nonminpush = ParseHex("0000210232780000feff00ffffffffffff21ff005f00ae21ae00000000060602060406564c2102320000060900fe00005f00ae21ae00100000060606060606000000000000000000000000000000000000000000000000000000000000000000");
const CScript nonminpush_script(nonminpush.begin(), nonminpush.end());
- BOOST_CHECK(miniscript::FromScript(nonminpush_script, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminpush_script, wsh_converter) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminpush_script, tap_converter) == nullptr);
// A non-minimal VERIFY (<key> CHECKSIG VERIFY 1)
std::vector<unsigned char> nonminverify = ParseHex("2103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ac6951");
const CScript nonminverify_script(nonminverify.begin(), nonminverify.end());
- BOOST_CHECK(miniscript::FromScript(nonminverify_script, CONVERTER) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminverify_script, wsh_converter) == nullptr);
+ BOOST_CHECK(miniscript::FromScript(nonminverify_script, tap_converter) == nullptr);
// A threshold as large as the number of subs is valid.
- Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
+ Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
// A threshold of 1 is valid.
- Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
+ Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
// A threshold with a k larger than the number of subs is invalid
- Test("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", TESTMODE_INVALID);
+ Test("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
// A threshold with a k null is invalid
- Test("thresh(0,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", TESTMODE_INVALID);
+ Test("thresh(0,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
// For CHECKMULTISIG the OP cost is the number of keys, but the stack size is the number of sigs (+1)
- const auto ms_multi = miniscript::FromString("multi(1,03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", CONVERTER);
+ const auto ms_multi = miniscript::FromString("multi(1,03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", wsh_converter);
BOOST_CHECK(ms_multi);
BOOST_CHECK_EQUAL(*ms_multi->GetOps(), 4); // 3 pubkeys + CMS
BOOST_CHECK_EQUAL(*ms_multi->GetStackSize(), 2); // 1 sig + dummy elem
@@ -509,47 +673,46 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
// Unfortunately, this rule is consensus for Taproot but only policy for P2WSH. Therefore we can't
// (for now) have 'd:' be 'u'. This tests we can't use a 'd:' wrapper for a thresh, which requires
// its subs to all be 'u' (taken from https://github.com/rust-bitcoin/rust-miniscript/discussions/341).
- const auto ms_minimalif = miniscript::FromString("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),sc:pk_k(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798),sdv:older(32))", CONVERTER);
+ const auto ms_minimalif = miniscript::FromString("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),sc:pk_k(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798),sdv:older(32))", wsh_converter);
BOOST_CHECK(ms_minimalif && !ms_minimalif->IsValid());
// A Miniscript with duplicate keys is not sane
- const auto ms_dup1 = miniscript::FromString("and_v(v:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", CONVERTER);
+ const auto ms_dup1 = miniscript::FromString("and_v(v:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
BOOST_CHECK(ms_dup1);
BOOST_CHECK(!ms_dup1->IsSane() && !ms_dup1->CheckDuplicateKey());
// Same with a disjunction, and different key nodes (pk and pkh)
- const auto ms_dup2 = miniscript::FromString("or_b(c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", CONVERTER);
+ const auto ms_dup2 = miniscript::FromString("or_b(c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
BOOST_CHECK(ms_dup2 && !ms_dup2->IsSane() && !ms_dup2->CheckDuplicateKey());
// Same when the duplicates are leaves or a larger tree
- const auto ms_dup3 = miniscript::FromString("or_i(and_b(pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)),and_b(older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", CONVERTER);
+ const auto ms_dup3 = miniscript::FromString("or_i(and_b(pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)),and_b(older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
BOOST_CHECK(ms_dup3 && !ms_dup3->IsSane() && !ms_dup3->CheckDuplicateKey());
// Same when the duplicates are on different levels in the tree
- const auto ms_dup4 = miniscript::FromString("thresh(2,pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),a:and_b(dv:older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", CONVERTER);
+ const auto ms_dup4 = miniscript::FromString("thresh(2,pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),a:and_b(dv:older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
BOOST_CHECK(ms_dup4 && !ms_dup4->IsSane() && !ms_dup4->CheckDuplicateKey());
// Sanity check the opposite is true, too. An otherwise sane Miniscript with no duplicate keys is sane.
- const auto ms_nondup = miniscript::FromString("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", CONVERTER);
+ const auto ms_nondup = miniscript::FromString("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", wsh_converter);
BOOST_CHECK(ms_nondup && ms_nondup->CheckDuplicateKey() && ms_nondup->IsSane());
// Test we find the first insane sub closer to be a leaf node. This fragment is insane for two reasons:
// 1. It can be spent without a signature
// 2. It contains timelock mixes
// We'll report the timelock mix error, as it's "deeper" (closer to be a leaf node) than the "no 's' property"
// error is.
- const auto ms_ins = miniscript::FromString("or_i(and_b(after(1),a:after(1000000000)),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", CONVERTER);
+ const auto ms_ins = miniscript::FromString("or_i(and_b(after(1),a:after(1000000000)),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", wsh_converter);
BOOST_CHECK(ms_ins && ms_ins->IsValid() && !ms_ins->IsSane());
const auto insane_sub = ms_ins->FindInsaneSub();
- BOOST_CHECK(insane_sub && *insane_sub->ToString(CONVERTER) == "and_b(after(1),a:after(1000000000))");
+ BOOST_CHECK(insane_sub && *insane_sub->ToString(wsh_converter) == "and_b(after(1),a:after(1000000000))");
// Timelock tests
- Test("after(100)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only heightlock
- Test("after(1000000000)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only timelock
- Test("or_b(l:after(100),al:after(1000000000))", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
- Test("and_b(after(100),a:after(1000000000))", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
+ Test("after(100)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only heightlock
+ Test("after(1000000000)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only timelock
+ Test("or_b(l:after(100),al:after(1000000000))", "?", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
+ Test("and_b(after(100),a:after(1000000000))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
/* This is correctly detected as non-malleable but for the wrong reason. The type system assumes that branches 1 and 2
can be spent together to create a non-malleble witness, but because of mixing of timelocks they cannot be spent together.
But since exactly one of the two after's can be satisfied, the witness involving the key cannot be malleated.
*/
- Test("thresh(2,ltv:after(1000000000),altv:after(100),a:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", TESTMODE_VALID | TESTMODE_TIMELOCKMIX | TESTMODE_NONMAL); // thresh with k = 2
+ Test("thresh(2,ltv:after(1000000000),altv:after(100),a:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "?", TESTMODE_VALID | TESTMODE_TIMELOCKMIX | TESTMODE_NONMAL); // thresh with k = 2
// This is actually non-malleable in practice, but we cannot detect it in type system. See above rationale
- Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "?", TESTMODE_VALID); // thresh with k = 1
-
+ Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "?", "?", TESTMODE_VALID); // thresh with k = 1
g_testdata.reset();
}
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 81b1283663..7c98c382e4 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -1088,9 +1088,9 @@ public:
bool reject{false};
auto msg = m_transport.GetReceivedMessage({}, reject);
if (reject) {
- ret.push_back(std::nullopt);
+ ret.emplace_back(std::nullopt);
} else {
- ret.push_back(std::move(msg));
+ ret.emplace_back(std::move(msg));
}
progress = true;
}
diff --git a/src/test/policy_fee_tests.cpp b/src/test/policy_fee_tests.cpp
index 25fb5343e3..29d70cb5f8 100644
--- a/src/test/policy_fee_tests.cpp
+++ b/src/test/policy_fee_tests.cpp
@@ -13,7 +13,8 @@ BOOST_AUTO_TEST_SUITE(policy_fee_tests)
BOOST_AUTO_TEST_CASE(FeeRounder)
{
- FeeFilterRounder fee_rounder{CFeeRate{1000}};
+ FastRandomContext rng{/*fDeterministic=*/true};
+ FeeFilterRounder fee_rounder{CFeeRate{1000}, rng};
// check that 1000 rounds to 974 or 1071
std::set<CAmount> results;
diff --git a/src/test/rbf_tests.cpp b/src/test/rbf_tests.cpp
index 10205cd641..fb6a3614c0 100644
--- a/src/test/rbf_tests.cpp
+++ b/src/test/rbf_tests.cpp
@@ -27,7 +27,7 @@ static inline CTransactionRef make_tx(const std::vector<CTransactionRef>& inputs
tx.vin[i].prevout.n = 0;
// Add a witness so wtxid != txid
CScriptWitness witness;
- witness.stack.push_back(std::vector<unsigned char>(i + 10));
+ witness.stack.emplace_back(i + 10);
tx.vin[i].scriptWitness = witness;
}
for (size_t i = 0; i < output_values.size(); ++i) {
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 4cad3ec68e..0d2460c606 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -428,11 +428,11 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
for (int64_t i = 0; i < 100; i++) {
- feerates.emplace_back(std::make_pair(1 ,1));
+ feerates.emplace_back(1 ,1);
}
for (int64_t i = 0; i < 100; i++) {
- feerates.emplace_back(std::make_pair(2 ,1));
+ feerates.emplace_back(2 ,1);
}
CalculatePercentilesByWeight(result, feerates, total_weight);
@@ -447,11 +447,11 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result2[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
feerates.clear();
- feerates.emplace_back(std::make_pair(1, 9));
- feerates.emplace_back(std::make_pair(2 , 16)); //10th + 25th percentile
- feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
- feerates.emplace_back(std::make_pair(5 ,10));
- feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
+ feerates.emplace_back(1, 9);
+ feerates.emplace_back(2 , 16); //10th + 25th percentile
+ feerates.emplace_back(4 ,50); //50th + 75th percentile
+ feerates.emplace_back(5 ,10);
+ feerates.emplace_back(9 ,15); // 90th percentile
CalculatePercentilesByWeight(result2, feerates, total_weight);
@@ -466,12 +466,12 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result3[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
feerates.clear();
- feerates.emplace_back(std::make_pair(1, 9));
- feerates.emplace_back(std::make_pair(2 , 11)); // 10th percentile
- feerates.emplace_back(std::make_pair(2 , 5)); // 25th percentile
- feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
- feerates.emplace_back(std::make_pair(5 ,10));
- feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
+ feerates.emplace_back(1, 9);
+ feerates.emplace_back(2 , 11); // 10th percentile
+ feerates.emplace_back(2 , 5); // 25th percentile
+ feerates.emplace_back(4 ,50); //50th + 75th percentile
+ feerates.emplace_back(5 ,10);
+ feerates.emplace_back(9 ,15); // 90th percentile
CalculatePercentilesByWeight(result3, feerates, total_weight);
@@ -486,11 +486,11 @@ BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
CAmount result4[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
feerates.clear();
- feerates.emplace_back(std::make_pair(1, 100));
- feerates.emplace_back(std::make_pair(2, 1));
- feerates.emplace_back(std::make_pair(3, 1));
- feerates.emplace_back(std::make_pair(3, 1));
- feerates.emplace_back(std::make_pair(999999, 1));
+ feerates.emplace_back(1, 100);
+ feerates.emplace_back(2, 1);
+ feerates.emplace_back(3, 1);
+ feerates.emplace_back(3, 1);
+ feerates.emplace_back(999999, 1);
CalculatePercentilesByWeight(result4, feerates, total_weight);
@@ -506,7 +506,7 @@ BOOST_AUTO_TEST_CASE(check_dup_param_names)
auto make_rpc = [](std::vector<std::tuple<std::string, ParamType>> param_names) {
std::vector<RPCArg> params;
std::vector<RPCArg> options;
- auto push_options = [&] { if (!options.empty()) params.emplace_back(RPCArg{strprintf("options%i", params.size()), RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", std::move(options)}); };
+ auto push_options = [&] { if (!options.empty()) params.emplace_back(strprintf("options%i", params.size()), RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", std::move(options)); };
for (auto& [param_name, param_type] : param_names) {
if (param_type == POSITIONAL) {
push_options();
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 94656b229e..624d0b2c12 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1637,6 +1637,37 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags)
BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_INVALID_FLAGS);
}
+/* Test bitcoinconsensus_verify_script returns spent outputs required err */
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_spent_outputs_required_err)
+{
+ unsigned int libconsensus_flags{bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT};
+ const int nIn{0};
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ bitcoinconsensus_error err;
+ int result{bitcoinconsensus_verify_script_with_spent_outputs(scriptPubKey.data(), scriptPubKey.size(), creditTx.vout[0].nValue, UCharCast(stream.data()), stream.size(), nullptr, 0, nIn, libconsensus_flags, &err)};
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+
+ result = bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), creditTx.vout[0].nValue, UCharCast(stream.data()), stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+
+ result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), UCharCast(stream.data()), stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED);
+}
+
#endif // defined(HAVE_CONSENSUS_LIB)
static std::vector<unsigned int> AllConsensusFlags()
@@ -1685,12 +1716,29 @@ static void AssetTest(const UniValue& test)
PrecomputedTransactionData txdata;
txdata.Init(tx, std::vector<CTxOut>(prevouts));
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, txdata);
+
+#if defined(HAVE_CONSENSUS_LIB)
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << tx;
+ std::vector<UTXO> utxos;
+ utxos.resize(prevouts.size());
+ for (size_t i = 0; i < prevouts.size(); i++) {
+ utxos[i].scriptPubKey = prevouts[i].scriptPubKey.data();
+ utxos[i].scriptPubKeySize = prevouts[i].scriptPubKey.size();
+ utxos[i].value = prevouts[i].nValue;
+ }
+#endif
+
for (const auto flags : ALL_CONSENSUS_FLAGS) {
// "final": true tests are valid for all flags. Others are only valid with flags that are
// a subset of test_flags.
if (fin || ((flags & test_flags) == flags)) {
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
BOOST_CHECK(ret);
+#if defined(HAVE_CONSENSUS_LIB)
+ int lib_ret = bitcoinconsensus_verify_script_with_spent_outputs(prevouts[idx].scriptPubKey.data(), prevouts[idx].scriptPubKey.size(), prevouts[idx].nValue, UCharCast(stream.data()), stream.size(), utxos.data(), utxos.size(), idx, flags, nullptr);
+ BOOST_CHECK(lib_ret == 1);
+#endif
}
}
}
@@ -1702,11 +1750,28 @@ static void AssetTest(const UniValue& test)
PrecomputedTransactionData txdata;
txdata.Init(tx, std::vector<CTxOut>(prevouts));
CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, txdata);
+
+#if defined(HAVE_CONSENSUS_LIB)
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << tx;
+ std::vector<UTXO> utxos;
+ utxos.resize(prevouts.size());
+ for (size_t i = 0; i < prevouts.size(); i++) {
+ utxos[i].scriptPubKey = prevouts[i].scriptPubKey.data();
+ utxos[i].scriptPubKeySize = prevouts[i].scriptPubKey.size();
+ utxos[i].value = prevouts[i].nValue;
+ }
+#endif
+
for (const auto flags : ALL_CONSENSUS_FLAGS) {
// If a test is supposed to fail with test_flags, it should also fail with any superset thereof.
if ((flags & test_flags) == test_flags) {
bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);
BOOST_CHECK(!ret);
+#if defined(HAVE_CONSENSUS_LIB)
+ int lib_ret = bitcoinconsensus_verify_script_with_spent_outputs(prevouts[idx].scriptPubKey.data(), prevouts[idx].scriptPubKey.size(), prevouts[idx].nValue, UCharCast(stream.data()), stream.size(), utxos.data(), utxos.size(), idx, flags, nullptr);
+ BOOST_CHECK(lib_ret == 0);
+#endif
}
}
}
diff --git a/src/test/settings_tests.cpp b/src/test/settings_tests.cpp
index eb11df0497..fa8ceb8dd6 100644
--- a/src/test/settings_tests.cpp
+++ b/src/test/settings_tests.cpp
@@ -119,16 +119,16 @@ static void CheckValues(const common::Settings& settings, const std::string& sin
BOOST_AUTO_TEST_CASE(Simple)
{
common::Settings settings;
- settings.command_line_options["name"].push_back("val1");
- settings.command_line_options["name"].push_back("val2");
- settings.ro_config["section"]["name"].push_back(2);
+ settings.command_line_options["name"].emplace_back("val1");
+ settings.command_line_options["name"].emplace_back("val2");
+ settings.ro_config["section"]["name"].emplace_back(2);
// The last given arg takes precedence when specified via commandline.
CheckValues(settings, R"("val2")", R"(["val1","val2",2])");
common::Settings settings2;
- settings2.ro_config["section"]["name"].push_back("val2");
- settings2.ro_config["section"]["name"].push_back("val3");
+ settings2.ro_config["section"]["name"].emplace_back("val2");
+ settings2.ro_config["section"]["name"].emplace_back("val3");
// The first given arg takes precedence when specified via config file.
CheckValues(settings2, R"("val2")", R"(["val2","val3"])");
@@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(Simple)
BOOST_AUTO_TEST_CASE(NullOverride)
{
common::Settings settings;
- settings.command_line_options["name"].push_back("value");
+ settings.command_line_options["name"].emplace_back("value");
BOOST_CHECK_EQUAL(R"("value")", GetSetting(settings, "section", "name", false, false, false).write().c_str());
settings.forced_settings["name"] = {};
BOOST_CHECK_EQUAL(R"(null)", GetSetting(settings, "section", "name", false, false, false).write().c_str());
@@ -202,11 +202,11 @@ BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
std::vector<common::SettingsValue>& dest) {
if (action == SET || action == SECTION_SET) {
for (int i = 0; i < 2; ++i) {
- dest.push_back(value_prefix + ToString(++value_suffix));
+ dest.emplace_back(value_prefix + ToString(++value_suffix));
desc += " " + name_prefix + name + "=" + dest.back().get_str();
}
} else if (action == NEGATE || action == SECTION_NEGATE) {
- dest.push_back(false);
+ dest.emplace_back(false);
desc += " " + name_prefix + "no" + name;
}
};
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 178b16772b..9653edd84b 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -100,7 +100,7 @@ void static RandomTransaction(CMutableTransaction& tx, bool fSingle)
int ins = (InsecureRandBits(2)) + 1;
int outs = fSingle ? ins : (InsecureRandBits(2)) + 1;
for (int in = 0; in < ins; in++) {
- tx.vin.push_back(CTxIn());
+ tx.vin.emplace_back();
CTxIn &txin = tx.vin.back();
txin.prevout.hash = InsecureRand256();
txin.prevout.n = InsecureRandBits(2);
@@ -108,7 +108,7 @@ void static RandomTransaction(CMutableTransaction& tx, bool fSingle)
txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : std::numeric_limits<uint32_t>::max();
}
for (int out = 0; out < outs; out++) {
- tx.vout.push_back(CTxOut());
+ tx.vout.emplace_back();
CTxOut &txout = tx.vout.back();
txout.nValue = InsecureRandMoneyAmount();
RandomScript(txout.scriptPubKey);
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index ec9490d745..c0bed50e1d 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -160,8 +160,8 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkey));
CScript scriptSig = CScript();
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
@@ -189,8 +189,8 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(ScriptHash(scriptSig));
scriptSig = CScript() << ToByteVector(scriptSig);
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
@@ -203,9 +203,9 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
CScript scriptSig = CScript();
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
- scriptWitness.stack.push_back(std::vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(witnessScript.begin(), witnessScript.end());
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
@@ -220,9 +220,9 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
CScript scriptSig = CScript() << ToByteVector(redeemScript);
CScriptWitness scriptWitness;
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
- scriptWitness.stack.push_back(std::vector<unsigned char>(0));
- scriptWitness.stack.push_back(std::vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(0);
+ scriptWitness.stack.emplace_back(witnessScript.begin(), witnessScript.end());
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
diff --git a/src/test/txpackage_tests.cpp b/src/test/txpackage_tests.cpp
index 571b58156f..4d9a5ef7f3 100644
--- a/src/test/txpackage_tests.cpp
+++ b/src/test/txpackage_tests.cpp
@@ -162,6 +162,7 @@ BOOST_FIXTURE_TEST_CASE(noncontextual_package_tests, TestChain100Setup)
BOOST_CHECK_EQUAL(state.GetResult(), PackageValidationResult::PCKG_POLICY);
BOOST_CHECK_EQUAL(state.GetRejectReason(), "package-not-sorted");
BOOST_CHECK(IsChildWithParents({tx_parent, tx_child}));
+ BOOST_CHECK(IsChildWithParentsTree({tx_parent, tx_child}));
}
// 24 Parents and 1 Child
@@ -172,9 +173,9 @@ BOOST_FIXTURE_TEST_CASE(noncontextual_package_tests, TestChain100Setup)
auto parent = MakeTransactionRef(CreateValidMempoolTransaction(m_coinbase_txns[i + 1],
0, 0, coinbaseKey, spk, CAmount(48 * COIN), false));
package.emplace_back(parent);
- child.vin.push_back(CTxIn(COutPoint(parent->GetHash(), 0)));
+ child.vin.emplace_back(COutPoint(parent->GetHash(), 0));
}
- child.vout.push_back(CTxOut(47 * COIN, spk2));
+ child.vout.emplace_back(47 * COIN, spk2);
// The child must be in the package.
BOOST_CHECK(!IsChildWithParents(package));
@@ -187,6 +188,7 @@ BOOST_FIXTURE_TEST_CASE(noncontextual_package_tests, TestChain100Setup)
PackageValidationState state;
BOOST_CHECK(CheckPackage(package, state));
BOOST_CHECK(IsChildWithParents(package));
+ BOOST_CHECK(IsChildWithParentsTree(package));
package.erase(package.begin());
BOOST_CHECK(IsChildWithParents(package));
@@ -199,26 +201,27 @@ BOOST_FIXTURE_TEST_CASE(noncontextual_package_tests, TestChain100Setup)
// 2 Parents and 1 Child where one parent depends on the other.
{
CMutableTransaction mtx_parent;
- mtx_parent.vin.push_back(CTxIn(COutPoint(m_coinbase_txns[0]->GetHash(), 0)));
- mtx_parent.vout.push_back(CTxOut(20 * COIN, spk));
- mtx_parent.vout.push_back(CTxOut(20 * COIN, spk2));
+ mtx_parent.vin.emplace_back(COutPoint(m_coinbase_txns[0]->GetHash(), 0));
+ mtx_parent.vout.emplace_back(20 * COIN, spk);
+ mtx_parent.vout.emplace_back(20 * COIN, spk2);
CTransactionRef tx_parent = MakeTransactionRef(mtx_parent);
CMutableTransaction mtx_parent_also_child;
- mtx_parent_also_child.vin.push_back(CTxIn(COutPoint(tx_parent->GetHash(), 0)));
- mtx_parent_also_child.vout.push_back(CTxOut(20 * COIN, spk));
+ mtx_parent_also_child.vin.emplace_back(COutPoint(tx_parent->GetHash(), 0));
+ mtx_parent_also_child.vout.emplace_back(20 * COIN, spk);
CTransactionRef tx_parent_also_child = MakeTransactionRef(mtx_parent_also_child);
CMutableTransaction mtx_child;
- mtx_child.vin.push_back(CTxIn(COutPoint(tx_parent->GetHash(), 1)));
- mtx_child.vin.push_back(CTxIn(COutPoint(tx_parent_also_child->GetHash(), 0)));
- mtx_child.vout.push_back(CTxOut(39 * COIN, spk));
+ mtx_child.vin.emplace_back(COutPoint(tx_parent->GetHash(), 1));
+ mtx_child.vin.emplace_back(COutPoint(tx_parent_also_child->GetHash(), 0));
+ mtx_child.vout.emplace_back(39 * COIN, spk);
CTransactionRef tx_child = MakeTransactionRef(mtx_child);
PackageValidationState state;
BOOST_CHECK(IsChildWithParents({tx_parent, tx_parent_also_child}));
BOOST_CHECK(IsChildWithParents({tx_parent, tx_child}));
BOOST_CHECK(IsChildWithParents({tx_parent, tx_parent_also_child, tx_child}));
+ BOOST_CHECK(!IsChildWithParentsTree({tx_parent, tx_parent_also_child, tx_child}));
// IsChildWithParents does not detect unsorted parents.
BOOST_CHECK(IsChildWithParents({tx_parent_also_child, tx_parent, tx_child}));
BOOST_CHECK(CheckPackage({tx_parent, tx_parent_also_child, tx_child}, state));
@@ -298,7 +301,7 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
// missing inputs, so the package validation isn't expected to happen.
{
CScriptWitness bad_witness;
- bad_witness.stack.push_back(std::vector<unsigned char>(1));
+ bad_witness.stack.emplace_back(1);
CMutableTransaction mtx_parent_invalid{mtx_parent};
mtx_parent_invalid.vin[0].scriptWitness = bad_witness;
CTransactionRef tx_parent_invalid = MakeTransactionRef(mtx_parent_invalid);
@@ -319,7 +322,7 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
}
// Child with missing parent.
- mtx_child.vin.push_back(CTxIn(COutPoint(package_unrelated[0]->GetHash(), 0)));
+ mtx_child.vin.emplace_back(COutPoint(package_unrelated[0]->GetHash(), 0));
Package package_missing_parent;
package_missing_parent.push_back(tx_parent);
package_missing_parent.push_back(MakeTransactionRef(mtx_child));
@@ -401,12 +404,12 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
// Make two children with the same txid but different witnesses.
CScriptWitness witness1;
- witness1.stack.push_back(std::vector<unsigned char>(1));
- witness1.stack.push_back(std::vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+ witness1.stack.emplace_back(1);
+ witness1.stack.emplace_back(witnessScript.begin(), witnessScript.end());
CScriptWitness witness2(witness1);
- witness2.stack.push_back(std::vector<unsigned char>(2));
- witness2.stack.push_back(std::vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+ witness2.stack.emplace_back(2);
+ witness2.stack.emplace_back(witnessScript.begin(), witnessScript.end());
CKey child_key;
child_key.MakeNewKey(true);
@@ -526,7 +529,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
CScript acs_script = CScript() << OP_TRUE;
CScript acs_spk = GetScriptForDestination(WitnessV0ScriptHash(acs_script));
CScriptWitness acs_witness;
- acs_witness.stack.push_back(std::vector<unsigned char>(acs_script.begin(), acs_script.end()));
+ acs_witness.stack.emplace_back(acs_script.begin(), acs_script.end());
// parent1 will already be in the mempool
auto mtx_parent1 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[1], /*input_vout=*/0,
@@ -540,11 +543,11 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
CScript grandparent2_script = CScript() << OP_DROP << OP_TRUE;
CScript grandparent2_spk = GetScriptForDestination(WitnessV0ScriptHash(grandparent2_script));
CScriptWitness parent2_witness1;
- parent2_witness1.stack.push_back(std::vector<unsigned char>(1));
- parent2_witness1.stack.push_back(std::vector<unsigned char>(grandparent2_script.begin(), grandparent2_script.end()));
+ parent2_witness1.stack.emplace_back(1);
+ parent2_witness1.stack.emplace_back(grandparent2_script.begin(), grandparent2_script.end());
CScriptWitness parent2_witness2;
- parent2_witness2.stack.push_back(std::vector<unsigned char>(2));
- parent2_witness2.stack.push_back(std::vector<unsigned char>(grandparent2_script.begin(), grandparent2_script.end()));
+ parent2_witness2.stack.emplace_back(2);
+ parent2_witness2.stack.emplace_back(grandparent2_script.begin(), grandparent2_script.end());
// Create grandparent2 creating an output with multiple spending paths. Submit to mempool.
auto mtx_grandparent2 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[2], /*input_vout=*/0,
@@ -590,13 +593,13 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
CScript mixed_child_spk = GetScriptForDestination(WitnessV0KeyHash(mixed_grandchild_key.GetPubKey()));
CMutableTransaction mtx_mixed_child;
- mtx_mixed_child.vin.push_back(CTxIn(COutPoint(ptx_parent1->GetHash(), 0)));
- mtx_mixed_child.vin.push_back(CTxIn(COutPoint(ptx_parent2_v1->GetHash(), 0)));
- mtx_mixed_child.vin.push_back(CTxIn(COutPoint(ptx_parent3->GetHash(), 0)));
+ mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent1->GetHash(), 0));
+ mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent2_v1->GetHash(), 0));
+ mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent3->GetHash(), 0));
mtx_mixed_child.vin[0].scriptWitness = acs_witness;
mtx_mixed_child.vin[1].scriptWitness = acs_witness;
mtx_mixed_child.vin[2].scriptWitness = acs_witness;
- mtx_mixed_child.vout.push_back(CTxOut((48 + 49 + 50 - 1) * COIN, mixed_child_spk));
+ mtx_mixed_child.vout.emplace_back((48 + 49 + 50 - 1) * COIN, mixed_child_spk);
CTransactionRef ptx_mixed_child = MakeTransactionRef(mtx_mixed_child);
package_mixed.push_back(ptx_mixed_child);
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 2947bc3fcb..e70c105c8a 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -256,6 +256,7 @@ TestingSetup::TestingSetup(
m_node.connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params()); // Deterministic randomness for tests.
PeerManager::Options peerman_opts;
ApplyArgsManOptions(*m_node.args, peerman_opts);
+ peerman_opts.deterministic_rng = true;
m_node.peerman = PeerManager::make(*m_node.connman, *m_node.addrman,
m_node.banman.get(), *m_node.chainman,
*m_node.mempool, peerman_opts);
@@ -399,7 +400,7 @@ std::vector<CTransactionRef> TestChain100Setup::PopulateMempool(FastRandomContex
for (size_t n{0}; n < num_inputs; ++n) {
if (unspent_prevouts.empty()) break;
const auto& [prevout, amount] = unspent_prevouts.front();
- mtx.vin.push_back(CTxIn(prevout, CScript()));
+ mtx.vin.emplace_back(prevout, CScript());
total_in += amount;
unspent_prevouts.pop_front();
}
@@ -408,7 +409,7 @@ std::vector<CTransactionRef> TestChain100Setup::PopulateMempool(FastRandomContex
const CAmount amount_per_output = (total_in - fee) / num_outputs;
for (size_t n{0}; n < num_outputs; ++n) {
CScript spk = CScript() << CScriptNum(num_transactions + n);
- mtx.vout.push_back(CTxOut(amount_per_output, spk));
+ mtx.vout.emplace_back(amount_per_output, spk);
}
CTransactionRef ptx = MakeTransactionRef(mtx);
mempool_transactions.push_back(ptx);
@@ -417,7 +418,7 @@ std::vector<CTransactionRef> TestChain100Setup::PopulateMempool(FastRandomContex
// it can be used to build a more complex transaction graph. Insert randomly into
// unspent_prevouts for extra randomness in the resulting structures.
for (size_t n{0}; n < num_outputs; ++n) {
- unspent_prevouts.push_back(std::make_pair(COutPoint(ptx->GetHash(), n), amount_per_output));
+ unspent_prevouts.emplace_back(COutPoint(ptx->GetHash(), n), amount_per_output);
std::swap(unspent_prevouts.back(), unspent_prevouts[det_rand.randrange(unspent_prevouts.size())]);
}
}
@@ -447,8 +448,8 @@ void TestChain100Setup::MockMempoolMinFee(const CFeeRate& target_feerate)
// Manually create an invalid transaction. Manually set the fee in the CTxMemPoolEntry to
// achieve the exact target feerate.
CMutableTransaction mtx = CMutableTransaction();
- mtx.vin.push_back(CTxIn{COutPoint{g_insecure_rand_ctx.rand256(), 0}});
- mtx.vout.push_back(CTxOut(1 * COIN, GetScriptForDestination(WitnessV0ScriptHash(CScript() << OP_TRUE))));
+ mtx.vin.emplace_back(COutPoint{g_insecure_rand_ctx.rand256(), 0});
+ mtx.vout.emplace_back(1 * COIN, GetScriptForDestination(WitnessV0ScriptHash(CScript() << OP_TRUE)));
const auto tx{MakeTransactionRef(mtx)};
LockPoints lp;
// The new mempool min feerate is equal to the removed package's feerate + incremental feerate.
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 67f71bd266..7d6c96ab40 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1023,9 +1023,9 @@ BOOST_AUTO_TEST_CASE(test_FormatParagraph)
BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
{
std::vector<std::string> comments;
- comments.push_back(std::string("comment1"));
+ comments.emplace_back("comment1");
std::vector<std::string> comments2;
- comments2.push_back(std::string("comment1"));
+ comments2.emplace_back("comment1");
comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/"));
BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/"));
diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp
index ae913939e8..45d3a58fd3 100644
--- a/src/test/util_threadnames_tests.cpp
+++ b/src/test/util_threadnames_tests.cpp
@@ -40,7 +40,7 @@ std::set<std::string> RenameEnMasse(int num_threads)
threads.reserve(num_threads);
for (int i = 0; i < num_threads; ++i) {
- threads.push_back(std::thread(RenameThisThread, i));
+ threads.emplace_back(RenameThisThread, i);
}
for (std::thread& thread : threads) thread.join();
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 411371f7c1..64cb5522eb 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -117,7 +117,7 @@ std::shared_ptr<const CBlock> MinerTestingSetup::BadBlock(const uint256& prev_ha
auto pblock = Block(prev_hash);
CMutableTransaction coinbase_spend;
- coinbase_spend.vin.push_back(CTxIn(COutPoint(pblock->vtx[0]->GetHash(), 0), CScript(), 0));
+ coinbase_spend.vin.emplace_back(COutPoint(pblock->vtx[0]->GetHash(), 0), CScript(), 0);
coinbase_spend.vout.push_back(pblock->vtx[0]->vout[0]);
CTransactionRef tx = MakeTransactionRef(coinbase_spend);
@@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
std::vector<CTransactionRef> txs;
for (int num_txs = 22; num_txs > 0; --num_txs) {
CMutableTransaction mtx;
- mtx.vin.push_back(CTxIn{COutPoint{last_mined->vtx[0]->GetHash(), 1}, CScript{}});
+ mtx.vin.emplace_back(COutPoint{last_mined->vtx[0]->GetHash(), 1}, CScript{});
mtx.vin[0].scriptWitness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE);
mtx.vout.push_back(last_mined->vtx[0]->vout[1]);
mtx.vout[0].nValue -= 1000;
diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp
index d34d98c219..2692037273 100644
--- a/src/test/validation_tests.cpp
+++ b/src/test/validation_tests.cpp
@@ -138,11 +138,11 @@ BOOST_AUTO_TEST_CASE(test_assumeutxo)
const auto out110 = *params->AssumeutxoForHeight(110);
BOOST_CHECK_EQUAL(out110.hash_serialized.ToString(), "1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618");
- BOOST_CHECK_EQUAL(out110.nChainTx, 110U);
+ BOOST_CHECK_EQUAL(out110.nChainTx, 111U);
const auto out110_2 = *params->AssumeutxoForBlockhash(uint256S("0x696e92821f65549c7ee134edceeeeaaa4105647a3c4fd9f298c0aec0ab50425c"));
BOOST_CHECK_EQUAL(out110_2.hash_serialized.ToString(), "1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618");
- BOOST_CHECK_EQUAL(out110_2.nChainTx, 110U);
+ BOOST_CHECK_EQUAL(out110_2.nChainTx, 111U);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index e021cfb06e..461662ad93 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -1021,7 +1021,7 @@ void CCoinsViewMemPool::PackageAddTransaction(const CTransactionRef& tx)
{
for (unsigned int n = 0; n < tx->vout.size(); ++n) {
m_temp_added.emplace(COutPoint(tx->GetHash(), n), Coin(tx->vout[n], MEMPOOL_HEIGHT, false));
- m_non_base_coins.emplace(COutPoint(tx->GetHash(), n));
+ m_non_base_coins.emplace(tx->GetHash(), n);
}
}
void CCoinsViewMemPool::Reset()
diff --git a/src/validation.cpp b/src/validation.cpp
index 30b3dde74f..290db8c9b2 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -68,8 +68,8 @@
#include <numeric>
#include <optional>
#include <string>
-#include <utility>
#include <tuple>
+#include <utility>
using kernel::CCoinsStats;
using kernel::CoinStatsHashType;
@@ -1287,6 +1287,12 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
// For transactions consisting of exactly one child and its parents, it suffices to use the
// package feerate (total modified fees / total virtual size) to check this requirement.
+ // Note that this is an aggregate feerate; this function has not checked that there are transactions
+ // too low feerate to pay for themselves, or that the child transactions are higher feerate than
+ // their parents. Using aggregate feerate may allow "parents pay for child" behavior and permit
+ // a child that is below mempool minimum feerate. To avoid these behaviors, callers of
+ // AcceptMultipleTransactions need to restrict txns topology (e.g. to ancestor sets) and check
+ // the feerates of individuals and subsets.
const auto m_total_vsize = std::accumulate(workspaces.cbegin(), workspaces.cend(), int64_t{0},
[](int64_t sum, auto& ws) { return sum + ws.m_vsize; });
const auto m_total_modified_fees = std::accumulate(workspaces.cbegin(), workspaces.cend(), CAmount{0},
@@ -2407,7 +2413,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
CTxUndo undoDummy;
if (i > 0) {
- blockundo.vtxundo.push_back(CTxUndo());
+ blockundo.vtxundo.emplace_back();
}
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
}
@@ -2990,7 +2996,7 @@ CBlockIndex* Chainstate::FindMostWorkChain()
CBlockIndex *pindexTest = pindexNew;
bool fInvalidAncestor = false;
while (pindexTest && !m_chain.Contains(pindexTest)) {
- assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0);
+ assert(pindexTest->HaveNumChainTxs() || pindexTest->nHeight == 0);
// Pruned nodes may have entries in setBlockIndexCandidates for
// which block files have been deleted. Remove those as candidates
@@ -3345,7 +3351,7 @@ bool Chainstate::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
// call preciousblock 2**31-1 times on the same set of tips...
m_chainman.nBlockReverseSequenceId--;
}
- if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->HaveTxsDownloaded()) {
+ if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->HaveNumChainTxs()) {
setBlockIndexCandidates.insert(pindex);
PruneBlockIndexCandidates();
}
@@ -3393,7 +3399,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
if (!m_chain.Contains(candidate) &&
!CBlockIndexWorkComparator()(candidate, pindex->pprev) &&
candidate->IsValid(BLOCK_VALID_TRANSACTIONS) &&
- candidate->HaveTxsDownloaded()) {
+ candidate->HaveNumChainTxs()) {
candidate_blocks_by_work.insert(std::make_pair(candidate->nChainWork, candidate));
}
}
@@ -3482,7 +3488,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
// Loop back over all block index entries and add any missing entries
// to setBlockIndexCandidates.
for (auto& [_, block_index] : m_blockman.m_block_index) {
- if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && block_index.HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(&block_index, m_chain.Tip())) {
+ if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && block_index.HaveNumChainTxs() && !setBlockIndexCandidates.value_comp()(&block_index, m_chain.Tip())) {
setBlockIndexCandidates.insert(&block_index);
}
}
@@ -3514,7 +3520,7 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
if (!block_index.IsValid() && block_index.GetAncestor(nHeight) == pindex) {
block_index.nStatus &= ~BLOCK_FAILED_MASK;
m_blockman.m_dirty_blockindex.insert(&block_index);
- if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && block_index.HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), &block_index)) {
+ if (block_index.IsValid(BLOCK_VALID_TRANSACTIONS) && block_index.HaveNumChainTxs() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), &block_index)) {
setBlockIndexCandidates.insert(&block_index);
}
if (&block_index == m_chainman.m_best_invalid) {
@@ -3577,7 +3583,7 @@ void ChainstateManager::ReceivedBlockTransactions(const CBlock& block, CBlockInd
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
m_blockman.m_dirty_blockindex.insert(pindexNew);
- if (pindexNew->pprev == nullptr || pindexNew->pprev->HaveTxsDownloaded()) {
+ if (pindexNew->pprev == nullptr || pindexNew->pprev->HaveNumChainTxs()) {
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
std::deque<CBlockIndex*> queue;
queue.push_back(pindexNew);
@@ -4560,7 +4566,7 @@ bool ChainstateManager::LoadBlockIndex()
// here.
if (pindex == GetSnapshotBaseBlock() ||
(pindex->IsValid(BLOCK_VALID_TRANSACTIONS) &&
- (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))) {
+ (pindex->HaveNumChainTxs() || pindex->pprev == nullptr))) {
for (Chainstate* chainstate : GetAll()) {
chainstate->TryAddBlockIndexCandidate(pindex);
@@ -4838,10 +4844,14 @@ void ChainstateManager::CheckBlockIndex()
CBlockIndex* pindexFirstAssumeValid = nullptr; // Oldest ancestor of pindex which has BLOCK_ASSUMED_VALID
while (pindex != nullptr) {
nNodes++;
- if (pindex->pprev && pindex->nTx > 0) {
- // nChainTx should increase monotonically
- assert(pindex->pprev->nChainTx <= pindex->nChainTx);
- }
+ // Make sure nChainTx sum is correctly computed.
+ unsigned int prev_chain_tx = pindex->pprev ? pindex->pprev->nChainTx : 0;
+ assert((pindex->nChainTx == pindex->nTx + prev_chain_tx)
+ // For testing, allow transaction counts to be completely unset.
+ || (pindex->nChainTx == 0 && pindex->nTx == 0)
+ // For testing, allow this nChainTx to be unset if previous is also unset.
+ || (pindex->nChainTx == 0 && prev_chain_tx == 0 && pindex->pprev));
+
if (pindexFirstAssumeValid == nullptr && pindex->nStatus & BLOCK_ASSUMED_VALID) pindexFirstAssumeValid = pindex;
if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
@@ -4880,7 +4890,7 @@ void ChainstateManager::CheckBlockIndex()
}
}
}
- if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
+ if (!pindex->HaveNumChainTxs()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
// Unless these indexes are assumed valid and pending block download on a
@@ -4910,9 +4920,9 @@ void ChainstateManager::CheckBlockIndex()
// actually seen a block's transactions.
assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0)); // This is pruning-independent.
}
- // All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveTxsDownloaded().
- assert((pindexFirstNeverProcessed == nullptr) == pindex->HaveTxsDownloaded());
- assert((pindexFirstNotTransactionsValid == nullptr) == pindex->HaveTxsDownloaded());
+ // All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveNumChainTxs().
+ assert((pindexFirstNeverProcessed == nullptr) == pindex->HaveNumChainTxs());
+ assert((pindexFirstNotTransactionsValid == nullptr) == pindex->HaveNumChainTxs());
assert(pindex->nHeight == nHeight); // nHeight must be consistent.
assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
@@ -5361,7 +5371,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
// ActivateSnapshot(), but is done so that we avoid doing the long work of staging
// a snapshot that isn't actually usable.
if (WITH_LOCK(::cs_main, return !CBlockIndexWorkComparator()(ActiveTip(), snapshot_start_block))) {
- LogPrintf("[snapshot] activation failed - height does not exceed active chainstate\n");
+ LogPrintf("[snapshot] activation failed - work does not exceed active chainstate\n");
return false;
}
@@ -5762,7 +5772,7 @@ ChainstateManager::~ChainstateManager()
m_versionbitscache.Clear();
}
-bool ChainstateManager::DetectSnapshotChainstate(CTxMemPool* mempool)
+bool ChainstateManager::DetectSnapshotChainstate()
{
assert(!m_snapshot_chainstate);
std::optional<fs::path> path = node::FindSnapshotChainstateDir(m_options.datadir);
diff --git a/src/validation.h b/src/validation.h
index 94a00e44a4..7ce60da634 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -836,9 +836,10 @@ private:
//! Once this pointer is set to a corresponding chainstate, it will not
//! be reset until init.cpp:Shutdown().
//!
- //! This is especially important when, e.g., calling ActivateBestChain()
- //! on all chainstates because we are not able to hold ::cs_main going into
- //! that call.
+ //! It is important for the pointer to not be deleted until shutdown,
+ //! because cs_main is not always held when the pointer is accessed, for
+ //! example when calling ActivateBestChain, so there's no way you could
+ //! prevent code from using the pointer while deleting it.
std::unique_ptr<Chainstate> m_ibd_chainstate GUARDED_BY(::cs_main);
//! A chainstate initialized on the basis of a UTXO snapshot. If this is
@@ -847,17 +848,14 @@ private:
//! Once this pointer is set to a corresponding chainstate, it will not
//! be reset until init.cpp:Shutdown().
//!
- //! This is especially important when, e.g., calling ActivateBestChain()
- //! on all chainstates because we are not able to hold ::cs_main going into
- //! that call.
+ //! It is important for the pointer to not be deleted until shutdown,
+ //! because cs_main is not always held when the pointer is accessed, for
+ //! example when calling ActivateBestChain, so there's no way you could
+ //! prevent code from using the pointer while deleting it.
std::unique_ptr<Chainstate> m_snapshot_chainstate GUARDED_BY(::cs_main);
//! Points to either the ibd or snapshot chainstate; indicates our
//! most-work chain.
- //!
- //! This is especially important when, e.g., calling ActivateBestChain()
- //! on all chainstates because we are not able to hold ::cs_main going into
- //! that call.
Chainstate* m_active_chainstate GUARDED_BY(::cs_main) {nullptr};
CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};
@@ -1203,7 +1201,7 @@ public:
//! When starting up, search the datadir for a chainstate based on a UTXO
//! snapshot that is in the process of being validated.
- bool DetectSnapshotChainstate(CTxMemPool* mempool) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ bool DetectSnapshotChainstate() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
void ResetChainstates() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index d100b69d3c..3e1ec667e0 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -573,13 +573,13 @@ RPCHelpMan importwallet()
}
}
nTimeBegin = std::min(nTimeBegin, nTime);
- keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
+ keys.emplace_back(key, nTime, fLabel, strLabel);
} else if(IsHex(vstr[0])) {
std::vector<unsigned char> vData(ParseHex(vstr[0]));
CScript script = CScript(vData.begin(), vData.end());
int64_t birth_time = ParseISO8601DateTime(vstr[1]);
if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
- scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
+ scripts.emplace_back(script, birth_time);
}
}
file.close();
@@ -759,7 +759,7 @@ RPCHelpMan dumpwallet()
std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
vKeyBirth.reserve(mapKeyBirth.size());
for (const auto& entry : mapKeyBirth) {
- vKeyBirth.push_back(std::make_pair(entry.second, entry.first));
+ vKeyBirth.emplace_back(entry.second, entry.first);
}
mapKeyBirth.clear();
std::sort(vKeyBirth.begin(), vKeyBirth.end());
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 3774e6a3ef..164ce9afed 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -343,7 +343,7 @@ static RPCHelpMan createwallet()
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false}, "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
{"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
- " Setting to \"false\" will create a legacy wallet; however, the legacy wallet type is being deprecated and"
+ " Setting to \"false\" will create a legacy wallet; This is only possible with the -deprecatedrpc=create_bdb setting because, the legacy wallet type is being deprecated and"
" support for creating and opening legacy wallets will be removed in the future."},
{"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
{"external_signer", RPCArg::Type::BOOL, RPCArg::Default{false}, "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."},
@@ -389,11 +389,16 @@ static RPCHelpMan createwallet()
if (!request.params[4].isNull() && request.params[4].get_bool()) {
flags |= WALLET_FLAG_AVOID_REUSE;
}
- if (request.params[5].isNull() || request.params[5].get_bool()) {
+ if (self.Arg<bool>(5)) {
#ifndef USE_SQLITE
throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)");
#endif
flags |= WALLET_FLAG_DESCRIPTORS;
+ } else {
+ if (!context.chain->rpcEnableDeprecated("create_bdb")) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "BDB wallet creation is deprecated and will be removed in a future release."
+ " In this release it can be re-enabled temporarily with the -deprecatedrpc=create_bdb setting.");
+ }
}
if (!request.params[7].isNull() && request.params[7].get_bool()) {
#ifdef ENABLE_EXTERNAL_SIGNER
diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp
index 0a0745b1c5..04c02b0dcc 100644
--- a/src/wallet/salvage.cpp
+++ b/src/wallet/salvage.cpp
@@ -146,7 +146,7 @@ bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bil
warnings.push_back(Untranslated("Salvage: WARNING: Number of keys in data does not match number of values."));
break;
}
- salvagedData.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
+ salvagedData.emplace_back(ParseHex(keyHex), ParseHex(valueHex));
}
}
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 20f735da12..bc3327cdb2 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1902,7 +1902,7 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
std::string desc_str;
bool watchonly = !desc->ToPrivateString(*this, desc_str);
if (watchonly && !m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- out.watch_descs.push_back({desc->ToString(), creation_time});
+ out.watch_descs.emplace_back(desc->ToString(), creation_time);
// Get the scriptPubKeys without writing this to the wallet
FlatSigningProvider provider;
@@ -1971,14 +1971,14 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
assert(IsMine(sh_spk) == ISMINE_NO && IsMine(witprog) == ISMINE_NO && IsMine(sh_wsh_spk) == ISMINE_NO);
std::unique_ptr<Descriptor> sh_desc = InferDescriptor(sh_spk, *GetSolvingProvider(sh_spk));
- out.solvable_descs.push_back({sh_desc->ToString(), creation_time});
+ out.solvable_descs.emplace_back(sh_desc->ToString(), creation_time);
const auto desc = InferDescriptor(witprog, *this);
if (desc->IsSolvable()) {
std::unique_ptr<Descriptor> wsh_desc = InferDescriptor(witprog, *GetSolvingProvider(witprog));
- out.solvable_descs.push_back({wsh_desc->ToString(), creation_time});
+ out.solvable_descs.emplace_back(wsh_desc->ToString(), creation_time);
std::unique_ptr<Descriptor> sh_wsh_desc = InferDescriptor(sh_wsh_spk, *GetSolvingProvider(sh_wsh_spk));
- out.solvable_descs.push_back({sh_wsh_desc->ToString(), creation_time});
+ out.solvable_descs.emplace_back(sh_wsh_desc->ToString(), creation_time);
}
}
}
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 7e6fba33aa..8314a2ddfa 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -1151,7 +1151,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
// behavior."
const uint32_t nSequence{coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL};
for (const auto& coin : selected_coins) {
- txNew.vin.push_back(CTxIn(coin->outpoint, CScript(), nSequence));
+ txNew.vin.emplace_back(coin->outpoint, CScript(), nSequence);
}
DiscourageFeeSniping(txNew, rng_fast, wallet.chain(), wallet.GetLastBlockHash(), wallet.GetLastBlockHeight());
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 21ed52731a..ad4bb3a9d2 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -49,7 +49,7 @@ BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
static CMutableTransaction TestSimpleSpend(const CTransaction& from, uint32_t index, const CKey& key, const CScript& pubkey)
{
CMutableTransaction mtx;
- mtx.vout.push_back({from.vout[index].nValue - DEFAULT_TRANSACTION_MAXFEE, pubkey});
+ mtx.vout.emplace_back(from.vout[index].nValue - DEFAULT_TRANSACTION_MAXFEE, pubkey);
mtx.vin.push_back({CTxIn{from.GetHash(), index}});
FillableSigningProvider keystore;
keystore.AddKey(key);
@@ -945,8 +945,8 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
const auto op_dest{*Assert(wallet.GetNewDestination(OutputType::BECH32M, ""))};
CMutableTransaction mtx;
- mtx.vout.push_back({COIN, GetScriptForDestination(op_dest)});
- mtx.vin.push_back(CTxIn(g_insecure_rand_ctx.rand256(), 0));
+ mtx.vout.emplace_back(COIN, GetScriptForDestination(op_dest));
+ mtx.vin.emplace_back(g_insecure_rand_ctx.rand256(), 0);
const auto& tx_id_to_spend = wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInMempool{})->GetHash();
{
@@ -961,7 +961,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
// 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));
+ mtx.vin.emplace_back(tx_id_to_spend, 0);
wallet.transactionAddedToMempool(MakeTransactionRef(mtx));
const uint256& good_tx_id = mtx.GetHash();
@@ -982,7 +982,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
// verify that we are not moving forward if the wallet cannot store it
GetMockableDatabase(wallet).m_pass = false;
mtx.vin.clear();
- mtx.vin.push_back(CTxIn(good_tx_id, 0));
+ mtx.vin.emplace_back(good_tx_id, 0);
BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx)),
std::runtime_error,
HasReason("DB error adding transaction to wallet, write failed"));
diff --git a/src/wallet/transaction.h b/src/wallet/transaction.h
index 1a79d7db4e..3b9cde9832 100644
--- a/src/wallet/transaction.h
+++ b/src/wallet/transaction.h
@@ -29,10 +29,12 @@ struct TxStateConfirmed {
int position_in_block;
explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
+ std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
};
//! State of transaction added to mempool.
struct TxStateInMempool {
+ std::string toString() const { return strprintf("InMempool"); }
};
//! State of rejected transaction that conflicts with a confirmed block.
@@ -41,6 +43,7 @@ struct TxStateConflicted {
int conflicting_block_height;
explicit TxStateConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
+ std::string toString() const { return strprintf("Conflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
};
//! State of transaction not confirmed or conflicting with a known block and
@@ -51,6 +54,7 @@ struct TxStateInactive {
bool abandoned;
explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
+ std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
};
//! State of transaction loaded in an unrecognized state with unexpected hash or
@@ -62,6 +66,7 @@ struct TxStateUnrecognized {
int index;
TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
+ std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
};
//! All possible CWalletTx states
@@ -109,6 +114,12 @@ static inline int TxStateSerializedIndex(const TxState& state)
}, state);
}
+//! Return TxState or SyncTxState as a string for logging or debugging.
+template<typename T>
+std::string TxStateString(const T& state)
+{
+ return std::visit([](const auto& s) { return s.toString(); }, state);
+}
/**
* Cachable amount subdivided into watchonly and spendable parts.
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index c240e88531..cb8671c8e7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1130,7 +1130,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const
}
//// debug print
- WalletLogPrintf("AddToWallet %s %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ WalletLogPrintf("AddToWallet %s %s%s %s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""), TxStateString(state));
// Write to disk
if (fInsertedNew || fUpdated)
@@ -4230,7 +4230,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
// Remember this wallet's walletdir to remove after unloading
std::vector<fs::path> wallet_dirs;
- wallet_dirs.push_back(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
+ wallet_dirs.emplace_back(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
// Unload the wallet locally
assert(local_wallet.use_count() == 1);
@@ -4243,7 +4243,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
// Get the directories to remove after unloading
for (std::shared_ptr<CWallet>& w : created_wallets) {
- wallet_dirs.push_back(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
+ wallet_dirs.emplace_back(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
}
// Unload the wallets